diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-04-12 14:25:14 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-04-12 14:41:59 -0400 |
commit | 7eab0f64a9eba5405222fdef0ede2468bf495efd (patch) | |
tree | ec99640b8d0b12adbfacb85c27683125debd14f2 | |
parent | cade455596504fae8e134a27189713ddf7c6d04d (diff) | |
parent | 8065248069097dddf9945acfb2081025e9618c16 (diff) |
Merge branch 'master' into for-davem
Conflicts:
drivers/net/wireless/iwlwifi/iwl-testmode.c
net/wireless/nl80211.c
185 files changed, 5524 insertions, 3085 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index c5ac6929c41c..f3e214f9e256 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl | |||
@@ -516,7 +516,7 @@ | |||
516 | !Finclude/net/mac80211.h ieee80211_start_tx_ba_cb_irqsafe | 516 | !Finclude/net/mac80211.h ieee80211_start_tx_ba_cb_irqsafe |
517 | !Finclude/net/mac80211.h ieee80211_stop_tx_ba_session | 517 | !Finclude/net/mac80211.h ieee80211_stop_tx_ba_session |
518 | !Finclude/net/mac80211.h ieee80211_stop_tx_ba_cb_irqsafe | 518 | !Finclude/net/mac80211.h ieee80211_stop_tx_ba_cb_irqsafe |
519 | !Finclude/net/mac80211.h rate_control_changed | 519 | !Finclude/net/mac80211.h ieee80211_rate_control_changed |
520 | !Finclude/net/mac80211.h ieee80211_tx_rate_control | 520 | !Finclude/net/mac80211.h ieee80211_tx_rate_control |
521 | !Finclude/net/mac80211.h rate_control_send_low | 521 | !Finclude/net/mac80211.h rate_control_send_low |
522 | </chapter> | 522 | </chapter> |
diff --git a/Documentation/networking/mac80211-auth-assoc-deauth.txt b/Documentation/networking/mac80211-auth-assoc-deauth.txt index e0a2aa585ca3..d7a15fe91bf7 100644 --- a/Documentation/networking/mac80211-auth-assoc-deauth.txt +++ b/Documentation/networking/mac80211-auth-assoc-deauth.txt | |||
@@ -23,7 +23,7 @@ BA session stop & deauth/disassoc frames | |||
23 | end note | 23 | end note |
24 | end | 24 | end |
25 | 25 | ||
26 | mac80211->driver: config(channel, non-HT) | 26 | mac80211->driver: config(channel, channel type) |
27 | mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap) | 27 | mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap) |
28 | mac80211->driver: sta_state(AP, exists) | 28 | mac80211->driver: sta_state(AP, exists) |
29 | 29 | ||
@@ -51,7 +51,7 @@ note over mac80211,driver: cleanup like for authenticate | |||
51 | end | 51 | end |
52 | 52 | ||
53 | alt not previously authenticated (FT) | 53 | alt not previously authenticated (FT) |
54 | mac80211->driver: config(channel, non-HT) | 54 | mac80211->driver: config(channel, channel type) |
55 | mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap) | 55 | mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap) |
56 | mac80211->driver: sta_state(AP, exists) | 56 | mac80211->driver: sta_state(AP, exists) |
57 | mac80211->driver: sta_state(AP, authenticated) | 57 | mac80211->driver: sta_state(AP, authenticated) |
@@ -67,10 +67,6 @@ end | |||
67 | 67 | ||
68 | mac80211->driver: set up QoS parameters | 68 | mac80211->driver: set up QoS parameters |
69 | 69 | ||
70 | alt is HT channel | ||
71 | mac80211->driver: config(channel, HT params) | ||
72 | end | ||
73 | |||
74 | mac80211->driver: bss_info_changed(QoS, HT, associated with AID) | 70 | mac80211->driver: bss_info_changed(QoS, HT, associated with AID) |
75 | mac80211->userspace: associated | 71 | mac80211->userspace: associated |
76 | 72 | ||
@@ -95,5 +91,5 @@ mac80211->driver: sta_state(AP,exists) | |||
95 | mac80211->driver: sta_state(AP,not-exists) | 91 | mac80211->driver: sta_state(AP,not-exists) |
96 | mac80211->driver: turn off powersave | 92 | mac80211->driver: turn off powersave |
97 | mac80211->driver: bss_info_changed(clear BSSID, not associated, no QoS, ...) | 93 | mac80211->driver: bss_info_changed(clear BSSID, not associated, no QoS, ...) |
98 | mac80211->driver: config(non-HT channel type) | 94 | mac80211->driver: config(channel type to non-HT) |
99 | mac80211->userspace: disconnected | 95 | mac80211->userspace: disconnected |
diff --git a/MAINTAINERS b/MAINTAINERS index d710c000805f..91a37da22e36 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1522,8 +1522,8 @@ M: Gustavo Padovan <gustavo@padovan.org> | |||
1522 | M: Johan Hedberg <johan.hedberg@gmail.com> | 1522 | M: Johan Hedberg <johan.hedberg@gmail.com> |
1523 | L: linux-bluetooth@vger.kernel.org | 1523 | L: linux-bluetooth@vger.kernel.org |
1524 | W: http://www.bluez.org/ | 1524 | W: http://www.bluez.org/ |
1525 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git | 1525 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git |
1526 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git | 1526 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git |
1527 | S: Maintained | 1527 | S: Maintained |
1528 | F: drivers/bluetooth/ | 1528 | F: drivers/bluetooth/ |
1529 | 1529 | ||
@@ -1533,8 +1533,8 @@ M: Gustavo Padovan <gustavo@padovan.org> | |||
1533 | M: Johan Hedberg <johan.hedberg@gmail.com> | 1533 | M: Johan Hedberg <johan.hedberg@gmail.com> |
1534 | L: linux-bluetooth@vger.kernel.org | 1534 | L: linux-bluetooth@vger.kernel.org |
1535 | W: http://www.bluez.org/ | 1535 | W: http://www.bluez.org/ |
1536 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git | 1536 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git |
1537 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git | 1537 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git |
1538 | S: Maintained | 1538 | S: Maintained |
1539 | F: net/bluetooth/ | 1539 | F: net/bluetooth/ |
1540 | F: include/net/bluetooth/ | 1540 | F: include/net/bluetooth/ |
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig index c1172dafdffa..fb7c80fb721e 100644 --- a/drivers/bcma/Kconfig +++ b/drivers/bcma/Kconfig | |||
@@ -29,7 +29,7 @@ config BCMA_HOST_PCI | |||
29 | 29 | ||
30 | config BCMA_DRIVER_PCI_HOSTMODE | 30 | config BCMA_DRIVER_PCI_HOSTMODE |
31 | bool "Driver for PCI core working in hostmode" | 31 | bool "Driver for PCI core working in hostmode" |
32 | depends on BCMA && MIPS | 32 | depends on BCMA && MIPS && BCMA_HOST_PCI |
33 | help | 33 | help |
34 | PCI core hostmode operation (external PCI bus). | 34 | PCI core hostmode operation (external PCI bus). |
35 | 35 | ||
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index 4e20bcfa7ec5..d2097a11c3c7 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include "bcma_private.h" | 12 | #include "bcma_private.h" |
13 | #include <linux/pci.h> | ||
13 | #include <linux/export.h> | 14 | #include <linux/export.h> |
14 | #include <linux/bcma/bcma.h> | 15 | #include <linux/bcma/bcma.h> |
15 | #include <asm/paccess.h> | 16 | #include <asm/paccess.h> |
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 48442476ec00..ae9edca7b56d 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -72,7 +72,9 @@ static struct usb_device_id ath3k_table[] = { | |||
72 | 72 | ||
73 | /* Atheros AR3012 with sflash firmware*/ | 73 | /* Atheros AR3012 with sflash firmware*/ |
74 | { USB_DEVICE(0x0CF3, 0x3004) }, | 74 | { USB_DEVICE(0x0CF3, 0x3004) }, |
75 | { USB_DEVICE(0x0CF3, 0x311D) }, | ||
75 | { USB_DEVICE(0x13d3, 0x3375) }, | 76 | { USB_DEVICE(0x13d3, 0x3375) }, |
77 | { USB_DEVICE(0x04CA, 0x3005) }, | ||
76 | 78 | ||
77 | /* Atheros AR5BBU12 with sflash firmware */ | 79 | /* Atheros AR5BBU12 with sflash firmware */ |
78 | { USB_DEVICE(0x0489, 0xE02C) }, | 80 | { USB_DEVICE(0x0489, 0xE02C) }, |
@@ -89,7 +91,9 @@ static struct usb_device_id ath3k_blist_tbl[] = { | |||
89 | 91 | ||
90 | /* Atheros AR3012 with sflash firmware*/ | 92 | /* Atheros AR3012 with sflash firmware*/ |
91 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 93 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
94 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, | ||
92 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 95 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
96 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | ||
93 | 97 | ||
94 | { } /* Terminating entry */ | 98 | { } /* Terminating entry */ |
95 | }; | 99 | }; |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 480cad920048..3311b812a0c6 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -61,7 +61,7 @@ static struct usb_device_id btusb_table[] = { | |||
61 | { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, | 61 | { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, |
62 | 62 | ||
63 | /* Broadcom SoftSailing reporting vendor specific */ | 63 | /* Broadcom SoftSailing reporting vendor specific */ |
64 | { USB_DEVICE(0x05ac, 0x21e1) }, | 64 | { USB_DEVICE(0x0a5c, 0x21e1) }, |
65 | 65 | ||
66 | /* Apple MacBookPro 7,1 */ | 66 | /* Apple MacBookPro 7,1 */ |
67 | { USB_DEVICE(0x05ac, 0x8213) }, | 67 | { USB_DEVICE(0x05ac, 0x8213) }, |
@@ -103,6 +103,7 @@ static struct usb_device_id btusb_table[] = { | |||
103 | /* Broadcom BCM20702A0 */ | 103 | /* Broadcom BCM20702A0 */ |
104 | { USB_DEVICE(0x0a5c, 0x21e3) }, | 104 | { USB_DEVICE(0x0a5c, 0x21e3) }, |
105 | { USB_DEVICE(0x0a5c, 0x21e6) }, | 105 | { USB_DEVICE(0x0a5c, 0x21e6) }, |
106 | { USB_DEVICE(0x0a5c, 0x21e8) }, | ||
106 | { USB_DEVICE(0x0a5c, 0x21f3) }, | 107 | { USB_DEVICE(0x0a5c, 0x21f3) }, |
107 | { USB_DEVICE(0x413c, 0x8197) }, | 108 | { USB_DEVICE(0x413c, 0x8197) }, |
108 | 109 | ||
@@ -129,7 +130,9 @@ static struct usb_device_id blacklist_table[] = { | |||
129 | 130 | ||
130 | /* Atheros 3012 with sflash firmware */ | 131 | /* Atheros 3012 with sflash firmware */ |
131 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 132 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
133 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, | ||
132 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 134 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
135 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | ||
133 | 136 | ||
134 | /* Atheros AR5BBU12 with sflash firmware */ | 137 | /* Atheros AR5BBU12 with sflash firmware */ |
135 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, | 138 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, |
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index fd5adb408f44..98a8c05d4f23 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -299,11 +299,11 @@ static void hci_uart_tty_close(struct tty_struct *tty) | |||
299 | hci_uart_close(hdev); | 299 | hci_uart_close(hdev); |
300 | 300 | ||
301 | if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { | 301 | if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) { |
302 | hu->proto->close(hu); | ||
303 | if (hdev) { | 302 | if (hdev) { |
304 | hci_unregister_dev(hdev); | 303 | hci_unregister_dev(hdev); |
305 | hci_free_dev(hdev); | 304 | hci_free_dev(hdev); |
306 | } | 305 | } |
306 | hu->proto->close(hu); | ||
307 | } | 307 | } |
308 | 308 | ||
309 | kfree(hu); | 309 | kfree(hu); |
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index 35e93704c4ef..5c008757662b 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include "ath5k.h" | 19 | #include "ath5k.h" |
18 | #include "reg.h" | 20 | #include "reg.h" |
19 | #include "debug.h" | 21 | #include "debug.h" |
@@ -728,33 +730,25 @@ void | |||
728 | ath5k_ani_print_counters(struct ath5k_hw *ah) | 730 | ath5k_ani_print_counters(struct ath5k_hw *ah) |
729 | { | 731 | { |
730 | /* clears too */ | 732 | /* clears too */ |
731 | printk(KERN_NOTICE "ACK fail\t%d\n", | 733 | pr_notice("ACK fail\t%d\n", ath5k_hw_reg_read(ah, AR5K_ACK_FAIL)); |
732 | ath5k_hw_reg_read(ah, AR5K_ACK_FAIL)); | 734 | pr_notice("RTS fail\t%d\n", ath5k_hw_reg_read(ah, AR5K_RTS_FAIL)); |
733 | printk(KERN_NOTICE "RTS fail\t%d\n", | 735 | pr_notice("RTS success\t%d\n", ath5k_hw_reg_read(ah, AR5K_RTS_OK)); |
734 | ath5k_hw_reg_read(ah, AR5K_RTS_FAIL)); | 736 | pr_notice("FCS error\t%d\n", ath5k_hw_reg_read(ah, AR5K_FCS_FAIL)); |
735 | printk(KERN_NOTICE "RTS success\t%d\n", | ||
736 | ath5k_hw_reg_read(ah, AR5K_RTS_OK)); | ||
737 | printk(KERN_NOTICE "FCS error\t%d\n", | ||
738 | ath5k_hw_reg_read(ah, AR5K_FCS_FAIL)); | ||
739 | 737 | ||
740 | /* no clear */ | 738 | /* no clear */ |
741 | printk(KERN_NOTICE "tx\t%d\n", | 739 | pr_notice("tx\t%d\n", ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX)); |
742 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX)); | 740 | pr_notice("rx\t%d\n", ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX)); |
743 | printk(KERN_NOTICE "rx\t%d\n", | 741 | pr_notice("busy\t%d\n", ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR)); |
744 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX)); | 742 | pr_notice("cycles\t%d\n", ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE)); |
745 | printk(KERN_NOTICE "busy\t%d\n", | 743 | |
746 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR)); | 744 | pr_notice("AR5K_PHYERR_CNT1\t%d\n", |
747 | printk(KERN_NOTICE "cycles\t%d\n", | 745 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)); |
748 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE)); | 746 | pr_notice("AR5K_PHYERR_CNT2\t%d\n", |
749 | 747 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)); | |
750 | printk(KERN_NOTICE "AR5K_PHYERR_CNT1\t%d\n", | 748 | pr_notice("AR5K_OFDM_FIL_CNT\t%d\n", |
751 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)); | 749 | ath5k_hw_reg_read(ah, AR5K_OFDM_FIL_CNT)); |
752 | printk(KERN_NOTICE "AR5K_PHYERR_CNT2\t%d\n", | 750 | pr_notice("AR5K_CCK_FIL_CNT\t%d\n", |
753 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)); | 751 | ath5k_hw_reg_read(ah, AR5K_CCK_FIL_CNT)); |
754 | printk(KERN_NOTICE "AR5K_OFDM_FIL_CNT\t%d\n", | ||
755 | ath5k_hw_reg_read(ah, AR5K_OFDM_FIL_CNT)); | ||
756 | printk(KERN_NOTICE "AR5K_CCK_FIL_CNT\t%d\n", | ||
757 | ath5k_hw_reg_read(ah, AR5K_CCK_FIL_CNT)); | ||
758 | } | 752 | } |
759 | 753 | ||
760 | #endif | 754 | #endif |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 8d434b8f5855..55ef93dd7438 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -76,26 +76,29 @@ | |||
76 | GENERIC DRIVER DEFINITIONS | 76 | GENERIC DRIVER DEFINITIONS |
77 | \****************************/ | 77 | \****************************/ |
78 | 78 | ||
79 | #define ATH5K_PRINTF(fmt, ...) \ | 79 | #define ATH5K_PRINTF(fmt, ...) \ |
80 | printk(KERN_WARNING "%s: " fmt, __func__, ##__VA_ARGS__) | 80 | pr_warn("%s: " fmt, __func__, ##__VA_ARGS__) |
81 | 81 | ||
82 | #define ATH5K_PRINTK(_sc, _level, _fmt, ...) \ | 82 | void __printf(3, 4) |
83 | printk(_level "ath5k %s: " _fmt, \ | 83 | _ath5k_printk(const struct ath5k_hw *ah, const char *level, |
84 | ((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \ | 84 | const char *fmt, ...); |
85 | ##__VA_ARGS__) | ||
86 | 85 | ||
87 | #define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \ | 86 | #define ATH5K_PRINTK(_sc, _level, _fmt, ...) \ |
88 | if (net_ratelimit()) \ | 87 | _ath5k_printk(_sc, _level, _fmt, ##__VA_ARGS__) |
89 | ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \ | ||
90 | } while (0) | ||
91 | 88 | ||
92 | #define ATH5K_INFO(_sc, _fmt, ...) \ | 89 | #define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) \ |
90 | do { \ | ||
91 | if (net_ratelimit()) \ | ||
92 | ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \ | ||
93 | } while (0) | ||
94 | |||
95 | #define ATH5K_INFO(_sc, _fmt, ...) \ | ||
93 | ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__) | 96 | ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__) |
94 | 97 | ||
95 | #define ATH5K_WARN(_sc, _fmt, ...) \ | 98 | #define ATH5K_WARN(_sc, _fmt, ...) \ |
96 | ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__) | 99 | ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__) |
97 | 100 | ||
98 | #define ATH5K_ERR(_sc, _fmt, ...) \ | 101 | #define ATH5K_ERR(_sc, _fmt, ...) \ |
99 | ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__) | 102 | ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__) |
100 | 103 | ||
101 | /* | 104 | /* |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index d7114c75fe9b..7106547a14dd 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -20,6 +20,8 @@ | |||
20 | * Attach/Detach Functions and helpers * | 20 | * Attach/Detach Functions and helpers * |
21 | \*************************************/ | 21 | \*************************************/ |
22 | 22 | ||
23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
24 | |||
23 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
24 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
25 | #include "ath5k.h" | 27 | #include "ath5k.h" |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 0e643b016b32..3007bba12d94 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -40,6 +40,8 @@ | |||
40 | * | 40 | * |
41 | */ | 41 | */ |
42 | 42 | ||
43 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
44 | |||
43 | #include <linux/module.h> | 45 | #include <linux/module.h> |
44 | #include <linux/delay.h> | 46 | #include <linux/delay.h> |
45 | #include <linux/dma-mapping.h> | 47 | #include <linux/dma-mapping.h> |
@@ -3038,3 +3040,23 @@ ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable) | |||
3038 | ath5k_hw_set_rx_filter(ah, rfilt); | 3040 | ath5k_hw_set_rx_filter(ah, rfilt); |
3039 | ah->filter_flags = rfilt; | 3041 | ah->filter_flags = rfilt; |
3040 | } | 3042 | } |
3043 | |||
3044 | void _ath5k_printk(const struct ath5k_hw *ah, const char *level, | ||
3045 | const char *fmt, ...) | ||
3046 | { | ||
3047 | struct va_format vaf; | ||
3048 | va_list args; | ||
3049 | |||
3050 | va_start(args, fmt); | ||
3051 | |||
3052 | vaf.fmt = fmt; | ||
3053 | vaf.va = &args; | ||
3054 | |||
3055 | if (ah && ah->hw) | ||
3056 | printk("%s" pr_fmt("%s: %pV"), | ||
3057 | level, wiphy_name(ah->hw->wiphy), &vaf); | ||
3058 | else | ||
3059 | printk("%s" pr_fmt("%pV"), level, &vaf); | ||
3060 | |||
3061 | va_end(args); | ||
3062 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index e5e8f45d86ac..9d00dab666a8 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -57,6 +57,9 @@ | |||
57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 57 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
58 | * THE POSSIBILITY OF SUCH DAMAGES. | 58 | * THE POSSIBILITY OF SUCH DAMAGES. |
59 | */ | 59 | */ |
60 | |||
61 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
62 | |||
60 | #include <linux/export.h> | 63 | #include <linux/export.h> |
61 | #include <linux/moduleparam.h> | 64 | #include <linux/moduleparam.h> |
62 | 65 | ||
@@ -247,10 +250,10 @@ static ssize_t write_file_beacon(struct file *file, | |||
247 | 250 | ||
248 | if (strncmp(buf, "disable", 7) == 0) { | 251 | if (strncmp(buf, "disable", 7) == 0) { |
249 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); | 252 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); |
250 | printk(KERN_INFO "debugfs disable beacons\n"); | 253 | pr_info("debugfs disable beacons\n"); |
251 | } else if (strncmp(buf, "enable", 6) == 0) { | 254 | } else if (strncmp(buf, "enable", 6) == 0) { |
252 | AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); | 255 | AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); |
253 | printk(KERN_INFO "debugfs enable beacons\n"); | 256 | pr_info("debugfs enable beacons\n"); |
254 | } | 257 | } |
255 | return count; | 258 | return count; |
256 | } | 259 | } |
@@ -450,19 +453,19 @@ static ssize_t write_file_antenna(struct file *file, | |||
450 | 453 | ||
451 | if (strncmp(buf, "diversity", 9) == 0) { | 454 | if (strncmp(buf, "diversity", 9) == 0) { |
452 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); | 455 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); |
453 | printk(KERN_INFO "ath5k debug: enable diversity\n"); | 456 | pr_info("debug: enable diversity\n"); |
454 | } else if (strncmp(buf, "fixed-a", 7) == 0) { | 457 | } else if (strncmp(buf, "fixed-a", 7) == 0) { |
455 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A); | 458 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_A); |
456 | printk(KERN_INFO "ath5k debugfs: fixed antenna A\n"); | 459 | pr_info("debug: fixed antenna A\n"); |
457 | } else if (strncmp(buf, "fixed-b", 7) == 0) { | 460 | } else if (strncmp(buf, "fixed-b", 7) == 0) { |
458 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B); | 461 | ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_FIXED_B); |
459 | printk(KERN_INFO "ath5k debug: fixed antenna B\n"); | 462 | pr_info("debug: fixed antenna B\n"); |
460 | } else if (strncmp(buf, "clear", 5) == 0) { | 463 | } else if (strncmp(buf, "clear", 5) == 0) { |
461 | for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) { | 464 | for (i = 0; i < ARRAY_SIZE(ah->stats.antenna_rx); i++) { |
462 | ah->stats.antenna_rx[i] = 0; | 465 | ah->stats.antenna_rx[i] = 0; |
463 | ah->stats.antenna_tx[i] = 0; | 466 | ah->stats.antenna_tx[i] = 0; |
464 | } | 467 | } |
465 | printk(KERN_INFO "ath5k debug: cleared antenna stats\n"); | 468 | pr_info("debug: cleared antenna stats\n"); |
466 | } | 469 | } |
467 | return count; | 470 | return count; |
468 | } | 471 | } |
@@ -632,7 +635,7 @@ static ssize_t write_file_frameerrors(struct file *file, | |||
632 | st->txerr_fifo = 0; | 635 | st->txerr_fifo = 0; |
633 | st->txerr_filt = 0; | 636 | st->txerr_filt = 0; |
634 | st->tx_all_count = 0; | 637 | st->tx_all_count = 0; |
635 | printk(KERN_INFO "ath5k debug: cleared frameerrors stats\n"); | 638 | pr_info("debug: cleared frameerrors stats\n"); |
636 | } | 639 | } |
637 | return count; | 640 | return count; |
638 | } | 641 | } |
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index f8bfa3ac2af0..bd8d4392d68b 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -21,6 +21,8 @@ | |||
21 | Hardware Descriptor Functions | 21 | Hardware Descriptor Functions |
22 | \******************************/ | 22 | \******************************/ |
23 | 23 | ||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
25 | |||
24 | #include "ath5k.h" | 26 | #include "ath5k.h" |
25 | #include "reg.h" | 27 | #include "reg.h" |
26 | #include "debug.h" | 28 | #include "debug.h" |
@@ -441,10 +443,8 @@ ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
441 | struct ath5k_desc *desc, | 443 | struct ath5k_desc *desc, |
442 | struct ath5k_tx_status *ts) | 444 | struct ath5k_tx_status *ts) |
443 | { | 445 | { |
444 | struct ath5k_hw_2w_tx_ctl *tx_ctl; | ||
445 | struct ath5k_hw_tx_status *tx_status; | 446 | struct ath5k_hw_tx_status *tx_status; |
446 | 447 | ||
447 | tx_ctl = &desc->ud.ds_tx5210.tx_ctl; | ||
448 | tx_status = &desc->ud.ds_tx5210.tx_stat; | 448 | tx_status = &desc->ud.ds_tx5210.tx_stat; |
449 | 449 | ||
450 | /* No frame has been send or error */ | 450 | /* No frame has been send or error */ |
@@ -495,11 +495,9 @@ ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
495 | struct ath5k_desc *desc, | 495 | struct ath5k_desc *desc, |
496 | struct ath5k_tx_status *ts) | 496 | struct ath5k_tx_status *ts) |
497 | { | 497 | { |
498 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | ||
499 | struct ath5k_hw_tx_status *tx_status; | 498 | struct ath5k_hw_tx_status *tx_status; |
500 | u32 txstat0, txstat1; | 499 | u32 txstat0, txstat1; |
501 | 500 | ||
502 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | ||
503 | tx_status = &desc->ud.ds_tx5212.tx_stat; | 501 | tx_status = &desc->ud.ds_tx5212.tx_stat; |
504 | 502 | ||
505 | txstat1 = ACCESS_ONCE(tx_status->tx_status_1); | 503 | txstat1 = ACCESS_ONCE(tx_status->tx_status_1); |
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 5cc9aa814697..ce86f158423b 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c | |||
@@ -29,6 +29,8 @@ | |||
29 | * status registers (ISR). | 29 | * status registers (ISR). |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
33 | |||
32 | #include "ath5k.h" | 34 | #include "ath5k.h" |
33 | #include "reg.h" | 35 | #include "reg.h" |
34 | #include "debug.h" | 36 | #include "debug.h" |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index cd708c15b774..4026c906cc7b 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -21,6 +21,8 @@ | |||
21 | * EEPROM access functions and helpers * | 21 | * EEPROM access functions and helpers * |
22 | \*************************************/ | 22 | \*************************************/ |
23 | 23 | ||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
25 | |||
24 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
25 | 27 | ||
26 | #include "ath5k.h" | 28 | #include "ath5k.h" |
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index a1ea78e05b47..ee1c2fa8b591 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c | |||
@@ -19,6 +19,8 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include "ath5k.h" | 24 | #include "ath5k.h" |
23 | #include "reg.h" | 25 | #include "reg.h" |
24 | #include "debug.h" | 26 | #include "debug.h" |
@@ -1574,8 +1576,7 @@ ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) | |||
1574 | 1576 | ||
1575 | /* AR5K_MODE_11B */ | 1577 | /* AR5K_MODE_11B */ |
1576 | if (mode > 2) { | 1578 | if (mode > 2) { |
1577 | ATH5K_ERR(ah, | 1579 | ATH5K_ERR(ah, "unsupported channel mode: %d\n", mode); |
1578 | "unsupported channel mode: %d\n", mode); | ||
1579 | return -EINVAL; | 1580 | return -EINVAL; |
1580 | } | 1581 | } |
1581 | 1582 | ||
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index c1151c723711..b9f708a45f4e 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c | |||
@@ -39,6 +39,8 @@ | |||
39 | * | 39 | * |
40 | */ | 40 | */ |
41 | 41 | ||
42 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
43 | |||
42 | #include <linux/pci.h> | 44 | #include <linux/pci.h> |
43 | #include "ath5k.h" | 45 | #include "ath5k.h" |
44 | 46 | ||
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 5c5329955414..22b80af0f47c 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -41,6 +41,8 @@ | |||
41 | * | 41 | * |
42 | */ | 42 | */ |
43 | 43 | ||
44 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
45 | |||
44 | #include <net/mac80211.h> | 46 | #include <net/mac80211.h> |
45 | #include <asm/unaligned.h> | 47 | #include <asm/unaligned.h> |
46 | 48 | ||
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c index 849fa060ebc4..53424e8e6d82 100644 --- a/drivers/net/wireless/ath/ath5k/pci.c +++ b/drivers/net/wireless/ath/ath5k/pci.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include <linux/nl80211.h> | 19 | #include <linux/nl80211.h> |
18 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
19 | #include <linux/pci-aspm.h> | 21 | #include <linux/pci-aspm.h> |
@@ -347,7 +349,7 @@ init_ath5k_pci(void) | |||
347 | 349 | ||
348 | ret = pci_register_driver(&ath5k_pci_driver); | 350 | ret = pci_register_driver(&ath5k_pci_driver); |
349 | if (ret) { | 351 | if (ret) { |
350 | printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); | 352 | pr_err("pci: can't register pci driver\n"); |
351 | return ret; | 353 | return ret; |
352 | } | 354 | } |
353 | 355 | ||
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 3a2845489a1b..8b71a2d947e0 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -22,6 +22,8 @@ | |||
22 | * PHY related functions * | 22 | * PHY related functions * |
23 | \***********************/ | 23 | \***********************/ |
24 | 24 | ||
25 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
26 | |||
25 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
26 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
27 | #include <asm/unaligned.h> | 29 | #include <asm/unaligned.h> |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 30b50f934172..a6de200538c3 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -20,6 +20,8 @@ | |||
20 | Queue Control Unit, DCF Control Unit Functions | 20 | Queue Control Unit, DCF Control Unit Functions |
21 | \********************************************/ | 21 | \********************************************/ |
22 | 22 | ||
23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
24 | |||
23 | #include "ath5k.h" | 25 | #include "ath5k.h" |
24 | #include "reg.h" | 26 | #include "reg.h" |
25 | #include "debug.h" | 27 | #include "debug.h" |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 200f165c0c6d..0c2dd4771c36 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -23,6 +23,8 @@ | |||
23 | Reset function and helpers | 23 | Reset function and helpers |
24 | \****************************/ | 24 | \****************************/ |
25 | 25 | ||
26 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
27 | |||
26 | #include <asm/unaligned.h> | 28 | #include <asm/unaligned.h> |
27 | 29 | ||
28 | #include <linux/pci.h> /* To determine if a card is pci-e */ | 30 | #include <linux/pci.h> /* To determine if a card is pci-e */ |
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c index 9364da7bd131..04cf0ca72610 100644 --- a/drivers/net/wireless/ath/ath5k/sysfs.c +++ b/drivers/net/wireless/ath/ath5k/sysfs.c | |||
@@ -1,3 +1,5 @@ | |||
1 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
2 | |||
1 | #include <linux/device.h> | 3 | #include <linux/device.h> |
2 | #include <linux/pci.h> | 4 | #include <linux/pci.h> |
3 | 5 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 00d38952b5fb..bdcc68fb1e37 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -15,6 +15,8 @@ | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
19 | |||
18 | #include <linux/moduleparam.h> | 20 | #include <linux/moduleparam.h> |
19 | #include <linux/inetdevice.h> | 21 | #include <linux/inetdevice.h> |
20 | #include <linux/export.h> | 22 | #include <linux/export.h> |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 03cae142f178..eb7cc2f5b96f 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
19 | #include <linux/moduleparam.h> | 21 | #include <linux/moduleparam.h> |
20 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
21 | #include <linux/export.h> | 23 | #include <linux/export.h> |
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 229e1922ebe4..07071fce8a0e 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -15,6 +15,8 @@ | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
19 | |||
18 | #include "core.h" | 20 | #include "core.h" |
19 | #include "hif-ops.h" | 21 | #include "hif-ops.h" |
20 | #include "cfg80211.h" | 22 | #include "cfg80211.h" |
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index f85353fd1792..521f0be990f1 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -15,6 +15,8 @@ | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
19 | |||
18 | #include "core.h" | 20 | #include "core.h" |
19 | #include "debug.h" | 21 | #include "debug.h" |
20 | 22 | ||
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 27d95fe5ade0..3f0b84723789 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -11,7 +11,10 @@ ath9k-$(CONFIG_ATH9K_PCI) += pci.o | |||
11 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o | 11 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o |
12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
13 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o | 13 | ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o |
14 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o | 14 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += \ |
15 | dfs.o \ | ||
16 | dfs_pattern_detector.o \ | ||
17 | dfs_pri_detector.o | ||
15 | 18 | ||
16 | obj-$(CONFIG_ATH9K) += ath9k.o | 19 | obj-$(CONFIG_ATH9K) += ath9k.o |
17 | 20 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 7e0ea4e98334..47a9fb4a116a 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -46,8 +46,8 @@ static const struct ani_ofdm_level_entry ofdm_level_table[] = { | |||
46 | { 5, 4, 1 }, /* lvl 5 */ | 46 | { 5, 4, 1 }, /* lvl 5 */ |
47 | { 6, 5, 1 }, /* lvl 6 */ | 47 | { 6, 5, 1 }, /* lvl 6 */ |
48 | { 7, 6, 1 }, /* lvl 7 */ | 48 | { 7, 6, 1 }, /* lvl 7 */ |
49 | { 7, 7, 1 }, /* lvl 8 */ | 49 | { 7, 6, 0 }, /* lvl 8 */ |
50 | { 7, 8, 0 } /* lvl 9 */ | 50 | { 7, 7, 0 } /* lvl 9 */ |
51 | }; | 51 | }; |
52 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ | 52 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ |
53 | ARRAY_SIZE(ofdm_level_table) | 53 | ARRAY_SIZE(ofdm_level_table) |
@@ -91,8 +91,8 @@ static const struct ani_cck_level_entry cck_level_table[] = { | |||
91 | { 4, 0 }, /* lvl 4 */ | 91 | { 4, 0 }, /* lvl 4 */ |
92 | { 5, 0 }, /* lvl 5 */ | 92 | { 5, 0 }, /* lvl 5 */ |
93 | { 6, 0 }, /* lvl 6 */ | 93 | { 6, 0 }, /* lvl 6 */ |
94 | { 7, 0 }, /* lvl 7 (only for high rssi) */ | 94 | { 6, 0 }, /* lvl 7 (only for high rssi) */ |
95 | { 8, 0 } /* lvl 8 (only for high rssi) */ | 95 | { 7, 0 } /* lvl 8 (only for high rssi) */ |
96 | }; | 96 | }; |
97 | 97 | ||
98 | #define ATH9K_ANI_CCK_NUM_LEVEL \ | 98 | #define ATH9K_ANI_CCK_NUM_LEVEL \ |
@@ -290,16 +290,9 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | |||
290 | ATH9K_ANI_FIRSTEP_LEVEL, | 290 | ATH9K_ANI_FIRSTEP_LEVEL, |
291 | entry_ofdm->fir_step_level); | 291 | entry_ofdm->fir_step_level); |
292 | 292 | ||
293 | if ((ah->opmode != NL80211_IFTYPE_STATION && | 293 | if ((aniState->noiseFloor >= aniState->rssiThrHigh) && |
294 | ah->opmode != NL80211_IFTYPE_ADHOC) || | 294 | (!aniState->ofdmWeakSigDetectOff != |
295 | aniState->noiseFloor <= aniState->rssiThrHigh) { | 295 | entry_ofdm->ofdm_weak_signal_on)) { |
296 | if (aniState->ofdmWeakSigDetectOff) | ||
297 | /* force on ofdm weak sig detect */ | ||
298 | ath9k_hw_ani_control(ah, | ||
299 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | ||
300 | true); | ||
301 | else if (aniState->ofdmWeakSigDetectOff == | ||
302 | entry_ofdm->ofdm_weak_signal_on) | ||
303 | ath9k_hw_ani_control(ah, | 296 | ath9k_hw_ani_control(ah, |
304 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, | 297 | ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, |
305 | entry_ofdm->ofdm_weak_signal_on); | 298 | entry_ofdm->ofdm_weak_signal_on); |
@@ -717,26 +710,30 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) | |||
717 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, | 710 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, |
718 | cckPhyErrRate, aniState->ofdmsTurn); | 711 | cckPhyErrRate, aniState->ofdmsTurn); |
719 | 712 | ||
720 | if (aniState->listenTime > 5 * ah->aniperiod) { | 713 | if (aniState->listenTime > ah->aniperiod) { |
721 | if (ofdmPhyErrRate <= ah->config.ofdm_trig_low && | 714 | if (cckPhyErrRate < ah->config.cck_trig_low && |
722 | cckPhyErrRate <= ah->config.cck_trig_low) { | 715 | ((ofdmPhyErrRate < ah->config.ofdm_trig_low && |
716 | aniState->ofdmNoiseImmunityLevel < | ||
717 | ATH9K_ANI_OFDM_DEF_LEVEL) || | ||
718 | (ofdmPhyErrRate < ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI && | ||
719 | aniState->ofdmNoiseImmunityLevel >= | ||
720 | ATH9K_ANI_OFDM_DEF_LEVEL))) { | ||
723 | ath9k_hw_ani_lower_immunity(ah); | 721 | ath9k_hw_ani_lower_immunity(ah); |
724 | aniState->ofdmsTurn = !aniState->ofdmsTurn; | 722 | aniState->ofdmsTurn = !aniState->ofdmsTurn; |
725 | } | 723 | } else if ((ofdmPhyErrRate > ah->config.ofdm_trig_high && |
726 | ath9k_ani_restart(ah); | 724 | aniState->ofdmNoiseImmunityLevel >= |
727 | } else if (aniState->listenTime > ah->aniperiod) { | 725 | ATH9K_ANI_OFDM_DEF_LEVEL) || |
728 | /* check to see if need to raise immunity */ | 726 | (ofdmPhyErrRate > |
729 | if (ofdmPhyErrRate > ah->config.ofdm_trig_high && | 727 | ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI && |
730 | (cckPhyErrRate <= ah->config.cck_trig_high || | 728 | aniState->ofdmNoiseImmunityLevel < |
731 | aniState->ofdmsTurn)) { | 729 | ATH9K_ANI_OFDM_DEF_LEVEL)) { |
732 | ath9k_hw_ani_ofdm_err_trigger(ah); | 730 | ath9k_hw_ani_ofdm_err_trigger(ah); |
733 | ath9k_ani_restart(ah); | ||
734 | aniState->ofdmsTurn = false; | 731 | aniState->ofdmsTurn = false; |
735 | } else if (cckPhyErrRate > ah->config.cck_trig_high) { | 732 | } else if (cckPhyErrRate > ah->config.cck_trig_high) { |
736 | ath9k_hw_ani_cck_err_trigger(ah); | 733 | ath9k_hw_ani_cck_err_trigger(ah); |
737 | ath9k_ani_restart(ah); | ||
738 | aniState->ofdmsTurn = true; | 734 | aniState->ofdmsTurn = true; |
739 | } | 735 | } |
736 | ath9k_ani_restart(ah); | ||
740 | } | 737 | } |
741 | } | 738 | } |
742 | EXPORT_SYMBOL(ath9k_hw_ani_monitor); | 739 | EXPORT_SYMBOL(ath9k_hw_ani_monitor); |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 83029d6c7b22..72e2b874e179 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -25,11 +25,13 @@ | |||
25 | 25 | ||
26 | /* units are errors per second */ | 26 | /* units are errors per second */ |
27 | #define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500 | 27 | #define ATH9K_ANI_OFDM_TRIG_HIGH_OLD 500 |
28 | #define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 1000 | 28 | #define ATH9K_ANI_OFDM_TRIG_HIGH_NEW 3500 |
29 | #define ATH9K_ANI_OFDM_TRIG_HIGH_BELOW_INI 1000 | ||
29 | 30 | ||
30 | /* units are errors per second */ | 31 | /* units are errors per second */ |
31 | #define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200 | 32 | #define ATH9K_ANI_OFDM_TRIG_LOW_OLD 200 |
32 | #define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400 | 33 | #define ATH9K_ANI_OFDM_TRIG_LOW_NEW 400 |
34 | #define ATH9K_ANI_OFDM_TRIG_LOW_ABOVE_INI 900 | ||
33 | 35 | ||
34 | /* units are errors per second */ | 36 | /* units are errors per second */ |
35 | #define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200 | 37 | #define ATH9K_ANI_CCK_TRIG_HIGH_OLD 200 |
@@ -53,7 +55,7 @@ | |||
53 | #define ATH9K_ANI_RSSI_THR_LOW 7 | 55 | #define ATH9K_ANI_RSSI_THR_LOW 7 |
54 | 56 | ||
55 | #define ATH9K_ANI_PERIOD_OLD 100 | 57 | #define ATH9K_ANI_PERIOD_OLD 100 |
56 | #define ATH9K_ANI_PERIOD_NEW 1000 | 58 | #define ATH9K_ANI_PERIOD_NEW 300 |
57 | 59 | ||
58 | /* in ms */ | 60 | /* in ms */ |
59 | #define ATH9K_ANI_POLLINTERVAL_OLD 100 | 61 | #define ATH9K_ANI_POLLINTERVAL_OLD 100 |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index d7d8e9199140..52ff5caf2d0b 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -1047,46 +1047,8 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1047 | break; | 1047 | break; |
1048 | } | 1048 | } |
1049 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | 1049 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ |
1050 | static const int m1ThreshLow[] = { 127, 50 }; | ||
1051 | static const int m2ThreshLow[] = { 127, 40 }; | ||
1052 | static const int m1Thresh[] = { 127, 0x4d }; | ||
1053 | static const int m2Thresh[] = { 127, 0x40 }; | ||
1054 | static const int m2CountThr[] = { 31, 16 }; | ||
1055 | static const int m2CountThrLow[] = { 63, 48 }; | ||
1056 | u32 on = param ? 1 : 0; | 1050 | u32 on = param ? 1 : 0; |
1057 | 1051 | ||
1058 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
1059 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, | ||
1060 | m1ThreshLow[on]); | ||
1061 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
1062 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, | ||
1063 | m2ThreshLow[on]); | ||
1064 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
1065 | AR_PHY_SFCORR_M1_THRESH, | ||
1066 | m1Thresh[on]); | ||
1067 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
1068 | AR_PHY_SFCORR_M2_THRESH, | ||
1069 | m2Thresh[on]); | ||
1070 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
1071 | AR_PHY_SFCORR_M2COUNT_THR, | ||
1072 | m2CountThr[on]); | ||
1073 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
1074 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, | ||
1075 | m2CountThrLow[on]); | ||
1076 | |||
1077 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1078 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, | ||
1079 | m1ThreshLow[on]); | ||
1080 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1081 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, | ||
1082 | m2ThreshLow[on]); | ||
1083 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1084 | AR_PHY_SFCORR_EXT_M1_THRESH, | ||
1085 | m1Thresh[on]); | ||
1086 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
1087 | AR_PHY_SFCORR_EXT_M2_THRESH, | ||
1088 | m2Thresh[on]); | ||
1089 | |||
1090 | if (on) | 1052 | if (on) |
1091 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, | 1053 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, |
1092 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | 1054 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 46c79a3d4737..952cb2b4656b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | |||
@@ -777,11 +777,11 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = { | |||
777 | {0x0000a074, 0x00000000}, | 777 | {0x0000a074, 0x00000000}, |
778 | {0x0000a078, 0x00000000}, | 778 | {0x0000a078, 0x00000000}, |
779 | {0x0000a07c, 0x00000000}, | 779 | {0x0000a07c, 0x00000000}, |
780 | {0x0000a080, 0x22222229}, | 780 | {0x0000a080, 0x1a1a1a1a}, |
781 | {0x0000a084, 0x1d1d1d1d}, | 781 | {0x0000a084, 0x1a1a1a1a}, |
782 | {0x0000a088, 0x1d1d1d1d}, | 782 | {0x0000a088, 0x1a1a1a1a}, |
783 | {0x0000a08c, 0x1d1d1d1d}, | 783 | {0x0000a08c, 0x1a1a1a1a}, |
784 | {0x0000a090, 0x171d1d1d}, | 784 | {0x0000a090, 0x171a1a1a}, |
785 | {0x0000a094, 0x11111717}, | 785 | {0x0000a094, 0x11111717}, |
786 | {0x0000a098, 0x00030311}, | 786 | {0x0000a098, 0x00030311}, |
787 | {0x0000a09c, 0x00000000}, | 787 | {0x0000a09c, 0x00000000}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index bc992b237ae5..79070bf04eab 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -823,55 +823,6 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
823 | * on == 0 means more noise imm | 823 | * on == 0 means more noise imm |
824 | */ | 824 | */ |
825 | u32 on = param ? 1 : 0; | 825 | u32 on = param ? 1 : 0; |
826 | /* | ||
827 | * make register setting for default | ||
828 | * (weak sig detect ON) come from INI file | ||
829 | */ | ||
830 | int m1ThreshLow = on ? | ||
831 | aniState->iniDef.m1ThreshLow : m1ThreshLow_off; | ||
832 | int m2ThreshLow = on ? | ||
833 | aniState->iniDef.m2ThreshLow : m2ThreshLow_off; | ||
834 | int m1Thresh = on ? | ||
835 | aniState->iniDef.m1Thresh : m1Thresh_off; | ||
836 | int m2Thresh = on ? | ||
837 | aniState->iniDef.m2Thresh : m2Thresh_off; | ||
838 | int m2CountThr = on ? | ||
839 | aniState->iniDef.m2CountThr : m2CountThr_off; | ||
840 | int m2CountThrLow = on ? | ||
841 | aniState->iniDef.m2CountThrLow : m2CountThrLow_off; | ||
842 | int m1ThreshLowExt = on ? | ||
843 | aniState->iniDef.m1ThreshLowExt : m1ThreshLowExt_off; | ||
844 | int m2ThreshLowExt = on ? | ||
845 | aniState->iniDef.m2ThreshLowExt : m2ThreshLowExt_off; | ||
846 | int m1ThreshExt = on ? | ||
847 | aniState->iniDef.m1ThreshExt : m1ThreshExt_off; | ||
848 | int m2ThreshExt = on ? | ||
849 | aniState->iniDef.m2ThreshExt : m2ThreshExt_off; | ||
850 | |||
851 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
852 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, | ||
853 | m1ThreshLow); | ||
854 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
855 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, | ||
856 | m2ThreshLow); | ||
857 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
858 | AR_PHY_SFCORR_M1_THRESH, m1Thresh); | ||
859 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
860 | AR_PHY_SFCORR_M2_THRESH, m2Thresh); | ||
861 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
862 | AR_PHY_SFCORR_M2COUNT_THR, m2CountThr); | ||
863 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
864 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, | ||
865 | m2CountThrLow); | ||
866 | |||
867 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
868 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLowExt); | ||
869 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
870 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLowExt); | ||
871 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
872 | AR_PHY_SFCORR_EXT_M1_THRESH, m1ThreshExt); | ||
873 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
874 | AR_PHY_SFCORR_EXT_M2_THRESH, m2ThreshExt); | ||
875 | 826 | ||
876 | if (on) | 827 | if (on) |
877 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, | 828 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 8c84049682ab..0a37631390db 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include "debug.h" | 26 | #include "debug.h" |
27 | #include "common.h" | 27 | #include "common.h" |
28 | #include "mci.h" | 28 | #include "mci.h" |
29 | #include "dfs.h" | ||
29 | 30 | ||
30 | /* | 31 | /* |
31 | * Header for the ath9k.ko driver core *only* -- hw code nor any other driver | 32 | * Header for the ath9k.ko driver core *only* -- hw code nor any other driver |
@@ -430,6 +431,8 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); | |||
430 | void ath_reset_work(struct work_struct *work); | 431 | void ath_reset_work(struct work_struct *work); |
431 | void ath_hw_check(struct work_struct *work); | 432 | void ath_hw_check(struct work_struct *work); |
432 | void ath_hw_pll_work(struct work_struct *work); | 433 | void ath_hw_pll_work(struct work_struct *work); |
434 | void ath_rx_poll(unsigned long data); | ||
435 | void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon); | ||
433 | void ath_paprd_calibrate(struct work_struct *work); | 436 | void ath_paprd_calibrate(struct work_struct *work); |
434 | void ath_ani_calibrate(unsigned long data); | 437 | void ath_ani_calibrate(unsigned long data); |
435 | void ath_start_ani(struct ath_common *common); | 438 | void ath_start_ani(struct ath_common *common); |
@@ -670,6 +673,7 @@ struct ath_softc { | |||
670 | struct ath_beacon_config cur_beacon_conf; | 673 | struct ath_beacon_config cur_beacon_conf; |
671 | struct delayed_work tx_complete_work; | 674 | struct delayed_work tx_complete_work; |
672 | struct delayed_work hw_pll_work; | 675 | struct delayed_work hw_pll_work; |
676 | struct timer_list rx_poll_timer; | ||
673 | 677 | ||
674 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 678 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
675 | struct ath_btcoex btcoex; | 679 | struct ath_btcoex btcoex; |
@@ -680,6 +684,7 @@ struct ath_softc { | |||
680 | 684 | ||
681 | struct ath_ant_comb ant_comb; | 685 | struct ath_ant_comb ant_comb; |
682 | u8 ant_tx, ant_rx; | 686 | u8 ant_tx, ant_rx; |
687 | struct dfs_pattern_detector *dfs_detector; | ||
683 | }; | 688 | }; |
684 | 689 | ||
685 | void ath9k_tasklet(unsigned long data); | 690 | void ath9k_tasklet(unsigned long data); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index ff47b32ecaf4..04edce941cb7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -524,6 +524,7 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
524 | PR("hw-put-tx-buf: ", puttxbuf); | 524 | PR("hw-put-tx-buf: ", puttxbuf); |
525 | PR("hw-tx-start: ", txstart); | 525 | PR("hw-tx-start: ", txstart); |
526 | PR("hw-tx-proc-desc: ", txprocdesc); | 526 | PR("hw-tx-proc-desc: ", txprocdesc); |
527 | PR("TX-Failed: ", txfailed); | ||
527 | len += snprintf(buf + len, size - len, | 528 | len += snprintf(buf + len, size - len, |
528 | "%s%11p%11p%10p%10p\n", "txq-memory-address:", | 529 | "%s%11p%11p%10p%10p\n", "txq-memory-address:", |
529 | sc->tx.txq_map[WME_AC_BE], | 530 | sc->tx.txq_map[WME_AC_BE], |
@@ -910,6 +911,21 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
910 | len += snprintf(buf + len, size - len, | 911 | len += snprintf(buf + len, size - len, |
911 | "%22s : %10u\n", "DECRYPT BUSY ERR", | 912 | "%22s : %10u\n", "DECRYPT BUSY ERR", |
912 | sc->debug.stats.rxstats.decrypt_busy_err); | 913 | sc->debug.stats.rxstats.decrypt_busy_err); |
914 | len += snprintf(buf + len, size - len, | ||
915 | "%22s : %10u\n", "RX-LENGTH-ERR", | ||
916 | sc->debug.stats.rxstats.rx_len_err); | ||
917 | len += snprintf(buf + len, size - len, | ||
918 | "%22s : %10u\n", "RX-OOM-ERR", | ||
919 | sc->debug.stats.rxstats.rx_oom_err); | ||
920 | len += snprintf(buf + len, size - len, | ||
921 | "%22s : %10u\n", "RX-RATE-ERR", | ||
922 | sc->debug.stats.rxstats.rx_rate_err); | ||
923 | len += snprintf(buf + len, size - len, | ||
924 | "%22s : %10u\n", "RX-DROP-RXFLUSH", | ||
925 | sc->debug.stats.rxstats.rx_drop_rxflush); | ||
926 | len += snprintf(buf + len, size - len, | ||
927 | "%22s : %10u\n", "RX-TOO-MANY-FRAGS", | ||
928 | sc->debug.stats.rxstats.rx_too_many_frags_err); | ||
913 | 929 | ||
914 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); | 930 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); |
915 | PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING); | 931 | PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING); |
@@ -944,6 +960,12 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
944 | len += snprintf(buf + len, size - len, | 960 | len += snprintf(buf + len, size - len, |
945 | "%22s : %10u\n", "RX-Bytes-All", | 961 | "%22s : %10u\n", "RX-Bytes-All", |
946 | sc->debug.stats.rxstats.rx_bytes_all); | 962 | sc->debug.stats.rxstats.rx_bytes_all); |
963 | len += snprintf(buf + len, size - len, | ||
964 | "%22s : %10u\n", "RX-Beacons", | ||
965 | sc->debug.stats.rxstats.rx_beacons); | ||
966 | len += snprintf(buf + len, size - len, | ||
967 | "%22s : %10u\n", "RX-Frags", | ||
968 | sc->debug.stats.rxstats.rx_frags); | ||
947 | 969 | ||
948 | if (len > size) | 970 | if (len > size) |
949 | len = size; | 971 | len = size; |
@@ -958,7 +980,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
958 | 980 | ||
959 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | 981 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) |
960 | { | 982 | { |
961 | #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ | ||
962 | #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ | 983 | #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ |
963 | #define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\ | 984 | #define RX_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].rs\ |
964 | [sc->debug.rsidx].c) | 985 | [sc->debug.rsidx].c) |
@@ -1004,7 +1025,6 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | |||
1004 | 1025 | ||
1005 | #endif | 1026 | #endif |
1006 | 1027 | ||
1007 | #undef RX_STAT_INC | ||
1008 | #undef RX_PHY_ERR_INC | 1028 | #undef RX_PHY_ERR_INC |
1009 | #undef RX_SAMP_DBG | 1029 | #undef RX_SAMP_DBG |
1010 | } | 1030 | } |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 64fcfad467bf..17f6cc27af32 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -113,6 +113,7 @@ struct ath_interrupt_stats { | |||
113 | * @puttxbuf: Number of times hardware was given txbuf to write. | 113 | * @puttxbuf: Number of times hardware was given txbuf to write. |
114 | * @txstart: Number of times hardware was told to start tx. | 114 | * @txstart: Number of times hardware was told to start tx. |
115 | * @txprocdesc: Number of times tx descriptor was processed | 115 | * @txprocdesc: Number of times tx descriptor was processed |
116 | * @txfailed: Out-of-memory or other errors in xmit path. | ||
116 | */ | 117 | */ |
117 | struct ath_tx_stats { | 118 | struct ath_tx_stats { |
118 | u32 tx_pkts_all; | 119 | u32 tx_pkts_all; |
@@ -135,8 +136,11 @@ struct ath_tx_stats { | |||
135 | u32 puttxbuf; | 136 | u32 puttxbuf; |
136 | u32 txstart; | 137 | u32 txstart; |
137 | u32 txprocdesc; | 138 | u32 txprocdesc; |
139 | u32 txfailed; | ||
138 | }; | 140 | }; |
139 | 141 | ||
142 | #define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++) | ||
143 | |||
140 | /** | 144 | /** |
141 | * struct ath_rx_stats - RX Statistics | 145 | * struct ath_rx_stats - RX Statistics |
142 | * @rx_pkts_all: No. of total frames received, including ones that | 146 | * @rx_pkts_all: No. of total frames received, including ones that |
@@ -153,6 +157,13 @@ struct ath_tx_stats { | |||
153 | * @post_delim_crc_err: Post-Frame delimiter CRC error detections | 157 | * @post_delim_crc_err: Post-Frame delimiter CRC error detections |
154 | * @decrypt_busy_err: Decryption interruptions counter | 158 | * @decrypt_busy_err: Decryption interruptions counter |
155 | * @phy_err_stats: Individual PHY error statistics | 159 | * @phy_err_stats: Individual PHY error statistics |
160 | * @rx_len_err: No. of frames discarded due to bad length. | ||
161 | * @rx_oom_err: No. of frames dropped due to OOM issues. | ||
162 | * @rx_rate_err: No. of frames dropped due to rate errors. | ||
163 | * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. | ||
164 | * @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH. | ||
165 | * @rx_beacons: No. of beacons received. | ||
166 | * @rx_frags: No. of rx-fragements received. | ||
156 | */ | 167 | */ |
157 | struct ath_rx_stats { | 168 | struct ath_rx_stats { |
158 | u32 rx_pkts_all; | 169 | u32 rx_pkts_all; |
@@ -165,6 +176,13 @@ struct ath_rx_stats { | |||
165 | u32 post_delim_crc_err; | 176 | u32 post_delim_crc_err; |
166 | u32 decrypt_busy_err; | 177 | u32 decrypt_busy_err; |
167 | u32 phy_err_stats[ATH9K_PHYERR_MAX]; | 178 | u32 phy_err_stats[ATH9K_PHYERR_MAX]; |
179 | u32 rx_len_err; | ||
180 | u32 rx_oom_err; | ||
181 | u32 rx_rate_err; | ||
182 | u32 rx_too_many_frags_err; | ||
183 | u32 rx_drop_rxflush; | ||
184 | u32 rx_beacons; | ||
185 | u32 rx_frags; | ||
168 | }; | 186 | }; |
169 | 187 | ||
170 | enum ath_reset_type { | 188 | enum ath_reset_type { |
@@ -174,6 +192,7 @@ enum ath_reset_type { | |||
174 | RESET_TYPE_TX_ERROR, | 192 | RESET_TYPE_TX_ERROR, |
175 | RESET_TYPE_TX_HANG, | 193 | RESET_TYPE_TX_HANG, |
176 | RESET_TYPE_PLL_HANG, | 194 | RESET_TYPE_PLL_HANG, |
195 | RESET_TYPE_MAC_HANG, | ||
177 | __RESET_TYPE_MAX | 196 | __RESET_TYPE_MAX |
178 | }; | 197 | }; |
179 | 198 | ||
@@ -247,6 +266,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); | |||
247 | 266 | ||
248 | #else | 267 | #else |
249 | 268 | ||
269 | #define RX_STAT_INC(c) /* NOP */ | ||
270 | |||
250 | static inline int ath9k_init_debug(struct ath_hw *ah) | 271 | static inline int ath9k_init_debug(struct ath_hw *ah) |
251 | { | 272 | { |
252 | return 0; | 273 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c index f4f56aff1e9d..92891f5fd454 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.c +++ b/drivers/net/wireless/ath/ath9k/dfs.c | |||
@@ -21,17 +21,6 @@ | |||
21 | #include "dfs.h" | 21 | #include "dfs.h" |
22 | #include "dfs_debug.h" | 22 | #include "dfs_debug.h" |
23 | 23 | ||
24 | /* | ||
25 | * TODO: move into or synchronize this with generic header | ||
26 | * as soon as IF is defined | ||
27 | */ | ||
28 | struct dfs_radar_pulse { | ||
29 | u16 freq; | ||
30 | u64 ts; | ||
31 | u32 width; | ||
32 | u8 rssi; | ||
33 | }; | ||
34 | |||
35 | /* internal struct to pass radar data */ | 24 | /* internal struct to pass radar data */ |
36 | struct ath_radar_data { | 25 | struct ath_radar_data { |
37 | u8 pulse_bw_info; | 26 | u8 pulse_bw_info; |
@@ -60,44 +49,44 @@ static u32 dur_to_usecs(struct ath_hw *ah, u32 dur) | |||
60 | #define EXT_CH_RADAR_FOUND 0x02 | 49 | #define EXT_CH_RADAR_FOUND 0x02 |
61 | static bool | 50 | static bool |
62 | ath9k_postprocess_radar_event(struct ath_softc *sc, | 51 | ath9k_postprocess_radar_event(struct ath_softc *sc, |
63 | struct ath_radar_data *are, | 52 | struct ath_radar_data *ard, |
64 | struct dfs_radar_pulse *drp) | 53 | struct pulse_event *pe) |
65 | { | 54 | { |
66 | u8 rssi; | 55 | u8 rssi; |
67 | u16 dur; | 56 | u16 dur; |
68 | 57 | ||
69 | ath_dbg(ath9k_hw_common(sc->sc_ah), DFS, | 58 | ath_dbg(ath9k_hw_common(sc->sc_ah), DFS, |
70 | "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n", | 59 | "pulse_bw_info=0x%x, pri,ext len/rssi=(%u/%u, %u/%u)\n", |
71 | are->pulse_bw_info, | 60 | ard->pulse_bw_info, |
72 | are->pulse_length_pri, are->rssi, | 61 | ard->pulse_length_pri, ard->rssi, |
73 | are->pulse_length_ext, are->ext_rssi); | 62 | ard->pulse_length_ext, ard->ext_rssi); |
74 | 63 | ||
75 | /* | 64 | /* |
76 | * Only the last 2 bits of the BW info are relevant, they indicate | 65 | * Only the last 2 bits of the BW info are relevant, they indicate |
77 | * which channel the radar was detected in. | 66 | * which channel the radar was detected in. |
78 | */ | 67 | */ |
79 | are->pulse_bw_info &= 0x03; | 68 | ard->pulse_bw_info &= 0x03; |
80 | 69 | ||
81 | switch (are->pulse_bw_info) { | 70 | switch (ard->pulse_bw_info) { |
82 | case PRI_CH_RADAR_FOUND: | 71 | case PRI_CH_RADAR_FOUND: |
83 | /* radar in ctrl channel */ | 72 | /* radar in ctrl channel */ |
84 | dur = are->pulse_length_pri; | 73 | dur = ard->pulse_length_pri; |
85 | DFS_STAT_INC(sc, pri_phy_errors); | 74 | DFS_STAT_INC(sc, pri_phy_errors); |
86 | /* | 75 | /* |
87 | * cannot use ctrl channel RSSI | 76 | * cannot use ctrl channel RSSI |
88 | * if extension channel is stronger | 77 | * if extension channel is stronger |
89 | */ | 78 | */ |
90 | rssi = (are->ext_rssi >= (are->rssi + 3)) ? 0 : are->rssi; | 79 | rssi = (ard->ext_rssi >= (ard->rssi + 3)) ? 0 : ard->rssi; |
91 | break; | 80 | break; |
92 | case EXT_CH_RADAR_FOUND: | 81 | case EXT_CH_RADAR_FOUND: |
93 | /* radar in extension channel */ | 82 | /* radar in extension channel */ |
94 | dur = are->pulse_length_ext; | 83 | dur = ard->pulse_length_ext; |
95 | DFS_STAT_INC(sc, ext_phy_errors); | 84 | DFS_STAT_INC(sc, ext_phy_errors); |
96 | /* | 85 | /* |
97 | * cannot use extension channel RSSI | 86 | * cannot use extension channel RSSI |
98 | * if control channel is stronger | 87 | * if control channel is stronger |
99 | */ | 88 | */ |
100 | rssi = (are->rssi >= (are->ext_rssi + 12)) ? 0 : are->ext_rssi; | 89 | rssi = (ard->rssi >= (ard->ext_rssi + 12)) ? 0 : ard->ext_rssi; |
101 | break; | 90 | break; |
102 | case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND): | 91 | case (PRI_CH_RADAR_FOUND | EXT_CH_RADAR_FOUND): |
103 | /* | 92 | /* |
@@ -107,14 +96,14 @@ ath9k_postprocess_radar_event(struct ath_softc *sc, | |||
107 | * Radiated testing, when pulse is on DC, different pri and | 96 | * Radiated testing, when pulse is on DC, different pri and |
108 | * ext durations are reported, so take the larger of the two | 97 | * ext durations are reported, so take the larger of the two |
109 | */ | 98 | */ |
110 | if (are->pulse_length_ext >= are->pulse_length_pri) | 99 | if (ard->pulse_length_ext >= ard->pulse_length_pri) |
111 | dur = are->pulse_length_ext; | 100 | dur = ard->pulse_length_ext; |
112 | else | 101 | else |
113 | dur = are->pulse_length_pri; | 102 | dur = ard->pulse_length_pri; |
114 | DFS_STAT_INC(sc, dc_phy_errors); | 103 | DFS_STAT_INC(sc, dc_phy_errors); |
115 | 104 | ||
116 | /* when both are present use stronger one */ | 105 | /* when both are present use stronger one */ |
117 | rssi = (are->rssi < are->ext_rssi) ? are->ext_rssi : are->rssi; | 106 | rssi = (ard->rssi < ard->ext_rssi) ? ard->ext_rssi : ard->rssi; |
118 | break; | 107 | break; |
119 | default: | 108 | default: |
120 | /* | 109 | /* |
@@ -137,8 +126,8 @@ ath9k_postprocess_radar_event(struct ath_softc *sc, | |||
137 | */ | 126 | */ |
138 | 127 | ||
139 | /* convert duration to usecs */ | 128 | /* convert duration to usecs */ |
140 | drp->width = dur_to_usecs(sc->sc_ah, dur); | 129 | pe->width = dur_to_usecs(sc->sc_ah, dur); |
141 | drp->rssi = rssi; | 130 | pe->rssi = rssi; |
142 | 131 | ||
143 | DFS_STAT_INC(sc, pulses_detected); | 132 | DFS_STAT_INC(sc, pulses_detected); |
144 | return true; | 133 | return true; |
@@ -155,12 +144,12 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | |||
155 | struct ath_radar_data ard; | 144 | struct ath_radar_data ard; |
156 | u16 datalen; | 145 | u16 datalen; |
157 | char *vdata_end; | 146 | char *vdata_end; |
158 | struct dfs_radar_pulse drp; | 147 | struct pulse_event pe; |
159 | struct ath_hw *ah = sc->sc_ah; | 148 | struct ath_hw *ah = sc->sc_ah; |
160 | struct ath_common *common = ath9k_hw_common(ah); | 149 | struct ath_common *common = ath9k_hw_common(ah); |
161 | 150 | ||
162 | if ((!(rs->rs_phyerr != ATH9K_PHYERR_RADAR)) && | 151 | if ((rs->rs_phyerr != ATH9K_PHYERR_RADAR) && |
163 | (!(rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT))) { | 152 | (rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT)) { |
164 | ath_dbg(common, DFS, | 153 | ath_dbg(common, DFS, |
165 | "Error: rs_phyer=0x%x not a radar error\n", | 154 | "Error: rs_phyer=0x%x not a radar error\n", |
166 | rs->rs_phyerr); | 155 | rs->rs_phyerr); |
@@ -189,27 +178,20 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | |||
189 | ard.pulse_bw_info = vdata_end[-1]; | 178 | ard.pulse_bw_info = vdata_end[-1]; |
190 | ard.pulse_length_ext = vdata_end[-2]; | 179 | ard.pulse_length_ext = vdata_end[-2]; |
191 | ard.pulse_length_pri = vdata_end[-3]; | 180 | ard.pulse_length_pri = vdata_end[-3]; |
192 | 181 | pe.freq = ah->curchan->channel; | |
193 | ath_dbg(common, DFS, | 182 | pe.ts = mactime; |
194 | "bw_info=%d, length_pri=%d, length_ext=%d, " | 183 | if (ath9k_postprocess_radar_event(sc, &ard, &pe)) { |
195 | "rssi_pri=%d, rssi_ext=%d\n", | 184 | struct dfs_pattern_detector *pd = sc->dfs_detector; |
196 | ard.pulse_bw_info, ard.pulse_length_pri, ard.pulse_length_ext, | ||
197 | ard.rssi, ard.ext_rssi); | ||
198 | |||
199 | drp.freq = ah->curchan->channel; | ||
200 | drp.ts = mactime; | ||
201 | if (ath9k_postprocess_radar_event(sc, &ard, &drp)) { | ||
202 | static u64 last_ts; | 185 | static u64 last_ts; |
203 | ath_dbg(common, DFS, | 186 | ath_dbg(common, DFS, |
204 | "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " | 187 | "ath9k_dfs_process_phyerr: channel=%d, ts=%llu, " |
205 | "width=%d, rssi=%d, delta_ts=%llu\n", | 188 | "width=%d, rssi=%d, delta_ts=%llu\n", |
206 | drp.freq, drp.ts, drp.width, drp.rssi, drp.ts-last_ts); | 189 | pe.freq, pe.ts, pe.width, pe.rssi, pe.ts-last_ts); |
207 | last_ts = drp.ts; | 190 | last_ts = pe.ts; |
208 | /* | 191 | if (pd != NULL && pd->add_pulse(pd, &pe)) { |
209 | * TODO: forward pulse to pattern detector | 192 | /* |
210 | * | 193 | * TODO: forward radar event to DFS management layer |
211 | * ieee80211_add_radar_pulse(drp.freq, drp.ts, | 194 | */ |
212 | * drp.width, drp.rssi); | 195 | } |
213 | */ | ||
214 | } | 196 | } |
215 | } | 197 | } |
diff --git a/drivers/net/wireless/ath/ath9k/dfs.h b/drivers/net/wireless/ath/ath9k/dfs.h index c2412857f122..3c839f06a06a 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.h +++ b/drivers/net/wireless/ath/ath9k/dfs.h | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #ifndef ATH9K_DFS_H | 18 | #ifndef ATH9K_DFS_H |
19 | #define ATH9K_DFS_H | 19 | #define ATH9K_DFS_H |
20 | #include "dfs_pattern_detector.h" | ||
20 | 21 | ||
21 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) | 22 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) |
22 | /** | 23 | /** |
@@ -31,13 +32,14 @@ | |||
31 | * | 32 | * |
32 | * The radar information provided as raw payload data is validated and | 33 | * The radar information provided as raw payload data is validated and |
33 | * filtered for false pulses. Events passing all tests are forwarded to | 34 | * filtered for false pulses. Events passing all tests are forwarded to |
34 | * the upper layer for pattern detection. | 35 | * the DFS detector for pattern detection. |
35 | */ | 36 | */ |
36 | void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | 37 | void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, |
37 | struct ath_rx_status *rs, u64 mactime); | 38 | struct ath_rx_status *rs, u64 mactime); |
38 | #else | 39 | #else |
39 | static inline void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, | 40 | static inline void |
40 | struct ath_rx_status *rs, u64 mactime) { } | 41 | ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data, |
42 | struct ath_rx_status *rs, u64 mactime) { } | ||
41 | #endif | 43 | #endif |
42 | 44 | ||
43 | #endif /* ATH9K_DFS_H */ | 45 | #endif /* ATH9K_DFS_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c new file mode 100644 index 000000000000..ea2a6cf7ef23 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Neratec Solutions AG | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | #include <linux/export.h> | ||
19 | |||
20 | #include "dfs_pattern_detector.h" | ||
21 | #include "dfs_pri_detector.h" | ||
22 | |||
23 | /* | ||
24 | * tolerated deviation of radar time stamp in usecs on both sides | ||
25 | * TODO: this might need to be HW-dependent | ||
26 | */ | ||
27 | #define PRI_TOLERANCE 16 | ||
28 | |||
29 | /** | ||
30 | * struct radar_types - contains array of patterns defined for one DFS domain | ||
31 | * @domain: DFS regulatory domain | ||
32 | * @num_radar_types: number of radar types to follow | ||
33 | * @radar_types: radar types array | ||
34 | */ | ||
35 | struct radar_types { | ||
36 | enum nl80211_dfs_regions region; | ||
37 | u32 num_radar_types; | ||
38 | const struct radar_detector_specs *radar_types; | ||
39 | }; | ||
40 | |||
41 | /* percentage on ppb threshold to trigger detection */ | ||
42 | #define MIN_PPB_THRESH 50 | ||
43 | #define PPB_THRESH(PPB) ((PPB * MIN_PPB_THRESH + 50) / 100) | ||
44 | #define PRF2PRI(PRF) ((1000000 + PRF / 2) / PRF) | ||
45 | |||
46 | #define ETSI_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB) \ | ||
47 | { \ | ||
48 | ID, WMIN, WMAX, (PRF2PRI(PMAX) - PRI_TOLERANCE), \ | ||
49 | (PRF2PRI(PMIN) * PRF + PRI_TOLERANCE), PRF, PPB * PRF, \ | ||
50 | PPB_THRESH(PPB), PRI_TOLERANCE, \ | ||
51 | } | ||
52 | |||
53 | /* radar types as defined by ETSI EN-301-893 v1.5.1 */ | ||
54 | static const struct radar_detector_specs etsi_radar_ref_types_v15[] = { | ||
55 | ETSI_PATTERN(0, 0, 1, 700, 700, 1, 18), | ||
56 | ETSI_PATTERN(1, 0, 5, 200, 1000, 1, 10), | ||
57 | ETSI_PATTERN(2, 0, 15, 200, 1600, 1, 15), | ||
58 | ETSI_PATTERN(3, 0, 15, 2300, 4000, 1, 25), | ||
59 | ETSI_PATTERN(4, 20, 30, 2000, 4000, 1, 20), | ||
60 | ETSI_PATTERN(5, 0, 2, 300, 400, 3, 10), | ||
61 | ETSI_PATTERN(6, 0, 2, 400, 1200, 3, 15), | ||
62 | }; | ||
63 | |||
64 | static const struct radar_types etsi_radar_types_v15 = { | ||
65 | .region = NL80211_DFS_ETSI, | ||
66 | .num_radar_types = ARRAY_SIZE(etsi_radar_ref_types_v15), | ||
67 | .radar_types = etsi_radar_ref_types_v15, | ||
68 | }; | ||
69 | |||
70 | /* for now, we support ETSI radar types, FCC and JP are TODO */ | ||
71 | static const struct radar_types *dfs_domains[] = { | ||
72 | &etsi_radar_types_v15, | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * get_dfs_domain_radar_types() - get radar types for a given DFS domain | ||
77 | * @param domain DFS domain | ||
78 | * @return radar_types ptr on success, NULL if DFS domain is not supported | ||
79 | */ | ||
80 | static const struct radar_types * | ||
81 | get_dfs_domain_radar_types(enum nl80211_dfs_regions region) | ||
82 | { | ||
83 | u32 i; | ||
84 | for (i = 0; i < ARRAY_SIZE(dfs_domains); i++) { | ||
85 | if (dfs_domains[i]->region == region) | ||
86 | return dfs_domains[i]; | ||
87 | } | ||
88 | return NULL; | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * struct channel_detector - detector elements for a DFS channel | ||
93 | * @head: list_head | ||
94 | * @freq: frequency for this channel detector in MHz | ||
95 | * @detectors: array of dynamically created detector elements for this freq | ||
96 | * | ||
97 | * Channel detectors are required to provide multi-channel DFS detection, e.g. | ||
98 | * to support off-channel scanning. A pattern detector has a list of channels | ||
99 | * radar pulses have been reported for in the past. | ||
100 | */ | ||
101 | struct channel_detector { | ||
102 | struct list_head head; | ||
103 | u16 freq; | ||
104 | struct pri_detector **detectors; | ||
105 | }; | ||
106 | |||
107 | /* channel_detector_reset() - reset detector lines for a given channel */ | ||
108 | static void channel_detector_reset(struct dfs_pattern_detector *dpd, | ||
109 | struct channel_detector *cd) | ||
110 | { | ||
111 | u32 i; | ||
112 | if (cd == NULL) | ||
113 | return; | ||
114 | for (i = 0; i < dpd->num_radar_types; i++) | ||
115 | cd->detectors[i]->reset(cd->detectors[i], dpd->last_pulse_ts); | ||
116 | } | ||
117 | |||
118 | /* channel_detector_exit() - destructor */ | ||
119 | static void channel_detector_exit(struct dfs_pattern_detector *dpd, | ||
120 | struct channel_detector *cd) | ||
121 | { | ||
122 | u32 i; | ||
123 | if (cd == NULL) | ||
124 | return; | ||
125 | list_del(&cd->head); | ||
126 | for (i = 0; i < dpd->num_radar_types; i++) { | ||
127 | struct pri_detector *de = cd->detectors[i]; | ||
128 | if (de != NULL) | ||
129 | de->exit(de); | ||
130 | } | ||
131 | kfree(cd->detectors); | ||
132 | kfree(cd); | ||
133 | } | ||
134 | |||
135 | static struct channel_detector * | ||
136 | channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq) | ||
137 | { | ||
138 | u32 sz, i; | ||
139 | struct channel_detector *cd; | ||
140 | |||
141 | cd = kmalloc(sizeof(*cd), GFP_KERNEL); | ||
142 | if (cd == NULL) | ||
143 | goto fail; | ||
144 | |||
145 | INIT_LIST_HEAD(&cd->head); | ||
146 | cd->freq = freq; | ||
147 | sz = sizeof(cd->detectors) * dpd->num_radar_types; | ||
148 | cd->detectors = kzalloc(sz, GFP_KERNEL); | ||
149 | if (cd->detectors == NULL) | ||
150 | goto fail; | ||
151 | |||
152 | for (i = 0; i < dpd->num_radar_types; i++) { | ||
153 | const struct radar_detector_specs *rs = &dpd->radar_spec[i]; | ||
154 | struct pri_detector *de = pri_detector_init(rs); | ||
155 | if (de == NULL) | ||
156 | goto fail; | ||
157 | cd->detectors[i] = de; | ||
158 | } | ||
159 | list_add(&cd->head, &dpd->channel_detectors); | ||
160 | return cd; | ||
161 | |||
162 | fail: | ||
163 | pr_err("failed to allocate channel_detector for freq=%d\n", freq); | ||
164 | channel_detector_exit(dpd, cd); | ||
165 | return NULL; | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * channel_detector_get() - get channel detector for given frequency | ||
170 | * @param dpd instance pointer | ||
171 | * @param freq frequency in MHz | ||
172 | * @return pointer to channel detector on success, NULL otherwise | ||
173 | * | ||
174 | * Return existing channel detector for the given frequency or return a | ||
175 | * newly create one. | ||
176 | */ | ||
177 | static struct channel_detector * | ||
178 | channel_detector_get(struct dfs_pattern_detector *dpd, u16 freq) | ||
179 | { | ||
180 | struct channel_detector *cd; | ||
181 | list_for_each_entry(cd, &dpd->channel_detectors, head) { | ||
182 | if (cd->freq == freq) | ||
183 | return cd; | ||
184 | } | ||
185 | return channel_detector_create(dpd, freq); | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * DFS Pattern Detector | ||
190 | */ | ||
191 | |||
192 | /* dpd_reset(): reset all channel detectors */ | ||
193 | static void dpd_reset(struct dfs_pattern_detector *dpd) | ||
194 | { | ||
195 | struct channel_detector *cd; | ||
196 | if (!list_empty(&dpd->channel_detectors)) | ||
197 | list_for_each_entry(cd, &dpd->channel_detectors, head) | ||
198 | channel_detector_reset(dpd, cd); | ||
199 | |||
200 | } | ||
201 | static void dpd_exit(struct dfs_pattern_detector *dpd) | ||
202 | { | ||
203 | struct channel_detector *cd, *cd0; | ||
204 | if (!list_empty(&dpd->channel_detectors)) | ||
205 | list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head) | ||
206 | channel_detector_exit(dpd, cd); | ||
207 | kfree(dpd); | ||
208 | } | ||
209 | |||
210 | static bool | ||
211 | dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) | ||
212 | { | ||
213 | u32 i; | ||
214 | bool ts_wraparound; | ||
215 | struct channel_detector *cd; | ||
216 | |||
217 | if (dpd->region == NL80211_DFS_UNSET) { | ||
218 | /* | ||
219 | * pulses received for a non-supported or un-initialized | ||
220 | * domain are treated as detected radars | ||
221 | */ | ||
222 | return true; | ||
223 | } | ||
224 | |||
225 | cd = channel_detector_get(dpd, event->freq); | ||
226 | if (cd == NULL) | ||
227 | return false; | ||
228 | |||
229 | ts_wraparound = (event->ts < dpd->last_pulse_ts); | ||
230 | dpd->last_pulse_ts = event->ts; | ||
231 | if (ts_wraparound) { | ||
232 | /* | ||
233 | * reset detector on time stamp wraparound | ||
234 | * with monotonic time stamps, this should never happen | ||
235 | */ | ||
236 | pr_warn("DFS: time stamp wraparound detected, resetting\n"); | ||
237 | dpd_reset(dpd); | ||
238 | } | ||
239 | /* do type individual pattern matching */ | ||
240 | for (i = 0; i < dpd->num_radar_types; i++) { | ||
241 | if (cd->detectors[i]->add_pulse(cd->detectors[i], event) != 0) { | ||
242 | channel_detector_reset(dpd, cd); | ||
243 | return true; | ||
244 | } | ||
245 | } | ||
246 | return false; | ||
247 | } | ||
248 | |||
249 | static bool dpd_set_domain(struct dfs_pattern_detector *dpd, | ||
250 | enum nl80211_dfs_regions region) | ||
251 | { | ||
252 | const struct radar_types *rt; | ||
253 | struct channel_detector *cd, *cd0; | ||
254 | |||
255 | if (dpd->region == region) | ||
256 | return true; | ||
257 | |||
258 | dpd->region = NL80211_DFS_UNSET; | ||
259 | |||
260 | rt = get_dfs_domain_radar_types(region); | ||
261 | if (rt == NULL) | ||
262 | return false; | ||
263 | |||
264 | /* delete all channel detectors for previous DFS domain */ | ||
265 | if (!list_empty(&dpd->channel_detectors)) | ||
266 | list_for_each_entry_safe(cd, cd0, &dpd->channel_detectors, head) | ||
267 | channel_detector_exit(dpd, cd); | ||
268 | dpd->radar_spec = rt->radar_types; | ||
269 | dpd->num_radar_types = rt->num_radar_types; | ||
270 | |||
271 | dpd->region = region; | ||
272 | return true; | ||
273 | } | ||
274 | |||
275 | static struct dfs_pattern_detector default_dpd = { | ||
276 | .exit = dpd_exit, | ||
277 | .set_domain = dpd_set_domain, | ||
278 | .add_pulse = dpd_add_pulse, | ||
279 | .region = NL80211_DFS_UNSET, | ||
280 | }; | ||
281 | |||
282 | struct dfs_pattern_detector * | ||
283 | dfs_pattern_detector_init(enum nl80211_dfs_regions region) | ||
284 | { | ||
285 | struct dfs_pattern_detector *dpd; | ||
286 | dpd = kmalloc(sizeof(*dpd), GFP_KERNEL); | ||
287 | if (dpd == NULL) { | ||
288 | pr_err("allocation of dfs_pattern_detector failed\n"); | ||
289 | return NULL; | ||
290 | } | ||
291 | *dpd = default_dpd; | ||
292 | INIT_LIST_HEAD(&dpd->channel_detectors); | ||
293 | |||
294 | if (dpd->set_domain(dpd, region)) | ||
295 | return dpd; | ||
296 | |||
297 | pr_err("Could not set DFS domain to %d. ", region); | ||
298 | return NULL; | ||
299 | } | ||
300 | EXPORT_SYMBOL(dfs_pattern_detector_init); | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h new file mode 100644 index 000000000000..fd0328a30995 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.h | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Neratec Solutions AG | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef DFS_PATTERN_DETECTOR_H | ||
18 | #define DFS_PATTERN_DETECTOR_H | ||
19 | |||
20 | #include <linux/types.h> | ||
21 | #include <linux/list.h> | ||
22 | #include <linux/nl80211.h> | ||
23 | |||
24 | /** | ||
25 | * struct pulse_event - describing pulses reported by PHY | ||
26 | * @ts: pulse time stamp in us | ||
27 | * @freq: channel frequency in MHz | ||
28 | * @width: pulse duration in us | ||
29 | * @rssi: rssi of radar event | ||
30 | */ | ||
31 | struct pulse_event { | ||
32 | u64 ts; | ||
33 | u16 freq; | ||
34 | u8 width; | ||
35 | u8 rssi; | ||
36 | }; | ||
37 | |||
38 | /** | ||
39 | * struct radar_detector_specs - detector specs for a radar pattern type | ||
40 | * @type_id: pattern type, as defined by regulatory | ||
41 | * @width_min: minimum radar pulse width in [us] | ||
42 | * @width_max: maximum radar pulse width in [us] | ||
43 | * @pri_min: minimum pulse repetition interval in [us] (including tolerance) | ||
44 | * @pri_max: minimum pri in [us] (including tolerance) | ||
45 | * @num_pri: maximum number of different pri for this type | ||
46 | * @ppb: pulses per bursts for this type | ||
47 | * @ppb_thresh: number of pulses required to trigger detection | ||
48 | * @max_pri_tolerance: pulse time stamp tolerance on both sides [us] | ||
49 | */ | ||
50 | struct radar_detector_specs { | ||
51 | u8 type_id; | ||
52 | u8 width_min; | ||
53 | u8 width_max; | ||
54 | u16 pri_min; | ||
55 | u16 pri_max; | ||
56 | u8 num_pri; | ||
57 | u8 ppb; | ||
58 | u8 ppb_thresh; | ||
59 | u8 max_pri_tolerance; | ||
60 | }; | ||
61 | |||
62 | /** | ||
63 | * struct dfs_pattern_detector - DFS pattern detector | ||
64 | * @exit(): destructor | ||
65 | * @set_domain(): set DFS domain, resets detector lines upon domain changes | ||
66 | * @add_pulse(): add radar pulse to detector, returns true on detection | ||
67 | * @region: active DFS region, NL80211_DFS_UNSET until set | ||
68 | * @num_radar_types: number of different radar types | ||
69 | * @last_pulse_ts: time stamp of last valid pulse in usecs | ||
70 | * @radar_detector_specs: array of radar detection specs | ||
71 | * @channel_detectors: list connecting channel_detector elements | ||
72 | */ | ||
73 | struct dfs_pattern_detector { | ||
74 | void (*exit)(struct dfs_pattern_detector *dpd); | ||
75 | bool (*set_domain)(struct dfs_pattern_detector *dpd, | ||
76 | enum nl80211_dfs_regions region); | ||
77 | bool (*add_pulse)(struct dfs_pattern_detector *dpd, | ||
78 | struct pulse_event *pe); | ||
79 | |||
80 | enum nl80211_dfs_regions region; | ||
81 | u8 num_radar_types; | ||
82 | u64 last_pulse_ts; | ||
83 | |||
84 | const struct radar_detector_specs *radar_spec; | ||
85 | struct list_head channel_detectors; | ||
86 | }; | ||
87 | |||
88 | /** | ||
89 | * dfs_pattern_detector_init() - constructor for pattern detector class | ||
90 | * @param region: DFS domain to be used, can be NL80211_DFS_UNSET at creation | ||
91 | * @return instance pointer on success, NULL otherwise | ||
92 | */ | ||
93 | #if defined(CONFIG_ATH9K_DFS_CERTIFIED) | ||
94 | extern struct dfs_pattern_detector * | ||
95 | dfs_pattern_detector_init(enum nl80211_dfs_regions region); | ||
96 | #else | ||
97 | static inline struct dfs_pattern_detector * | ||
98 | dfs_pattern_detector_init(enum nl80211_dfs_regions region) | ||
99 | { | ||
100 | return NULL; | ||
101 | } | ||
102 | #endif /* CONFIG_ATH9K_DFS_CERTIFIED */ | ||
103 | |||
104 | #endif /* DFS_PATTERN_DETECTOR_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c new file mode 100644 index 000000000000..025e88a64fa4 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c | |||
@@ -0,0 +1,390 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Neratec Solutions AG | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/slab.h> | ||
18 | |||
19 | #include "dfs_pattern_detector.h" | ||
20 | #include "dfs_pri_detector.h" | ||
21 | |||
22 | /** | ||
23 | * struct pri_sequence - sequence of pulses matching one PRI | ||
24 | * @head: list_head | ||
25 | * @pri: pulse repetition interval (PRI) in usecs | ||
26 | * @dur: duration of sequence in usecs | ||
27 | * @count: number of pulses in this sequence | ||
28 | * @count_falses: number of not matching pulses in this sequence | ||
29 | * @first_ts: time stamp of first pulse in usecs | ||
30 | * @last_ts: time stamp of last pulse in usecs | ||
31 | * @deadline_ts: deadline when this sequence becomes invalid (first_ts + dur) | ||
32 | */ | ||
33 | struct pri_sequence { | ||
34 | struct list_head head; | ||
35 | u32 pri; | ||
36 | u32 dur; | ||
37 | u32 count; | ||
38 | u32 count_falses; | ||
39 | u64 first_ts; | ||
40 | u64 last_ts; | ||
41 | u64 deadline_ts; | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * struct pulse_elem - elements in pulse queue | ||
46 | * @ts: time stamp in usecs | ||
47 | */ | ||
48 | struct pulse_elem { | ||
49 | struct list_head head; | ||
50 | u64 ts; | ||
51 | }; | ||
52 | |||
53 | /** | ||
54 | * pde_get_multiple() - get number of multiples considering a given tolerance | ||
55 | * @return factor if abs(val - factor*fraction) <= tolerance, 0 otherwise | ||
56 | */ | ||
57 | static u32 pde_get_multiple(u32 val, u32 fraction, u32 tolerance) | ||
58 | { | ||
59 | u32 remainder; | ||
60 | u32 factor; | ||
61 | u32 delta; | ||
62 | |||
63 | if (fraction == 0) | ||
64 | return 0; | ||
65 | |||
66 | delta = (val < fraction) ? (fraction - val) : (val - fraction); | ||
67 | |||
68 | if (delta <= tolerance) | ||
69 | /* val and fraction are within tolerance */ | ||
70 | return 1; | ||
71 | |||
72 | factor = val / fraction; | ||
73 | remainder = val % fraction; | ||
74 | if (remainder > tolerance) { | ||
75 | /* no exact match */ | ||
76 | if ((fraction - remainder) <= tolerance) | ||
77 | /* remainder is within tolerance */ | ||
78 | factor++; | ||
79 | else | ||
80 | factor = 0; | ||
81 | } | ||
82 | return factor; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * DOC: Singleton Pulse and Sequence Pools | ||
87 | * | ||
88 | * Instances of pri_sequence and pulse_elem are kept in singleton pools to | ||
89 | * reduce the number of dynamic allocations. They are shared between all | ||
90 | * instances and grow up to the peak number of simultaneously used objects. | ||
91 | * | ||
92 | * Memory is freed after all references to the pools are released. | ||
93 | */ | ||
94 | static u32 singleton_pool_references; | ||
95 | static LIST_HEAD(pulse_pool); | ||
96 | static LIST_HEAD(pseq_pool); | ||
97 | |||
98 | static struct pulse_elem *pulse_queue_get_tail(struct pri_detector *pde) | ||
99 | { | ||
100 | struct list_head *l = &pde->pulses; | ||
101 | if (list_empty(l)) | ||
102 | return NULL; | ||
103 | return list_entry(l->prev, struct pulse_elem, head); | ||
104 | } | ||
105 | |||
106 | static bool pulse_queue_dequeue(struct pri_detector *pde) | ||
107 | { | ||
108 | struct pulse_elem *p = pulse_queue_get_tail(pde); | ||
109 | if (p != NULL) { | ||
110 | list_del_init(&p->head); | ||
111 | pde->count--; | ||
112 | /* give it back to pool */ | ||
113 | list_add(&p->head, &pulse_pool); | ||
114 | } | ||
115 | return (pde->count > 0); | ||
116 | } | ||
117 | |||
118 | /* remove pulses older than window */ | ||
119 | static void pulse_queue_check_window(struct pri_detector *pde) | ||
120 | { | ||
121 | u64 min_valid_ts; | ||
122 | struct pulse_elem *p; | ||
123 | |||
124 | /* there is no delta time with less than 2 pulses */ | ||
125 | if (pde->count < 2) | ||
126 | return; | ||
127 | |||
128 | if (pde->last_ts <= pde->window_size) | ||
129 | return; | ||
130 | |||
131 | min_valid_ts = pde->last_ts - pde->window_size; | ||
132 | while ((p = pulse_queue_get_tail(pde)) != NULL) { | ||
133 | if (p->ts >= min_valid_ts) | ||
134 | return; | ||
135 | pulse_queue_dequeue(pde); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static bool pulse_queue_enqueue(struct pri_detector *pde, u64 ts) | ||
140 | { | ||
141 | struct pulse_elem *p; | ||
142 | if (!list_empty(&pulse_pool)) { | ||
143 | p = list_first_entry(&pulse_pool, struct pulse_elem, head); | ||
144 | list_del(&p->head); | ||
145 | } else { | ||
146 | p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
147 | if (p == NULL) { | ||
148 | pr_err("failed to allocate pulse_elem\n"); | ||
149 | return false; | ||
150 | } | ||
151 | } | ||
152 | INIT_LIST_HEAD(&p->head); | ||
153 | p->ts = ts; | ||
154 | list_add(&p->head, &pde->pulses); | ||
155 | pde->count++; | ||
156 | pde->last_ts = ts; | ||
157 | pulse_queue_check_window(pde); | ||
158 | if (pde->count >= pde->max_count) | ||
159 | pulse_queue_dequeue(pde); | ||
160 | return true; | ||
161 | } | ||
162 | |||
163 | static bool pseq_handler_create_sequences(struct pri_detector *pde, | ||
164 | u64 ts, u32 min_count) | ||
165 | { | ||
166 | struct pulse_elem *p; | ||
167 | list_for_each_entry(p, &pde->pulses, head) { | ||
168 | struct pri_sequence ps, *new_ps; | ||
169 | struct pulse_elem *p2; | ||
170 | u32 tmp_false_count; | ||
171 | u64 min_valid_ts; | ||
172 | u32 delta_ts = ts - p->ts; | ||
173 | |||
174 | if (delta_ts < pde->rs->pri_min) | ||
175 | /* ignore too small pri */ | ||
176 | continue; | ||
177 | |||
178 | if (delta_ts > pde->rs->pri_max) | ||
179 | /* stop on too large pri (sorted list) */ | ||
180 | break; | ||
181 | |||
182 | /* build a new sequence with new potential pri */ | ||
183 | ps.count = 2; | ||
184 | ps.count_falses = 0; | ||
185 | ps.first_ts = p->ts; | ||
186 | ps.last_ts = ts; | ||
187 | ps.pri = ts - p->ts; | ||
188 | ps.dur = ps.pri * (pde->rs->ppb - 1) | ||
189 | + 2 * pde->rs->max_pri_tolerance; | ||
190 | |||
191 | p2 = p; | ||
192 | tmp_false_count = 0; | ||
193 | min_valid_ts = ts - ps.dur; | ||
194 | /* check which past pulses are candidates for new sequence */ | ||
195 | list_for_each_entry_continue(p2, &pde->pulses, head) { | ||
196 | u32 factor; | ||
197 | if (p2->ts < min_valid_ts) | ||
198 | /* stop on crossing window border */ | ||
199 | break; | ||
200 | /* check if pulse match (multi)PRI */ | ||
201 | factor = pde_get_multiple(ps.last_ts - p2->ts, ps.pri, | ||
202 | pde->rs->max_pri_tolerance); | ||
203 | if (factor > 0) { | ||
204 | ps.count++; | ||
205 | ps.first_ts = p2->ts; | ||
206 | /* | ||
207 | * on match, add the intermediate falses | ||
208 | * and reset counter | ||
209 | */ | ||
210 | ps.count_falses += tmp_false_count; | ||
211 | tmp_false_count = 0; | ||
212 | } else { | ||
213 | /* this is a potential false one */ | ||
214 | tmp_false_count++; | ||
215 | } | ||
216 | } | ||
217 | if (ps.count < min_count) | ||
218 | /* did not reach minimum count, drop sequence */ | ||
219 | continue; | ||
220 | |||
221 | /* this is a valid one, add it */ | ||
222 | ps.deadline_ts = ps.first_ts + ps.dur; | ||
223 | |||
224 | if (!list_empty(&pseq_pool)) { | ||
225 | new_ps = list_first_entry(&pseq_pool, | ||
226 | struct pri_sequence, head); | ||
227 | list_del(&new_ps->head); | ||
228 | } else { | ||
229 | new_ps = kmalloc(sizeof(*new_ps), GFP_KERNEL); | ||
230 | if (new_ps == NULL) | ||
231 | return false; | ||
232 | } | ||
233 | memcpy(new_ps, &ps, sizeof(ps)); | ||
234 | INIT_LIST_HEAD(&new_ps->head); | ||
235 | list_add(&new_ps->head, &pde->sequences); | ||
236 | } | ||
237 | return true; | ||
238 | } | ||
239 | |||
240 | /* check new ts and add to all matching existing sequences */ | ||
241 | static u32 | ||
242 | pseq_handler_add_to_existing_seqs(struct pri_detector *pde, u64 ts) | ||
243 | { | ||
244 | u32 max_count = 0; | ||
245 | struct pri_sequence *ps, *ps2; | ||
246 | list_for_each_entry_safe(ps, ps2, &pde->sequences, head) { | ||
247 | u32 delta_ts; | ||
248 | u32 factor; | ||
249 | |||
250 | /* first ensure that sequence is within window */ | ||
251 | if (ts > ps->deadline_ts) { | ||
252 | list_del_init(&ps->head); | ||
253 | list_add(&ps->head, &pseq_pool); | ||
254 | continue; | ||
255 | } | ||
256 | |||
257 | delta_ts = ts - ps->last_ts; | ||
258 | factor = pde_get_multiple(delta_ts, ps->pri, | ||
259 | pde->rs->max_pri_tolerance); | ||
260 | if (factor > 0) { | ||
261 | ps->last_ts = ts; | ||
262 | ps->count++; | ||
263 | |||
264 | if (max_count < ps->count) | ||
265 | max_count = ps->count; | ||
266 | } else { | ||
267 | ps->count_falses++; | ||
268 | } | ||
269 | } | ||
270 | return max_count; | ||
271 | } | ||
272 | |||
273 | static struct pri_sequence * | ||
274 | pseq_handler_check_detection(struct pri_detector *pde) | ||
275 | { | ||
276 | struct pri_sequence *ps; | ||
277 | |||
278 | if (list_empty(&pde->sequences)) | ||
279 | return NULL; | ||
280 | |||
281 | list_for_each_entry(ps, &pde->sequences, head) { | ||
282 | /* | ||
283 | * we assume to have enough matching confidence if we | ||
284 | * 1) have enough pulses | ||
285 | * 2) have more matching than false pulses | ||
286 | */ | ||
287 | if ((ps->count >= pde->rs->ppb_thresh) && | ||
288 | (ps->count * pde->rs->num_pri >= ps->count_falses)) | ||
289 | return ps; | ||
290 | } | ||
291 | return NULL; | ||
292 | } | ||
293 | |||
294 | |||
295 | /* free pulse queue and sequences list and give objects back to pools */ | ||
296 | static void pri_detector_reset(struct pri_detector *pde, u64 ts) | ||
297 | { | ||
298 | struct pri_sequence *ps, *ps0; | ||
299 | struct pulse_elem *p, *p0; | ||
300 | list_for_each_entry_safe(ps, ps0, &pde->sequences, head) { | ||
301 | list_del_init(&ps->head); | ||
302 | list_add(&ps->head, &pseq_pool); | ||
303 | } | ||
304 | list_for_each_entry_safe(p, p0, &pde->pulses, head) { | ||
305 | list_del_init(&p->head); | ||
306 | list_add(&p->head, &pulse_pool); | ||
307 | } | ||
308 | pde->count = 0; | ||
309 | pde->last_ts = ts; | ||
310 | } | ||
311 | |||
312 | static void pri_detector_exit(struct pri_detector *de) | ||
313 | { | ||
314 | pri_detector_reset(de, 0); | ||
315 | |||
316 | singleton_pool_references--; | ||
317 | if (singleton_pool_references == 0) { | ||
318 | /* free singleton pools with no references left */ | ||
319 | struct pri_sequence *ps, *ps0; | ||
320 | struct pulse_elem *p, *p0; | ||
321 | |||
322 | list_for_each_entry_safe(p, p0, &pulse_pool, head) { | ||
323 | list_del(&p->head); | ||
324 | kfree(p); | ||
325 | } | ||
326 | list_for_each_entry_safe(ps, ps0, &pseq_pool, head) { | ||
327 | list_del(&ps->head); | ||
328 | kfree(ps); | ||
329 | } | ||
330 | } | ||
331 | kfree(de); | ||
332 | } | ||
333 | |||
334 | static bool pri_detector_add_pulse(struct pri_detector *de, | ||
335 | struct pulse_event *event) | ||
336 | { | ||
337 | u32 max_updated_seq; | ||
338 | struct pri_sequence *ps; | ||
339 | u64 ts = event->ts; | ||
340 | const struct radar_detector_specs *rs = de->rs; | ||
341 | |||
342 | /* ignore pulses not within width range */ | ||
343 | if ((rs->width_min > event->width) || (rs->width_max < event->width)) | ||
344 | return false; | ||
345 | |||
346 | if ((ts - de->last_ts) < rs->max_pri_tolerance) | ||
347 | /* if delta to last pulse is too short, don't use this pulse */ | ||
348 | return false; | ||
349 | de->last_ts = ts; | ||
350 | |||
351 | max_updated_seq = pseq_handler_add_to_existing_seqs(de, ts); | ||
352 | |||
353 | if (!pseq_handler_create_sequences(de, ts, max_updated_seq)) { | ||
354 | pr_err("failed to create pulse sequences\n"); | ||
355 | pri_detector_reset(de, ts); | ||
356 | return false; | ||
357 | } | ||
358 | |||
359 | ps = pseq_handler_check_detection(de); | ||
360 | |||
361 | if (ps != NULL) { | ||
362 | pr_info("DFS: radar found: pri=%d, count=%d, count_false=%d\n", | ||
363 | ps->pri, ps->count, ps->count_falses); | ||
364 | pri_detector_reset(de, ts); | ||
365 | return true; | ||
366 | } | ||
367 | pulse_queue_enqueue(de, ts); | ||
368 | return false; | ||
369 | } | ||
370 | |||
371 | struct pri_detector * | ||
372 | pri_detector_init(const struct radar_detector_specs *rs) | ||
373 | { | ||
374 | struct pri_detector *de; | ||
375 | de = kzalloc(sizeof(*de), GFP_KERNEL); | ||
376 | if (de == NULL) | ||
377 | return NULL; | ||
378 | de->exit = pri_detector_exit; | ||
379 | de->add_pulse = pri_detector_add_pulse; | ||
380 | de->reset = pri_detector_reset; | ||
381 | |||
382 | INIT_LIST_HEAD(&de->sequences); | ||
383 | INIT_LIST_HEAD(&de->pulses); | ||
384 | de->window_size = rs->pri_max * rs->ppb * rs->num_pri; | ||
385 | de->max_count = rs->ppb * 2; | ||
386 | de->rs = rs; | ||
387 | |||
388 | singleton_pool_references++; | ||
389 | return de; | ||
390 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h new file mode 100644 index 000000000000..81cde9f28e44 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Neratec Solutions AG | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef DFS_PRI_DETECTOR_H | ||
18 | #define DFS_PRI_DETECTOR_H | ||
19 | |||
20 | #include <linux/list.h> | ||
21 | |||
22 | /** | ||
23 | * struct pri_detector - PRI detector element for a dedicated radar type | ||
24 | * @exit(): destructor | ||
25 | * @add_pulse(): add pulse event, returns true if pattern was detected | ||
26 | * @reset(): clear states and reset to given time stamp | ||
27 | * @rs: detector specs for this detector element | ||
28 | * @last_ts: last pulse time stamp considered for this element in usecs | ||
29 | * @sequences: list_head holding potential pulse sequences | ||
30 | * @pulses: list connecting pulse_elem objects | ||
31 | * @count: number of pulses in queue | ||
32 | * @max_count: maximum number of pulses to be queued | ||
33 | * @window_size: window size back from newest pulse time stamp in usecs | ||
34 | */ | ||
35 | struct pri_detector { | ||
36 | void (*exit) (struct pri_detector *de); | ||
37 | bool (*add_pulse)(struct pri_detector *de, struct pulse_event *e); | ||
38 | void (*reset) (struct pri_detector *de, u64 ts); | ||
39 | |||
40 | /* private: internal use only */ | ||
41 | const struct radar_detector_specs *rs; | ||
42 | u64 last_ts; | ||
43 | struct list_head sequences; | ||
44 | struct list_head pulses; | ||
45 | u32 count; | ||
46 | u32 max_count; | ||
47 | u32 window_size; | ||
48 | }; | ||
49 | |||
50 | struct pri_detector *pri_detector_init(const struct radar_detector_specs *rs); | ||
51 | |||
52 | #endif /* DFS_PRI_DETECTOR_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index de5ee15ee639..25213d521bc2 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include "htc.h" | 19 | #include "htc.h" |
18 | 20 | ||
19 | MODULE_AUTHOR("Atheros Communications"); | 21 | MODULE_AUTHOR("Atheros Communications"); |
@@ -711,7 +713,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
711 | 713 | ||
712 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 714 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
713 | 715 | ||
714 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 716 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN | |
717 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | ||
715 | 718 | ||
716 | hw->queues = 4; | 719 | hw->queues = 4; |
717 | hw->channel_change_time = 5000; | 720 | hw->channel_change_time = 5000; |
@@ -966,9 +969,7 @@ int ath9k_htc_resume(struct htc_target *htc_handle) | |||
966 | static int __init ath9k_htc_init(void) | 969 | static int __init ath9k_htc_init(void) |
967 | { | 970 | { |
968 | if (ath9k_hif_usb_init() < 0) { | 971 | if (ath9k_hif_usb_init() < 0) { |
969 | printk(KERN_ERR | 972 | pr_err("No USB devices found, driver not installed\n"); |
970 | "ath9k_htc: No USB devices found," | ||
971 | " driver not installed.\n"); | ||
972 | return -ENODEV; | 973 | return -ENODEV; |
973 | } | 974 | } |
974 | 975 | ||
@@ -979,6 +980,6 @@ module_init(ath9k_htc_init); | |||
979 | static void __exit ath9k_htc_exit(void) | 980 | static void __exit ath9k_htc_exit(void) |
980 | { | 981 | { |
981 | ath9k_hif_usb_exit(); | 982 | ath9k_hif_usb_exit(); |
982 | printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); | 983 | pr_info("Driver unloaded\n"); |
983 | } | 984 | } |
984 | module_exit(ath9k_htc_exit); | 985 | module_exit(ath9k_htc_exit); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index c25226a32ddc..4a9570dfba72 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include "htc.h" | 19 | #include "htc.h" |
18 | 20 | ||
19 | static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, | 21 | static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, |
@@ -461,7 +463,7 @@ int ath9k_htc_hw_init(struct htc_target *target, | |||
461 | char *product, u32 drv_info) | 463 | char *product, u32 drv_info) |
462 | { | 464 | { |
463 | if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) { | 465 | if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) { |
464 | printk(KERN_ERR "Failed to initialize the device\n"); | 466 | pr_err("Failed to initialize the device\n"); |
465 | return -ENODEV; | 467 | return -ENODEV; |
466 | } | 468 | } |
467 | 469 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 6c69e4e8b1cb..d1345a8a2b15 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1491,11 +1491,84 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) | |||
1491 | } | 1491 | } |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | static bool ath9k_hw_check_dcs(u32 dma_dbg, u32 num_dcu_states, | ||
1495 | int *hang_state, int *hang_pos) | ||
1496 | { | ||
1497 | static u32 dcu_chain_state[] = {5, 6, 9}; /* DCU chain stuck states */ | ||
1498 | u32 chain_state, dcs_pos, i; | ||
1499 | |||
1500 | for (dcs_pos = 0; dcs_pos < num_dcu_states; dcs_pos++) { | ||
1501 | chain_state = (dma_dbg >> (5 * dcs_pos)) & 0x1f; | ||
1502 | for (i = 0; i < 3; i++) { | ||
1503 | if (chain_state == dcu_chain_state[i]) { | ||
1504 | *hang_state = chain_state; | ||
1505 | *hang_pos = dcs_pos; | ||
1506 | return true; | ||
1507 | } | ||
1508 | } | ||
1509 | } | ||
1510 | return false; | ||
1511 | } | ||
1512 | |||
1513 | #define DCU_COMPLETE_STATE 1 | ||
1514 | #define DCU_COMPLETE_STATE_MASK 0x3 | ||
1515 | #define NUM_STATUS_READS 50 | ||
1516 | static bool ath9k_hw_detect_mac_hang(struct ath_hw *ah) | ||
1517 | { | ||
1518 | u32 chain_state, comp_state, dcs_reg = AR_DMADBG_4; | ||
1519 | u32 i, hang_pos, hang_state, num_state = 6; | ||
1520 | |||
1521 | comp_state = REG_READ(ah, AR_DMADBG_6); | ||
1522 | |||
1523 | if ((comp_state & DCU_COMPLETE_STATE_MASK) != DCU_COMPLETE_STATE) { | ||
1524 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
1525 | "MAC Hang signature not found at DCU complete\n"); | ||
1526 | return false; | ||
1527 | } | ||
1528 | |||
1529 | chain_state = REG_READ(ah, dcs_reg); | ||
1530 | if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos)) | ||
1531 | goto hang_check_iter; | ||
1532 | |||
1533 | dcs_reg = AR_DMADBG_5; | ||
1534 | num_state = 4; | ||
1535 | chain_state = REG_READ(ah, dcs_reg); | ||
1536 | if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos)) | ||
1537 | goto hang_check_iter; | ||
1538 | |||
1539 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
1540 | "MAC Hang signature 1 not found\n"); | ||
1541 | return false; | ||
1542 | |||
1543 | hang_check_iter: | ||
1544 | ath_dbg(ath9k_hw_common(ah), RESET, | ||
1545 | "DCU registers: chain %08x complete %08x Hang: state %d pos %d\n", | ||
1546 | chain_state, comp_state, hang_state, hang_pos); | ||
1547 | |||
1548 | for (i = 0; i < NUM_STATUS_READS; i++) { | ||
1549 | chain_state = REG_READ(ah, dcs_reg); | ||
1550 | chain_state = (chain_state >> (5 * hang_pos)) & 0x1f; | ||
1551 | comp_state = REG_READ(ah, AR_DMADBG_6); | ||
1552 | |||
1553 | if (((comp_state & DCU_COMPLETE_STATE_MASK) != | ||
1554 | DCU_COMPLETE_STATE) || | ||
1555 | (chain_state != hang_state)) | ||
1556 | return false; | ||
1557 | } | ||
1558 | |||
1559 | ath_dbg(ath9k_hw_common(ah), RESET, "MAC Hang signature 1 found\n"); | ||
1560 | |||
1561 | return true; | ||
1562 | } | ||
1563 | |||
1494 | bool ath9k_hw_check_alive(struct ath_hw *ah) | 1564 | bool ath9k_hw_check_alive(struct ath_hw *ah) |
1495 | { | 1565 | { |
1496 | int count = 50; | 1566 | int count = 50; |
1497 | u32 reg; | 1567 | u32 reg; |
1498 | 1568 | ||
1569 | if (AR_SREV_9300(ah)) | ||
1570 | return !ath9k_hw_detect_mac_hang(ah); | ||
1571 | |||
1499 | if (AR_SREV_9285_12_OR_LATER(ah)) | 1572 | if (AR_SREV_9285_12_OR_LATER(ah)) |
1500 | return true; | 1573 | return true; |
1501 | 1574 | ||
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index cb006458fc4b..7a6b9f69a7b1 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
18 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
19 | #include <linux/ath9k_platform.h> | 21 | #include <linux/ath9k_platform.h> |
@@ -519,6 +521,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
519 | atomic_set(&ah->intr_ref_cnt, -1); | 521 | atomic_set(&ah->intr_ref_cnt, -1); |
520 | sc->sc_ah = ah; | 522 | sc->sc_ah = ah; |
521 | 523 | ||
524 | sc->dfs_detector = dfs_pattern_detector_init(NL80211_DFS_UNSET); | ||
525 | |||
522 | if (!pdata) { | 526 | if (!pdata) { |
523 | ah->ah_flags |= AH_USE_EEPROM; | 527 | ah->ah_flags |= AH_USE_EEPROM; |
524 | sc->sc_ah->led_pin = -1; | 528 | sc->sc_ah->led_pin = -1; |
@@ -676,6 +680,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
676 | 680 | ||
677 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 681 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
678 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; | 682 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; |
683 | hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | ||
679 | 684 | ||
680 | hw->queues = 4; | 685 | hw->queues = 4; |
681 | hw->max_rates = 4; | 686 | hw->max_rates = 4; |
@@ -779,6 +784,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, | |||
779 | goto error_world; | 784 | goto error_world; |
780 | } | 785 | } |
781 | 786 | ||
787 | setup_timer(&sc->rx_poll_timer, ath_rx_poll, (unsigned long)sc); | ||
782 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; | 788 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; |
783 | 789 | ||
784 | ath_init_leds(sc); | 790 | ath_init_leds(sc); |
@@ -821,6 +827,8 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
821 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 827 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
822 | 828 | ||
823 | ath9k_hw_deinit(sc->sc_ah); | 829 | ath9k_hw_deinit(sc->sc_ah); |
830 | if (sc->dfs_detector != NULL) | ||
831 | sc->dfs_detector->exit(sc->dfs_detector); | ||
824 | 832 | ||
825 | kfree(sc->sc_ah); | 833 | kfree(sc->sc_ah); |
826 | sc->sc_ah = NULL; | 834 | sc->sc_ah = NULL; |
@@ -866,17 +874,14 @@ static int __init ath9k_init(void) | |||
866 | /* Register rate control algorithm */ | 874 | /* Register rate control algorithm */ |
867 | error = ath_rate_control_register(); | 875 | error = ath_rate_control_register(); |
868 | if (error != 0) { | 876 | if (error != 0) { |
869 | printk(KERN_ERR | 877 | pr_err("Unable to register rate control algorithm: %d\n", |
870 | "ath9k: Unable to register rate control " | 878 | error); |
871 | "algorithm: %d\n", | ||
872 | error); | ||
873 | goto err_out; | 879 | goto err_out; |
874 | } | 880 | } |
875 | 881 | ||
876 | error = ath_pci_init(); | 882 | error = ath_pci_init(); |
877 | if (error < 0) { | 883 | if (error < 0) { |
878 | printk(KERN_ERR | 884 | pr_err("No PCI devices found, driver not installed\n"); |
879 | "ath9k: No PCI devices found, driver not installed.\n"); | ||
880 | error = -ENODEV; | 885 | error = -ENODEV; |
881 | goto err_rate_unregister; | 886 | goto err_rate_unregister; |
882 | } | 887 | } |
@@ -905,6 +910,6 @@ static void __exit ath9k_exit(void) | |||
905 | ath_ahb_exit(); | 910 | ath_ahb_exit(); |
906 | ath_pci_exit(); | 911 | ath_pci_exit(); |
907 | ath_rate_control_unregister(); | 912 | ath_rate_control_unregister(); |
908 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); | 913 | pr_info("%s: Driver unloaded\n", dev_info); |
909 | } | 914 | } |
910 | module_exit(ath9k_exit); | 915 | module_exit(ath9k_exit); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 215eb2536b1e..c8d123957188 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -118,15 +118,13 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
118 | if (--sc->ps_usecount != 0) | 118 | if (--sc->ps_usecount != 0) |
119 | goto unlock; | 119 | goto unlock; |
120 | 120 | ||
121 | if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) | 121 | if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) |
122 | goto unlock; | ||
123 | |||
124 | if (sc->ps_idle) | ||
125 | mode = ATH9K_PM_FULL_SLEEP; | 122 | mode = ATH9K_PM_FULL_SLEEP; |
126 | else if (sc->ps_enabled && | 123 | else if (sc->ps_enabled && |
127 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | | 124 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | |
128 | PS_WAIT_FOR_CAB | | 125 | PS_WAIT_FOR_CAB | |
129 | PS_WAIT_FOR_PSPOLL_DATA))) | 126 | PS_WAIT_FOR_PSPOLL_DATA | |
127 | PS_WAIT_FOR_TX_ACK))) | ||
130 | mode = ATH9K_PM_NETWORK_SLEEP; | 128 | mode = ATH9K_PM_NETWORK_SLEEP; |
131 | else | 129 | else |
132 | goto unlock; | 130 | goto unlock; |
@@ -243,6 +241,7 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) | |||
243 | 241 | ||
244 | sc->hw_busy_count = 0; | 242 | sc->hw_busy_count = 0; |
245 | del_timer_sync(&common->ani.timer); | 243 | del_timer_sync(&common->ani.timer); |
244 | del_timer_sync(&sc->rx_poll_timer); | ||
246 | 245 | ||
247 | ath9k_debug_samp_bb_mac(sc); | 246 | ath9k_debug_samp_bb_mac(sc); |
248 | ath9k_hw_disable_interrupts(ah); | 247 | ath9k_hw_disable_interrupts(ah); |
@@ -284,6 +283,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
284 | 283 | ||
285 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 284 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
286 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); | 285 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); |
286 | ath_start_rx_poll(sc, 3); | ||
287 | if (!common->disable_ani) | 287 | if (!common->disable_ani) |
288 | ath_start_ani(common); | 288 | ath_start_ani(common); |
289 | } | 289 | } |
@@ -914,10 +914,19 @@ void ath_hw_check(struct work_struct *work) | |||
914 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 914 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
915 | unsigned long flags; | 915 | unsigned long flags; |
916 | int busy; | 916 | int busy; |
917 | u8 is_alive, nbeacon = 1; | ||
917 | 918 | ||
918 | ath9k_ps_wakeup(sc); | 919 | ath9k_ps_wakeup(sc); |
919 | if (ath9k_hw_check_alive(sc->sc_ah)) | 920 | is_alive = ath9k_hw_check_alive(sc->sc_ah); |
921 | |||
922 | if (is_alive && !AR_SREV_9300(sc->sc_ah)) | ||
920 | goto out; | 923 | goto out; |
924 | else if (!is_alive && AR_SREV_9300(sc->sc_ah)) { | ||
925 | ath_dbg(common, RESET, | ||
926 | "DCU stuck is detected. Schedule chip reset\n"); | ||
927 | RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG); | ||
928 | goto sched_reset; | ||
929 | } | ||
921 | 930 | ||
922 | spin_lock_irqsave(&common->cc_lock, flags); | 931 | spin_lock_irqsave(&common->cc_lock, flags); |
923 | busy = ath_update_survey_stats(sc); | 932 | busy = ath_update_survey_stats(sc); |
@@ -928,12 +937,18 @@ void ath_hw_check(struct work_struct *work) | |||
928 | if (busy >= 99) { | 937 | if (busy >= 99) { |
929 | if (++sc->hw_busy_count >= 3) { | 938 | if (++sc->hw_busy_count >= 3) { |
930 | RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); | 939 | RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); |
931 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | 940 | goto sched_reset; |
932 | } | 941 | } |
933 | 942 | } else if (busy >= 0) { | |
934 | } else if (busy >= 0) | ||
935 | sc->hw_busy_count = 0; | 943 | sc->hw_busy_count = 0; |
944 | nbeacon = 3; | ||
945 | } | ||
946 | |||
947 | ath_start_rx_poll(sc, nbeacon); | ||
948 | goto out; | ||
936 | 949 | ||
950 | sched_reset: | ||
951 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | ||
937 | out: | 952 | out: |
938 | ath9k_ps_restore(sc); | 953 | ath9k_ps_restore(sc); |
939 | } | 954 | } |
@@ -1135,6 +1150,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1135 | 1150 | ||
1136 | if (ath_tx_start(hw, skb, &txctl) != 0) { | 1151 | if (ath_tx_start(hw, skb, &txctl) != 0) { |
1137 | ath_dbg(common, XMIT, "TX failed\n"); | 1152 | ath_dbg(common, XMIT, "TX failed\n"); |
1153 | TX_STAT_INC(txctl.txq->axq_qnum, txfailed); | ||
1138 | goto exit; | 1154 | goto exit; |
1139 | } | 1155 | } |
1140 | 1156 | ||
@@ -1153,6 +1169,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1153 | mutex_lock(&sc->mutex); | 1169 | mutex_lock(&sc->mutex); |
1154 | 1170 | ||
1155 | ath_cancel_work(sc); | 1171 | ath_cancel_work(sc); |
1172 | del_timer_sync(&sc->rx_poll_timer); | ||
1156 | 1173 | ||
1157 | if (sc->sc_flags & SC_OP_INVALID) { | 1174 | if (sc->sc_flags & SC_OP_INVALID) { |
1158 | ath_dbg(common, ANY, "Device not present\n"); | 1175 | ath_dbg(common, ANY, "Device not present\n"); |
@@ -1385,6 +1402,24 @@ static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, | |||
1385 | } | 1402 | } |
1386 | } | 1403 | } |
1387 | 1404 | ||
1405 | void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon) | ||
1406 | { | ||
1407 | if (!AR_SREV_9300(sc->sc_ah)) | ||
1408 | return; | ||
1409 | |||
1410 | if (!(sc->sc_flags & SC_OP_PRIM_STA_VIF)) | ||
1411 | return; | ||
1412 | |||
1413 | mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies | ||
1414 | (nbeacon * sc->cur_beacon_conf.beacon_interval)); | ||
1415 | } | ||
1416 | |||
1417 | void ath_rx_poll(unsigned long data) | ||
1418 | { | ||
1419 | struct ath_softc *sc = (struct ath_softc *)data; | ||
1420 | |||
1421 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | ||
1422 | } | ||
1388 | 1423 | ||
1389 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 1424 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
1390 | struct ieee80211_vif *vif) | 1425 | struct ieee80211_vif *vif) |
@@ -1906,6 +1941,8 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
1906 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; | 1941 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; |
1907 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | 1942 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; |
1908 | 1943 | ||
1944 | ath_start_rx_poll(sc, 3); | ||
1945 | |||
1909 | if (!common->disable_ani) { | 1946 | if (!common->disable_ani) { |
1910 | sc->sc_flags |= SC_OP_ANI_RUN; | 1947 | sc->sc_flags |= SC_OP_ANI_RUN; |
1911 | ath_start_ani(common); | 1948 | ath_start_ani(common); |
@@ -1945,6 +1982,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
1945 | /* Stop ANI */ | 1982 | /* Stop ANI */ |
1946 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 1983 | sc->sc_flags &= ~SC_OP_ANI_RUN; |
1947 | del_timer_sync(&common->ani.timer); | 1984 | del_timer_sync(&common->ani.timer); |
1985 | del_timer_sync(&sc->rx_poll_timer); | ||
1948 | memset(&sc->caldata, 0, sizeof(sc->caldata)); | 1986 | memset(&sc->caldata, 0, sizeof(sc->caldata)); |
1949 | } | 1987 | } |
1950 | } | 1988 | } |
@@ -1988,6 +2026,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1988 | } else { | 2026 | } else { |
1989 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 2027 | sc->sc_flags &= ~SC_OP_ANI_RUN; |
1990 | del_timer_sync(&common->ani.timer); | 2028 | del_timer_sync(&common->ani.timer); |
2029 | del_timer_sync(&sc->rx_poll_timer); | ||
1991 | } | 2030 | } |
1992 | } | 2031 | } |
1993 | 2032 | ||
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 77dc327def8d..a856b51255f4 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include <linux/nl80211.h> | 19 | #include <linux/nl80211.h> |
18 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
19 | #include <linux/pci-aspm.h> | 21 | #include <linux/pci-aspm.h> |
@@ -171,14 +173,13 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
171 | 173 | ||
172 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | 174 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
173 | if (ret) { | 175 | if (ret) { |
174 | printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); | 176 | pr_err("32-bit DMA not available\n"); |
175 | goto err_dma; | 177 | goto err_dma; |
176 | } | 178 | } |
177 | 179 | ||
178 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | 180 | ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
179 | if (ret) { | 181 | if (ret) { |
180 | printk(KERN_ERR "ath9k: 32-bit DMA consistent " | 182 | pr_err("32-bit DMA consistent DMA enable failed\n"); |
181 | "DMA enable failed\n"); | ||
182 | goto err_dma; | 183 | goto err_dma; |
183 | } | 184 | } |
184 | 185 | ||
@@ -224,7 +225,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
224 | 225 | ||
225 | mem = pci_iomap(pdev, 0, 0); | 226 | mem = pci_iomap(pdev, 0, 0); |
226 | if (!mem) { | 227 | if (!mem) { |
227 | printk(KERN_ERR "PCI memory map error\n") ; | 228 | pr_err("PCI memory map error\n") ; |
228 | ret = -EIO; | 229 | ret = -EIO; |
229 | goto err_iomap; | 230 | goto err_iomap; |
230 | } | 231 | } |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 08bb45532701..92a6c0a87f89 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1436,7 +1436,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1436 | 1436 | ||
1437 | static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | 1437 | static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, |
1438 | struct ieee80211_sta *sta, void *priv_sta, | 1438 | struct ieee80211_sta *sta, void *priv_sta, |
1439 | u32 changed, enum nl80211_channel_type oper_chan_type) | 1439 | u32 changed) |
1440 | { | 1440 | { |
1441 | struct ath_softc *sc = priv; | 1441 | struct ath_softc *sc = priv; |
1442 | struct ath_rate_priv *ath_rc_priv = priv_sta; | 1442 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
@@ -1447,12 +1447,11 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | |||
1447 | 1447 | ||
1448 | /* FIXME: Handle AP mode later when we support CWM */ | 1448 | /* FIXME: Handle AP mode later when we support CWM */ |
1449 | 1449 | ||
1450 | if (changed & IEEE80211_RC_HT_CHANGED) { | 1450 | if (changed & IEEE80211_RC_BW_CHANGED) { |
1451 | if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) | 1451 | if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) |
1452 | return; | 1452 | return; |
1453 | 1453 | ||
1454 | if (oper_chan_type == NL80211_CHAN_HT40MINUS || | 1454 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) |
1455 | oper_chan_type == NL80211_CHAN_HT40PLUS) | ||
1456 | oper_cw40 = true; | 1455 | oper_cw40 = true; |
1457 | 1456 | ||
1458 | if (oper_cw40) | 1457 | if (oper_cw40) |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 1c4583c7ff7c..301ef3e57145 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -824,15 +824,20 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
824 | if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID) | 824 | if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID) |
825 | rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; | 825 | rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; |
826 | 826 | ||
827 | if (!rx_stats->rs_datalen) | 827 | if (!rx_stats->rs_datalen) { |
828 | RX_STAT_INC(rx_len_err); | ||
828 | return false; | 829 | return false; |
830 | } | ||
831 | |||
829 | /* | 832 | /* |
830 | * rs_status follows rs_datalen so if rs_datalen is too large | 833 | * rs_status follows rs_datalen so if rs_datalen is too large |
831 | * we can take a hint that hardware corrupted it, so ignore | 834 | * we can take a hint that hardware corrupted it, so ignore |
832 | * those frames. | 835 | * those frames. |
833 | */ | 836 | */ |
834 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) | 837 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) { |
838 | RX_STAT_INC(rx_len_err); | ||
835 | return false; | 839 | return false; |
840 | } | ||
836 | 841 | ||
837 | /* Only use error bits from the last fragment */ | 842 | /* Only use error bits from the last fragment */ |
838 | if (rx_stats->rs_more) | 843 | if (rx_stats->rs_more) |
@@ -902,6 +907,7 @@ static int ath9k_process_rate(struct ath_common *common, | |||
902 | struct ieee80211_supported_band *sband; | 907 | struct ieee80211_supported_band *sband; |
903 | enum ieee80211_band band; | 908 | enum ieee80211_band band; |
904 | unsigned int i = 0; | 909 | unsigned int i = 0; |
910 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
905 | 911 | ||
906 | band = hw->conf.channel->band; | 912 | band = hw->conf.channel->band; |
907 | sband = hw->wiphy->bands[band]; | 913 | sband = hw->wiphy->bands[band]; |
@@ -936,7 +942,7 @@ static int ath9k_process_rate(struct ath_common *common, | |||
936 | ath_dbg(common, ANY, | 942 | ath_dbg(common, ANY, |
937 | "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", | 943 | "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", |
938 | rx_stats->rs_rate); | 944 | rx_stats->rs_rate); |
939 | 945 | RX_STAT_INC(rx_rate_err); | |
940 | return -EINVAL; | 946 | return -EINVAL; |
941 | } | 947 | } |
942 | 948 | ||
@@ -1823,10 +1829,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1823 | 1829 | ||
1824 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); | 1830 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); |
1825 | rxs = IEEE80211_SKB_RXCB(hdr_skb); | 1831 | rxs = IEEE80211_SKB_RXCB(hdr_skb); |
1826 | if (ieee80211_is_beacon(hdr->frame_control) && | 1832 | if (ieee80211_is_beacon(hdr->frame_control)) { |
1827 | !is_zero_ether_addr(common->curbssid) && | 1833 | RX_STAT_INC(rx_beacons); |
1828 | !compare_ether_addr(hdr->addr3, common->curbssid)) | 1834 | if (!is_zero_ether_addr(common->curbssid) && |
1829 | rs.is_mybeacon = true; | 1835 | !compare_ether_addr(hdr->addr3, common->curbssid)) |
1836 | rs.is_mybeacon = true; | ||
1837 | else | ||
1838 | rs.is_mybeacon = false; | ||
1839 | } | ||
1830 | else | 1840 | else |
1831 | rs.is_mybeacon = false; | 1841 | rs.is_mybeacon = false; |
1832 | 1842 | ||
@@ -1836,8 +1846,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1836 | * If we're asked to flush receive queue, directly | 1846 | * If we're asked to flush receive queue, directly |
1837 | * chain it back at the queue without processing it. | 1847 | * chain it back at the queue without processing it. |
1838 | */ | 1848 | */ |
1839 | if (sc->sc_flags & SC_OP_RXFLUSH) | 1849 | if (sc->sc_flags & SC_OP_RXFLUSH) { |
1850 | RX_STAT_INC(rx_drop_rxflush); | ||
1840 | goto requeue_drop_frag; | 1851 | goto requeue_drop_frag; |
1852 | } | ||
1841 | 1853 | ||
1842 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); | 1854 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); |
1843 | 1855 | ||
@@ -1855,6 +1867,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1855 | if (retval) | 1867 | if (retval) |
1856 | goto requeue_drop_frag; | 1868 | goto requeue_drop_frag; |
1857 | 1869 | ||
1870 | if (rs.is_mybeacon) { | ||
1871 | sc->hw_busy_count = 0; | ||
1872 | ath_start_rx_poll(sc, 3); | ||
1873 | } | ||
1858 | /* Ensure we always have an skb to requeue once we are done | 1874 | /* Ensure we always have an skb to requeue once we are done |
1859 | * processing the current buffer's skb */ | 1875 | * processing the current buffer's skb */ |
1860 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); | 1876 | requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC); |
@@ -1863,8 +1879,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1863 | * tell hardware it can give us a new frame using the old | 1879 | * tell hardware it can give us a new frame using the old |
1864 | * skb and put it at the tail of the sc->rx.rxbuf list for | 1880 | * skb and put it at the tail of the sc->rx.rxbuf list for |
1865 | * processing. */ | 1881 | * processing. */ |
1866 | if (!requeue_skb) | 1882 | if (!requeue_skb) { |
1883 | RX_STAT_INC(rx_oom_err); | ||
1867 | goto requeue_drop_frag; | 1884 | goto requeue_drop_frag; |
1885 | } | ||
1868 | 1886 | ||
1869 | /* Unmap the frame */ | 1887 | /* Unmap the frame */ |
1870 | dma_unmap_single(sc->dev, bf->bf_buf_addr, | 1888 | dma_unmap_single(sc->dev, bf->bf_buf_addr, |
@@ -1895,6 +1913,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1895 | } | 1913 | } |
1896 | 1914 | ||
1897 | if (rs.rs_more) { | 1915 | if (rs.rs_more) { |
1916 | RX_STAT_INC(rx_frags); | ||
1898 | /* | 1917 | /* |
1899 | * rs_more indicates chained descriptors which can be | 1918 | * rs_more indicates chained descriptors which can be |
1900 | * used to link buffers together for a sort of | 1919 | * used to link buffers together for a sort of |
@@ -1904,6 +1923,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1904 | /* too many fragments - cannot handle frame */ | 1923 | /* too many fragments - cannot handle frame */ |
1905 | dev_kfree_skb_any(sc->rx.frag); | 1924 | dev_kfree_skb_any(sc->rx.frag); |
1906 | dev_kfree_skb_any(skb); | 1925 | dev_kfree_skb_any(skb); |
1926 | RX_STAT_INC(rx_too_many_frags_err); | ||
1907 | skb = NULL; | 1927 | skb = NULL; |
1908 | } | 1928 | } |
1909 | sc->rx.frag = skb; | 1929 | sc->rx.frag = skb; |
@@ -1915,6 +1935,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1915 | 1935 | ||
1916 | if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) { | 1936 | if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) { |
1917 | dev_kfree_skb(skb); | 1937 | dev_kfree_skb(skb); |
1938 | RX_STAT_INC(rx_oom_err); | ||
1918 | goto requeue_drop_frag; | 1939 | goto requeue_drop_frag; |
1919 | } | 1940 | } |
1920 | 1941 | ||
diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h index 885c42778b8b..65919c902f55 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.h +++ b/drivers/net/wireless/ath/carl9170/cmd.h | |||
@@ -114,7 +114,7 @@ __regwrite_out : \ | |||
114 | 114 | ||
115 | #define carl9170_regwrite_result() \ | 115 | #define carl9170_regwrite_result() \ |
116 | __err; \ | 116 | __err; \ |
117 | } while (0); | 117 | } while (0) |
118 | 118 | ||
119 | 119 | ||
120 | #define carl9170_async_regwrite_get_buf() \ | 120 | #define carl9170_async_regwrite_get_buf() \ |
@@ -126,7 +126,7 @@ do { \ | |||
126 | __err = -ENOMEM; \ | 126 | __err = -ENOMEM; \ |
127 | goto __async_regwrite_out; \ | 127 | goto __async_regwrite_out; \ |
128 | } \ | 128 | } \ |
129 | } while (0); | 129 | } while (0) |
130 | 130 | ||
131 | #define carl9170_async_regwrite_begin(carl) \ | 131 | #define carl9170_async_regwrite_begin(carl) \ |
132 | do { \ | 132 | do { \ |
@@ -169,6 +169,6 @@ __async_regwrite_out: \ | |||
169 | 169 | ||
170 | #define carl9170_async_regwrite_result() \ | 170 | #define carl9170_async_regwrite_result() \ |
171 | __err; \ | 171 | __err; \ |
172 | } while (0); | 172 | } while (0) |
173 | 173 | ||
174 | #endif /* __CMD_H */ | 174 | #endif /* __CMD_H */ |
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index cffde8d9a521..5c73c03872f3 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c | |||
@@ -355,6 +355,8 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) | |||
355 | 355 | ||
356 | ar->hw->wiphy->interface_modes |= if_comb_types; | 356 | ar->hw->wiphy->interface_modes |= if_comb_types; |
357 | 357 | ||
358 | ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | ||
359 | |||
358 | #undef SUPPORTED | 360 | #undef SUPPORTED |
359 | return carl9170_fw_tx_sequence(ar); | 361 | return carl9170_fw_tx_sequence(ar); |
360 | } | 362 | } |
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c index ea2c737138d3..8e99540cd90e 100644 --- a/drivers/net/wireless/ath/main.c +++ b/drivers/net/wireless/ath/main.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
19 | 21 | ||
@@ -49,7 +51,7 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, | |||
49 | if (off != 0) | 51 | if (off != 0) |
50 | skb_reserve(skb, common->cachelsz - off); | 52 | skb_reserve(skb, common->cachelsz - off); |
51 | } else { | 53 | } else { |
52 | printk(KERN_ERR "skbuff alloc of size %u failed\n", len); | 54 | pr_err("skbuff alloc of size %u failed\n", len); |
53 | return NULL; | 55 | return NULL; |
54 | } | 56 | } |
55 | 57 | ||
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 10dea37431b3..d81698015bf7 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -14,6 +14,8 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
18 | |||
17 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
18 | #include <linux/export.h> | 20 | #include <linux/export.h> |
19 | #include <net/cfg80211.h> | 21 | #include <net/cfg80211.h> |
@@ -562,7 +564,7 @@ static int __ath_regd_init(struct ath_regulatory *reg) | |||
562 | printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd); | 564 | printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd); |
563 | 565 | ||
564 | if (!ath_regd_is_eeprom_valid(reg)) { | 566 | if (!ath_regd_is_eeprom_valid(reg)) { |
565 | printk(KERN_ERR "ath: Invalid EEPROM contents\n"); | 567 | pr_err("Invalid EEPROM contents\n"); |
566 | return -EINVAL; | 568 | return -EINVAL; |
567 | } | 569 | } |
568 | 570 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c79e6638c88d..05ea95ba6de0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -4010,6 +4010,20 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
4010 | if (modparam_nohwcrypt) | 4010 | if (modparam_nohwcrypt) |
4011 | return -ENOSPC; /* User disabled HW-crypto */ | 4011 | return -ENOSPC; /* User disabled HW-crypto */ |
4012 | 4012 | ||
4013 | if ((vif->type == NL80211_IFTYPE_ADHOC || | ||
4014 | vif->type == NL80211_IFTYPE_MESH_POINT) && | ||
4015 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || | ||
4016 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && | ||
4017 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
4018 | /* | ||
4019 | * For now, disable hw crypto for the RSN IBSS group keys. This | ||
4020 | * could be optimized in the future, but until that gets | ||
4021 | * implemented, use of software crypto for group addressed | ||
4022 | * frames is a acceptable to allow RSN IBSS to be used. | ||
4023 | */ | ||
4024 | return -EOPNOTSUPP; | ||
4025 | } | ||
4026 | |||
4013 | mutex_lock(&wl->mutex); | 4027 | mutex_lock(&wl->mutex); |
4014 | 4028 | ||
4015 | dev = wl->current_dev; | 4029 | dev = wl->current_dev; |
@@ -5275,6 +5289,8 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) | |||
5275 | BIT(NL80211_IFTYPE_WDS) | | 5289 | BIT(NL80211_IFTYPE_WDS) | |
5276 | BIT(NL80211_IFTYPE_ADHOC); | 5290 | BIT(NL80211_IFTYPE_ADHOC); |
5277 | 5291 | ||
5292 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
5293 | |||
5278 | hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1; | 5294 | hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1; |
5279 | wl->mac80211_initially_registered_queues = hw->queues; | 5295 | wl->mac80211_initially_registered_queues = hw->queues; |
5280 | hw->max_rates = 2; | 5296 | hw->max_rates = 2; |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 2c5367884b3f..cba413536270 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -378,7 +378,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
378 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | 378 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) |
379 | phy_ctl |= B43_TXH_PHY_SHORTPRMBL; | 379 | phy_ctl |= B43_TXH_PHY_SHORTPRMBL; |
380 | 380 | ||
381 | switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { | 381 | switch (b43_ieee80211_antenna_sanitize(dev, 0)) { |
382 | case 0: /* Default */ | 382 | case 0: /* Default */ |
383 | phy_ctl |= B43_TXH_PHY_ANT01AUTO; | 383 | phy_ctl |= B43_TXH_PHY_ANT01AUTO; |
384 | break; | 384 | break; |
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 5188fab0b377..e6c573af494d 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c | |||
@@ -277,19 +277,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
277 | phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM; | 277 | phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM; |
278 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | 278 | if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) |
279 | phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; | 279 | phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; |
280 | switch (info->antenna_sel_tx) { | 280 | phy_ctl |= B43legacy_TX4_PHY_ANTLAST; |
281 | case 0: | ||
282 | phy_ctl |= B43legacy_TX4_PHY_ANTLAST; | ||
283 | break; | ||
284 | case 1: | ||
285 | phy_ctl |= B43legacy_TX4_PHY_ANT0; | ||
286 | break; | ||
287 | case 2: | ||
288 | phy_ctl |= B43legacy_TX4_PHY_ANT1; | ||
289 | break; | ||
290 | default: | ||
291 | B43legacy_BUG_ON(1); | ||
292 | } | ||
293 | 281 | ||
294 | /* MAC control */ | 282 | /* MAC control */ |
295 | rates = info->control.rates; | 283 | rates = info->control.rates; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/d11.h b/drivers/net/wireless/brcm80211/brcmsmac/d11.h index 1948cb2771e9..3f659e09f1cc 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/d11.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/d11.h | |||
@@ -733,7 +733,7 @@ struct cck_phy_hdr { | |||
733 | do { \ | 733 | do { \ |
734 | plcp[1] = len & 0xff; \ | 734 | plcp[1] = len & 0xff; \ |
735 | plcp[2] = ((len >> 8) & 0xff); \ | 735 | plcp[2] = ((len >> 8) & 0xff); \ |
736 | } while (0); | 736 | } while (0) |
737 | 737 | ||
738 | #define BRCMS_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU) | 738 | #define BRCMS_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU) |
739 | #define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU) | 739 | #define BRCMS_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU) |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h index e5b1c77ae0eb..973125242490 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.h +++ b/drivers/net/wireless/ipw2x00/ipw2100.h | |||
@@ -135,15 +135,6 @@ enum { | |||
135 | IPW_HW_STATE_ENABLED = 0 | 135 | IPW_HW_STATE_ENABLED = 0 |
136 | }; | 136 | }; |
137 | 137 | ||
138 | struct ssid_context { | ||
139 | char ssid[IW_ESSID_MAX_SIZE + 1]; | ||
140 | int ssid_len; | ||
141 | unsigned char bssid[ETH_ALEN]; | ||
142 | int port_type; | ||
143 | int channel; | ||
144 | |||
145 | }; | ||
146 | |||
147 | extern const char *port_type_str[]; | 138 | extern const char *port_type_str[]; |
148 | extern const char *band_str[]; | 139 | extern const char *band_str[]; |
149 | 140 | ||
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index 8874588fb929..0b22fb421735 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h | |||
@@ -584,61 +584,6 @@ struct libipw_tim_parameters { | |||
584 | 584 | ||
585 | /*******************************************************/ | 585 | /*******************************************************/ |
586 | 586 | ||
587 | enum { /* libipw_basic_report.map */ | ||
588 | LIBIPW_BASIC_MAP_BSS = (1 << 0), | ||
589 | LIBIPW_BASIC_MAP_OFDM = (1 << 1), | ||
590 | LIBIPW_BASIC_MAP_UNIDENTIFIED = (1 << 2), | ||
591 | LIBIPW_BASIC_MAP_RADAR = (1 << 3), | ||
592 | LIBIPW_BASIC_MAP_UNMEASURED = (1 << 4), | ||
593 | /* Bits 5-7 are reserved */ | ||
594 | |||
595 | }; | ||
596 | struct libipw_basic_report { | ||
597 | u8 channel; | ||
598 | __le64 start_time; | ||
599 | __le16 duration; | ||
600 | u8 map; | ||
601 | } __packed; | ||
602 | |||
603 | enum { /* libipw_measurement_request.mode */ | ||
604 | /* Bit 0 is reserved */ | ||
605 | LIBIPW_MEASUREMENT_ENABLE = (1 << 1), | ||
606 | LIBIPW_MEASUREMENT_REQUEST = (1 << 2), | ||
607 | LIBIPW_MEASUREMENT_REPORT = (1 << 3), | ||
608 | /* Bits 4-7 are reserved */ | ||
609 | }; | ||
610 | |||
611 | enum { | ||
612 | LIBIPW_REPORT_BASIC = 0, /* required */ | ||
613 | LIBIPW_REPORT_CCA = 1, /* optional */ | ||
614 | LIBIPW_REPORT_RPI = 2, /* optional */ | ||
615 | /* 3-255 reserved */ | ||
616 | }; | ||
617 | |||
618 | struct libipw_measurement_params { | ||
619 | u8 channel; | ||
620 | __le64 start_time; | ||
621 | __le16 duration; | ||
622 | } __packed; | ||
623 | |||
624 | struct libipw_measurement_request { | ||
625 | struct libipw_info_element ie; | ||
626 | u8 token; | ||
627 | u8 mode; | ||
628 | u8 type; | ||
629 | struct libipw_measurement_params params[0]; | ||
630 | } __packed; | ||
631 | |||
632 | struct libipw_measurement_report { | ||
633 | struct libipw_info_element ie; | ||
634 | u8 token; | ||
635 | u8 mode; | ||
636 | u8 type; | ||
637 | union { | ||
638 | struct libipw_basic_report basic[0]; | ||
639 | } u; | ||
640 | } __packed; | ||
641 | |||
642 | struct libipw_tpc_report { | 587 | struct libipw_tpc_report { |
643 | u8 transmit_power; | 588 | u8 transmit_power; |
644 | u8 link_margin; | 589 | u8 link_margin; |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index c46275a92565..f2baf94f069c 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -2850,9 +2850,9 @@ void | |||
2850 | il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags, | 2850 | il4965_hwrate_to_tx_control(struct il_priv *il, u32 rate_n_flags, |
2851 | struct ieee80211_tx_info *info) | 2851 | struct ieee80211_tx_info *info) |
2852 | { | 2852 | { |
2853 | struct ieee80211_tx_rate *r = &info->control.rates[0]; | 2853 | struct ieee80211_tx_rate *r = &info->status.rates[0]; |
2854 | 2854 | ||
2855 | info->antenna_sel_tx = | 2855 | info->status.antenna = |
2856 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | 2856 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); |
2857 | if (rate_n_flags & RATE_MCS_HT_MSK) | 2857 | if (rate_n_flags & RATE_MCS_HT_MSK) |
2858 | r->flags |= IEEE80211_TX_RC_MCS; | 2858 | r->flags |= IEEE80211_TX_RC_MCS; |
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c index 11ab1247fae1..f3b8e91aa3dc 100644 --- a/drivers/net/wireless/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/iwlegacy/4965-rs.c | |||
@@ -873,7 +873,7 @@ il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband, | |||
873 | tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI) || | 873 | tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI) || |
874 | tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH) || | 874 | tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH) || |
875 | tbl_type.is_dup != !!(mac_flags & IEEE80211_TX_RC_DUP_DATA) || | 875 | tbl_type.is_dup != !!(mac_flags & IEEE80211_TX_RC_DUP_DATA) || |
876 | tbl_type.ant_type != info->antenna_sel_tx || | 876 | tbl_type.ant_type != info->status.antenna || |
877 | !!(tx_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS) | 877 | !!(tx_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS) |
878 | || !!(tx_rate & RATE_MCS_GF_MSK) != | 878 | || !!(tx_rate & RATE_MCS_GF_MSK) != |
879 | !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD) || rs_idx != mac_idx) { | 879 | !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD) || rs_idx != mac_idx) { |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 2fe62730dddd..565611eef0d4 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -136,3 +136,11 @@ config IWLWIFI_EXPERIMENTAL_MFP | |||
136 | even if the microcode doesn't advertise it. | 136 | even if the microcode doesn't advertise it. |
137 | 137 | ||
138 | Say Y only if you want to experiment with MFP. | 138 | Say Y only if you want to experiment with MFP. |
139 | |||
140 | config IWLWIFI_UCODE16 | ||
141 | bool "support uCode 16.0" | ||
142 | depends on IWLWIFI | ||
143 | help | ||
144 | This option enables support for uCode version 16.0. | ||
145 | |||
146 | Say Y if you want to use 16.0 microcode. | ||
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 85d163ed3db1..c7c4a995dfe5 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -17,6 +17,8 @@ iwlwifi-objs += iwl-drv.o | |||
17 | iwlwifi-objs += iwl-notif-wait.o | 17 | iwlwifi-objs += iwl-notif-wait.o |
18 | iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o | 18 | iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o |
19 | 19 | ||
20 | |||
21 | iwlwifi-$(CONFIG_IWLWIFI_UCODE16) += iwl-phy-db.o | ||
20 | iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 22 | iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
21 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 23 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
22 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-testmode.o | 24 | iwlwifi-$(CONFIG_IWLWIFI_DEVICE_TESTMODE) += iwl-testmode.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 5b0d888f746b..95c59e39b803 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -157,7 +157,6 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
157 | 157 | ||
158 | static const struct iwl_base_params iwl1000_base_params = { | 158 | static const struct iwl_base_params iwl1000_base_params = { |
159 | .num_of_queues = IWLAGN_NUM_QUEUES, | 159 | .num_of_queues = IWLAGN_NUM_QUEUES, |
160 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
161 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 160 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
162 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 161 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
163 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 162 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 5635b9e2c69e..e1329a13f0fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -86,9 +86,8 @@ static void iwl2000_nic_config(struct iwl_priv *priv) | |||
86 | { | 86 | { |
87 | iwl_rf_config(priv); | 87 | iwl_rf_config(priv); |
88 | 88 | ||
89 | if (cfg(priv)->iq_invert) | 89 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, |
90 | iwl_set_bit(trans(priv), CSR_GP_DRIVER_REG, | 90 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); |
91 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); | ||
92 | } | 91 | } |
93 | 92 | ||
94 | static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { | 93 | static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { |
@@ -172,7 +171,6 @@ static struct iwl_lib_ops iwl2030_lib = { | |||
172 | static const struct iwl_base_params iwl2000_base_params = { | 171 | static const struct iwl_base_params iwl2000_base_params = { |
173 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 172 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
174 | .num_of_queues = IWLAGN_NUM_QUEUES, | 173 | .num_of_queues = IWLAGN_NUM_QUEUES, |
175 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
176 | .pll_cfg_val = 0, | 174 | .pll_cfg_val = 0, |
177 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, | 175 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, |
178 | .shadow_ram_support = true, | 176 | .shadow_ram_support = true, |
@@ -191,7 +189,6 @@ static const struct iwl_base_params iwl2000_base_params = { | |||
191 | static const struct iwl_base_params iwl2030_base_params = { | 189 | static const struct iwl_base_params iwl2030_base_params = { |
192 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 190 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
193 | .num_of_queues = IWLAGN_NUM_QUEUES, | 191 | .num_of_queues = IWLAGN_NUM_QUEUES, |
194 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
195 | .pll_cfg_val = 0, | 192 | .pll_cfg_val = 0, |
196 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, | 193 | .max_ll_items = OTP_MAX_LL_ITEMS_2x00, |
197 | .shadow_ram_support = true, | 194 | .shadow_ram_support = true, |
@@ -234,8 +231,7 @@ static const struct iwl_bt_params iwl2030_bt_params = { | |||
234 | .base_params = &iwl2000_base_params, \ | 231 | .base_params = &iwl2000_base_params, \ |
235 | .need_temp_offset_calib = true, \ | 232 | .need_temp_offset_calib = true, \ |
236 | .temp_offset_v2 = true, \ | 233 | .temp_offset_v2 = true, \ |
237 | .led_mode = IWL_LED_RF_STATE, \ | 234 | .led_mode = IWL_LED_RF_STATE |
238 | .iq_invert = true \ | ||
239 | 235 | ||
240 | const struct iwl_cfg iwl2000_2bgn_cfg = { | 236 | const struct iwl_cfg iwl2000_2bgn_cfg = { |
241 | .name = "Intel(R) Centrino(R) Wireless-N 2200 BGN", | 237 | .name = "Intel(R) Centrino(R) Wireless-N 2200 BGN", |
@@ -264,8 +260,7 @@ const struct iwl_cfg iwl2000_2bgn_d_cfg = { | |||
264 | .need_temp_offset_calib = true, \ | 260 | .need_temp_offset_calib = true, \ |
265 | .temp_offset_v2 = true, \ | 261 | .temp_offset_v2 = true, \ |
266 | .led_mode = IWL_LED_RF_STATE, \ | 262 | .led_mode = IWL_LED_RF_STATE, \ |
267 | .adv_pm = true, \ | 263 | .adv_pm = true |
268 | .iq_invert = true \ | ||
269 | 264 | ||
270 | const struct iwl_cfg iwl2030_2bgn_cfg = { | 265 | const struct iwl_cfg iwl2030_2bgn_cfg = { |
271 | .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN", | 266 | .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN", |
@@ -288,8 +283,7 @@ const struct iwl_cfg iwl2030_2bgn_cfg = { | |||
288 | .temp_offset_v2 = true, \ | 283 | .temp_offset_v2 = true, \ |
289 | .led_mode = IWL_LED_RF_STATE, \ | 284 | .led_mode = IWL_LED_RF_STATE, \ |
290 | .adv_pm = true, \ | 285 | .adv_pm = true, \ |
291 | .rx_with_siso_diversity = true, \ | 286 | .rx_with_siso_diversity = true |
292 | .iq_invert = true \ | ||
293 | 287 | ||
294 | const struct iwl_cfg iwl105_bgn_cfg = { | 288 | const struct iwl_cfg iwl105_bgn_cfg = { |
295 | .name = "Intel(R) Centrino(R) Wireless-N 105 BGN", | 289 | .name = "Intel(R) Centrino(R) Wireless-N 105 BGN", |
@@ -319,8 +313,7 @@ const struct iwl_cfg iwl105_bgn_d_cfg = { | |||
319 | .temp_offset_v2 = true, \ | 313 | .temp_offset_v2 = true, \ |
320 | .led_mode = IWL_LED_RF_STATE, \ | 314 | .led_mode = IWL_LED_RF_STATE, \ |
321 | .adv_pm = true, \ | 315 | .adv_pm = true, \ |
322 | .rx_with_siso_diversity = true, \ | 316 | .rx_with_siso_diversity = true |
323 | .iq_invert = true \ | ||
324 | 317 | ||
325 | const struct iwl_cfg iwl135_bgn_cfg = { | 318 | const struct iwl_cfg iwl135_bgn_cfg = { |
326 | .name = "Intel(R) Centrino(R) Wireless-N 135 BGN", | 319 | .name = "Intel(R) Centrino(R) Wireless-N 135 BGN", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index a805e97b89af..34bc8dd0064b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -308,7 +308,6 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
308 | static const struct iwl_base_params iwl5000_base_params = { | 308 | static const struct iwl_base_params iwl5000_base_params = { |
309 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, | 309 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
310 | .num_of_queues = IWLAGN_NUM_QUEUES, | 310 | .num_of_queues = IWLAGN_NUM_QUEUES, |
311 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
312 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 311 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
313 | .led_compensation = 51, | 312 | .led_compensation = 51, |
314 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 313 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 64060cd738b5..7075570a0f2c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -269,7 +269,6 @@ static struct iwl_lib_ops iwl6030_lib = { | |||
269 | static const struct iwl_base_params iwl6000_base_params = { | 269 | static const struct iwl_base_params iwl6000_base_params = { |
270 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 270 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
271 | .num_of_queues = IWLAGN_NUM_QUEUES, | 271 | .num_of_queues = IWLAGN_NUM_QUEUES, |
272 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
273 | .pll_cfg_val = 0, | 272 | .pll_cfg_val = 0, |
274 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 273 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
275 | .shadow_ram_support = true, | 274 | .shadow_ram_support = true, |
@@ -286,7 +285,6 @@ static const struct iwl_base_params iwl6000_base_params = { | |||
286 | static const struct iwl_base_params iwl6050_base_params = { | 285 | static const struct iwl_base_params iwl6050_base_params = { |
287 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 286 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
288 | .num_of_queues = IWLAGN_NUM_QUEUES, | 287 | .num_of_queues = IWLAGN_NUM_QUEUES, |
289 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
290 | .pll_cfg_val = 0, | 288 | .pll_cfg_val = 0, |
291 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, | 289 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, |
292 | .shadow_ram_support = true, | 290 | .shadow_ram_support = true, |
@@ -303,7 +301,6 @@ static const struct iwl_base_params iwl6050_base_params = { | |||
303 | static const struct iwl_base_params iwl6000_g2_base_params = { | 301 | static const struct iwl_base_params iwl6000_g2_base_params = { |
304 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 302 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
305 | .num_of_queues = IWLAGN_NUM_QUEUES, | 303 | .num_of_queues = IWLAGN_NUM_QUEUES, |
306 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
307 | .pll_cfg_val = 0, | 304 | .pll_cfg_val = 0, |
308 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 305 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
309 | .shadow_ram_support = true, | 306 | .shadow_ram_support = true, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index d0ec0abd3c89..c797ab19d933 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h | |||
@@ -103,9 +103,6 @@ | |||
103 | /* EEPROM */ | 103 | /* EEPROM */ |
104 | #define IWLAGN_EEPROM_IMG_SIZE 2048 | 104 | #define IWLAGN_EEPROM_IMG_SIZE 2048 |
105 | 105 | ||
106 | #define IWLAGN_CMD_FIFO_NUM 7 | ||
107 | #define IWLAGN_NUM_QUEUES 20 | 106 | #define IWLAGN_NUM_QUEUES 20 |
108 | #define IWLAGN_NUM_AMPDU_QUEUES 9 | ||
109 | #define IWLAGN_FIRST_AMPDU_QUEUE 11 | ||
110 | 107 | ||
111 | #endif /* __iwl_agn_hw_h__ */ | 108 | #endif /* __iwl_agn_hw_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 56f41c9409d1..4da4ab23cce7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -228,7 +228,7 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | |||
228 | IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | | 228 | IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | |
229 | IWL_SCD_MGMT_MSK; | 229 | IWL_SCD_MGMT_MSK; |
230 | if ((flush_control & BIT(IWL_RXON_CTX_PAN)) && | 230 | if ((flush_control & BIT(IWL_RXON_CTX_PAN)) && |
231 | (priv->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS))) | 231 | (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS))) |
232 | flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK | | 232 | flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK | |
233 | IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK | | 233 | IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK | |
234 | IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | | 234 | IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK | |
@@ -615,7 +615,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv, | |||
615 | struct iwl_bt_uart_msg *uart_msg) | 615 | struct iwl_bt_uart_msg *uart_msg) |
616 | { | 616 | { |
617 | IWL_DEBUG_COEX(priv, "Message Type = 0x%X, SSN = 0x%X, " | 617 | IWL_DEBUG_COEX(priv, "Message Type = 0x%X, SSN = 0x%X, " |
618 | "Update Req = 0x%X", | 618 | "Update Req = 0x%X\n", |
619 | (BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >> | 619 | (BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >> |
620 | BT_UART_MSG_FRAME1MSGTYPE_POS, | 620 | BT_UART_MSG_FRAME1MSGTYPE_POS, |
621 | (BT_UART_MSG_FRAME1SSN_MSK & uart_msg->frame1) >> | 621 | (BT_UART_MSG_FRAME1SSN_MSK & uart_msg->frame1) >> |
@@ -624,7 +624,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv, | |||
624 | BT_UART_MSG_FRAME1UPDATEREQ_POS); | 624 | BT_UART_MSG_FRAME1UPDATEREQ_POS); |
625 | 625 | ||
626 | IWL_DEBUG_COEX(priv, "Open connections = 0x%X, Traffic load = 0x%X, " | 626 | IWL_DEBUG_COEX(priv, "Open connections = 0x%X, Traffic load = 0x%X, " |
627 | "Chl_SeqN = 0x%X, In band = 0x%X", | 627 | "Chl_SeqN = 0x%X, In band = 0x%X\n", |
628 | (BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >> | 628 | (BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >> |
629 | BT_UART_MSG_FRAME2OPENCONNECTIONS_POS, | 629 | BT_UART_MSG_FRAME2OPENCONNECTIONS_POS, |
630 | (BT_UART_MSG_FRAME2TRAFFICLOAD_MSK & uart_msg->frame2) >> | 630 | (BT_UART_MSG_FRAME2TRAFFICLOAD_MSK & uart_msg->frame2) >> |
@@ -635,7 +635,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv, | |||
635 | BT_UART_MSG_FRAME2INBAND_POS); | 635 | BT_UART_MSG_FRAME2INBAND_POS); |
636 | 636 | ||
637 | IWL_DEBUG_COEX(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, " | 637 | IWL_DEBUG_COEX(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, " |
638 | "ACL = 0x%X, Master = 0x%X, OBEX = 0x%X", | 638 | "ACL = 0x%X, Master = 0x%X, OBEX = 0x%X\n", |
639 | (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >> | 639 | (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >> |
640 | BT_UART_MSG_FRAME3SCOESCO_POS, | 640 | BT_UART_MSG_FRAME3SCOESCO_POS, |
641 | (BT_UART_MSG_FRAME3SNIFF_MSK & uart_msg->frame3) >> | 641 | (BT_UART_MSG_FRAME3SNIFF_MSK & uart_msg->frame3) >> |
@@ -649,12 +649,12 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv, | |||
649 | (BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >> | 649 | (BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >> |
650 | BT_UART_MSG_FRAME3OBEX_POS); | 650 | BT_UART_MSG_FRAME3OBEX_POS); |
651 | 651 | ||
652 | IWL_DEBUG_COEX(priv, "Idle duration = 0x%X", | 652 | IWL_DEBUG_COEX(priv, "Idle duration = 0x%X\n", |
653 | (BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >> | 653 | (BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >> |
654 | BT_UART_MSG_FRAME4IDLEDURATION_POS); | 654 | BT_UART_MSG_FRAME4IDLEDURATION_POS); |
655 | 655 | ||
656 | IWL_DEBUG_COEX(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, " | 656 | IWL_DEBUG_COEX(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, " |
657 | "eSCO Retransmissions = 0x%X", | 657 | "eSCO Retransmissions = 0x%X\n", |
658 | (BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >> | 658 | (BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >> |
659 | BT_UART_MSG_FRAME5TXACTIVITY_POS, | 659 | BT_UART_MSG_FRAME5TXACTIVITY_POS, |
660 | (BT_UART_MSG_FRAME5RXACTIVITY_MSK & uart_msg->frame5) >> | 660 | (BT_UART_MSG_FRAME5RXACTIVITY_MSK & uart_msg->frame5) >> |
@@ -662,14 +662,14 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv, | |||
662 | (BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >> | 662 | (BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >> |
663 | BT_UART_MSG_FRAME5ESCORETRANSMIT_POS); | 663 | BT_UART_MSG_FRAME5ESCORETRANSMIT_POS); |
664 | 664 | ||
665 | IWL_DEBUG_COEX(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X", | 665 | IWL_DEBUG_COEX(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X\n", |
666 | (BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >> | 666 | (BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >> |
667 | BT_UART_MSG_FRAME6SNIFFINTERVAL_POS, | 667 | BT_UART_MSG_FRAME6SNIFFINTERVAL_POS, |
668 | (BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >> | 668 | (BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >> |
669 | BT_UART_MSG_FRAME6DISCOVERABLE_POS); | 669 | BT_UART_MSG_FRAME6DISCOVERABLE_POS); |
670 | 670 | ||
671 | IWL_DEBUG_COEX(priv, "Sniff Activity = 0x%X, Page = " | 671 | IWL_DEBUG_COEX(priv, "Sniff Activity = 0x%X, Page = " |
672 | "0x%X, Inquiry = 0x%X, Connectable = 0x%X", | 672 | "0x%X, Inquiry = 0x%X, Connectable = 0x%X\n", |
673 | (BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >> | 673 | (BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >> |
674 | BT_UART_MSG_FRAME7SNIFFACTIVITY_POS, | 674 | BT_UART_MSG_FRAME7SNIFFACTIVITY_POS, |
675 | (BT_UART_MSG_FRAME7PAGE_MSK & uart_msg->frame7) >> | 675 | (BT_UART_MSG_FRAME7PAGE_MSK & uart_msg->frame7) >> |
@@ -856,7 +856,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) | |||
856 | void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | 856 | void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) |
857 | { | 857 | { |
858 | bool is_single = is_single_rx_stream(priv); | 858 | bool is_single = is_single_rx_stream(priv); |
859 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->shrd->status); | 859 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); |
860 | u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; | 860 | u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; |
861 | u32 active_chains; | 861 | u32 active_chains; |
862 | u16 rx_chain; | 862 | u16 rx_chain; |
@@ -1298,6 +1298,12 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1298 | return -EIO; | 1298 | return -EIO; |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | if (test_bit(STATUS_FW_ERROR, &priv->status)) { | ||
1302 | IWL_ERR(priv, "Command %s failed: FW Error\n", | ||
1303 | get_cmd_string(cmd->id)); | ||
1304 | return -EIO; | ||
1305 | } | ||
1306 | |||
1301 | /* | 1307 | /* |
1302 | * Synchronous commands from this op-mode must hold | 1308 | * Synchronous commands from this op-mode must hold |
1303 | * the mutex, this ensures we don't try to send two | 1309 | * the mutex, this ensures we don't try to send two |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 7e590b349dd7..b936ae7e00a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -969,7 +969,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
969 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || | 969 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || |
970 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || | 970 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || |
971 | (tbl_type.is_dup != !!(mac_flags & IEEE80211_TX_RC_DUP_DATA)) || | 971 | (tbl_type.is_dup != !!(mac_flags & IEEE80211_TX_RC_DUP_DATA)) || |
972 | (tbl_type.ant_type != info->antenna_sel_tx) || | 972 | (tbl_type.ant_type != info->status.antenna) || |
973 | (!!(tx_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS)) || | 973 | (!!(tx_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS)) || |
974 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || | 974 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || |
975 | (rs_index != mac_index)) { | 975 | (rs_index != mac_index)) { |
@@ -2166,7 +2166,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) | |||
2166 | (lq_sta->total_success > lq_sta->max_success_limit) || | 2166 | (lq_sta->total_success > lq_sta->max_success_limit) || |
2167 | ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer) | 2167 | ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer) |
2168 | && (flush_interval_passed))) { | 2168 | && (flush_interval_passed))) { |
2169 | IWL_DEBUG_RATE(priv, "LQ: stay is expired %d %d %d\n:", | 2169 | IWL_DEBUG_RATE(priv, "LQ: stay is expired %d %d %d\n", |
2170 | lq_sta->total_failed, | 2170 | lq_sta->total_failed, |
2171 | lq_sta->total_success, | 2171 | lq_sta->total_success, |
2172 | flush_interval_passed); | 2172 | flush_interval_passed); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index f4b84d1596e3..e12f11d50b88 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c | |||
@@ -794,7 +794,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
794 | return; | 794 | return; |
795 | } | 795 | } |
796 | 796 | ||
797 | offset = (void *)hdr - rxb_addr(rxb); | 797 | offset = (void *)hdr - rxb_addr(rxb) + rxb_offset(rxb); |
798 | p = rxb_steal_page(rxb); | 798 | p = rxb_steal_page(rxb); |
799 | skb_add_rx_frag(skb, 0, p, offset, len, len); | 799 | skb_add_rx_frag(skb, 0, p, offset, len, len); |
800 | 800 | ||
@@ -970,7 +970,7 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv, | |||
970 | } | 970 | } |
971 | 971 | ||
972 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | 972 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { |
973 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | 973 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d\n", |
974 | phy_res->cfg_phy_cnt); | 974 | phy_res->cfg_phy_cnt); |
975 | return 0; | 975 | return 0; |
976 | } | 976 | } |
@@ -1134,9 +1134,6 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1134 | handlers[REPLY_COMPRESSED_BA] = | 1134 | handlers[REPLY_COMPRESSED_BA] = |
1135 | iwlagn_rx_reply_compressed_ba; | 1135 | iwlagn_rx_reply_compressed_ba; |
1136 | 1136 | ||
1137 | /* init calibration handlers */ | ||
1138 | priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = | ||
1139 | iwlagn_rx_calib_result; | ||
1140 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; | 1137 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; |
1141 | 1138 | ||
1142 | /* set up notification wait support */ | 1139 | /* set up notification wait support */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 2e1a31797a9e..79d857d81b41 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -24,6 +24,7 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #include <linux/etherdevice.h> | ||
27 | #include "iwl-dev.h" | 28 | #include "iwl-dev.h" |
28 | #include "iwl-agn.h" | 29 | #include "iwl-agn.h" |
29 | #include "iwl-core.h" | 30 | #include "iwl-core.h" |
@@ -59,9 +60,12 @@ static int iwlagn_disable_pan(struct iwl_priv *priv, | |||
59 | __le32 old_filter = send->filter_flags; | 60 | __le32 old_filter = send->filter_flags; |
60 | u8 old_dev_type = send->dev_type; | 61 | u8 old_dev_type = send->dev_type; |
61 | int ret; | 62 | int ret; |
63 | static const u8 deactivate_cmd[] = { | ||
64 | REPLY_WIPAN_DEACTIVATION_COMPLETE | ||
65 | }; | ||
62 | 66 | ||
63 | iwl_init_notification_wait(&priv->notif_wait, &disable_wait, | 67 | iwl_init_notification_wait(&priv->notif_wait, &disable_wait, |
64 | REPLY_WIPAN_DEACTIVATION_COMPLETE, | 68 | deactivate_cmd, ARRAY_SIZE(deactivate_cmd), |
65 | NULL, NULL); | 69 | NULL, NULL); |
66 | 70 | ||
67 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 71 | send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
@@ -186,6 +190,109 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, | |||
186 | return ret; | 190 | return ret; |
187 | } | 191 | } |
188 | 192 | ||
193 | static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | ||
194 | { | ||
195 | u16 new_val; | ||
196 | u16 beacon_factor; | ||
197 | |||
198 | /* | ||
199 | * If mac80211 hasn't given us a beacon interval, program | ||
200 | * the default into the device (not checking this here | ||
201 | * would cause the adjustment below to return the maximum | ||
202 | * value, which may break PAN.) | ||
203 | */ | ||
204 | if (!beacon_val) | ||
205 | return DEFAULT_BEACON_INTERVAL; | ||
206 | |||
207 | /* | ||
208 | * If the beacon interval we obtained from the peer | ||
209 | * is too large, we'll have to wake up more often | ||
210 | * (and in IBSS case, we'll beacon too much) | ||
211 | * | ||
212 | * For example, if max_beacon_val is 4096, and the | ||
213 | * requested beacon interval is 7000, we'll have to | ||
214 | * use 3500 to be able to wake up on the beacons. | ||
215 | * | ||
216 | * This could badly influence beacon detection stats. | ||
217 | */ | ||
218 | |||
219 | beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val; | ||
220 | new_val = beacon_val / beacon_factor; | ||
221 | |||
222 | if (!new_val) | ||
223 | new_val = max_beacon_val; | ||
224 | |||
225 | return new_val; | ||
226 | } | ||
227 | |||
228 | static int iwl_send_rxon_timing(struct iwl_priv *priv, | ||
229 | struct iwl_rxon_context *ctx) | ||
230 | { | ||
231 | u64 tsf; | ||
232 | s32 interval_tm, rem; | ||
233 | struct ieee80211_conf *conf = NULL; | ||
234 | u16 beacon_int; | ||
235 | struct ieee80211_vif *vif = ctx->vif; | ||
236 | |||
237 | conf = &priv->hw->conf; | ||
238 | |||
239 | lockdep_assert_held(&priv->mutex); | ||
240 | |||
241 | memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); | ||
242 | |||
243 | ctx->timing.timestamp = cpu_to_le64(priv->timestamp); | ||
244 | ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval); | ||
245 | |||
246 | beacon_int = vif ? vif->bss_conf.beacon_int : 0; | ||
247 | |||
248 | /* | ||
249 | * TODO: For IBSS we need to get atim_window from mac80211, | ||
250 | * for now just always use 0 | ||
251 | */ | ||
252 | ctx->timing.atim_window = 0; | ||
253 | |||
254 | if (ctx->ctxid == IWL_RXON_CTX_PAN && | ||
255 | (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION) && | ||
256 | iwl_is_associated(priv, IWL_RXON_CTX_BSS) && | ||
257 | priv->contexts[IWL_RXON_CTX_BSS].vif && | ||
258 | priv->contexts[IWL_RXON_CTX_BSS].vif->bss_conf.beacon_int) { | ||
259 | ctx->timing.beacon_interval = | ||
260 | priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval; | ||
261 | beacon_int = le16_to_cpu(ctx->timing.beacon_interval); | ||
262 | } else if (ctx->ctxid == IWL_RXON_CTX_BSS && | ||
263 | iwl_is_associated(priv, IWL_RXON_CTX_PAN) && | ||
264 | priv->contexts[IWL_RXON_CTX_PAN].vif && | ||
265 | priv->contexts[IWL_RXON_CTX_PAN].vif->bss_conf.beacon_int && | ||
266 | (!iwl_is_associated_ctx(ctx) || !ctx->vif || | ||
267 | !ctx->vif->bss_conf.beacon_int)) { | ||
268 | ctx->timing.beacon_interval = | ||
269 | priv->contexts[IWL_RXON_CTX_PAN].timing.beacon_interval; | ||
270 | beacon_int = le16_to_cpu(ctx->timing.beacon_interval); | ||
271 | } else { | ||
272 | beacon_int = iwl_adjust_beacon_interval(beacon_int, | ||
273 | IWL_MAX_UCODE_BEACON_INTERVAL * TIME_UNIT); | ||
274 | ctx->timing.beacon_interval = cpu_to_le16(beacon_int); | ||
275 | } | ||
276 | |||
277 | ctx->beacon_int = beacon_int; | ||
278 | |||
279 | tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ | ||
280 | interval_tm = beacon_int * TIME_UNIT; | ||
281 | rem = do_div(tsf, interval_tm); | ||
282 | ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); | ||
283 | |||
284 | ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1; | ||
285 | |||
286 | IWL_DEBUG_ASSOC(priv, | ||
287 | "beacon interval %d beacon timer %d beacon tim %d\n", | ||
288 | le16_to_cpu(ctx->timing.beacon_interval), | ||
289 | le32_to_cpu(ctx->timing.beacon_init_val), | ||
290 | le16_to_cpu(ctx->timing.atim_window)); | ||
291 | |||
292 | return iwl_dvm_send_cmd_pdu(priv, ctx->rxon_timing_cmd, | ||
293 | CMD_SYNC, sizeof(ctx->timing), &ctx->timing); | ||
294 | } | ||
295 | |||
189 | static int iwlagn_rxon_disconn(struct iwl_priv *priv, | 296 | static int iwlagn_rxon_disconn(struct iwl_priv *priv, |
190 | struct iwl_rxon_context *ctx) | 297 | struct iwl_rxon_context *ctx) |
191 | { | 298 | { |
@@ -309,7 +416,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
309 | int slot0 = 300, slot1 = 0; | 416 | int slot0 = 300, slot1 = 0; |
310 | int ret; | 417 | int ret; |
311 | 418 | ||
312 | if (priv->shrd->valid_contexts == BIT(IWL_RXON_CTX_BSS)) | 419 | if (priv->valid_contexts == BIT(IWL_RXON_CTX_BSS)) |
313 | return 0; | 420 | return 0; |
314 | 421 | ||
315 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 422 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); |
@@ -394,6 +501,154 @@ int iwlagn_set_pan_params(struct iwl_priv *priv) | |||
394 | return ret; | 501 | return ret; |
395 | } | 502 | } |
396 | 503 | ||
504 | static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, | ||
505 | struct iwl_rxon_context *ctx, int hw_decrypt) | ||
506 | { | ||
507 | struct iwl_rxon_cmd *rxon = &ctx->staging; | ||
508 | |||
509 | if (hw_decrypt) | ||
510 | rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; | ||
511 | else | ||
512 | rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; | ||
513 | |||
514 | } | ||
515 | |||
516 | /* validate RXON structure is valid */ | ||
517 | static int iwl_check_rxon_cmd(struct iwl_priv *priv, | ||
518 | struct iwl_rxon_context *ctx) | ||
519 | { | ||
520 | struct iwl_rxon_cmd *rxon = &ctx->staging; | ||
521 | u32 errors = 0; | ||
522 | |||
523 | if (rxon->flags & RXON_FLG_BAND_24G_MSK) { | ||
524 | if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) { | ||
525 | IWL_WARN(priv, "check 2.4G: wrong narrow\n"); | ||
526 | errors |= BIT(0); | ||
527 | } | ||
528 | if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) { | ||
529 | IWL_WARN(priv, "check 2.4G: wrong radar\n"); | ||
530 | errors |= BIT(1); | ||
531 | } | ||
532 | } else { | ||
533 | if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) { | ||
534 | IWL_WARN(priv, "check 5.2G: not short slot!\n"); | ||
535 | errors |= BIT(2); | ||
536 | } | ||
537 | if (rxon->flags & RXON_FLG_CCK_MSK) { | ||
538 | IWL_WARN(priv, "check 5.2G: CCK!\n"); | ||
539 | errors |= BIT(3); | ||
540 | } | ||
541 | } | ||
542 | if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) { | ||
543 | IWL_WARN(priv, "mac/bssid mcast!\n"); | ||
544 | errors |= BIT(4); | ||
545 | } | ||
546 | |||
547 | /* make sure basic rates 6Mbps and 1Mbps are supported */ | ||
548 | if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 && | ||
549 | (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) { | ||
550 | IWL_WARN(priv, "neither 1 nor 6 are basic\n"); | ||
551 | errors |= BIT(5); | ||
552 | } | ||
553 | |||
554 | if (le16_to_cpu(rxon->assoc_id) > 2007) { | ||
555 | IWL_WARN(priv, "aid > 2007\n"); | ||
556 | errors |= BIT(6); | ||
557 | } | ||
558 | |||
559 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) | ||
560 | == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) { | ||
561 | IWL_WARN(priv, "CCK and short slot\n"); | ||
562 | errors |= BIT(7); | ||
563 | } | ||
564 | |||
565 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) | ||
566 | == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { | ||
567 | IWL_WARN(priv, "CCK and auto detect"); | ||
568 | errors |= BIT(8); | ||
569 | } | ||
570 | |||
571 | if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | | ||
572 | RXON_FLG_TGG_PROTECT_MSK)) == | ||
573 | RXON_FLG_TGG_PROTECT_MSK) { | ||
574 | IWL_WARN(priv, "TGg but no auto-detect\n"); | ||
575 | errors |= BIT(9); | ||
576 | } | ||
577 | |||
578 | if (rxon->channel == 0) { | ||
579 | IWL_WARN(priv, "zero channel is invalid\n"); | ||
580 | errors |= BIT(10); | ||
581 | } | ||
582 | |||
583 | WARN(errors, "Invalid RXON (%#x), channel %d", | ||
584 | errors, le16_to_cpu(rxon->channel)); | ||
585 | |||
586 | return errors ? -EINVAL : 0; | ||
587 | } | ||
588 | |||
589 | /** | ||
590 | * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed | ||
591 | * @priv: staging_rxon is compared to active_rxon | ||
592 | * | ||
593 | * If the RXON structure is changing enough to require a new tune, | ||
594 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that | ||
595 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. | ||
596 | */ | ||
597 | static int iwl_full_rxon_required(struct iwl_priv *priv, | ||
598 | struct iwl_rxon_context *ctx) | ||
599 | { | ||
600 | const struct iwl_rxon_cmd *staging = &ctx->staging; | ||
601 | const struct iwl_rxon_cmd *active = &ctx->active; | ||
602 | |||
603 | #define CHK(cond) \ | ||
604 | if ((cond)) { \ | ||
605 | IWL_DEBUG_INFO(priv, "need full RXON - " #cond "\n"); \ | ||
606 | return 1; \ | ||
607 | } | ||
608 | |||
609 | #define CHK_NEQ(c1, c2) \ | ||
610 | if ((c1) != (c2)) { \ | ||
611 | IWL_DEBUG_INFO(priv, "need full RXON - " \ | ||
612 | #c1 " != " #c2 " - %d != %d\n", \ | ||
613 | (c1), (c2)); \ | ||
614 | return 1; \ | ||
615 | } | ||
616 | |||
617 | /* These items are only settable from the full RXON command */ | ||
618 | CHK(!iwl_is_associated_ctx(ctx)); | ||
619 | CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr)); | ||
620 | CHK(compare_ether_addr(staging->node_addr, active->node_addr)); | ||
621 | CHK(compare_ether_addr(staging->wlap_bssid_addr, | ||
622 | active->wlap_bssid_addr)); | ||
623 | CHK_NEQ(staging->dev_type, active->dev_type); | ||
624 | CHK_NEQ(staging->channel, active->channel); | ||
625 | CHK_NEQ(staging->air_propagation, active->air_propagation); | ||
626 | CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates, | ||
627 | active->ofdm_ht_single_stream_basic_rates); | ||
628 | CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates, | ||
629 | active->ofdm_ht_dual_stream_basic_rates); | ||
630 | CHK_NEQ(staging->ofdm_ht_triple_stream_basic_rates, | ||
631 | active->ofdm_ht_triple_stream_basic_rates); | ||
632 | CHK_NEQ(staging->assoc_id, active->assoc_id); | ||
633 | |||
634 | /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can | ||
635 | * be updated with the RXON_ASSOC command -- however only some | ||
636 | * flag transitions are allowed using RXON_ASSOC */ | ||
637 | |||
638 | /* Check if we are not switching bands */ | ||
639 | CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK, | ||
640 | active->flags & RXON_FLG_BAND_24G_MSK); | ||
641 | |||
642 | /* Check if we are switching association toggle */ | ||
643 | CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK, | ||
644 | active->filter_flags & RXON_FILTER_ASSOC_MSK); | ||
645 | |||
646 | #undef CHK | ||
647 | #undef CHK_NEQ | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | |||
397 | /** | 652 | /** |
398 | * iwlagn_commit_rxon - commit staging_rxon to hardware | 653 | * iwlagn_commit_rxon - commit staging_rxon to hardware |
399 | * | 654 | * |
@@ -547,7 +802,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
547 | const struct iwl_channel_info *ch_info; | 802 | const struct iwl_channel_info *ch_info; |
548 | int ret = 0; | 803 | int ret = 0; |
549 | 804 | ||
550 | IWL_DEBUG_MAC80211(priv, "enter: changed %#x", changed); | 805 | IWL_DEBUG_MAC80211(priv, "enter: changed %#x\n", changed); |
551 | 806 | ||
552 | mutex_lock(&priv->mutex); | 807 | mutex_lock(&priv->mutex); |
553 | 808 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 34adedc74d35..697f2032bfd6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -40,6 +40,17 @@ | |||
40 | #include "iwl-agn.h" | 40 | #include "iwl-agn.h" |
41 | #include "iwl-trans.h" | 41 | #include "iwl-trans.h" |
42 | 42 | ||
43 | static const u8 tid_to_ac[] = { | ||
44 | IEEE80211_AC_BE, | ||
45 | IEEE80211_AC_BK, | ||
46 | IEEE80211_AC_BK, | ||
47 | IEEE80211_AC_BE, | ||
48 | IEEE80211_AC_VI, | ||
49 | IEEE80211_AC_VI, | ||
50 | IEEE80211_AC_VO, | ||
51 | IEEE80211_AC_VO, | ||
52 | }; | ||
53 | |||
43 | static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, | 54 | static void iwlagn_tx_cmd_protection(struct iwl_priv *priv, |
44 | struct ieee80211_tx_info *info, | 55 | struct ieee80211_tx_info *info, |
45 | __le16 fc, __le32 *tx_flags) | 56 | __le16 fc, __le32 *tx_flags) |
@@ -293,6 +304,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
293 | u16 len, seq_number = 0; | 304 | u16 len, seq_number = 0; |
294 | u8 sta_id, tid = IWL_MAX_TID_COUNT; | 305 | u8 sta_id, tid = IWL_MAX_TID_COUNT; |
295 | bool is_agg = false; | 306 | bool is_agg = false; |
307 | int txq_id; | ||
296 | 308 | ||
297 | if (info->control.vif) | 309 | if (info->control.vif) |
298 | ctx = iwl_rxon_ctx_from_vif(info->control.vif); | 310 | ctx = iwl_rxon_ctx_from_vif(info->control.vif); |
@@ -435,7 +447,27 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
435 | /* Copy MAC header from skb into command buffer */ | 447 | /* Copy MAC header from skb into command buffer */ |
436 | memcpy(tx_cmd->hdr, hdr, hdr_len); | 448 | memcpy(tx_cmd->hdr, hdr, hdr_len); |
437 | 449 | ||
438 | if (iwl_trans_tx(trans(priv), skb, dev_cmd, ctx->ctxid, sta_id, tid)) | 450 | if (is_agg) |
451 | txq_id = priv->tid_data[sta_id][tid].agg.txq_id; | ||
452 | else if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
453 | /* | ||
454 | * Send this frame after DTIM -- there's a special queue | ||
455 | * reserved for this for contexts that support AP mode. | ||
456 | */ | ||
457 | txq_id = ctx->mcast_queue; | ||
458 | |||
459 | /* | ||
460 | * The microcode will clear the more data | ||
461 | * bit in the last frame it transmits. | ||
462 | */ | ||
463 | hdr->frame_control |= | ||
464 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
465 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
466 | txq_id = IWL_AUX_QUEUE; | ||
467 | else | ||
468 | txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; | ||
469 | |||
470 | if (iwl_trans_tx(trans(priv), skb, dev_cmd, txq_id)) | ||
439 | goto drop_unlock_sta; | 471 | goto drop_unlock_sta; |
440 | 472 | ||
441 | if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc) && | 473 | if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc) && |
@@ -464,11 +496,32 @@ drop_unlock_priv: | |||
464 | return -1; | 496 | return -1; |
465 | } | 497 | } |
466 | 498 | ||
499 | static int iwlagn_alloc_agg_txq(struct iwl_priv *priv, int ac) | ||
500 | { | ||
501 | int q; | ||
502 | |||
503 | for (q = IWLAGN_FIRST_AMPDU_QUEUE; | ||
504 | q < cfg(priv)->base_params->num_of_queues; q++) { | ||
505 | if (!test_and_set_bit(q, priv->agg_q_alloc)) { | ||
506 | priv->queue_to_ac[q] = ac; | ||
507 | return q; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | return -ENOSPC; | ||
512 | } | ||
513 | |||
514 | static void iwlagn_dealloc_agg_txq(struct iwl_priv *priv, int q) | ||
515 | { | ||
516 | clear_bit(q, priv->agg_q_alloc); | ||
517 | priv->queue_to_ac[q] = IWL_INVALID_AC; | ||
518 | } | ||
519 | |||
467 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | 520 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, |
468 | struct ieee80211_sta *sta, u16 tid) | 521 | struct ieee80211_sta *sta, u16 tid) |
469 | { | 522 | { |
470 | struct iwl_tid_data *tid_data; | 523 | struct iwl_tid_data *tid_data; |
471 | int sta_id; | 524 | int sta_id, txq_id; |
472 | 525 | ||
473 | sta_id = iwl_sta_id(sta); | 526 | sta_id = iwl_sta_id(sta); |
474 | 527 | ||
@@ -480,6 +533,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
480 | spin_lock_bh(&priv->sta_lock); | 533 | spin_lock_bh(&priv->sta_lock); |
481 | 534 | ||
482 | tid_data = &priv->tid_data[sta_id][tid]; | 535 | tid_data = &priv->tid_data[sta_id][tid]; |
536 | txq_id = priv->tid_data[sta_id][tid].agg.txq_id; | ||
483 | 537 | ||
484 | switch (priv->tid_data[sta_id][tid].agg.state) { | 538 | switch (priv->tid_data[sta_id][tid].agg.state) { |
485 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | 539 | case IWL_EMPTYING_HW_QUEUE_ADDBA: |
@@ -504,9 +558,13 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
504 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); | 558 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); |
505 | 559 | ||
506 | /* There are still packets for this RA / TID in the HW */ | 560 | /* There are still packets for this RA / TID in the HW */ |
507 | if (tid_data->agg.ssn != tid_data->next_reclaimed) { | 561 | if (!test_bit(txq_id, priv->agg_q_alloc)) { |
562 | IWL_DEBUG_TX_QUEUES(priv, | ||
563 | "stopping AGG on STA/TID %d/%d but hwq %d not used\n", | ||
564 | sta_id, tid, txq_id); | ||
565 | } else if (tid_data->agg.ssn != tid_data->next_reclaimed) { | ||
508 | IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, " | 566 | IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, " |
509 | "next_recl = %d", | 567 | "next_recl = %d\n", |
510 | tid_data->agg.ssn, | 568 | tid_data->agg.ssn, |
511 | tid_data->next_reclaimed); | 569 | tid_data->next_reclaimed); |
512 | priv->tid_data[sta_id][tid].agg.state = | 570 | priv->tid_data[sta_id][tid].agg.state = |
@@ -515,14 +573,17 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
515 | return 0; | 573 | return 0; |
516 | } | 574 | } |
517 | 575 | ||
518 | IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d", | 576 | IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n", |
519 | tid_data->agg.ssn); | 577 | tid_data->agg.ssn); |
520 | turn_off: | 578 | turn_off: |
521 | priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; | 579 | priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; |
522 | 580 | ||
523 | spin_unlock_bh(&priv->sta_lock); | 581 | spin_unlock_bh(&priv->sta_lock); |
524 | 582 | ||
525 | iwl_trans_tx_agg_disable(trans(priv), sta_id, tid); | 583 | if (test_bit(txq_id, priv->agg_q_alloc)) { |
584 | iwl_trans_tx_agg_disable(trans(priv), txq_id); | ||
585 | iwlagn_dealloc_agg_txq(priv, txq_id); | ||
586 | } | ||
526 | 587 | ||
527 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 588 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
528 | 589 | ||
@@ -533,8 +594,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
533 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 594 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
534 | { | 595 | { |
535 | struct iwl_tid_data *tid_data; | 596 | struct iwl_tid_data *tid_data; |
536 | int sta_id; | 597 | int sta_id, txq_id, ret; |
537 | int ret; | ||
538 | 598 | ||
539 | IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n", | 599 | IWL_DEBUG_HT(priv, "TX AGG request on ra = %pM tid = %d\n", |
540 | sta->addr, tid); | 600 | sta->addr, tid); |
@@ -552,36 +612,37 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
552 | return -ENXIO; | 612 | return -ENXIO; |
553 | } | 613 | } |
554 | 614 | ||
615 | txq_id = iwlagn_alloc_agg_txq(priv, tid_to_ac[tid]); | ||
616 | if (txq_id < 0) { | ||
617 | IWL_DEBUG_TX_QUEUES(priv, | ||
618 | "No free aggregation queue for %pM/%d\n", | ||
619 | sta->addr, tid); | ||
620 | return txq_id; | ||
621 | } | ||
622 | |||
555 | ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | 623 | ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); |
556 | if (ret) | 624 | if (ret) |
557 | return ret; | 625 | return ret; |
558 | 626 | ||
559 | spin_lock_bh(&priv->sta_lock); | 627 | spin_lock_bh(&priv->sta_lock); |
560 | |||
561 | tid_data = &priv->tid_data[sta_id][tid]; | 628 | tid_data = &priv->tid_data[sta_id][tid]; |
562 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); | 629 | tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); |
630 | tid_data->agg.txq_id = txq_id; | ||
563 | 631 | ||
564 | *ssn = tid_data->agg.ssn; | 632 | *ssn = tid_data->agg.ssn; |
565 | 633 | ||
566 | ret = iwl_trans_tx_agg_alloc(trans(priv), sta_id, tid); | ||
567 | if (ret) { | ||
568 | spin_unlock_bh(&priv->sta_lock); | ||
569 | return ret; | ||
570 | } | ||
571 | |||
572 | if (*ssn == tid_data->next_reclaimed) { | 634 | if (*ssn == tid_data->next_reclaimed) { |
573 | IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d", | 635 | IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n", |
574 | tid_data->agg.ssn); | 636 | tid_data->agg.ssn); |
575 | tid_data->agg.state = IWL_AGG_ON; | 637 | tid_data->agg.state = IWL_AGG_ON; |
576 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 638 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
577 | } else { | 639 | } else { |
578 | IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, " | 640 | IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, " |
579 | "next_reclaimed = %d", | 641 | "next_reclaimed = %d\n", |
580 | tid_data->agg.ssn, | 642 | tid_data->agg.ssn, |
581 | tid_data->next_reclaimed); | 643 | tid_data->next_reclaimed); |
582 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | 644 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; |
583 | } | 645 | } |
584 | |||
585 | spin_unlock_bh(&priv->sta_lock); | 646 | spin_unlock_bh(&priv->sta_lock); |
586 | 647 | ||
587 | return ret; | 648 | return ret; |
@@ -592,15 +653,20 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
592 | { | 653 | { |
593 | struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; | 654 | struct iwl_station_priv *sta_priv = (void *) sta->drv_priv; |
594 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | 655 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); |
656 | int q, fifo; | ||
595 | u16 ssn; | 657 | u16 ssn; |
596 | 658 | ||
597 | buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); | 659 | buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); |
598 | 660 | ||
599 | spin_lock_bh(&priv->sta_lock); | 661 | spin_lock_bh(&priv->sta_lock); |
600 | ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn; | 662 | ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn; |
663 | q = priv->tid_data[sta_priv->sta_id][tid].agg.txq_id; | ||
601 | spin_unlock_bh(&priv->sta_lock); | 664 | spin_unlock_bh(&priv->sta_lock); |
602 | 665 | ||
603 | iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, sta_priv->sta_id, tid, | 666 | fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; |
667 | |||
668 | iwl_trans_tx_agg_setup(trans(priv), q, fifo, | ||
669 | sta_priv->sta_id, tid, | ||
604 | buf_size, ssn); | 670 | buf_size, ssn); |
605 | 671 | ||
606 | /* | 672 | /* |
@@ -666,7 +732,9 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) | |||
666 | IWL_DEBUG_TX_QUEUES(priv, | 732 | IWL_DEBUG_TX_QUEUES(priv, |
667 | "Can continue DELBA flow ssn = next_recl =" | 733 | "Can continue DELBA flow ssn = next_recl =" |
668 | " %d", tid_data->next_reclaimed); | 734 | " %d", tid_data->next_reclaimed); |
669 | iwl_trans_tx_agg_disable(trans(priv), sta_id, tid); | 735 | iwl_trans_tx_agg_disable(trans(priv), |
736 | tid_data->agg.txq_id); | ||
737 | iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id); | ||
670 | tid_data->agg.state = IWL_AGG_OFF; | 738 | tid_data->agg.state = IWL_AGG_OFF; |
671 | ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); | 739 | ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid); |
672 | } | 740 | } |
@@ -711,9 +779,9 @@ static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, | |||
711 | static void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | 779 | static void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, |
712 | struct ieee80211_tx_info *info) | 780 | struct ieee80211_tx_info *info) |
713 | { | 781 | { |
714 | struct ieee80211_tx_rate *r = &info->control.rates[0]; | 782 | struct ieee80211_tx_rate *r = &info->status.rates[0]; |
715 | 783 | ||
716 | info->antenna_sel_tx = | 784 | info->status.antenna = |
717 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | 785 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); |
718 | if (rate_n_flags & RATE_MCS_HT_MSK) | 786 | if (rate_n_flags & RATE_MCS_HT_MSK) |
719 | r->flags |= IEEE80211_TX_RC_MCS; | 787 | r->flags |= IEEE80211_TX_RC_MCS; |
@@ -1005,6 +1073,29 @@ static void iwl_check_abort_status(struct iwl_priv *priv, | |||
1005 | } | 1073 | } |
1006 | } | 1074 | } |
1007 | 1075 | ||
1076 | static int iwl_reclaim(struct iwl_priv *priv, int sta_id, int tid, | ||
1077 | int txq_id, int ssn, struct sk_buff_head *skbs) | ||
1078 | { | ||
1079 | if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && | ||
1080 | tid != IWL_TID_NON_QOS && | ||
1081 | txq_id != priv->tid_data[sta_id][tid].agg.txq_id)) { | ||
1082 | /* | ||
1083 | * FIXME: this is a uCode bug which need to be addressed, | ||
1084 | * log the information and return for now. | ||
1085 | * Since it is can possibly happen very often and in order | ||
1086 | * not to fill the syslog, don't use IWL_ERR or IWL_WARN | ||
1087 | */ | ||
1088 | IWL_DEBUG_TX_QUEUES(priv, | ||
1089 | "Bad queue mapping txq_id=%d, agg_txq[sta:%d,tid:%d]=%d\n", | ||
1090 | txq_id, sta_id, tid, | ||
1091 | priv->tid_data[sta_id][tid].agg.txq_id); | ||
1092 | return 1; | ||
1093 | } | ||
1094 | |||
1095 | iwl_trans_reclaim(trans(priv), txq_id, ssn, skbs); | ||
1096 | return 0; | ||
1097 | } | ||
1098 | |||
1008 | int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | 1099 | int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, |
1009 | struct iwl_device_cmd *cmd) | 1100 | struct iwl_device_cmd *cmd) |
1010 | { | 1101 | { |
@@ -1059,13 +1150,12 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1059 | if (tid != IWL_TID_NON_QOS) { | 1150 | if (tid != IWL_TID_NON_QOS) { |
1060 | priv->tid_data[sta_id][tid].next_reclaimed = | 1151 | priv->tid_data[sta_id][tid].next_reclaimed = |
1061 | next_reclaimed; | 1152 | next_reclaimed; |
1062 | IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", | 1153 | IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", |
1063 | next_reclaimed); | 1154 | next_reclaimed); |
1064 | } | 1155 | } |
1065 | 1156 | ||
1066 | /*we can free until ssn % q.n_bd not inclusive */ | 1157 | /*we can free until ssn % q.n_bd not inclusive */ |
1067 | WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, | 1158 | WARN_ON(iwl_reclaim(priv, sta_id, tid, txq_id, ssn, &skbs)); |
1068 | txq_id, ssn, &skbs)); | ||
1069 | iwlagn_check_ratid_empty(priv, sta_id, tid); | 1159 | iwlagn_check_ratid_empty(priv, sta_id, tid); |
1070 | freed = 0; | 1160 | freed = 0; |
1071 | 1161 | ||
@@ -1183,8 +1273,8 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1183 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | 1273 | /* Release all TFDs before the SSN, i.e. all TFDs in front of |
1184 | * block-ack window (we assume that they've been successfully | 1274 | * block-ack window (we assume that they've been successfully |
1185 | * transmitted ... if not, it's too late anyway). */ | 1275 | * transmitted ... if not, it's too late anyway). */ |
1186 | if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, | 1276 | if (iwl_reclaim(priv, sta_id, tid, scd_flow, |
1187 | ba_resp_scd_ssn, &reclaimed_skbs)) { | 1277 | ba_resp_scd_ssn, &reclaimed_skbs)) { |
1188 | spin_unlock(&priv->sta_lock); | 1278 | spin_unlock(&priv->sta_lock); |
1189 | return 0; | 1279 | return 0; |
1190 | } | 1280 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f1226dbf789d..22c953d65be5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -26,6 +26,9 @@ | |||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
27 | * | 27 | * |
28 | *****************************************************************************/ | 28 | *****************************************************************************/ |
29 | |||
30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
31 | |||
29 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 33 | #include <linux/module.h> |
31 | #include <linux/init.h> | 34 | #include <linux/init.h> |
@@ -379,7 +382,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv) | |||
379 | u32 num_wraps; /* # times uCode wrapped to top of log */ | 382 | u32 num_wraps; /* # times uCode wrapped to top of log */ |
380 | u32 next_entry; /* index of next entry to be written by uCode */ | 383 | u32 next_entry; /* index of next entry to be written by uCode */ |
381 | 384 | ||
382 | base = priv->shrd->device_pointers.log_event_table; | 385 | base = priv->device_pointers.log_event_table; |
383 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 386 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
384 | iwl_read_targ_mem_words(trans(priv), base, &read, sizeof(read)); | 387 | iwl_read_targ_mem_words(trans(priv), base, &read, sizeof(read)); |
385 | 388 | ||
@@ -488,6 +491,93 @@ static void iwl_bg_tx_flush(struct work_struct *work) | |||
488 | iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); | 491 | iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); |
489 | } | 492 | } |
490 | 493 | ||
494 | /* | ||
495 | * queue/FIFO/AC mapping definitions | ||
496 | */ | ||
497 | |||
498 | #define IWL_TX_FIFO_BK 0 /* shared */ | ||
499 | #define IWL_TX_FIFO_BE 1 | ||
500 | #define IWL_TX_FIFO_VI 2 /* shared */ | ||
501 | #define IWL_TX_FIFO_VO 3 | ||
502 | #define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK | ||
503 | #define IWL_TX_FIFO_BE_IPAN 4 | ||
504 | #define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI | ||
505 | #define IWL_TX_FIFO_VO_IPAN 5 | ||
506 | /* re-uses the VO FIFO, uCode will properly flush/schedule */ | ||
507 | #define IWL_TX_FIFO_AUX 5 | ||
508 | #define IWL_TX_FIFO_UNUSED -1 | ||
509 | |||
510 | #define IWLAGN_CMD_FIFO_NUM 7 | ||
511 | |||
512 | /* | ||
513 | * This queue number is required for proper operation | ||
514 | * because the ucode will stop/start the scheduler as | ||
515 | * required. | ||
516 | */ | ||
517 | #define IWL_IPAN_MCAST_QUEUE 8 | ||
518 | |||
519 | static const u8 iwlagn_default_queue_to_tx_fifo[] = { | ||
520 | IWL_TX_FIFO_VO, | ||
521 | IWL_TX_FIFO_VI, | ||
522 | IWL_TX_FIFO_BE, | ||
523 | IWL_TX_FIFO_BK, | ||
524 | IWLAGN_CMD_FIFO_NUM, | ||
525 | }; | ||
526 | |||
527 | static const u8 iwlagn_ipan_queue_to_tx_fifo[] = { | ||
528 | IWL_TX_FIFO_VO, | ||
529 | IWL_TX_FIFO_VI, | ||
530 | IWL_TX_FIFO_BE, | ||
531 | IWL_TX_FIFO_BK, | ||
532 | IWL_TX_FIFO_BK_IPAN, | ||
533 | IWL_TX_FIFO_BE_IPAN, | ||
534 | IWL_TX_FIFO_VI_IPAN, | ||
535 | IWL_TX_FIFO_VO_IPAN, | ||
536 | IWL_TX_FIFO_BE_IPAN, | ||
537 | IWLAGN_CMD_FIFO_NUM, | ||
538 | IWL_TX_FIFO_AUX, | ||
539 | }; | ||
540 | |||
541 | static const u8 iwlagn_bss_ac_to_fifo[] = { | ||
542 | IWL_TX_FIFO_VO, | ||
543 | IWL_TX_FIFO_VI, | ||
544 | IWL_TX_FIFO_BE, | ||
545 | IWL_TX_FIFO_BK, | ||
546 | }; | ||
547 | |||
548 | static const u8 iwlagn_bss_ac_to_queue[] = { | ||
549 | 0, 1, 2, 3, | ||
550 | }; | ||
551 | |||
552 | static const u8 iwlagn_pan_ac_to_fifo[] = { | ||
553 | IWL_TX_FIFO_VO_IPAN, | ||
554 | IWL_TX_FIFO_VI_IPAN, | ||
555 | IWL_TX_FIFO_BE_IPAN, | ||
556 | IWL_TX_FIFO_BK_IPAN, | ||
557 | }; | ||
558 | |||
559 | static const u8 iwlagn_pan_ac_to_queue[] = { | ||
560 | 7, 6, 5, 4, | ||
561 | }; | ||
562 | |||
563 | static const u8 iwlagn_bss_queue_to_ac[] = { | ||
564 | IEEE80211_AC_VO, | ||
565 | IEEE80211_AC_VI, | ||
566 | IEEE80211_AC_BE, | ||
567 | IEEE80211_AC_BK, | ||
568 | }; | ||
569 | |||
570 | static const u8 iwlagn_pan_queue_to_ac[] = { | ||
571 | IEEE80211_AC_VO, | ||
572 | IEEE80211_AC_VI, | ||
573 | IEEE80211_AC_BE, | ||
574 | IEEE80211_AC_BK, | ||
575 | IEEE80211_AC_BK, | ||
576 | IEEE80211_AC_BE, | ||
577 | IEEE80211_AC_VI, | ||
578 | IEEE80211_AC_VO, | ||
579 | }; | ||
580 | |||
491 | static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | 581 | static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) |
492 | { | 582 | { |
493 | int i; | 583 | int i; |
@@ -496,9 +586,9 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
496 | * The default context is always valid, | 586 | * The default context is always valid, |
497 | * the PAN context depends on uCode. | 587 | * the PAN context depends on uCode. |
498 | */ | 588 | */ |
499 | priv->shrd->valid_contexts = BIT(IWL_RXON_CTX_BSS); | 589 | priv->valid_contexts = BIT(IWL_RXON_CTX_BSS); |
500 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) | 590 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) |
501 | priv->shrd->valid_contexts |= BIT(IWL_RXON_CTX_PAN); | 591 | priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN); |
502 | 592 | ||
503 | for (i = 0; i < NUM_IWL_RXON_CTX; i++) | 593 | for (i = 0; i < NUM_IWL_RXON_CTX; i++) |
504 | priv->contexts[i].ctxid = i; | 594 | priv->contexts[i].ctxid = i; |
@@ -520,6 +610,10 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
520 | priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS; | 610 | priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS; |
521 | priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS; | 611 | priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS; |
522 | priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS; | 612 | priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS; |
613 | memcpy(priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue, | ||
614 | iwlagn_bss_ac_to_queue, sizeof(iwlagn_bss_ac_to_queue)); | ||
615 | memcpy(priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo, | ||
616 | iwlagn_bss_ac_to_fifo, sizeof(iwlagn_bss_ac_to_fifo)); | ||
523 | 617 | ||
524 | priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON; | 618 | priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON; |
525 | priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = | 619 | priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = |
@@ -542,6 +636,11 @@ static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
542 | priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; | 636 | priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP; |
543 | priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; | 637 | priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA; |
544 | priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; | 638 | priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P; |
639 | memcpy(priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue, | ||
640 | iwlagn_pan_ac_to_queue, sizeof(iwlagn_pan_ac_to_queue)); | ||
641 | memcpy(priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo, | ||
642 | iwlagn_pan_ac_to_fifo, sizeof(iwlagn_pan_ac_to_fifo)); | ||
643 | priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE; | ||
545 | 644 | ||
546 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); | 645 | BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2); |
547 | } | 646 | } |
@@ -824,11 +923,10 @@ void iwl_down(struct iwl_priv *priv) | |||
824 | STATUS_RF_KILL_HW | | 923 | STATUS_RF_KILL_HW | |
825 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << | 924 | test_bit(STATUS_GEO_CONFIGURED, &priv->status) << |
826 | STATUS_GEO_CONFIGURED | | 925 | STATUS_GEO_CONFIGURED | |
926 | test_bit(STATUS_FW_ERROR, &priv->status) << | ||
927 | STATUS_FW_ERROR | | ||
827 | test_bit(STATUS_EXIT_PENDING, &priv->status) << | 928 | test_bit(STATUS_EXIT_PENDING, &priv->status) << |
828 | STATUS_EXIT_PENDING; | 929 | STATUS_EXIT_PENDING; |
829 | priv->shrd->status &= | ||
830 | test_bit(STATUS_FW_ERROR, &priv->shrd->status) << | ||
831 | STATUS_FW_ERROR; | ||
832 | 930 | ||
833 | dev_kfree_skb(priv->beacon_skb); | 931 | dev_kfree_skb(priv->beacon_skb); |
834 | priv->beacon_skb = NULL; | 932 | priv->beacon_skb = NULL; |
@@ -869,6 +967,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv) | |||
869 | u8 bt_load; | 967 | u8 bt_load; |
870 | u8 bt_status; | 968 | u8 bt_status; |
871 | bool bt_is_sco; | 969 | bool bt_is_sco; |
970 | int i; | ||
872 | 971 | ||
873 | lockdep_assert_held(&priv->mutex); | 972 | lockdep_assert_held(&priv->mutex); |
874 | 973 | ||
@@ -898,6 +997,15 @@ void iwlagn_prepare_restart(struct iwl_priv *priv) | |||
898 | priv->bt_traffic_load = bt_load; | 997 | priv->bt_traffic_load = bt_load; |
899 | priv->bt_status = bt_status; | 998 | priv->bt_status = bt_status; |
900 | priv->bt_is_sco = bt_is_sco; | 999 | priv->bt_is_sco = bt_is_sco; |
1000 | |||
1001 | /* reset all queues */ | ||
1002 | for (i = 0; i < IEEE80211_NUM_ACS; i++) | ||
1003 | atomic_set(&priv->ac_stop_count[i], 0); | ||
1004 | |||
1005 | for (i = IWLAGN_FIRST_AMPDU_QUEUE; i < IWL_MAX_HW_QUEUES; i++) | ||
1006 | priv->queue_to_ac[i] = IWL_INVALID_AC; | ||
1007 | |||
1008 | memset(priv->agg_q_alloc, 0, sizeof(priv->agg_q_alloc)); | ||
901 | } | 1009 | } |
902 | 1010 | ||
903 | static void iwl_bg_restart(struct work_struct *data) | 1011 | static void iwl_bg_restart(struct work_struct *data) |
@@ -907,7 +1015,7 @@ static void iwl_bg_restart(struct work_struct *data) | |||
907 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 1015 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
908 | return; | 1016 | return; |
909 | 1017 | ||
910 | if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) { | 1018 | if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { |
911 | mutex_lock(&priv->mutex); | 1019 | mutex_lock(&priv->mutex); |
912 | iwlagn_prepare_restart(priv); | 1020 | iwlagn_prepare_restart(priv); |
913 | mutex_unlock(&priv->mutex); | 1021 | mutex_unlock(&priv->mutex); |
@@ -1028,6 +1136,189 @@ static void iwl_init_hw_rates(struct ieee80211_rate *rates) | |||
1028 | } | 1136 | } |
1029 | } | 1137 | } |
1030 | 1138 | ||
1139 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | ||
1140 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | ||
1141 | static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, | ||
1142 | struct ieee80211_sta_ht_cap *ht_info, | ||
1143 | enum ieee80211_band band) | ||
1144 | { | ||
1145 | u16 max_bit_rate = 0; | ||
1146 | u8 rx_chains_num = hw_params(priv).rx_chains_num; | ||
1147 | u8 tx_chains_num = hw_params(priv).tx_chains_num; | ||
1148 | |||
1149 | ht_info->cap = 0; | ||
1150 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | ||
1151 | |||
1152 | ht_info->ht_supported = true; | ||
1153 | |||
1154 | if (cfg(priv)->ht_params && | ||
1155 | cfg(priv)->ht_params->ht_greenfield_support) | ||
1156 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
1157 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
1158 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||
1159 | if (hw_params(priv).ht40_channel & BIT(band)) { | ||
1160 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
1161 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
1162 | ht_info->mcs.rx_mask[4] = 0x01; | ||
1163 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||
1164 | } | ||
1165 | |||
1166 | if (iwlagn_mod_params.amsdu_size_8K) | ||
1167 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
1168 | |||
1169 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | ||
1170 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; | ||
1171 | |||
1172 | ht_info->mcs.rx_mask[0] = 0xFF; | ||
1173 | if (rx_chains_num >= 2) | ||
1174 | ht_info->mcs.rx_mask[1] = 0xFF; | ||
1175 | if (rx_chains_num >= 3) | ||
1176 | ht_info->mcs.rx_mask[2] = 0xFF; | ||
1177 | |||
1178 | /* Highest supported Rx data rate */ | ||
1179 | max_bit_rate *= rx_chains_num; | ||
1180 | WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||
1181 | ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||
1182 | |||
1183 | /* Tx MCS capabilities */ | ||
1184 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
1185 | if (tx_chains_num != rx_chains_num) { | ||
1186 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
1187 | ht_info->mcs.tx_params |= ((tx_chains_num - 1) << | ||
1188 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
1189 | } | ||
1190 | } | ||
1191 | |||
1192 | /** | ||
1193 | * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom | ||
1194 | */ | ||
1195 | static int iwl_init_geos(struct iwl_priv *priv) | ||
1196 | { | ||
1197 | struct iwl_channel_info *ch; | ||
1198 | struct ieee80211_supported_band *sband; | ||
1199 | struct ieee80211_channel *channels; | ||
1200 | struct ieee80211_channel *geo_ch; | ||
1201 | struct ieee80211_rate *rates; | ||
1202 | int i = 0; | ||
1203 | s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN; | ||
1204 | |||
1205 | if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || | ||
1206 | priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { | ||
1207 | IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); | ||
1208 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1209 | return 0; | ||
1210 | } | ||
1211 | |||
1212 | channels = kcalloc(priv->channel_count, | ||
1213 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
1214 | if (!channels) | ||
1215 | return -ENOMEM; | ||
1216 | |||
1217 | rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate), | ||
1218 | GFP_KERNEL); | ||
1219 | if (!rates) { | ||
1220 | kfree(channels); | ||
1221 | return -ENOMEM; | ||
1222 | } | ||
1223 | |||
1224 | /* 5.2GHz channels start after the 2.4GHz channels */ | ||
1225 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; | ||
1226 | sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; | ||
1227 | /* just OFDM */ | ||
1228 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; | ||
1229 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; | ||
1230 | |||
1231 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
1232 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
1233 | IEEE80211_BAND_5GHZ); | ||
1234 | |||
1235 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; | ||
1236 | sband->channels = channels; | ||
1237 | /* OFDM & CCK */ | ||
1238 | sband->bitrates = rates; | ||
1239 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY; | ||
1240 | |||
1241 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
1242 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
1243 | IEEE80211_BAND_2GHZ); | ||
1244 | |||
1245 | priv->ieee_channels = channels; | ||
1246 | priv->ieee_rates = rates; | ||
1247 | |||
1248 | for (i = 0; i < priv->channel_count; i++) { | ||
1249 | ch = &priv->channel_info[i]; | ||
1250 | |||
1251 | /* FIXME: might be removed if scan is OK */ | ||
1252 | if (!is_channel_valid(ch)) | ||
1253 | continue; | ||
1254 | |||
1255 | sband = &priv->bands[ch->band]; | ||
1256 | |||
1257 | geo_ch = &sband->channels[sband->n_channels++]; | ||
1258 | |||
1259 | geo_ch->center_freq = | ||
1260 | ieee80211_channel_to_frequency(ch->channel, ch->band); | ||
1261 | geo_ch->max_power = ch->max_power_avg; | ||
1262 | geo_ch->max_antenna_gain = 0xff; | ||
1263 | geo_ch->hw_value = ch->channel; | ||
1264 | |||
1265 | if (is_channel_valid(ch)) { | ||
1266 | if (!(ch->flags & EEPROM_CHANNEL_IBSS)) | ||
1267 | geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; | ||
1268 | |||
1269 | if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||
1270 | geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
1271 | |||
1272 | if (ch->flags & EEPROM_CHANNEL_RADAR) | ||
1273 | geo_ch->flags |= IEEE80211_CHAN_RADAR; | ||
1274 | |||
1275 | geo_ch->flags |= ch->ht40_extension_channel; | ||
1276 | |||
1277 | if (ch->max_power_avg > max_tx_power) | ||
1278 | max_tx_power = ch->max_power_avg; | ||
1279 | } else { | ||
1280 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | ||
1281 | } | ||
1282 | |||
1283 | IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", | ||
1284 | ch->channel, geo_ch->center_freq, | ||
1285 | is_channel_a_band(ch) ? "5.2" : "2.4", | ||
1286 | geo_ch->flags & IEEE80211_CHAN_DISABLED ? | ||
1287 | "restricted" : "valid", | ||
1288 | geo_ch->flags); | ||
1289 | } | ||
1290 | |||
1291 | priv->tx_power_device_lmt = max_tx_power; | ||
1292 | priv->tx_power_user_lmt = max_tx_power; | ||
1293 | priv->tx_power_next = max_tx_power; | ||
1294 | |||
1295 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && | ||
1296 | hw_params(priv).sku & EEPROM_SKU_CAP_BAND_52GHZ) { | ||
1297 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " | ||
1298 | "Please send your %s to maintainer.\n", | ||
1299 | trans(priv)->hw_id_str); | ||
1300 | hw_params(priv).sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; | ||
1301 | } | ||
1302 | |||
1303 | IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", | ||
1304 | priv->bands[IEEE80211_BAND_2GHZ].n_channels, | ||
1305 | priv->bands[IEEE80211_BAND_5GHZ].n_channels); | ||
1306 | |||
1307 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1308 | |||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | /* | ||
1313 | * iwl_free_geos - undo allocations in iwl_init_geos | ||
1314 | */ | ||
1315 | static void iwl_free_geos(struct iwl_priv *priv) | ||
1316 | { | ||
1317 | kfree(priv->ieee_channels); | ||
1318 | kfree(priv->ieee_rates); | ||
1319 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
1320 | } | ||
1321 | |||
1031 | static int iwl_init_drv(struct iwl_priv *priv) | 1322 | static int iwl_init_drv(struct iwl_priv *priv) |
1032 | { | 1323 | { |
1033 | int ret; | 1324 | int ret; |
@@ -1130,8 +1421,6 @@ static void iwl_set_hw_params(struct iwl_priv *priv) | |||
1130 | if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL) | 1421 | if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL) |
1131 | hw_params(priv).sku &= ~EEPROM_SKU_CAP_11N_ENABLE; | 1422 | hw_params(priv).sku &= ~EEPROM_SKU_CAP_11N_ENABLE; |
1132 | 1423 | ||
1133 | hw_params(priv).num_ampdu_queues = | ||
1134 | cfg(priv)->base_params->num_of_ampdu_queues; | ||
1135 | hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout; | 1424 | hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout; |
1136 | 1425 | ||
1137 | /* Device-specific setup */ | 1426 | /* Device-specific setup */ |
@@ -1178,7 +1467,6 @@ static void iwl_debug_config(struct iwl_priv *priv) | |||
1178 | static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | 1467 | static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, |
1179 | const struct iwl_fw *fw) | 1468 | const struct iwl_fw *fw) |
1180 | { | 1469 | { |
1181 | int err = 0; | ||
1182 | struct iwl_priv *priv; | 1470 | struct iwl_priv *priv; |
1183 | struct ieee80211_hw *hw; | 1471 | struct ieee80211_hw *hw; |
1184 | struct iwl_op_mode *op_mode; | 1472 | struct iwl_op_mode *op_mode; |
@@ -1193,6 +1481,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1193 | STATISTICS_NOTIFICATION, | 1481 | STATISTICS_NOTIFICATION, |
1194 | REPLY_TX, | 1482 | REPLY_TX, |
1195 | }; | 1483 | }; |
1484 | const u8 *q_to_ac; | ||
1485 | int n_q_to_ac; | ||
1486 | int i; | ||
1196 | 1487 | ||
1197 | /************************ | 1488 | /************************ |
1198 | * 1. Allocating HW data | 1489 | * 1. Allocating HW data |
@@ -1201,7 +1492,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1201 | if (!hw) { | 1492 | if (!hw) { |
1202 | pr_err("%s: Cannot allocate network device\n", | 1493 | pr_err("%s: Cannot allocate network device\n", |
1203 | cfg(trans)->name); | 1494 | cfg(trans)->name); |
1204 | err = -ENOMEM; | ||
1205 | goto out; | 1495 | goto out; |
1206 | } | 1496 | } |
1207 | 1497 | ||
@@ -1210,8 +1500,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1210 | priv = IWL_OP_MODE_GET_DVM(op_mode); | 1500 | priv = IWL_OP_MODE_GET_DVM(op_mode); |
1211 | priv->shrd = trans->shrd; | 1501 | priv->shrd = trans->shrd; |
1212 | priv->fw = fw; | 1502 | priv->fw = fw; |
1213 | /* TODO: remove fw from shared data later */ | ||
1214 | priv->shrd->fw = fw; | ||
1215 | 1503 | ||
1216 | /* | 1504 | /* |
1217 | * Populate the state variables that the transport layer needs | 1505 | * Populate the state variables that the transport layer needs |
@@ -1230,9 +1518,19 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1230 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { | 1518 | if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) { |
1231 | priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; | 1519 | priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN; |
1232 | trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; | 1520 | trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; |
1521 | trans_cfg.queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; | ||
1522 | trans_cfg.n_queue_to_fifo = | ||
1523 | ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo); | ||
1524 | q_to_ac = iwlagn_pan_queue_to_ac; | ||
1525 | n_q_to_ac = ARRAY_SIZE(iwlagn_pan_queue_to_ac); | ||
1233 | } else { | 1526 | } else { |
1234 | priv->sta_key_max_num = STA_KEY_MAX_NUM; | 1527 | priv->sta_key_max_num = STA_KEY_MAX_NUM; |
1235 | trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; | 1528 | trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; |
1529 | trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo; | ||
1530 | trans_cfg.n_queue_to_fifo = | ||
1531 | ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); | ||
1532 | q_to_ac = iwlagn_bss_queue_to_ac; | ||
1533 | n_q_to_ac = ARRAY_SIZE(iwlagn_bss_queue_to_ac); | ||
1236 | } | 1534 | } |
1237 | 1535 | ||
1238 | /* Configure transport layer */ | 1536 | /* Configure transport layer */ |
@@ -1273,26 +1571,24 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1273 | IWL_INFO(priv, "Detected %s, REV=0x%X\n", | 1571 | IWL_INFO(priv, "Detected %s, REV=0x%X\n", |
1274 | cfg(priv)->name, trans(priv)->hw_rev); | 1572 | cfg(priv)->name, trans(priv)->hw_rev); |
1275 | 1573 | ||
1276 | err = iwl_trans_start_hw(trans(priv)); | 1574 | if (iwl_trans_start_hw(trans(priv))) |
1277 | if (err) | ||
1278 | goto out_free_traffic_mem; | 1575 | goto out_free_traffic_mem; |
1279 | 1576 | ||
1280 | /***************** | 1577 | /***************** |
1281 | * 3. Read EEPROM | 1578 | * 3. Read EEPROM |
1282 | *****************/ | 1579 | *****************/ |
1283 | err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev); | 1580 | /* Read the EEPROM */ |
1284 | /* Reset chip to save power until we load uCode during "up". */ | 1581 | if (iwl_eeprom_init(trans(priv), trans(priv)->hw_rev)) { |
1285 | iwl_trans_stop_hw(trans(priv)); | ||
1286 | if (err) { | ||
1287 | IWL_ERR(priv, "Unable to init EEPROM\n"); | 1582 | IWL_ERR(priv, "Unable to init EEPROM\n"); |
1288 | goto out_free_traffic_mem; | 1583 | goto out_free_traffic_mem; |
1289 | } | 1584 | } |
1290 | err = iwl_eeprom_check_version(priv); | 1585 | /* Reset chip to save power until we load uCode during "up". */ |
1291 | if (err) | 1586 | iwl_trans_stop_hw(trans(priv)); |
1587 | |||
1588 | if (iwl_eeprom_check_version(priv)) | ||
1292 | goto out_free_eeprom; | 1589 | goto out_free_eeprom; |
1293 | 1590 | ||
1294 | err = iwl_eeprom_init_hw_params(priv); | 1591 | if (iwl_eeprom_init_hw_params(priv)) |
1295 | if (err) | ||
1296 | goto out_free_eeprom; | 1592 | goto out_free_eeprom; |
1297 | 1593 | ||
1298 | /* extract MAC Address */ | 1594 | /* extract MAC Address */ |
@@ -1323,6 +1619,11 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1323 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; | 1619 | ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; |
1324 | priv->sta_key_max_num = STA_KEY_MAX_NUM; | 1620 | priv->sta_key_max_num = STA_KEY_MAX_NUM; |
1325 | trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; | 1621 | trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; |
1622 | trans_cfg.queue_to_fifo = iwlagn_default_queue_to_tx_fifo; | ||
1623 | trans_cfg.n_queue_to_fifo = | ||
1624 | ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); | ||
1625 | q_to_ac = iwlagn_bss_queue_to_ac; | ||
1626 | n_q_to_ac = ARRAY_SIZE(iwlagn_bss_queue_to_ac); | ||
1326 | 1627 | ||
1327 | /* Configure transport layer again*/ | 1628 | /* Configure transport layer again*/ |
1328 | iwl_trans_configure(trans(priv), &trans_cfg); | 1629 | iwl_trans_configure(trans(priv), &trans_cfg); |
@@ -1331,10 +1632,22 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1331 | /******************* | 1632 | /******************* |
1332 | * 5. Setup priv | 1633 | * 5. Setup priv |
1333 | *******************/ | 1634 | *******************/ |
1635 | for (i = 0; i < IEEE80211_NUM_ACS; i++) | ||
1636 | atomic_set(&priv->ac_stop_count[i], 0); | ||
1334 | 1637 | ||
1335 | err = iwl_init_drv(priv); | 1638 | for (i = 0; i < IWL_MAX_HW_QUEUES; i++) { |
1336 | if (err) | 1639 | if (i < n_q_to_ac) |
1640 | priv->queue_to_ac[i] = q_to_ac[i]; | ||
1641 | else | ||
1642 | priv->queue_to_ac[i] = IWL_INVALID_AC; | ||
1643 | } | ||
1644 | |||
1645 | WARN_ON(trans_cfg.queue_to_fifo[trans_cfg.cmd_queue] != | ||
1646 | IWLAGN_CMD_FIFO_NUM); | ||
1647 | |||
1648 | if (iwl_init_drv(priv)) | ||
1337 | goto out_free_eeprom; | 1649 | goto out_free_eeprom; |
1650 | |||
1338 | /* At this point both hw and priv are initialized. */ | 1651 | /* At this point both hw and priv are initialized. */ |
1339 | 1652 | ||
1340 | /******************** | 1653 | /******************** |
@@ -1367,15 +1680,12 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1367 | * | 1680 | * |
1368 | * 7. Setup and register with mac80211 and debugfs | 1681 | * 7. Setup and register with mac80211 and debugfs |
1369 | **************************************************/ | 1682 | **************************************************/ |
1370 | err = iwlagn_mac_setup_register(priv, &fw->ucode_capa); | 1683 | if (iwlagn_mac_setup_register(priv, &fw->ucode_capa)) |
1371 | if (err) | ||
1372 | goto out_destroy_workqueue; | 1684 | goto out_destroy_workqueue; |
1373 | 1685 | ||
1374 | err = iwl_dbgfs_register(priv, DRV_NAME); | 1686 | if (iwl_dbgfs_register(priv, DRV_NAME)) |
1375 | if (err) | ||
1376 | IWL_ERR(priv, | 1687 | IWL_ERR(priv, |
1377 | "failed to create debugfs files. Ignoring error: %d\n", | 1688 | "failed to create debugfs files. Ignoring error\n"); |
1378 | err); | ||
1379 | 1689 | ||
1380 | return op_mode; | 1690 | return op_mode; |
1381 | 1691 | ||
@@ -1429,13 +1739,399 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) | |||
1429 | ieee80211_free_hw(priv->hw); | 1739 | ieee80211_free_hw(priv->hw); |
1430 | } | 1740 | } |
1431 | 1741 | ||
1742 | static const char * const desc_lookup_text[] = { | ||
1743 | "OK", | ||
1744 | "FAIL", | ||
1745 | "BAD_PARAM", | ||
1746 | "BAD_CHECKSUM", | ||
1747 | "NMI_INTERRUPT_WDG", | ||
1748 | "SYSASSERT", | ||
1749 | "FATAL_ERROR", | ||
1750 | "BAD_COMMAND", | ||
1751 | "HW_ERROR_TUNE_LOCK", | ||
1752 | "HW_ERROR_TEMPERATURE", | ||
1753 | "ILLEGAL_CHAN_FREQ", | ||
1754 | "VCC_NOT_STABLE", | ||
1755 | "FH_ERROR", | ||
1756 | "NMI_INTERRUPT_HOST", | ||
1757 | "NMI_INTERRUPT_ACTION_PT", | ||
1758 | "NMI_INTERRUPT_UNKNOWN", | ||
1759 | "UCODE_VERSION_MISMATCH", | ||
1760 | "HW_ERROR_ABS_LOCK", | ||
1761 | "HW_ERROR_CAL_LOCK_FAIL", | ||
1762 | "NMI_INTERRUPT_INST_ACTION_PT", | ||
1763 | "NMI_INTERRUPT_DATA_ACTION_PT", | ||
1764 | "NMI_TRM_HW_ER", | ||
1765 | "NMI_INTERRUPT_TRM", | ||
1766 | "NMI_INTERRUPT_BREAK_POINT", | ||
1767 | "DEBUG_0", | ||
1768 | "DEBUG_1", | ||
1769 | "DEBUG_2", | ||
1770 | "DEBUG_3", | ||
1771 | }; | ||
1772 | |||
1773 | static struct { char *name; u8 num; } advanced_lookup[] = { | ||
1774 | { "NMI_INTERRUPT_WDG", 0x34 }, | ||
1775 | { "SYSASSERT", 0x35 }, | ||
1776 | { "UCODE_VERSION_MISMATCH", 0x37 }, | ||
1777 | { "BAD_COMMAND", 0x38 }, | ||
1778 | { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, | ||
1779 | { "FATAL_ERROR", 0x3D }, | ||
1780 | { "NMI_TRM_HW_ERR", 0x46 }, | ||
1781 | { "NMI_INTERRUPT_TRM", 0x4C }, | ||
1782 | { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, | ||
1783 | { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, | ||
1784 | { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, | ||
1785 | { "NMI_INTERRUPT_HOST", 0x66 }, | ||
1786 | { "NMI_INTERRUPT_ACTION_PT", 0x7C }, | ||
1787 | { "NMI_INTERRUPT_UNKNOWN", 0x84 }, | ||
1788 | { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, | ||
1789 | { "ADVANCED_SYSASSERT", 0 }, | ||
1790 | }; | ||
1791 | |||
1792 | static const char *desc_lookup(u32 num) | ||
1793 | { | ||
1794 | int i; | ||
1795 | int max = ARRAY_SIZE(desc_lookup_text); | ||
1796 | |||
1797 | if (num < max) | ||
1798 | return desc_lookup_text[num]; | ||
1799 | |||
1800 | max = ARRAY_SIZE(advanced_lookup) - 1; | ||
1801 | for (i = 0; i < max; i++) { | ||
1802 | if (advanced_lookup[i].num == num) | ||
1803 | break; | ||
1804 | } | ||
1805 | return advanced_lookup[i].name; | ||
1806 | } | ||
1807 | |||
1808 | #define ERROR_START_OFFSET (1 * sizeof(u32)) | ||
1809 | #define ERROR_ELEM_SIZE (7 * sizeof(u32)) | ||
1810 | |||
1811 | static void iwl_dump_nic_error_log(struct iwl_priv *priv) | ||
1812 | { | ||
1813 | struct iwl_trans *trans = trans(priv); | ||
1814 | u32 base; | ||
1815 | struct iwl_error_event_table table; | ||
1816 | |||
1817 | base = priv->device_pointers.error_event_table; | ||
1818 | if (priv->cur_ucode == IWL_UCODE_INIT) { | ||
1819 | if (!base) | ||
1820 | base = priv->fw->init_errlog_ptr; | ||
1821 | } else { | ||
1822 | if (!base) | ||
1823 | base = priv->fw->inst_errlog_ptr; | ||
1824 | } | ||
1825 | |||
1826 | if (!iwlagn_hw_valid_rtc_data_addr(base)) { | ||
1827 | IWL_ERR(priv, | ||
1828 | "Not valid error log pointer 0x%08X for %s uCode\n", | ||
1829 | base, | ||
1830 | (priv->cur_ucode == IWL_UCODE_INIT) | ||
1831 | ? "Init" : "RT"); | ||
1832 | return; | ||
1833 | } | ||
1834 | |||
1835 | /*TODO: Update dbgfs with ISR error stats obtained below */ | ||
1836 | iwl_read_targ_mem_words(trans, base, &table, sizeof(table)); | ||
1837 | |||
1838 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { | ||
1839 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); | ||
1840 | IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", | ||
1841 | priv->shrd->status, table.valid); | ||
1842 | } | ||
1843 | |||
1844 | trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, | ||
1845 | table.data1, table.data2, table.line, | ||
1846 | table.blink1, table.blink2, table.ilink1, | ||
1847 | table.ilink2, table.bcon_time, table.gp1, | ||
1848 | table.gp2, table.gp3, table.ucode_ver, | ||
1849 | table.hw_ver, table.brd_ver); | ||
1850 | IWL_ERR(priv, "0x%08X | %-28s\n", table.error_id, | ||
1851 | desc_lookup(table.error_id)); | ||
1852 | IWL_ERR(priv, "0x%08X | uPc\n", table.pc); | ||
1853 | IWL_ERR(priv, "0x%08X | branchlink1\n", table.blink1); | ||
1854 | IWL_ERR(priv, "0x%08X | branchlink2\n", table.blink2); | ||
1855 | IWL_ERR(priv, "0x%08X | interruptlink1\n", table.ilink1); | ||
1856 | IWL_ERR(priv, "0x%08X | interruptlink2\n", table.ilink2); | ||
1857 | IWL_ERR(priv, "0x%08X | data1\n", table.data1); | ||
1858 | IWL_ERR(priv, "0x%08X | data2\n", table.data2); | ||
1859 | IWL_ERR(priv, "0x%08X | line\n", table.line); | ||
1860 | IWL_ERR(priv, "0x%08X | beacon time\n", table.bcon_time); | ||
1861 | IWL_ERR(priv, "0x%08X | tsf low\n", table.tsf_low); | ||
1862 | IWL_ERR(priv, "0x%08X | tsf hi\n", table.tsf_hi); | ||
1863 | IWL_ERR(priv, "0x%08X | time gp1\n", table.gp1); | ||
1864 | IWL_ERR(priv, "0x%08X | time gp2\n", table.gp2); | ||
1865 | IWL_ERR(priv, "0x%08X | time gp3\n", table.gp3); | ||
1866 | IWL_ERR(priv, "0x%08X | uCode version\n", table.ucode_ver); | ||
1867 | IWL_ERR(priv, "0x%08X | hw version\n", table.hw_ver); | ||
1868 | IWL_ERR(priv, "0x%08X | board version\n", table.brd_ver); | ||
1869 | IWL_ERR(priv, "0x%08X | hcmd\n", table.hcmd); | ||
1870 | IWL_ERR(priv, "0x%08X | isr0\n", table.isr0); | ||
1871 | IWL_ERR(priv, "0x%08X | isr1\n", table.isr1); | ||
1872 | IWL_ERR(priv, "0x%08X | isr2\n", table.isr2); | ||
1873 | IWL_ERR(priv, "0x%08X | isr3\n", table.isr3); | ||
1874 | IWL_ERR(priv, "0x%08X | isr4\n", table.isr4); | ||
1875 | IWL_ERR(priv, "0x%08X | isr_pref\n", table.isr_pref); | ||
1876 | IWL_ERR(priv, "0x%08X | wait_event\n", table.wait_event); | ||
1877 | IWL_ERR(priv, "0x%08X | l2p_control\n", table.l2p_control); | ||
1878 | IWL_ERR(priv, "0x%08X | l2p_duration\n", table.l2p_duration); | ||
1879 | IWL_ERR(priv, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid); | ||
1880 | IWL_ERR(priv, "0x%08X | l2p_addr_match\n", table.l2p_addr_match); | ||
1881 | IWL_ERR(priv, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel); | ||
1882 | IWL_ERR(priv, "0x%08X | timestamp\n", table.u_timestamp); | ||
1883 | IWL_ERR(priv, "0x%08X | flow_handler\n", table.flow_handler); | ||
1884 | } | ||
1885 | |||
1886 | #define EVENT_START_OFFSET (4 * sizeof(u32)) | ||
1887 | |||
1888 | /** | ||
1889 | * iwl_print_event_log - Dump error event log to syslog | ||
1890 | * | ||
1891 | */ | ||
1892 | static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | ||
1893 | u32 num_events, u32 mode, | ||
1894 | int pos, char **buf, size_t bufsz) | ||
1895 | { | ||
1896 | u32 i; | ||
1897 | u32 base; /* SRAM byte address of event log header */ | ||
1898 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ | ||
1899 | u32 ptr; /* SRAM byte address of log data */ | ||
1900 | u32 ev, time, data; /* event log data */ | ||
1901 | unsigned long reg_flags; | ||
1902 | |||
1903 | struct iwl_trans *trans = trans(priv); | ||
1904 | |||
1905 | if (num_events == 0) | ||
1906 | return pos; | ||
1907 | |||
1908 | base = priv->device_pointers.log_event_table; | ||
1909 | if (priv->cur_ucode == IWL_UCODE_INIT) { | ||
1910 | if (!base) | ||
1911 | base = priv->fw->init_evtlog_ptr; | ||
1912 | } else { | ||
1913 | if (!base) | ||
1914 | base = priv->fw->inst_evtlog_ptr; | ||
1915 | } | ||
1916 | |||
1917 | if (mode == 0) | ||
1918 | event_size = 2 * sizeof(u32); | ||
1919 | else | ||
1920 | event_size = 3 * sizeof(u32); | ||
1921 | |||
1922 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | ||
1923 | |||
1924 | /* Make sure device is powered up for SRAM reads */ | ||
1925 | spin_lock_irqsave(&trans->reg_lock, reg_flags); | ||
1926 | if (unlikely(!iwl_grab_nic_access(trans))) | ||
1927 | goto out_unlock; | ||
1928 | |||
1929 | /* Set starting address; reads will auto-increment */ | ||
1930 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); | ||
1931 | |||
1932 | /* "time" is actually "data" for mode 0 (no timestamp). | ||
1933 | * place event id # at far right for easier visual parsing. */ | ||
1934 | for (i = 0; i < num_events; i++) { | ||
1935 | ev = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | ||
1936 | time = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | ||
1937 | if (mode == 0) { | ||
1938 | /* data, ev */ | ||
1939 | if (bufsz) { | ||
1940 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1941 | "EVT_LOG:0x%08x:%04u\n", | ||
1942 | time, ev); | ||
1943 | } else { | ||
1944 | trace_iwlwifi_dev_ucode_event(trans->dev, 0, | ||
1945 | time, ev); | ||
1946 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", | ||
1947 | time, ev); | ||
1948 | } | ||
1949 | } else { | ||
1950 | data = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | ||
1951 | if (bufsz) { | ||
1952 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
1953 | "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
1954 | time, data, ev); | ||
1955 | } else { | ||
1956 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
1957 | time, data, ev); | ||
1958 | trace_iwlwifi_dev_ucode_event(trans->dev, time, | ||
1959 | data, ev); | ||
1960 | } | ||
1961 | } | ||
1962 | } | ||
1963 | |||
1964 | /* Allow device to power down */ | ||
1965 | iwl_release_nic_access(trans); | ||
1966 | out_unlock: | ||
1967 | spin_unlock_irqrestore(&trans->reg_lock, reg_flags); | ||
1968 | return pos; | ||
1969 | } | ||
1970 | |||
1971 | /** | ||
1972 | * iwl_print_last_event_logs - Dump the newest # of event log to syslog | ||
1973 | */ | ||
1974 | static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | ||
1975 | u32 num_wraps, u32 next_entry, | ||
1976 | u32 size, u32 mode, | ||
1977 | int pos, char **buf, size_t bufsz) | ||
1978 | { | ||
1979 | /* | ||
1980 | * display the newest DEFAULT_LOG_ENTRIES entries | ||
1981 | * i.e the entries just before the next ont that uCode would fill. | ||
1982 | */ | ||
1983 | if (num_wraps) { | ||
1984 | if (next_entry < size) { | ||
1985 | pos = iwl_print_event_log(priv, | ||
1986 | capacity - (size - next_entry), | ||
1987 | size - next_entry, mode, | ||
1988 | pos, buf, bufsz); | ||
1989 | pos = iwl_print_event_log(priv, 0, | ||
1990 | next_entry, mode, | ||
1991 | pos, buf, bufsz); | ||
1992 | } else | ||
1993 | pos = iwl_print_event_log(priv, next_entry - size, | ||
1994 | size, mode, pos, buf, bufsz); | ||
1995 | } else { | ||
1996 | if (next_entry < size) { | ||
1997 | pos = iwl_print_event_log(priv, 0, next_entry, | ||
1998 | mode, pos, buf, bufsz); | ||
1999 | } else { | ||
2000 | pos = iwl_print_event_log(priv, next_entry - size, | ||
2001 | size, mode, pos, buf, bufsz); | ||
2002 | } | ||
2003 | } | ||
2004 | return pos; | ||
2005 | } | ||
2006 | |||
2007 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) | ||
2008 | |||
2009 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | ||
2010 | char **buf, bool display) | ||
2011 | { | ||
2012 | u32 base; /* SRAM byte address of event log header */ | ||
2013 | u32 capacity; /* event log capacity in # entries */ | ||
2014 | u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ | ||
2015 | u32 num_wraps; /* # times uCode wrapped to top of log */ | ||
2016 | u32 next_entry; /* index of next entry to be written by uCode */ | ||
2017 | u32 size; /* # entries that we'll print */ | ||
2018 | u32 logsize; | ||
2019 | int pos = 0; | ||
2020 | size_t bufsz = 0; | ||
2021 | struct iwl_trans *trans = trans(priv); | ||
2022 | |||
2023 | base = priv->device_pointers.log_event_table; | ||
2024 | if (priv->cur_ucode == IWL_UCODE_INIT) { | ||
2025 | logsize = priv->fw->init_evtlog_size; | ||
2026 | if (!base) | ||
2027 | base = priv->fw->init_evtlog_ptr; | ||
2028 | } else { | ||
2029 | logsize = priv->fw->inst_evtlog_size; | ||
2030 | if (!base) | ||
2031 | base = priv->fw->inst_evtlog_ptr; | ||
2032 | } | ||
2033 | |||
2034 | if (!iwlagn_hw_valid_rtc_data_addr(base)) { | ||
2035 | IWL_ERR(priv, | ||
2036 | "Invalid event log pointer 0x%08X for %s uCode\n", | ||
2037 | base, | ||
2038 | (priv->cur_ucode == IWL_UCODE_INIT) | ||
2039 | ? "Init" : "RT"); | ||
2040 | return -EINVAL; | ||
2041 | } | ||
2042 | |||
2043 | /* event log header */ | ||
2044 | capacity = iwl_read_targ_mem(trans, base); | ||
2045 | mode = iwl_read_targ_mem(trans, base + (1 * sizeof(u32))); | ||
2046 | num_wraps = iwl_read_targ_mem(trans, base + (2 * sizeof(u32))); | ||
2047 | next_entry = iwl_read_targ_mem(trans, base + (3 * sizeof(u32))); | ||
2048 | |||
2049 | if (capacity > logsize) { | ||
2050 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d " | ||
2051 | "entries\n", capacity, logsize); | ||
2052 | capacity = logsize; | ||
2053 | } | ||
2054 | |||
2055 | if (next_entry > logsize) { | ||
2056 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | ||
2057 | next_entry, logsize); | ||
2058 | next_entry = logsize; | ||
2059 | } | ||
2060 | |||
2061 | size = num_wraps ? capacity : next_entry; | ||
2062 | |||
2063 | /* bail out if nothing in log */ | ||
2064 | if (size == 0) { | ||
2065 | IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n"); | ||
2066 | return pos; | ||
2067 | } | ||
2068 | |||
2069 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2070 | if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log) | ||
2071 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) | ||
2072 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; | ||
2073 | #else | ||
2074 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) | ||
2075 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; | ||
2076 | #endif | ||
2077 | IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", | ||
2078 | size); | ||
2079 | |||
2080 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
2081 | if (display) { | ||
2082 | if (full_log) | ||
2083 | bufsz = capacity * 48; | ||
2084 | else | ||
2085 | bufsz = size * 48; | ||
2086 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
2087 | if (!*buf) | ||
2088 | return -ENOMEM; | ||
2089 | } | ||
2090 | if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) { | ||
2091 | /* | ||
2092 | * if uCode has wrapped back to top of log, | ||
2093 | * start at the oldest entry, | ||
2094 | * i.e the next one that uCode would fill. | ||
2095 | */ | ||
2096 | if (num_wraps) | ||
2097 | pos = iwl_print_event_log(priv, next_entry, | ||
2098 | capacity - next_entry, mode, | ||
2099 | pos, buf, bufsz); | ||
2100 | /* (then/else) start at top of log */ | ||
2101 | pos = iwl_print_event_log(priv, 0, | ||
2102 | next_entry, mode, pos, buf, bufsz); | ||
2103 | } else | ||
2104 | pos = iwl_print_last_event_logs(priv, capacity, num_wraps, | ||
2105 | next_entry, size, mode, | ||
2106 | pos, buf, bufsz); | ||
2107 | #else | ||
2108 | pos = iwl_print_last_event_logs(priv, capacity, num_wraps, | ||
2109 | next_entry, size, mode, | ||
2110 | pos, buf, bufsz); | ||
2111 | #endif | ||
2112 | return pos; | ||
2113 | } | ||
2114 | |||
2115 | static void iwl_nic_error(struct iwl_op_mode *op_mode) | ||
2116 | { | ||
2117 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
2118 | |||
2119 | IWL_ERR(priv, "Loaded firmware version: %s\n", | ||
2120 | priv->fw->fw_version); | ||
2121 | |||
2122 | iwl_dump_nic_error_log(priv); | ||
2123 | iwl_dump_nic_event_log(priv, false, NULL, false); | ||
2124 | |||
2125 | iwlagn_fw_error(priv, false); | ||
2126 | } | ||
2127 | |||
1432 | static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) | 2128 | static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode) |
1433 | { | 2129 | { |
1434 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2130 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
1435 | 2131 | ||
1436 | if (!iwl_check_for_ct_kill(priv)) { | 2132 | if (!iwl_check_for_ct_kill(priv)) { |
1437 | IWL_ERR(priv, "Restarting adapter queue is full\n"); | 2133 | IWL_ERR(priv, "Restarting adapter queue is full\n"); |
1438 | iwl_nic_error(op_mode); | 2134 | iwlagn_fw_error(priv, false); |
1439 | } | 2135 | } |
1440 | } | 2136 | } |
1441 | 2137 | ||
@@ -1446,17 +2142,39 @@ static void iwl_nic_config(struct iwl_op_mode *op_mode) | |||
1446 | cfg(priv)->lib->nic_config(priv); | 2142 | cfg(priv)->lib->nic_config(priv); |
1447 | } | 2143 | } |
1448 | 2144 | ||
1449 | static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac) | 2145 | static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) |
1450 | { | 2146 | { |
1451 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2147 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2148 | int ac = priv->queue_to_ac[queue]; | ||
2149 | |||
2150 | if (WARN_ON_ONCE(ac == IWL_INVALID_AC)) | ||
2151 | return; | ||
2152 | |||
2153 | if (atomic_inc_return(&priv->ac_stop_count[ac]) > 1) { | ||
2154 | IWL_DEBUG_TX_QUEUES(priv, | ||
2155 | "queue %d (AC %d) already stopped\n", | ||
2156 | queue, ac); | ||
2157 | return; | ||
2158 | } | ||
1452 | 2159 | ||
1453 | set_bit(ac, &priv->transport_queue_stop); | 2160 | set_bit(ac, &priv->transport_queue_stop); |
1454 | ieee80211_stop_queue(priv->hw, ac); | 2161 | ieee80211_stop_queue(priv->hw, ac); |
1455 | } | 2162 | } |
1456 | 2163 | ||
1457 | static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac) | 2164 | static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) |
1458 | { | 2165 | { |
1459 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 2166 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
2167 | int ac = priv->queue_to_ac[queue]; | ||
2168 | |||
2169 | if (WARN_ON_ONCE(ac == IWL_INVALID_AC)) | ||
2170 | return; | ||
2171 | |||
2172 | if (atomic_dec_return(&priv->ac_stop_count[ac]) > 0) { | ||
2173 | IWL_DEBUG_TX_QUEUES(priv, | ||
2174 | "queue %d (AC %d) already awake\n", | ||
2175 | queue, ac); | ||
2176 | return; | ||
2177 | } | ||
1460 | 2178 | ||
1461 | clear_bit(ac, &priv->transport_queue_stop); | 2179 | clear_bit(ac, &priv->transport_queue_stop); |
1462 | 2180 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 3780a03f2716..51001622430b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -65,6 +65,13 @@ | |||
65 | 65 | ||
66 | #include "iwl-dev.h" | 66 | #include "iwl-dev.h" |
67 | 67 | ||
68 | /* The first 11 queues (0-10) are used otherwise */ | ||
69 | #define IWLAGN_FIRST_AMPDU_QUEUE 11 | ||
70 | |||
71 | /* AUX (TX during scan dwell) queue */ | ||
72 | #define IWL_AUX_QUEUE 10 | ||
73 | |||
74 | |||
68 | struct iwl_ucode_capabilities; | 75 | struct iwl_ucode_capabilities; |
69 | 76 | ||
70 | extern struct ieee80211_ops iwlagn_hw_ops; | 77 | extern struct ieee80211_ops iwlagn_hw_ops; |
@@ -85,7 +92,6 @@ int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode, | |||
85 | struct iwl_rx_cmd_buffer *rxb, | 92 | struct iwl_rx_cmd_buffer *rxb, |
86 | struct iwl_device_cmd *cmd); | 93 | struct iwl_device_cmd *cmd); |
87 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); | 94 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); |
88 | void iwl_nic_error(struct iwl_op_mode *op_mode); | ||
89 | 95 | ||
90 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); | 96 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); |
91 | 97 | ||
@@ -115,9 +121,6 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf, | |||
115 | struct iwl_rxon_context *ctx); | 121 | struct iwl_rxon_context *ctx); |
116 | 122 | ||
117 | /* uCode */ | 123 | /* uCode */ |
118 | int iwlagn_rx_calib_result(struct iwl_priv *priv, | ||
119 | struct iwl_rx_cmd_buffer *rxb, | ||
120 | struct iwl_device_cmd *cmd); | ||
121 | int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); | 124 | int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type); |
122 | void iwl_send_prio_tbl(struct iwl_priv *priv); | 125 | void iwl_send_prio_tbl(struct iwl_priv *priv); |
123 | int iwl_init_alive_start(struct iwl_priv *priv); | 126 | int iwl_init_alive_start(struct iwl_priv *priv); |
@@ -128,6 +131,9 @@ int iwl_send_calib_results(struct iwl_priv *priv); | |||
128 | int iwl_calib_set(struct iwl_priv *priv, | 131 | int iwl_calib_set(struct iwl_priv *priv, |
129 | const struct iwl_calib_hdr *cmd, int len); | 132 | const struct iwl_calib_hdr *cmd, int len); |
130 | void iwl_calib_free_results(struct iwl_priv *priv); | 133 | void iwl_calib_free_results(struct iwl_priv *priv); |
134 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand); | ||
135 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | ||
136 | char **buf, bool display); | ||
131 | 137 | ||
132 | /* lib */ | 138 | /* lib */ |
133 | int iwlagn_send_tx_power(struct iwl_priv *priv); | 139 | int iwlagn_send_tx_power(struct iwl_priv *priv); |
@@ -386,6 +392,15 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) | |||
386 | return iwl_is_ready(priv); | 392 | return iwl_is_ready(priv); |
387 | } | 393 | } |
388 | 394 | ||
395 | static inline void iwl_dvm_set_pmi(struct iwl_priv *priv, bool state) | ||
396 | { | ||
397 | if (state) | ||
398 | set_bit(STATUS_POWER_PMI, &priv->status); | ||
399 | else | ||
400 | clear_bit(STATUS_POWER_PMI, &priv->status); | ||
401 | iwl_trans_set_pmi(trans(priv), state); | ||
402 | } | ||
403 | |||
389 | #ifdef CONFIG_IWLWIFI_DEBUG | 404 | #ifdef CONFIG_IWLWIFI_DEBUG |
390 | #define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \ | 405 | #define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \ |
391 | do { \ | 406 | do { \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 46490d3b95b9..88ea31d9eb75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -28,7 +28,6 @@ | |||
28 | 28 | ||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
34 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
@@ -44,189 +43,6 @@ | |||
44 | 43 | ||
45 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 44 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
46 | 45 | ||
47 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | ||
48 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | ||
49 | static void iwl_init_ht_hw_capab(const struct iwl_priv *priv, | ||
50 | struct ieee80211_sta_ht_cap *ht_info, | ||
51 | enum ieee80211_band band) | ||
52 | { | ||
53 | u16 max_bit_rate = 0; | ||
54 | u8 rx_chains_num = hw_params(priv).rx_chains_num; | ||
55 | u8 tx_chains_num = hw_params(priv).tx_chains_num; | ||
56 | |||
57 | ht_info->cap = 0; | ||
58 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | ||
59 | |||
60 | ht_info->ht_supported = true; | ||
61 | |||
62 | if (cfg(priv)->ht_params && | ||
63 | cfg(priv)->ht_params->ht_greenfield_support) | ||
64 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
65 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | ||
66 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | ||
67 | if (hw_params(priv).ht40_channel & BIT(band)) { | ||
68 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
69 | ht_info->cap |= IEEE80211_HT_CAP_SGI_40; | ||
70 | ht_info->mcs.rx_mask[4] = 0x01; | ||
71 | max_bit_rate = MAX_BIT_RATE_40_MHZ; | ||
72 | } | ||
73 | |||
74 | if (iwlagn_mod_params.amsdu_size_8K) | ||
75 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | ||
76 | |||
77 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | ||
78 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; | ||
79 | |||
80 | ht_info->mcs.rx_mask[0] = 0xFF; | ||
81 | if (rx_chains_num >= 2) | ||
82 | ht_info->mcs.rx_mask[1] = 0xFF; | ||
83 | if (rx_chains_num >= 3) | ||
84 | ht_info->mcs.rx_mask[2] = 0xFF; | ||
85 | |||
86 | /* Highest supported Rx data rate */ | ||
87 | max_bit_rate *= rx_chains_num; | ||
88 | WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); | ||
89 | ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); | ||
90 | |||
91 | /* Tx MCS capabilities */ | ||
92 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | ||
93 | if (tx_chains_num != rx_chains_num) { | ||
94 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | ||
95 | ht_info->mcs.tx_params |= ((tx_chains_num - 1) << | ||
96 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom | ||
102 | */ | ||
103 | int iwl_init_geos(struct iwl_priv *priv) | ||
104 | { | ||
105 | struct iwl_channel_info *ch; | ||
106 | struct ieee80211_supported_band *sband; | ||
107 | struct ieee80211_channel *channels; | ||
108 | struct ieee80211_channel *geo_ch; | ||
109 | struct ieee80211_rate *rates; | ||
110 | int i = 0; | ||
111 | s8 max_tx_power = IWLAGN_TX_POWER_TARGET_POWER_MIN; | ||
112 | |||
113 | if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || | ||
114 | priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { | ||
115 | IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); | ||
116 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | channels = kcalloc(priv->channel_count, | ||
121 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
122 | if (!channels) | ||
123 | return -ENOMEM; | ||
124 | |||
125 | rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate), | ||
126 | GFP_KERNEL); | ||
127 | if (!rates) { | ||
128 | kfree(channels); | ||
129 | return -ENOMEM; | ||
130 | } | ||
131 | |||
132 | /* 5.2GHz channels start after the 2.4GHz channels */ | ||
133 | sband = &priv->bands[IEEE80211_BAND_5GHZ]; | ||
134 | sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; | ||
135 | /* just OFDM */ | ||
136 | sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; | ||
137 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; | ||
138 | |||
139 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
140 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
141 | IEEE80211_BAND_5GHZ); | ||
142 | |||
143 | sband = &priv->bands[IEEE80211_BAND_2GHZ]; | ||
144 | sband->channels = channels; | ||
145 | /* OFDM & CCK */ | ||
146 | sband->bitrates = rates; | ||
147 | sband->n_bitrates = IWL_RATE_COUNT_LEGACY; | ||
148 | |||
149 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) | ||
150 | iwl_init_ht_hw_capab(priv, &sband->ht_cap, | ||
151 | IEEE80211_BAND_2GHZ); | ||
152 | |||
153 | priv->ieee_channels = channels; | ||
154 | priv->ieee_rates = rates; | ||
155 | |||
156 | for (i = 0; i < priv->channel_count; i++) { | ||
157 | ch = &priv->channel_info[i]; | ||
158 | |||
159 | /* FIXME: might be removed if scan is OK */ | ||
160 | if (!is_channel_valid(ch)) | ||
161 | continue; | ||
162 | |||
163 | sband = &priv->bands[ch->band]; | ||
164 | |||
165 | geo_ch = &sband->channels[sband->n_channels++]; | ||
166 | |||
167 | geo_ch->center_freq = | ||
168 | ieee80211_channel_to_frequency(ch->channel, ch->band); | ||
169 | geo_ch->max_power = ch->max_power_avg; | ||
170 | geo_ch->max_antenna_gain = 0xff; | ||
171 | geo_ch->hw_value = ch->channel; | ||
172 | |||
173 | if (is_channel_valid(ch)) { | ||
174 | if (!(ch->flags & EEPROM_CHANNEL_IBSS)) | ||
175 | geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; | ||
176 | |||
177 | if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) | ||
178 | geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
179 | |||
180 | if (ch->flags & EEPROM_CHANNEL_RADAR) | ||
181 | geo_ch->flags |= IEEE80211_CHAN_RADAR; | ||
182 | |||
183 | geo_ch->flags |= ch->ht40_extension_channel; | ||
184 | |||
185 | if (ch->max_power_avg > max_tx_power) | ||
186 | max_tx_power = ch->max_power_avg; | ||
187 | } else { | ||
188 | geo_ch->flags |= IEEE80211_CHAN_DISABLED; | ||
189 | } | ||
190 | |||
191 | IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", | ||
192 | ch->channel, geo_ch->center_freq, | ||
193 | is_channel_a_band(ch) ? "5.2" : "2.4", | ||
194 | geo_ch->flags & IEEE80211_CHAN_DISABLED ? | ||
195 | "restricted" : "valid", | ||
196 | geo_ch->flags); | ||
197 | } | ||
198 | |||
199 | priv->tx_power_device_lmt = max_tx_power; | ||
200 | priv->tx_power_user_lmt = max_tx_power; | ||
201 | priv->tx_power_next = max_tx_power; | ||
202 | |||
203 | if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && | ||
204 | hw_params(priv).sku & EEPROM_SKU_CAP_BAND_52GHZ) { | ||
205 | IWL_INFO(priv, "Incorrectly detected BG card as ABG. " | ||
206 | "Please send your %s to maintainer.\n", | ||
207 | trans(priv)->hw_id_str); | ||
208 | hw_params(priv).sku &= ~EEPROM_SKU_CAP_BAND_52GHZ; | ||
209 | } | ||
210 | |||
211 | IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", | ||
212 | priv->bands[IEEE80211_BAND_2GHZ].n_channels, | ||
213 | priv->bands[IEEE80211_BAND_5GHZ].n_channels); | ||
214 | |||
215 | set_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * iwl_free_geos - undo allocations in iwl_init_geos | ||
222 | */ | ||
223 | void iwl_free_geos(struct iwl_priv *priv) | ||
224 | { | ||
225 | kfree(priv->ieee_channels); | ||
226 | kfree(priv->ieee_rates); | ||
227 | clear_bit(STATUS_GEO_CONFIGURED, &priv->status); | ||
228 | } | ||
229 | |||
230 | static bool iwl_is_channel_extension(struct iwl_priv *priv, | 46 | static bool iwl_is_channel_extension(struct iwl_priv *priv, |
231 | enum ieee80211_band band, | 47 | enum ieee80211_band band, |
232 | u16 channel, u8 extension_chan_offset) | 48 | u16 channel, u8 extension_chan_offset) |
@@ -271,255 +87,6 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
271 | ctx->ht.extension_chan_offset); | 87 | ctx->ht.extension_chan_offset); |
272 | } | 88 | } |
273 | 89 | ||
274 | static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | ||
275 | { | ||
276 | u16 new_val; | ||
277 | u16 beacon_factor; | ||
278 | |||
279 | /* | ||
280 | * If mac80211 hasn't given us a beacon interval, program | ||
281 | * the default into the device (not checking this here | ||
282 | * would cause the adjustment below to return the maximum | ||
283 | * value, which may break PAN.) | ||
284 | */ | ||
285 | if (!beacon_val) | ||
286 | return DEFAULT_BEACON_INTERVAL; | ||
287 | |||
288 | /* | ||
289 | * If the beacon interval we obtained from the peer | ||
290 | * is too large, we'll have to wake up more often | ||
291 | * (and in IBSS case, we'll beacon too much) | ||
292 | * | ||
293 | * For example, if max_beacon_val is 4096, and the | ||
294 | * requested beacon interval is 7000, we'll have to | ||
295 | * use 3500 to be able to wake up on the beacons. | ||
296 | * | ||
297 | * This could badly influence beacon detection stats. | ||
298 | */ | ||
299 | |||
300 | beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val; | ||
301 | new_val = beacon_val / beacon_factor; | ||
302 | |||
303 | if (!new_val) | ||
304 | new_val = max_beacon_val; | ||
305 | |||
306 | return new_val; | ||
307 | } | ||
308 | |||
309 | int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | ||
310 | { | ||
311 | u64 tsf; | ||
312 | s32 interval_tm, rem; | ||
313 | struct ieee80211_conf *conf = NULL; | ||
314 | u16 beacon_int; | ||
315 | struct ieee80211_vif *vif = ctx->vif; | ||
316 | |||
317 | conf = &priv->hw->conf; | ||
318 | |||
319 | lockdep_assert_held(&priv->mutex); | ||
320 | |||
321 | memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); | ||
322 | |||
323 | ctx->timing.timestamp = cpu_to_le64(priv->timestamp); | ||
324 | ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval); | ||
325 | |||
326 | beacon_int = vif ? vif->bss_conf.beacon_int : 0; | ||
327 | |||
328 | /* | ||
329 | * TODO: For IBSS we need to get atim_window from mac80211, | ||
330 | * for now just always use 0 | ||
331 | */ | ||
332 | ctx->timing.atim_window = 0; | ||
333 | |||
334 | if (ctx->ctxid == IWL_RXON_CTX_PAN && | ||
335 | (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION) && | ||
336 | iwl_is_associated(priv, IWL_RXON_CTX_BSS) && | ||
337 | priv->contexts[IWL_RXON_CTX_BSS].vif && | ||
338 | priv->contexts[IWL_RXON_CTX_BSS].vif->bss_conf.beacon_int) { | ||
339 | ctx->timing.beacon_interval = | ||
340 | priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval; | ||
341 | beacon_int = le16_to_cpu(ctx->timing.beacon_interval); | ||
342 | } else if (ctx->ctxid == IWL_RXON_CTX_BSS && | ||
343 | iwl_is_associated(priv, IWL_RXON_CTX_PAN) && | ||
344 | priv->contexts[IWL_RXON_CTX_PAN].vif && | ||
345 | priv->contexts[IWL_RXON_CTX_PAN].vif->bss_conf.beacon_int && | ||
346 | (!iwl_is_associated_ctx(ctx) || !ctx->vif || | ||
347 | !ctx->vif->bss_conf.beacon_int)) { | ||
348 | ctx->timing.beacon_interval = | ||
349 | priv->contexts[IWL_RXON_CTX_PAN].timing.beacon_interval; | ||
350 | beacon_int = le16_to_cpu(ctx->timing.beacon_interval); | ||
351 | } else { | ||
352 | beacon_int = iwl_adjust_beacon_interval(beacon_int, | ||
353 | IWL_MAX_UCODE_BEACON_INTERVAL * TIME_UNIT); | ||
354 | ctx->timing.beacon_interval = cpu_to_le16(beacon_int); | ||
355 | } | ||
356 | |||
357 | ctx->beacon_int = beacon_int; | ||
358 | |||
359 | tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ | ||
360 | interval_tm = beacon_int * TIME_UNIT; | ||
361 | rem = do_div(tsf, interval_tm); | ||
362 | ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); | ||
363 | |||
364 | ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1; | ||
365 | |||
366 | IWL_DEBUG_ASSOC(priv, | ||
367 | "beacon interval %d beacon timer %d beacon tim %d\n", | ||
368 | le16_to_cpu(ctx->timing.beacon_interval), | ||
369 | le32_to_cpu(ctx->timing.beacon_init_val), | ||
370 | le16_to_cpu(ctx->timing.atim_window)); | ||
371 | |||
372 | return iwl_dvm_send_cmd_pdu(priv, ctx->rxon_timing_cmd, | ||
373 | CMD_SYNC, sizeof(ctx->timing), &ctx->timing); | ||
374 | } | ||
375 | |||
376 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | ||
377 | int hw_decrypt) | ||
378 | { | ||
379 | struct iwl_rxon_cmd *rxon = &ctx->staging; | ||
380 | |||
381 | if (hw_decrypt) | ||
382 | rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; | ||
383 | else | ||
384 | rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; | ||
385 | |||
386 | } | ||
387 | |||
388 | /* validate RXON structure is valid */ | ||
389 | int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) | ||
390 | { | ||
391 | struct iwl_rxon_cmd *rxon = &ctx->staging; | ||
392 | u32 errors = 0; | ||
393 | |||
394 | if (rxon->flags & RXON_FLG_BAND_24G_MSK) { | ||
395 | if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) { | ||
396 | IWL_WARN(priv, "check 2.4G: wrong narrow\n"); | ||
397 | errors |= BIT(0); | ||
398 | } | ||
399 | if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) { | ||
400 | IWL_WARN(priv, "check 2.4G: wrong radar\n"); | ||
401 | errors |= BIT(1); | ||
402 | } | ||
403 | } else { | ||
404 | if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) { | ||
405 | IWL_WARN(priv, "check 5.2G: not short slot!\n"); | ||
406 | errors |= BIT(2); | ||
407 | } | ||
408 | if (rxon->flags & RXON_FLG_CCK_MSK) { | ||
409 | IWL_WARN(priv, "check 5.2G: CCK!\n"); | ||
410 | errors |= BIT(3); | ||
411 | } | ||
412 | } | ||
413 | if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) { | ||
414 | IWL_WARN(priv, "mac/bssid mcast!\n"); | ||
415 | errors |= BIT(4); | ||
416 | } | ||
417 | |||
418 | /* make sure basic rates 6Mbps and 1Mbps are supported */ | ||
419 | if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 && | ||
420 | (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) { | ||
421 | IWL_WARN(priv, "neither 1 nor 6 are basic\n"); | ||
422 | errors |= BIT(5); | ||
423 | } | ||
424 | |||
425 | if (le16_to_cpu(rxon->assoc_id) > 2007) { | ||
426 | IWL_WARN(priv, "aid > 2007\n"); | ||
427 | errors |= BIT(6); | ||
428 | } | ||
429 | |||
430 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) | ||
431 | == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) { | ||
432 | IWL_WARN(priv, "CCK and short slot\n"); | ||
433 | errors |= BIT(7); | ||
434 | } | ||
435 | |||
436 | if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) | ||
437 | == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { | ||
438 | IWL_WARN(priv, "CCK and auto detect"); | ||
439 | errors |= BIT(8); | ||
440 | } | ||
441 | |||
442 | if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | | ||
443 | RXON_FLG_TGG_PROTECT_MSK)) == | ||
444 | RXON_FLG_TGG_PROTECT_MSK) { | ||
445 | IWL_WARN(priv, "TGg but no auto-detect\n"); | ||
446 | errors |= BIT(9); | ||
447 | } | ||
448 | |||
449 | if (rxon->channel == 0) { | ||
450 | IWL_WARN(priv, "zero channel is invalid\n"); | ||
451 | errors |= BIT(10); | ||
452 | } | ||
453 | |||
454 | WARN(errors, "Invalid RXON (%#x), channel %d", | ||
455 | errors, le16_to_cpu(rxon->channel)); | ||
456 | |||
457 | return errors ? -EINVAL : 0; | ||
458 | } | ||
459 | |||
460 | /** | ||
461 | * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed | ||
462 | * @priv: staging_rxon is compared to active_rxon | ||
463 | * | ||
464 | * If the RXON structure is changing enough to require a new tune, | ||
465 | * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that | ||
466 | * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. | ||
467 | */ | ||
468 | int iwl_full_rxon_required(struct iwl_priv *priv, | ||
469 | struct iwl_rxon_context *ctx) | ||
470 | { | ||
471 | const struct iwl_rxon_cmd *staging = &ctx->staging; | ||
472 | const struct iwl_rxon_cmd *active = &ctx->active; | ||
473 | |||
474 | #define CHK(cond) \ | ||
475 | if ((cond)) { \ | ||
476 | IWL_DEBUG_INFO(priv, "need full RXON - " #cond "\n"); \ | ||
477 | return 1; \ | ||
478 | } | ||
479 | |||
480 | #define CHK_NEQ(c1, c2) \ | ||
481 | if ((c1) != (c2)) { \ | ||
482 | IWL_DEBUG_INFO(priv, "need full RXON - " \ | ||
483 | #c1 " != " #c2 " - %d != %d\n", \ | ||
484 | (c1), (c2)); \ | ||
485 | return 1; \ | ||
486 | } | ||
487 | |||
488 | /* These items are only settable from the full RXON command */ | ||
489 | CHK(!iwl_is_associated_ctx(ctx)); | ||
490 | CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr)); | ||
491 | CHK(compare_ether_addr(staging->node_addr, active->node_addr)); | ||
492 | CHK(compare_ether_addr(staging->wlap_bssid_addr, | ||
493 | active->wlap_bssid_addr)); | ||
494 | CHK_NEQ(staging->dev_type, active->dev_type); | ||
495 | CHK_NEQ(staging->channel, active->channel); | ||
496 | CHK_NEQ(staging->air_propagation, active->air_propagation); | ||
497 | CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates, | ||
498 | active->ofdm_ht_single_stream_basic_rates); | ||
499 | CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates, | ||
500 | active->ofdm_ht_dual_stream_basic_rates); | ||
501 | CHK_NEQ(staging->ofdm_ht_triple_stream_basic_rates, | ||
502 | active->ofdm_ht_triple_stream_basic_rates); | ||
503 | CHK_NEQ(staging->assoc_id, active->assoc_id); | ||
504 | |||
505 | /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can | ||
506 | * be updated with the RXON_ASSOC command -- however only some | ||
507 | * flag transitions are allowed using RXON_ASSOC */ | ||
508 | |||
509 | /* Check if we are not switching bands */ | ||
510 | CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK, | ||
511 | active->flags & RXON_FLG_BAND_24G_MSK); | ||
512 | |||
513 | /* Check if we are switching association toggle */ | ||
514 | CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK, | ||
515 | active->filter_flags & RXON_FILTER_ASSOC_MSK); | ||
516 | |||
517 | #undef CHK | ||
518 | #undef CHK_NEQ | ||
519 | |||
520 | return 0; | ||
521 | } | ||
522 | |||
523 | static void _iwl_set_rxon_ht(struct iwl_priv *priv, | 90 | static void _iwl_set_rxon_ht(struct iwl_priv *priv, |
524 | struct iwl_ht_config *ht_conf, | 91 | struct iwl_ht_config *ht_conf, |
525 | struct iwl_rxon_context *ctx) | 92 | struct iwl_rxon_context *ctx) |
@@ -595,46 +162,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) | |||
595 | _iwl_set_rxon_ht(priv, ht_conf, ctx); | 162 | _iwl_set_rxon_ht(priv, ht_conf, ctx); |
596 | } | 163 | } |
597 | 164 | ||
598 | /* Return valid, unused, channel for a passive scan to reset the RF */ | ||
599 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, | ||
600 | enum ieee80211_band band) | ||
601 | { | ||
602 | const struct iwl_channel_info *ch_info; | ||
603 | int i; | ||
604 | u8 channel = 0; | ||
605 | u8 min, max; | ||
606 | struct iwl_rxon_context *ctx; | ||
607 | |||
608 | if (band == IEEE80211_BAND_5GHZ) { | ||
609 | min = 14; | ||
610 | max = priv->channel_count; | ||
611 | } else { | ||
612 | min = 0; | ||
613 | max = 14; | ||
614 | } | ||
615 | |||
616 | for (i = min; i < max; i++) { | ||
617 | bool busy = false; | ||
618 | |||
619 | for_each_context(priv, ctx) { | ||
620 | busy = priv->channel_info[i].channel == | ||
621 | le16_to_cpu(ctx->staging.channel); | ||
622 | if (busy) | ||
623 | break; | ||
624 | } | ||
625 | |||
626 | if (busy) | ||
627 | continue; | ||
628 | |||
629 | channel = priv->channel_info[i].channel; | ||
630 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
631 | if (is_channel_valid(ch_info)) | ||
632 | break; | ||
633 | } | ||
634 | |||
635 | return channel; | ||
636 | } | ||
637 | |||
638 | /** | 165 | /** |
639 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON | 166 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON |
640 | * @ch: requested channel as a pointer to struct ieee80211_channel | 167 | * @ch: requested channel as a pointer to struct ieee80211_channel |
@@ -828,7 +355,7 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv, | |||
828 | } | 355 | } |
829 | #endif | 356 | #endif |
830 | 357 | ||
831 | static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | 358 | void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) |
832 | { | 359 | { |
833 | unsigned int reload_msec; | 360 | unsigned int reload_msec; |
834 | unsigned long reload_jiffies; | 361 | unsigned long reload_jiffies; |
@@ -842,7 +369,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand) | |||
842 | priv->ucode_loaded = false; | 369 | priv->ucode_loaded = false; |
843 | 370 | ||
844 | /* Set the FW error flag -- cleared on iwl_down */ | 371 | /* Set the FW error flag -- cleared on iwl_down */ |
845 | set_bit(STATUS_FW_ERROR, &priv->shrd->status); | 372 | set_bit(STATUS_FW_ERROR, &priv->status); |
846 | 373 | ||
847 | /* Cancel currently queued command. */ | 374 | /* Cancel currently queued command. */ |
848 | clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); | 375 | clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); |
@@ -1451,13 +978,6 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | |||
1451 | return cpu_to_le32(res); | 978 | return cpu_to_le32(res); |
1452 | } | 979 | } |
1453 | 980 | ||
1454 | void iwl_nic_error(struct iwl_op_mode *op_mode) | ||
1455 | { | ||
1456 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | ||
1457 | |||
1458 | iwlagn_fw_error(priv, false); | ||
1459 | } | ||
1460 | |||
1461 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | 981 | void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) |
1462 | { | 982 | { |
1463 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); | 983 | struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 635eb685edeb..7aa3060fc6b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -93,18 +93,12 @@ struct iwl_lib_ops { | |||
93 | * L i b * | 93 | * L i b * |
94 | ***************************/ | 94 | ***************************/ |
95 | 95 | ||
96 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, | ||
97 | int hw_decrypt); | ||
98 | int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
99 | int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
100 | void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, | 96 | void iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, |
101 | struct iwl_rxon_context *ctx); | 97 | struct iwl_rxon_context *ctx); |
102 | void iwl_set_flags_for_band(struct iwl_priv *priv, | 98 | void iwl_set_flags_for_band(struct iwl_priv *priv, |
103 | struct iwl_rxon_context *ctx, | 99 | struct iwl_rxon_context *ctx, |
104 | enum ieee80211_band band, | 100 | enum ieee80211_band band, |
105 | struct ieee80211_vif *vif); | 101 | struct ieee80211_vif *vif); |
106 | u8 iwl_get_single_channel_number(struct iwl_priv *priv, | ||
107 | enum ieee80211_band band); | ||
108 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); | 102 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); |
109 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 103 | bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
110 | struct iwl_rxon_context *ctx, | 104 | struct iwl_rxon_context *ctx, |
@@ -204,19 +198,10 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval); | |||
204 | __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | 198 | __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, |
205 | u32 addon, u32 beacon_interval); | 199 | u32 addon, u32 beacon_interval); |
206 | 200 | ||
207 | |||
208 | /***************************************************** | ||
209 | * GEOS | ||
210 | ******************************************************/ | ||
211 | int iwl_init_geos(struct iwl_priv *priv); | ||
212 | void iwl_free_geos(struct iwl_priv *priv); | ||
213 | |||
214 | extern void iwl_send_bt_config(struct iwl_priv *priv); | 201 | extern void iwl_send_bt_config(struct iwl_priv *priv); |
215 | extern int iwl_send_statistics_request(struct iwl_priv *priv, | 202 | extern int iwl_send_statistics_request(struct iwl_priv *priv, |
216 | u8 flags, bool clear); | 203 | u8 flags, bool clear); |
217 | 204 | ||
218 | int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx); | ||
219 | |||
220 | static inline const struct ieee80211_supported_band *iwl_get_hw_mode( | 205 | static inline const struct ieee80211_supported_band *iwl_get_hw_mode( |
221 | struct iwl_priv *priv, enum ieee80211_band band) | 206 | struct iwl_priv *priv, enum ieee80211_band band) |
222 | { | 207 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 2bbaebd99ad4..d109d1bbb3a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -234,7 +234,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
234 | IWL_ERR(priv, "No uCode has been loadded.\n"); | 234 | IWL_ERR(priv, "No uCode has been loadded.\n"); |
235 | return -EINVAL; | 235 | return -EINVAL; |
236 | } | 236 | } |
237 | img = &priv->fw->img[priv->shrd->ucode_type]; | 237 | img = &priv->fw->img[priv->cur_ucode]; |
238 | priv->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; | 238 | priv->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len; |
239 | } | 239 | } |
240 | len = priv->dbgfs_sram_len; | 240 | len = priv->dbgfs_sram_len; |
@@ -369,14 +369,19 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
369 | i, station->sta.sta.addr, | 369 | i, station->sta.sta.addr, |
370 | station->sta.station_flags_msk); | 370 | station->sta.station_flags_msk); |
371 | pos += scnprintf(buf + pos, bufsz - pos, | 371 | pos += scnprintf(buf + pos, bufsz - pos, |
372 | "TID\tseq_num\trate_n_flags\n"); | 372 | "TID seqno next_rclmd " |
373 | "rate_n_flags state txq\n"); | ||
373 | 374 | ||
374 | for (j = 0; j < IWL_MAX_TID_COUNT; j++) { | 375 | for (j = 0; j < IWL_MAX_TID_COUNT; j++) { |
375 | tid_data = &priv->tid_data[i][j]; | 376 | tid_data = &priv->tid_data[i][j]; |
376 | pos += scnprintf(buf + pos, bufsz - pos, | 377 | pos += scnprintf(buf + pos, bufsz - pos, |
377 | "%d:\t%#x\t%#x", | 378 | "%d: 0x%.4x 0x%.4x 0x%.8x " |
379 | "%d %.2d", | ||
378 | j, tid_data->seq_number, | 380 | j, tid_data->seq_number, |
379 | tid_data->agg.rate_n_flags); | 381 | tid_data->next_reclaimed, |
382 | tid_data->agg.rate_n_flags, | ||
383 | tid_data->agg.state, | ||
384 | tid_data->agg.txq_id); | ||
380 | 385 | ||
381 | if (tid_data->agg.wait_for_ba) | 386 | if (tid_data->agg.wait_for_ba) |
382 | pos += scnprintf(buf + pos, bufsz - pos, | 387 | pos += scnprintf(buf + pos, bufsz - pos, |
@@ -544,9 +549,9 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
544 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", | 549 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", |
545 | test_bit(STATUS_SCAN_HW, &priv->status)); | 550 | test_bit(STATUS_SCAN_HW, &priv->status)); |
546 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", | 551 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", |
547 | test_bit(STATUS_POWER_PMI, &priv->shrd->status)); | 552 | test_bit(STATUS_POWER_PMI, &priv->status)); |
548 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", | 553 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", |
549 | test_bit(STATUS_FW_ERROR, &priv->shrd->status)); | 554 | test_bit(STATUS_FW_ERROR, &priv->status)); |
550 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 555 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
551 | } | 556 | } |
552 | 557 | ||
@@ -2473,6 +2478,44 @@ static ssize_t iwl_dbgfs_echo_test_write(struct file *file, | |||
2473 | return count; | 2478 | return count; |
2474 | } | 2479 | } |
2475 | 2480 | ||
2481 | static ssize_t iwl_dbgfs_log_event_read(struct file *file, | ||
2482 | char __user *user_buf, | ||
2483 | size_t count, loff_t *ppos) | ||
2484 | { | ||
2485 | struct iwl_priv *priv = file->private_data; | ||
2486 | char *buf; | ||
2487 | int pos = 0; | ||
2488 | ssize_t ret = -ENOMEM; | ||
2489 | |||
2490 | ret = pos = iwl_dump_nic_event_log(priv, true, &buf, true); | ||
2491 | if (buf) { | ||
2492 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2493 | kfree(buf); | ||
2494 | } | ||
2495 | return ret; | ||
2496 | } | ||
2497 | |||
2498 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, | ||
2499 | const char __user *user_buf, | ||
2500 | size_t count, loff_t *ppos) | ||
2501 | { | ||
2502 | struct iwl_priv *priv = file->private_data; | ||
2503 | u32 event_log_flag; | ||
2504 | char buf[8]; | ||
2505 | int buf_size; | ||
2506 | |||
2507 | memset(buf, 0, sizeof(buf)); | ||
2508 | buf_size = min(count, sizeof(buf) - 1); | ||
2509 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2510 | return -EFAULT; | ||
2511 | if (sscanf(buf, "%d", &event_log_flag) != 1) | ||
2512 | return -EFAULT; | ||
2513 | if (event_log_flag == 1) | ||
2514 | iwl_dump_nic_event_log(priv, true, NULL, false); | ||
2515 | |||
2516 | return count; | ||
2517 | } | ||
2518 | |||
2476 | DEBUGFS_READ_FILE_OPS(rx_statistics); | 2519 | DEBUGFS_READ_FILE_OPS(rx_statistics); |
2477 | DEBUGFS_READ_FILE_OPS(tx_statistics); | 2520 | DEBUGFS_READ_FILE_OPS(tx_statistics); |
2478 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 2521 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
@@ -2497,6 +2540,7 @@ DEBUGFS_READ_FILE_OPS(bt_traffic); | |||
2497 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); | 2540 | DEBUGFS_READ_WRITE_FILE_OPS(protection_mode); |
2498 | DEBUGFS_READ_FILE_OPS(reply_tx_error); | 2541 | DEBUGFS_READ_FILE_OPS(reply_tx_error); |
2499 | DEBUGFS_WRITE_FILE_OPS(echo_test); | 2542 | DEBUGFS_WRITE_FILE_OPS(echo_test); |
2543 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); | ||
2500 | 2544 | ||
2501 | /* | 2545 | /* |
2502 | * Create the debugfs files and directories | 2546 | * Create the debugfs files and directories |
@@ -2560,6 +2604,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
2560 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); | 2604 | DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); |
2561 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); | 2605 | DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR); |
2562 | DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); | 2606 | DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); |
2607 | DEBUGFS_ADD_FILE(log_event, dir_debug, S_IWUSR | S_IRUSR); | ||
2608 | |||
2563 | if (iwl_advanced_bt_coexist(priv)) | 2609 | if (iwl_advanced_bt_coexist(priv)) |
2564 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); | 2610 | DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); |
2565 | 2611 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 16956b777f96..99be58940e27 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -220,8 +220,7 @@ enum iwl_agg_state { | |||
220 | * Tx response (REPLY_TX), and the block ack notification | 220 | * Tx response (REPLY_TX), and the block ack notification |
221 | * (REPLY_COMPRESSED_BA). | 221 | * (REPLY_COMPRESSED_BA). |
222 | * @state: state of the BA agreement establishment / tear down. | 222 | * @state: state of the BA agreement establishment / tear down. |
223 | * @txq_id: Tx queue used by the BA session - used by the transport layer. | 223 | * @txq_id: Tx queue used by the BA session |
224 | * Needed by the upper layer for debugfs only. | ||
225 | * @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or | 224 | * @ssn: the first packet to be sent in AGG HW queue in Tx AGG start flow, or |
226 | * the first packet to be sent in legacy HW queue in Tx AGG stop flow. | 225 | * the first packet to be sent in legacy HW queue in Tx AGG stop flow. |
227 | * Basically when next_reclaimed reaches ssn, we can tell mac80211 that | 226 | * Basically when next_reclaimed reaches ssn, we can tell mac80211 that |
@@ -623,6 +622,10 @@ struct iwl_force_reset { | |||
623 | struct iwl_rxon_context { | 622 | struct iwl_rxon_context { |
624 | struct ieee80211_vif *vif; | 623 | struct ieee80211_vif *vif; |
625 | 624 | ||
625 | u8 mcast_queue; | ||
626 | u8 ac_to_queue[IEEE80211_NUM_ACS]; | ||
627 | u8 ac_to_fifo[IEEE80211_NUM_ACS]; | ||
628 | |||
626 | /* | 629 | /* |
627 | * We could use the vif to indicate active, but we | 630 | * We could use the vif to indicate active, but we |
628 | * also need it to be active during disabling when | 631 | * also need it to be active during disabling when |
@@ -720,6 +723,11 @@ struct iwl_priv { | |||
720 | 723 | ||
721 | unsigned long transport_queue_stop; | 724 | unsigned long transport_queue_stop; |
722 | bool passive_no_rx; | 725 | bool passive_no_rx; |
726 | #define IWL_INVALID_AC 0xff | ||
727 | u8 queue_to_ac[IWL_MAX_HW_QUEUES]; | ||
728 | atomic_t ac_stop_count[IEEE80211_NUM_ACS]; | ||
729 | |||
730 | unsigned long agg_q_alloc[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; | ||
723 | 731 | ||
724 | /* ieee device used by generic ieee processing code */ | 732 | /* ieee device used by generic ieee processing code */ |
725 | struct ieee80211_hw *hw; | 733 | struct ieee80211_hw *hw; |
@@ -731,6 +739,7 @@ struct iwl_priv { | |||
731 | struct workqueue_struct *workqueue; | 739 | struct workqueue_struct *workqueue; |
732 | 740 | ||
733 | enum ieee80211_band band; | 741 | enum ieee80211_band band; |
742 | u8 valid_contexts; | ||
734 | 743 | ||
735 | void (*pre_rx_handler)(struct iwl_priv *priv, | 744 | void (*pre_rx_handler)(struct iwl_priv *priv, |
736 | struct iwl_rx_cmd_buffer *rxb); | 745 | struct iwl_rx_cmd_buffer *rxb); |
@@ -982,6 +991,15 @@ struct iwl_priv { | |||
982 | __le64 replay_ctr; | 991 | __le64 replay_ctr; |
983 | __le16 last_seq_ctl; | 992 | __le16 last_seq_ctl; |
984 | bool have_rekey_data; | 993 | bool have_rekey_data; |
994 | |||
995 | /* device_pointers: pointers to ucode event tables */ | ||
996 | struct { | ||
997 | u32 error_event_table; | ||
998 | u32 log_event_table; | ||
999 | } device_pointers; | ||
1000 | |||
1001 | /* indicator of loaded ucode image */ | ||
1002 | enum iwl_ucode_type cur_ucode; | ||
985 | }; /*iwl_priv */ | 1003 | }; /*iwl_priv */ |
986 | 1004 | ||
987 | extern struct kmem_cache *iwl_tx_cmd_pool; | 1005 | extern struct kmem_cache *iwl_tx_cmd_pool; |
@@ -998,7 +1016,7 @@ iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) | |||
998 | #define for_each_context(priv, ctx) \ | 1016 | #define for_each_context(priv, ctx) \ |
999 | for (ctx = &priv->contexts[IWL_RXON_CTX_BSS]; \ | 1017 | for (ctx = &priv->contexts[IWL_RXON_CTX_BSS]; \ |
1000 | ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \ | 1018 | ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \ |
1001 | if (priv->shrd->valid_contexts & BIT(ctx->ctxid)) | 1019 | if (priv->valid_contexts & BIT(ctx->ctxid)) |
1002 | 1020 | ||
1003 | static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx) | 1021 | static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx) |
1004 | { | 1022 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index b6805f8e9a01..f1c675a2a6f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c | |||
@@ -157,7 +157,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
157 | */ | 157 | */ |
158 | 158 | ||
159 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | | 159 | hw->flags |= IEEE80211_HW_SUPPORTS_PS | |
160 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; | 160 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
161 | IEEE80211_HW_SCAN_WHILE_IDLE; | ||
161 | 162 | ||
162 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) | 163 | if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE) |
163 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 164 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
@@ -437,7 +438,6 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
437 | unsigned long flags; | 438 | unsigned long flags; |
438 | u32 base, status = 0xffffffff; | 439 | u32 base, status = 0xffffffff; |
439 | int ret = -EIO; | 440 | int ret = -EIO; |
440 | const struct fw_img *img; | ||
441 | 441 | ||
442 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 442 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
443 | mutex_lock(&priv->mutex); | 443 | mutex_lock(&priv->mutex); |
@@ -445,7 +445,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
445 | iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, | 445 | iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, |
446 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); | 446 | CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); |
447 | 447 | ||
448 | base = priv->shrd->device_pointers.error_event_table; | 448 | base = priv->device_pointers.error_event_table; |
449 | if (iwlagn_hw_valid_rtc_data_addr(base)) { | 449 | if (iwlagn_hw_valid_rtc_data_addr(base)) { |
450 | spin_lock_irqsave(&trans(priv)->reg_lock, flags); | 450 | spin_lock_irqsave(&trans(priv)->reg_lock, flags); |
451 | ret = iwl_grab_nic_access_silent(trans(priv)); | 451 | ret = iwl_grab_nic_access_silent(trans(priv)); |
@@ -458,6 +458,8 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw) | |||
458 | 458 | ||
459 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 459 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
460 | if (ret == 0) { | 460 | if (ret == 0) { |
461 | const struct fw_img *img; | ||
462 | |||
461 | img = &(priv->fw->img[IWL_UCODE_WOWLAN]); | 463 | img = &(priv->fw->img[IWL_UCODE_WOWLAN]); |
462 | if (!priv->wowlan_sram) { | 464 | if (!priv->wowlan_sram) { |
463 | priv->wowlan_sram = | 465 | priv->wowlan_sram = |
@@ -653,6 +655,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
653 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); | 655 | ret = iwl_sta_rx_agg_stop(priv, sta, tid); |
654 | break; | 656 | break; |
655 | case IEEE80211_AMPDU_TX_START: | 657 | case IEEE80211_AMPDU_TX_START: |
658 | if (!trans(priv)->ops->tx_agg_setup) | ||
659 | break; | ||
656 | if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) | 660 | if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) |
657 | break; | 661 | break; |
658 | IWL_DEBUG_HT(priv, "start Tx\n"); | 662 | IWL_DEBUG_HT(priv, "start Tx\n"); |
@@ -1003,7 +1007,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw, | |||
1003 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; | 1007 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; |
1004 | int err = 0; | 1008 | int err = 0; |
1005 | 1009 | ||
1006 | if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | 1010 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) |
1007 | return -EOPNOTSUPP; | 1011 | return -EOPNOTSUPP; |
1008 | 1012 | ||
1009 | if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) | 1013 | if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT))) |
@@ -1091,7 +1095,7 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
1091 | { | 1095 | { |
1092 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 1096 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
1093 | 1097 | ||
1094 | if (!(priv->shrd->valid_contexts & BIT(IWL_RXON_CTX_PAN))) | 1098 | if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) |
1095 | return -EOPNOTSUPP; | 1099 | return -EOPNOTSUPP; |
1096 | 1100 | ||
1097 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 1101 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c index 88dc4a0f96b4..0066b899fe5c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.c +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.c | |||
@@ -75,21 +75,45 @@ void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait) | |||
75 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, | 75 | void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait, |
76 | struct iwl_rx_packet *pkt) | 76 | struct iwl_rx_packet *pkt) |
77 | { | 77 | { |
78 | bool triggered = false; | ||
79 | |||
78 | if (!list_empty(¬if_wait->notif_waits)) { | 80 | if (!list_empty(¬if_wait->notif_waits)) { |
79 | struct iwl_notification_wait *w; | 81 | struct iwl_notification_wait *w; |
80 | 82 | ||
81 | spin_lock(¬if_wait->notif_wait_lock); | 83 | spin_lock(¬if_wait->notif_wait_lock); |
82 | list_for_each_entry(w, ¬if_wait->notif_waits, list) { | 84 | list_for_each_entry(w, ¬if_wait->notif_waits, list) { |
83 | if (w->cmd != pkt->hdr.cmd) | 85 | int i; |
86 | bool found = false; | ||
87 | |||
88 | /* | ||
89 | * If it already finished (triggered) or has been | ||
90 | * aborted then don't evaluate it again to avoid races, | ||
91 | * Otherwise the function could be called again even | ||
92 | * though it returned true before | ||
93 | */ | ||
94 | if (w->triggered || w->aborted) | ||
95 | continue; | ||
96 | |||
97 | for (i = 0; i < w->n_cmds; i++) { | ||
98 | if (w->cmds[i] == pkt->hdr.cmd) { | ||
99 | found = true; | ||
100 | break; | ||
101 | } | ||
102 | } | ||
103 | if (!found) | ||
84 | continue; | 104 | continue; |
85 | w->triggered = true; | 105 | |
86 | if (w->fn) | 106 | if (!w->fn || w->fn(notif_wait, pkt, w->fn_data)) { |
87 | w->fn(notif_wait, pkt, w->fn_data); | 107 | w->triggered = true; |
108 | triggered = true; | ||
109 | } | ||
88 | } | 110 | } |
89 | spin_unlock(¬if_wait->notif_wait_lock); | 111 | spin_unlock(¬if_wait->notif_wait_lock); |
90 | 112 | ||
91 | wake_up_all(¬if_wait->notif_waitq); | ||
92 | } | 113 | } |
114 | |||
115 | if (triggered) | ||
116 | wake_up_all(¬if_wait->notif_waitq); | ||
93 | } | 117 | } |
94 | 118 | ||
95 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | 119 | void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) |
@@ -109,14 +133,18 @@ void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) | |||
109 | void | 133 | void |
110 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, | 134 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait, |
111 | struct iwl_notification_wait *wait_entry, | 135 | struct iwl_notification_wait *wait_entry, |
112 | u8 cmd, | 136 | const u8 *cmds, int n_cmds, |
113 | void (*fn)(struct iwl_notif_wait_data *notif_wait, | 137 | bool (*fn)(struct iwl_notif_wait_data *notif_wait, |
114 | struct iwl_rx_packet *pkt, void *data), | 138 | struct iwl_rx_packet *pkt, void *data), |
115 | void *fn_data) | 139 | void *fn_data) |
116 | { | 140 | { |
141 | if (WARN_ON(n_cmds > MAX_NOTIF_CMDS)) | ||
142 | n_cmds = MAX_NOTIF_CMDS; | ||
143 | |||
117 | wait_entry->fn = fn; | 144 | wait_entry->fn = fn; |
118 | wait_entry->fn_data = fn_data; | 145 | wait_entry->fn_data = fn_data; |
119 | wait_entry->cmd = cmd; | 146 | wait_entry->n_cmds = n_cmds; |
147 | memcpy(wait_entry->cmds, cmds, n_cmds); | ||
120 | wait_entry->triggered = false; | 148 | wait_entry->triggered = false; |
121 | wait_entry->aborted = false; | 149 | wait_entry->aborted = false; |
122 | 150 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h index 5e8af957aa7b..821523100cf1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-notif-wait.h +++ b/drivers/net/wireless/iwlwifi/iwl-notif-wait.h | |||
@@ -72,11 +72,19 @@ struct iwl_notif_wait_data { | |||
72 | wait_queue_head_t notif_waitq; | 72 | wait_queue_head_t notif_waitq; |
73 | }; | 73 | }; |
74 | 74 | ||
75 | #define MAX_NOTIF_CMDS 5 | ||
76 | |||
75 | /** | 77 | /** |
76 | * struct iwl_notification_wait - notification wait entry | 78 | * struct iwl_notification_wait - notification wait entry |
77 | * @list: list head for global list | 79 | * @list: list head for global list |
78 | * @fn: function called with the notification | 80 | * @fn: Function called with the notification. If the function |
79 | * @cmd: command ID | 81 | * returns true, the wait is over, if it returns false then |
82 | * the waiter stays blocked. If no function is given, any | ||
83 | * of the listed commands will unblock the waiter. | ||
84 | * @cmds: command IDs | ||
85 | * @n_cmds: number of command IDs | ||
86 | * @triggered: waiter should be woken up | ||
87 | * @aborted: wait was aborted | ||
80 | * | 88 | * |
81 | * This structure is not used directly, to wait for a | 89 | * This structure is not used directly, to wait for a |
82 | * notification declare it on the stack, and call | 90 | * notification declare it on the stack, and call |
@@ -93,11 +101,12 @@ struct iwl_notif_wait_data { | |||
93 | struct iwl_notification_wait { | 101 | struct iwl_notification_wait { |
94 | struct list_head list; | 102 | struct list_head list; |
95 | 103 | ||
96 | void (*fn)(struct iwl_notif_wait_data *notif_data, | 104 | bool (*fn)(struct iwl_notif_wait_data *notif_data, |
97 | struct iwl_rx_packet *pkt, void *data); | 105 | struct iwl_rx_packet *pkt, void *data); |
98 | void *fn_data; | 106 | void *fn_data; |
99 | 107 | ||
100 | u8 cmd; | 108 | u8 cmds[MAX_NOTIF_CMDS]; |
109 | u8 n_cmds; | ||
101 | bool triggered, aborted; | 110 | bool triggered, aborted; |
102 | }; | 111 | }; |
103 | 112 | ||
@@ -112,8 +121,8 @@ void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data); | |||
112 | void __acquires(wait_entry) | 121 | void __acquires(wait_entry) |
113 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data, | 122 | iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data, |
114 | struct iwl_notification_wait *wait_entry, | 123 | struct iwl_notification_wait *wait_entry, |
115 | u8 cmd, | 124 | const u8 *cmds, int n_cmds, |
116 | void (*fn)(struct iwl_notif_wait_data *notif_data, | 125 | bool (*fn)(struct iwl_notif_wait_data *notif_data, |
117 | struct iwl_rx_packet *pkt, void *data), | 126 | struct iwl_rx_packet *pkt, void *data), |
118 | void *fn_data); | 127 | void *fn_data); |
119 | 128 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h index 6ea4163ff56a..b1fd251e88d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h +++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h | |||
@@ -111,10 +111,10 @@ struct iwl_fw; | |||
111 | * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the | 111 | * @rx: Rx notification to the op_mode. rxb is the Rx buffer itself. Cmd is the |
112 | * HCMD the this Rx responds to. | 112 | * HCMD the this Rx responds to. |
113 | * Must be atomic. | 113 | * Must be atomic. |
114 | * @queue_full: notifies that a HW queue is full. Ac is the ac of the queue | 114 | * @queue_full: notifies that a HW queue is full. |
115 | * Must be atomic | 115 | * Must be atomic |
116 | * @queue_not_full: notifies that a HW queue is not full any more. | 116 | * @queue_not_full: notifies that a HW queue is not full any more. |
117 | * Ac is the ac of the queue. Must be atomic | 117 | * Must be atomic |
118 | * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that | 118 | * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that |
119 | * the radio is killed. Must be atomic. | 119 | * the radio is killed. Must be atomic. |
120 | * @free_skb: allows the transport layer to free skbs that haven't been | 120 | * @free_skb: allows the transport layer to free skbs that haven't been |
@@ -132,8 +132,8 @@ struct iwl_op_mode_ops { | |||
132 | void (*stop)(struct iwl_op_mode *op_mode); | 132 | void (*stop)(struct iwl_op_mode *op_mode); |
133 | int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, | 133 | int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb, |
134 | struct iwl_device_cmd *cmd); | 134 | struct iwl_device_cmd *cmd); |
135 | void (*queue_full)(struct iwl_op_mode *op_mode, u8 ac); | 135 | void (*queue_full)(struct iwl_op_mode *op_mode, int queue); |
136 | void (*queue_not_full)(struct iwl_op_mode *op_mode, u8 ac); | 136 | void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue); |
137 | void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); | 137 | void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); |
138 | void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb); | 138 | void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb); |
139 | void (*nic_error)(struct iwl_op_mode *op_mode); | 139 | void (*nic_error)(struct iwl_op_mode *op_mode); |
@@ -169,15 +169,16 @@ static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode, | |||
169 | return op_mode->ops->rx(op_mode, rxb, cmd); | 169 | return op_mode->ops->rx(op_mode, rxb, cmd); |
170 | } | 170 | } |
171 | 171 | ||
172 | static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode, u8 ac) | 172 | static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode, |
173 | int queue) | ||
173 | { | 174 | { |
174 | op_mode->ops->queue_full(op_mode, ac); | 175 | op_mode->ops->queue_full(op_mode, queue); |
175 | } | 176 | } |
176 | 177 | ||
177 | static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode, | 178 | static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode, |
178 | u8 ac) | 179 | int queue) |
179 | { | 180 | { |
180 | op_mode->ops->queue_not_full(op_mode, ac); | 181 | op_mode->ops->queue_not_full(op_mode, queue); |
181 | } | 182 | } |
182 | 183 | ||
183 | static inline void iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, | 184 | static inline void iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index c5e339ee918b..f3e56b04d775 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c | |||
@@ -60,6 +60,9 @@ | |||
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 | |||
64 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
65 | |||
63 | #include <linux/module.h> | 66 | #include <linux/module.h> |
64 | #include <linux/pci.h> | 67 | #include <linux/pci.h> |
65 | #include <linux/pci-aspm.h> | 68 | #include <linux/pci-aspm.h> |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c new file mode 100644 index 000000000000..d65305d08ebf --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c | |||
@@ -0,0 +1,273 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #include <linux/slab.h> | ||
65 | #include <linux/string.h> | ||
66 | |||
67 | #include "iwl-debug.h" | ||
68 | #include "iwl-shared.h" | ||
69 | #include "iwl-dev.h" | ||
70 | |||
71 | #include "iwl-phy-db.h" | ||
72 | |||
73 | #define CHANNEL_NUM_SIZE 4 /* num of channels in calib_ch size */ | ||
74 | |||
75 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_shared *shrd) | ||
76 | { | ||
77 | struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), | ||
78 | GFP_KERNEL); | ||
79 | |||
80 | if (!phy_db) | ||
81 | return phy_db; | ||
82 | |||
83 | phy_db->shrd = shrd; | ||
84 | |||
85 | /* TODO: add default values of the phy db. */ | ||
86 | return phy_db; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * get phy db section: returns a pointer to a phy db section specified by | ||
91 | * type and channel group id. | ||
92 | */ | ||
93 | static struct iwl_phy_db_entry * | ||
94 | iwl_phy_db_get_section(struct iwl_phy_db *phy_db, | ||
95 | enum iwl_phy_db_section_type type, | ||
96 | u16 chg_id) | ||
97 | { | ||
98 | if (!phy_db || type < 0 || type >= IWL_PHY_DB_MAX) | ||
99 | return NULL; | ||
100 | |||
101 | switch (type) { | ||
102 | case IWL_PHY_DB_CFG: | ||
103 | return &phy_db->cfg; | ||
104 | case IWL_PHY_DB_CALIB_NCH: | ||
105 | return &phy_db->calib_nch; | ||
106 | case IWL_PHY_DB_CALIB_CH: | ||
107 | return &phy_db->calib_ch; | ||
108 | case IWL_PHY_DB_CALIB_CHG_PAPD: | ||
109 | if (chg_id < 0 || chg_id >= IWL_NUM_PAPD_CH_GROUPS) | ||
110 | return NULL; | ||
111 | return &phy_db->calib_ch_group_papd[chg_id]; | ||
112 | case IWL_PHY_DB_CALIB_CHG_TXP: | ||
113 | if (chg_id < 0 || chg_id >= IWL_NUM_TXP_CH_GROUPS) | ||
114 | return NULL; | ||
115 | return &phy_db->calib_ch_group_txp[chg_id]; | ||
116 | default: | ||
117 | return NULL; | ||
118 | } | ||
119 | return NULL; | ||
120 | } | ||
121 | |||
122 | static void iwl_phy_db_free_section(struct iwl_phy_db *phy_db, | ||
123 | enum iwl_phy_db_section_type type, | ||
124 | u16 chg_id) | ||
125 | { | ||
126 | struct iwl_phy_db_entry *entry = | ||
127 | iwl_phy_db_get_section(phy_db, type, chg_id); | ||
128 | if (!entry) | ||
129 | return; | ||
130 | |||
131 | kfree(entry->data); | ||
132 | entry->data = NULL; | ||
133 | entry->size = 0; | ||
134 | } | ||
135 | |||
136 | void iwl_phy_db_free(struct iwl_phy_db *phy_db) | ||
137 | { | ||
138 | int i; | ||
139 | |||
140 | if (!phy_db) | ||
141 | return; | ||
142 | |||
143 | iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CFG, 0); | ||
144 | iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_NCH, 0); | ||
145 | iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CH, 0); | ||
146 | for (i = 0; i < IWL_NUM_PAPD_CH_GROUPS; i++) | ||
147 | iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_PAPD, i); | ||
148 | for (i = 0; i < IWL_NUM_TXP_CH_GROUPS; i++) | ||
149 | iwl_phy_db_free_section(phy_db, IWL_PHY_DB_CALIB_CHG_TXP, i); | ||
150 | |||
151 | kfree(phy_db); | ||
152 | } | ||
153 | |||
154 | int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, | ||
155 | enum iwl_phy_db_section_type type, u8 *data, | ||
156 | u16 size, gfp_t alloc_ctx) | ||
157 | { | ||
158 | struct iwl_phy_db_entry *entry; | ||
159 | u16 chg_id = 0; | ||
160 | |||
161 | if (!phy_db) | ||
162 | return -EINVAL; | ||
163 | |||
164 | if (type == IWL_PHY_DB_CALIB_CHG_PAPD || | ||
165 | type == IWL_PHY_DB_CALIB_CHG_TXP) | ||
166 | chg_id = le16_to_cpup((__le16 *)data); | ||
167 | |||
168 | entry = iwl_phy_db_get_section(phy_db, type, chg_id); | ||
169 | if (!entry) | ||
170 | return -EINVAL; | ||
171 | |||
172 | kfree(entry->data); | ||
173 | entry->data = kmemdup(data, size, alloc_ctx); | ||
174 | if (!entry->data) { | ||
175 | entry->size = 0; | ||
176 | return -ENOMEM; | ||
177 | } | ||
178 | |||
179 | entry->size = size; | ||
180 | |||
181 | if (type == IWL_PHY_DB_CALIB_CH) { | ||
182 | phy_db->channel_num = le32_to_cpup((__le32 *)data); | ||
183 | phy_db->channel_size = | ||
184 | (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static int is_valid_channel(u16 ch_id) | ||
191 | { | ||
192 | if (ch_id <= 14 || | ||
193 | (36 <= ch_id && ch_id <= 64 && ch_id % 4 == 0) || | ||
194 | (100 <= ch_id && ch_id <= 140 && ch_id % 4 == 0) || | ||
195 | (145 <= ch_id && ch_id <= 165 && ch_id % 4 == 1)) | ||
196 | return 1; | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static u8 ch_id_to_ch_index(u16 ch_id) | ||
201 | { | ||
202 | if (WARN_ON(!is_valid_channel(ch_id))) | ||
203 | return 0xff; | ||
204 | |||
205 | if (ch_id <= 14) | ||
206 | return ch_id - 1; | ||
207 | if (ch_id <= 64) | ||
208 | return (ch_id + 20) / 4; | ||
209 | if (ch_id <= 140) | ||
210 | return (ch_id - 12) / 4; | ||
211 | return (ch_id - 13) / 4; | ||
212 | } | ||
213 | |||
214 | |||
215 | static u16 channel_id_to_papd(u16 ch_id) | ||
216 | { | ||
217 | if (WARN_ON(!is_valid_channel(ch_id))) | ||
218 | return 0xff; | ||
219 | |||
220 | if (1 <= ch_id && ch_id <= 14) | ||
221 | return 0; | ||
222 | if (36 <= ch_id && ch_id <= 64) | ||
223 | return 1; | ||
224 | if (100 <= ch_id && ch_id <= 140) | ||
225 | return 2; | ||
226 | return 3; | ||
227 | } | ||
228 | |||
229 | static u16 channel_id_to_txp(struct iwl_phy_db *phy_db, u16 ch_id) | ||
230 | { | ||
231 | /* TODO David*/ | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, | ||
236 | enum iwl_phy_db_section_type type, u8 **data, | ||
237 | u16 *size, u16 ch_id) | ||
238 | { | ||
239 | struct iwl_phy_db_entry *entry; | ||
240 | u32 channel_num; | ||
241 | u32 channel_size; | ||
242 | u16 ch_group_id = 0; | ||
243 | u16 index; | ||
244 | |||
245 | if (!phy_db) | ||
246 | return -EINVAL; | ||
247 | |||
248 | /* find wanted channel group */ | ||
249 | if (type == IWL_PHY_DB_CALIB_CHG_PAPD) | ||
250 | ch_group_id = channel_id_to_papd(ch_id); | ||
251 | else if (type == IWL_PHY_DB_CALIB_CHG_TXP) | ||
252 | ch_group_id = channel_id_to_txp(phy_db, ch_id); | ||
253 | |||
254 | entry = iwl_phy_db_get_section(phy_db, type, ch_group_id); | ||
255 | if (!entry) | ||
256 | return -EINVAL; | ||
257 | |||
258 | if (type == IWL_PHY_DB_CALIB_CH) { | ||
259 | index = ch_id_to_ch_index(ch_id); | ||
260 | channel_num = phy_db->channel_num; | ||
261 | channel_size = phy_db->channel_size; | ||
262 | if (index >= channel_num) { | ||
263 | IWL_ERR(phy_db, "Wrong channel number %d", ch_id); | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | *data = entry->data + CHANNEL_NUM_SIZE + index * channel_size; | ||
267 | *size = channel_size; | ||
268 | } else { | ||
269 | *data = entry->data; | ||
270 | *size = entry->size; | ||
271 | } | ||
272 | return 0; | ||
273 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.h b/drivers/net/wireless/iwlwifi/iwl-phy-db.h new file mode 100644 index 000000000000..ba91a8b28398 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.h | |||
@@ -0,0 +1,123 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | |||
64 | #ifndef __IWL_PHYDB_H__ | ||
65 | #define __IWL_PHYDB_H__ | ||
66 | |||
67 | #include <linux/types.h> | ||
68 | |||
69 | #define IWL_NUM_PAPD_CH_GROUPS 4 | ||
70 | #define IWL_NUM_TXP_CH_GROUPS 8 | ||
71 | |||
72 | struct iwl_phy_db_entry { | ||
73 | u16 size; | ||
74 | u8 *data; | ||
75 | }; | ||
76 | |||
77 | struct iwl_shared; | ||
78 | |||
79 | /** | ||
80 | * struct iwl_phy_db - stores phy configuration and calibration data. | ||
81 | * | ||
82 | * @cfg: phy configuration. | ||
83 | * @calib_nch: non channel specific calibration data. | ||
84 | * @calib_ch: channel specific calibration data. | ||
85 | * @calib_ch_group_papd: calibration data related to papd channel group. | ||
86 | * @calib_ch_group_txp: calibration data related to tx power chanel group. | ||
87 | */ | ||
88 | struct iwl_phy_db { | ||
89 | struct iwl_phy_db_entry cfg; | ||
90 | struct iwl_phy_db_entry calib_nch; | ||
91 | struct iwl_phy_db_entry calib_ch; | ||
92 | struct iwl_phy_db_entry calib_ch_group_papd[IWL_NUM_PAPD_CH_GROUPS]; | ||
93 | struct iwl_phy_db_entry calib_ch_group_txp[IWL_NUM_TXP_CH_GROUPS]; | ||
94 | |||
95 | u32 channel_num; | ||
96 | u32 channel_size; | ||
97 | |||
98 | /* for an access to the logger */ | ||
99 | const struct iwl_shared *shrd; | ||
100 | }; | ||
101 | |||
102 | enum iwl_phy_db_section_type { | ||
103 | IWL_PHY_DB_CFG = 1, | ||
104 | IWL_PHY_DB_CALIB_NCH, | ||
105 | IWL_PHY_DB_CALIB_CH, | ||
106 | IWL_PHY_DB_CALIB_CHG_PAPD, | ||
107 | IWL_PHY_DB_CALIB_CHG_TXP, | ||
108 | IWL_PHY_DB_MAX | ||
109 | }; | ||
110 | |||
111 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_shared *shrd); | ||
112 | |||
113 | void iwl_phy_db_free(struct iwl_phy_db *phy_db); | ||
114 | |||
115 | int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, | ||
116 | enum iwl_phy_db_section_type type, u8 *data, | ||
117 | u16 size, gfp_t alloc_ctx); | ||
118 | |||
119 | int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, | ||
120 | enum iwl_phy_db_section_type type, u8 **data, | ||
121 | u16 *size, u16 ch_id); | ||
122 | |||
123 | #endif /* __IWL_PHYDB_H__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 958d9d09aee3..7bc7a82aba47 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -403,12 +403,12 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd, | |||
403 | } | 403 | } |
404 | 404 | ||
405 | if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) | 405 | if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) |
406 | set_bit(STATUS_POWER_PMI, &priv->shrd->status); | 406 | iwl_dvm_set_pmi(priv, true); |
407 | 407 | ||
408 | ret = iwl_set_power(priv, cmd); | 408 | ret = iwl_set_power(priv, cmd); |
409 | if (!ret) { | 409 | if (!ret) { |
410 | if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) | 410 | if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) |
411 | clear_bit(STATUS_POWER_PMI, &priv->shrd->status); | 411 | iwl_dvm_set_pmi(priv, false); |
412 | 412 | ||
413 | if (update_chains) | 413 | if (update_chains) |
414 | iwl_update_chain_flags(priv); | 414 | iwl_update_chain_flags(priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 902efe4bc898..dcf5b12071b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -69,7 +69,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) | |||
69 | if (!test_bit(STATUS_READY, &priv->status) || | 69 | if (!test_bit(STATUS_READY, &priv->status) || |
70 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || | 70 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status) || |
71 | !test_bit(STATUS_SCAN_HW, &priv->status) || | 71 | !test_bit(STATUS_SCAN_HW, &priv->status) || |
72 | test_bit(STATUS_FW_ERROR, &priv->shrd->status)) | 72 | test_bit(STATUS_FW_ERROR, &priv->status)) |
73 | return -EIO; | 73 | return -EIO; |
74 | 74 | ||
75 | ret = iwl_dvm_send_cmd(priv, &cmd); | 75 | ret = iwl_dvm_send_cmd(priv, &cmd); |
@@ -451,6 +451,46 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | |||
451 | return iwl_limit_dwell(priv, passive); | 451 | return iwl_limit_dwell(priv, passive); |
452 | } | 452 | } |
453 | 453 | ||
454 | /* Return valid, unused, channel for a passive scan to reset the RF */ | ||
455 | static u8 iwl_get_single_channel_number(struct iwl_priv *priv, | ||
456 | enum ieee80211_band band) | ||
457 | { | ||
458 | const struct iwl_channel_info *ch_info; | ||
459 | int i; | ||
460 | u8 channel = 0; | ||
461 | u8 min, max; | ||
462 | struct iwl_rxon_context *ctx; | ||
463 | |||
464 | if (band == IEEE80211_BAND_5GHZ) { | ||
465 | min = 14; | ||
466 | max = priv->channel_count; | ||
467 | } else { | ||
468 | min = 0; | ||
469 | max = 14; | ||
470 | } | ||
471 | |||
472 | for (i = min; i < max; i++) { | ||
473 | bool busy = false; | ||
474 | |||
475 | for_each_context(priv, ctx) { | ||
476 | busy = priv->channel_info[i].channel == | ||
477 | le16_to_cpu(ctx->staging.channel); | ||
478 | if (busy) | ||
479 | break; | ||
480 | } | ||
481 | |||
482 | if (busy) | ||
483 | continue; | ||
484 | |||
485 | channel = priv->channel_info[i].channel; | ||
486 | ch_info = iwl_get_channel_info(priv, band, channel); | ||
487 | if (is_channel_valid(ch_info)) | ||
488 | break; | ||
489 | } | ||
490 | |||
491 | return channel; | ||
492 | } | ||
493 | |||
454 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, | 494 | static int iwl_get_single_channel_for_scan(struct iwl_priv *priv, |
455 | struct ieee80211_vif *vif, | 495 | struct ieee80211_vif *vif, |
456 | enum ieee80211_band band, | 496 | enum ieee80211_band band, |
@@ -793,9 +833,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
793 | 833 | ||
794 | band = priv->scan_band; | 834 | band = priv->scan_band; |
795 | 835 | ||
796 | if (cfg(priv)->scan_rx_antennas[band]) | ||
797 | rx_ant = cfg(priv)->scan_rx_antennas[band]; | ||
798 | |||
799 | if (band == IEEE80211_BAND_2GHZ && | 836 | if (band == IEEE80211_BAND_2GHZ && |
800 | cfg(priv)->bt_params && | 837 | cfg(priv)->bt_params && |
801 | cfg(priv)->bt_params->advanced_bt_coexist) { | 838 | cfg(priv)->bt_params->advanced_bt_coexist) { |
@@ -809,8 +846,12 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
809 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); | 846 | rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); |
810 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); | 847 | scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); |
811 | 848 | ||
812 | /* In power save mode use one chain, otherwise use all chains */ | 849 | /* |
813 | if (test_bit(STATUS_POWER_PMI, &priv->shrd->status)) { | 850 | * In power save mode while associated use one chain, |
851 | * otherwise use all chains | ||
852 | */ | ||
853 | if (test_bit(STATUS_POWER_PMI, &priv->status) && | ||
854 | !(priv->hw->conf.flags & IEEE80211_CONF_IDLE)) { | ||
814 | /* rx_ant has been set to all valid chains previously */ | 855 | /* rx_ant has been set to all valid chains previously */ |
815 | active_chains = rx_ant & | 856 | active_chains = rx_ant & |
816 | ((u8)(priv->chain_noise_data.active_chains)); | 857 | ((u8)(priv->chain_noise_data.active_chains)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index b515d657a0ad..983b41e43d4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h | |||
@@ -160,7 +160,6 @@ struct iwl_mod_params { | |||
160 | * | 160 | * |
161 | * Holds the module parameters | 161 | * Holds the module parameters |
162 | * | 162 | * |
163 | * @num_ampdu_queues: num of ampdu queues | ||
164 | * @tx_chains_num: Number of TX chains | 163 | * @tx_chains_num: Number of TX chains |
165 | * @rx_chains_num: Number of RX chains | 164 | * @rx_chains_num: Number of RX chains |
166 | * @valid_tx_ant: usable antennas for TX | 165 | * @valid_tx_ant: usable antennas for TX |
@@ -176,7 +175,6 @@ struct iwl_mod_params { | |||
176 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic | 175 | * @use_rts_for_aggregation: use rts/cts protection for HT traffic |
177 | */ | 176 | */ |
178 | struct iwl_hw_params { | 177 | struct iwl_hw_params { |
179 | u8 num_ampdu_queues; | ||
180 | u8 tx_chains_num; | 178 | u8 tx_chains_num; |
181 | u8 rx_chains_num; | 179 | u8 rx_chains_num; |
182 | u8 valid_tx_ant; | 180 | u8 valid_tx_ant; |
@@ -217,7 +215,6 @@ enum iwl_led_mode { | |||
217 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | 215 | * @chain_noise_num_beacons: number of beacons used to compute chain noise |
218 | * @adv_thermal_throttle: support advance thermal throttle | 216 | * @adv_thermal_throttle: support advance thermal throttle |
219 | * @support_ct_kill_exit: support ct kill exit condition | 217 | * @support_ct_kill_exit: support ct kill exit condition |
220 | * @support_wimax_coexist: support wimax/wifi co-exist | ||
221 | * @plcp_delta_threshold: plcp error rate threshold used to trigger | 218 | * @plcp_delta_threshold: plcp error rate threshold used to trigger |
222 | * radio tuning when there is a high receiving plcp error rate | 219 | * radio tuning when there is a high receiving plcp error rate |
223 | * @chain_noise_scale: default chain noise scale used for gain computation | 220 | * @chain_noise_scale: default chain noise scale used for gain computation |
@@ -231,7 +228,6 @@ enum iwl_led_mode { | |||
231 | struct iwl_base_params { | 228 | struct iwl_base_params { |
232 | int eeprom_size; | 229 | int eeprom_size; |
233 | int num_of_queues; /* def: HW dependent */ | 230 | int num_of_queues; /* def: HW dependent */ |
234 | int num_of_ampdu_queues;/* def: HW dependent */ | ||
235 | /* for iwl_apm_init() */ | 231 | /* for iwl_apm_init() */ |
236 | u32 pll_cfg_val; | 232 | u32 pll_cfg_val; |
237 | 233 | ||
@@ -240,7 +236,6 @@ struct iwl_base_params { | |||
240 | u16 led_compensation; | 236 | u16 led_compensation; |
241 | bool adv_thermal_throttle; | 237 | bool adv_thermal_throttle; |
242 | bool support_ct_kill_exit; | 238 | bool support_ct_kill_exit; |
243 | const bool support_wimax_coexist; | ||
244 | u8 plcp_delta_threshold; | 239 | u8 plcp_delta_threshold; |
245 | s32 chain_noise_scale; | 240 | s32 chain_noise_scale; |
246 | unsigned int wd_timeout; | 241 | unsigned int wd_timeout; |
@@ -299,21 +294,15 @@ struct iwl_ht_params { | |||
299 | * @need_temp_offset_calib: need to perform temperature offset calibration | 294 | * @need_temp_offset_calib: need to perform temperature offset calibration |
300 | * @no_xtal_calib: some devices do not need crystal calibration data, | 295 | * @no_xtal_calib: some devices do not need crystal calibration data, |
301 | * don't send it to those | 296 | * don't send it to those |
302 | * @scan_rx_antennas: available antenna for scan operation | ||
303 | * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) | 297 | * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) |
304 | * @adv_pm: advance power management | 298 | * @adv_pm: advance power management |
305 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity | 299 | * @rx_with_siso_diversity: 1x1 device with rx antenna diversity |
306 | * @internal_wimax_coex: internal wifi/wimax combo device | 300 | * @internal_wimax_coex: internal wifi/wimax combo device |
307 | * @iq_invert: I/Q inversion | ||
308 | * @temp_offset_v2: support v2 of temperature offset calibration | 301 | * @temp_offset_v2: support v2 of temperature offset calibration |
309 | * | 302 | * |
310 | * We enable the driver to be backward compatible wrt API version. The | 303 | * We enable the driver to be backward compatible wrt. hardware features. |
311 | * driver specifies which APIs it supports (with @ucode_api_max being the | 304 | * API differences in uCode shouldn't be handled here but through TLVs |
312 | * highest and @ucode_api_min the lowest). Firmware will only be loaded if | 305 | * and/or the uCode API version instead. |
313 | * it has a supported API version. | ||
314 | * | ||
315 | * The ideal usage of this infrastructure is to treat a new ucode API | ||
316 | * release as a new hardware revision. | ||
317 | */ | 306 | */ |
318 | struct iwl_cfg { | 307 | struct iwl_cfg { |
319 | /* params specific to an individual device within a device family */ | 308 | /* params specific to an individual device within a device family */ |
@@ -337,12 +326,10 @@ struct iwl_cfg { | |||
337 | const struct iwl_bt_params *bt_params; | 326 | const struct iwl_bt_params *bt_params; |
338 | const bool need_temp_offset_calib; /* if used set to true */ | 327 | const bool need_temp_offset_calib; /* if used set to true */ |
339 | const bool no_xtal_calib; | 328 | const bool no_xtal_calib; |
340 | u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; | ||
341 | enum iwl_led_mode led_mode; | 329 | enum iwl_led_mode led_mode; |
342 | const bool adv_pm; | 330 | const bool adv_pm; |
343 | const bool rx_with_siso_diversity; | 331 | const bool rx_with_siso_diversity; |
344 | const bool internal_wimax_coex; | 332 | const bool internal_wimax_coex; |
345 | const bool iq_invert; | ||
346 | const bool temp_offset_v2; | 333 | const bool temp_offset_v2; |
347 | }; | 334 | }; |
348 | 335 | ||
@@ -351,7 +338,6 @@ struct iwl_cfg { | |||
351 | * | 338 | * |
352 | * @status: STATUS_* | 339 | * @status: STATUS_* |
353 | * @wowlan: are we running wowlan uCode | 340 | * @wowlan: are we running wowlan uCode |
354 | * @valid_contexts: microcode/device supports multiple contexts | ||
355 | * @bus: pointer to the bus layer data | 341 | * @bus: pointer to the bus layer data |
356 | * @cfg: see struct iwl_cfg | 342 | * @cfg: see struct iwl_cfg |
357 | * @priv: pointer to the upper layer data | 343 | * @priv: pointer to the upper layer data |
@@ -360,30 +346,18 @@ struct iwl_cfg { | |||
360 | * @hw_params: see struct iwl_hw_params | 346 | * @hw_params: see struct iwl_hw_params |
361 | * @lock: protect general shared data | 347 | * @lock: protect general shared data |
362 | * @eeprom: pointer to the eeprom/OTP image | 348 | * @eeprom: pointer to the eeprom/OTP image |
363 | * @ucode_type: indicator of loaded ucode image | ||
364 | * @device_pointers: pointers to ucode event tables | ||
365 | */ | 349 | */ |
366 | struct iwl_shared { | 350 | struct iwl_shared { |
367 | unsigned long status; | 351 | unsigned long status; |
368 | u8 valid_contexts; | ||
369 | 352 | ||
370 | const struct iwl_cfg *cfg; | 353 | const struct iwl_cfg *cfg; |
371 | struct iwl_trans *trans; | 354 | struct iwl_trans *trans; |
372 | void *drv; | 355 | void *drv; |
373 | struct iwl_hw_params hw_params; | 356 | struct iwl_hw_params hw_params; |
374 | const struct iwl_fw *fw; | ||
375 | 357 | ||
376 | /* eeprom -- this is in the card's little endian byte order */ | 358 | /* eeprom -- this is in the card's little endian byte order */ |
377 | u8 *eeprom; | 359 | u8 *eeprom; |
378 | 360 | ||
379 | /* ucode related variables */ | ||
380 | enum iwl_ucode_type ucode_type; | ||
381 | |||
382 | struct { | ||
383 | u32 error_event_table; | ||
384 | u32 log_event_table; | ||
385 | } device_pointers; | ||
386 | |||
387 | }; | 361 | }; |
388 | 362 | ||
389 | /*Whatever _m is (iwl_trans, iwl_priv, these macros will work */ | 363 | /*Whatever _m is (iwl_trans, iwl_priv, these macros will work */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index a54e20e7b17f..f31a0629c6c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c | |||
@@ -423,10 +423,13 @@ nla_put_failure: | |||
423 | static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) | 423 | static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) |
424 | { | 424 | { |
425 | struct iwl_notification_wait calib_wait; | 425 | struct iwl_notification_wait calib_wait; |
426 | static const u8 calib_complete[] = { | ||
427 | CALIBRATION_COMPLETE_NOTIFICATION | ||
428 | }; | ||
426 | int ret; | 429 | int ret; |
427 | 430 | ||
428 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, | 431 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, |
429 | CALIBRATION_COMPLETE_NOTIFICATION, | 432 | calib_complete, ARRAY_SIZE(calib_complete), |
430 | NULL, NULL); | 433 | NULL, NULL); |
431 | ret = iwl_init_alive_start(priv); | 434 | ret = iwl_init_alive_start(priv); |
432 | if (ret) { | 435 | if (ret) { |
@@ -605,11 +608,11 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
605 | IWL_ERR(priv, "No uCode has not been loaded\n"); | 608 | IWL_ERR(priv, "No uCode has not been loaded\n"); |
606 | return -EINVAL; | 609 | return -EINVAL; |
607 | } else { | 610 | } else { |
608 | img = &priv->fw->img[priv->shrd->ucode_type]; | 611 | img = &priv->fw->img[priv->cur_ucode]; |
609 | inst_size = img->sec[IWL_UCODE_SECTION_INST].len; | 612 | inst_size = img->sec[IWL_UCODE_SECTION_INST].len; |
610 | data_size = img->sec[IWL_UCODE_SECTION_DATA].len; | 613 | data_size = img->sec[IWL_UCODE_SECTION_DATA].len; |
611 | } | 614 | } |
612 | if (nla_put_u32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type) || | 615 | if (nla_put_u32(skb, IWL_TM_ATTR_FW_TYPE, priv->cur_ucode) || |
613 | nla_put_u32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size) || | 616 | nla_put_u32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size) || |
614 | nla_put_u32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size)) | 617 | nla_put_u32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size)) |
615 | goto nla_put_failure; | 618 | goto nla_put_failure; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 1c2fe87bd7e2..32adee3b54e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | |||
@@ -136,13 +136,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) | |||
136 | return --index & (n_bd - 1); | 136 | return --index & (n_bd - 1); |
137 | } | 137 | } |
138 | 138 | ||
139 | /* | ||
140 | * This queue number is required for proper operation | ||
141 | * because the ucode will stop/start the scheduler as | ||
142 | * required. | ||
143 | */ | ||
144 | #define IWL_IPAN_MCAST_QUEUE 8 | ||
145 | |||
146 | struct iwl_cmd_meta { | 139 | struct iwl_cmd_meta { |
147 | /* only for SYNC commands, iff the reply skb is wanted */ | 140 | /* only for SYNC commands, iff the reply skb is wanted */ |
148 | struct iwl_host_cmd *source; | 141 | struct iwl_host_cmd *source; |
@@ -199,9 +192,6 @@ struct iwl_queue { | |||
199 | * lock: queue lock | 192 | * lock: queue lock |
200 | * @time_stamp: time (in jiffies) of last read_ptr change | 193 | * @time_stamp: time (in jiffies) of last read_ptr change |
201 | * @need_update: indicates need to update read/write index | 194 | * @need_update: indicates need to update read/write index |
202 | * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled | ||
203 | * @sta_id: valid if sched_retry is set | ||
204 | * @tid: valid if sched_retry is set | ||
205 | * | 195 | * |
206 | * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame | 196 | * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame |
207 | * descriptors) and required locking structures. | 197 | * descriptors) and required locking structures. |
@@ -218,12 +208,7 @@ struct iwl_tx_queue { | |||
218 | spinlock_t lock; | 208 | spinlock_t lock; |
219 | unsigned long time_stamp; | 209 | unsigned long time_stamp; |
220 | u8 need_update; | 210 | u8 need_update; |
221 | u8 sched_retry; | ||
222 | u8 active; | 211 | u8 active; |
223 | u8 swq_id; | ||
224 | |||
225 | u16 sta_id; | ||
226 | u16 tid; | ||
227 | }; | 212 | }; |
228 | 213 | ||
229 | /** | 214 | /** |
@@ -236,13 +221,6 @@ struct iwl_tx_queue { | |||
236 | * @scd_base_addr: scheduler sram base address in SRAM | 221 | * @scd_base_addr: scheduler sram base address in SRAM |
237 | * @scd_bc_tbls: pointer to the byte count table of the scheduler | 222 | * @scd_bc_tbls: pointer to the byte count table of the scheduler |
238 | * @kw: keep warm address | 223 | * @kw: keep warm address |
239 | * @ac_to_fifo: to what fifo is a specifc AC mapped ? | ||
240 | * @ac_to_queue: to what tx queue is a specifc AC mapped ? | ||
241 | * @mcast_queue: | ||
242 | * @txq: Tx DMA processing queues | ||
243 | * @txq_ctx_active_msk: what queue is active | ||
244 | * queue_stopped: tracks what queue is stopped | ||
245 | * queue_stop_count: tracks what SW queue is stopped | ||
246 | * @pci_dev: basic pci-network driver stuff | 224 | * @pci_dev: basic pci-network driver stuff |
247 | * @hw_base: pci hardware address support | 225 | * @hw_base: pci hardware address support |
248 | * @ucode_write_complete: indicates that the ucode has been copied. | 226 | * @ucode_write_complete: indicates that the ucode has been copied. |
@@ -272,16 +250,9 @@ struct iwl_trans_pcie { | |||
272 | struct iwl_dma_ptr scd_bc_tbls; | 250 | struct iwl_dma_ptr scd_bc_tbls; |
273 | struct iwl_dma_ptr kw; | 251 | struct iwl_dma_ptr kw; |
274 | 252 | ||
275 | const u8 *ac_to_fifo[NUM_IWL_RXON_CTX]; | ||
276 | const u8 *ac_to_queue[NUM_IWL_RXON_CTX]; | ||
277 | u8 mcast_queue[NUM_IWL_RXON_CTX]; | ||
278 | u8 agg_txq[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT]; | ||
279 | |||
280 | struct iwl_tx_queue *txq; | 253 | struct iwl_tx_queue *txq; |
281 | unsigned long txq_ctx_active_msk; | 254 | unsigned long queue_used[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; |
282 | #define IWL_MAX_HW_QUEUES 32 | ||
283 | unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; | 255 | unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; |
284 | atomic_t queue_stop_count[4]; | ||
285 | 256 | ||
286 | /* PCI bus related data */ | 257 | /* PCI bus related data */ |
287 | struct pci_dev *pci_dev; | 258 | struct pci_dev *pci_dev; |
@@ -293,6 +264,8 @@ struct iwl_trans_pcie { | |||
293 | u8 cmd_queue; | 264 | u8 cmd_queue; |
294 | u8 n_no_reclaim_cmds; | 265 | u8 n_no_reclaim_cmds; |
295 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; | 266 | u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS]; |
267 | u8 setup_q_to_fifo[IWL_MAX_HW_QUEUES]; | ||
268 | u8 n_q_to_fifo; | ||
296 | }; | 269 | }; |
297 | 270 | ||
298 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ | 271 | #define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \ |
@@ -331,15 +304,12 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, | |||
331 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, | 304 | void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans, |
332 | struct iwl_tx_queue *txq, | 305 | struct iwl_tx_queue *txq, |
333 | u16 byte_cnt); | 306 | u16 byte_cnt); |
334 | int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, | 307 | void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int queue); |
335 | int sta_id, int tid); | ||
336 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); | 308 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, int txq_id, u32 index); |
337 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | 309 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, |
338 | struct iwl_tx_queue *txq, | 310 | struct iwl_tx_queue *txq, |
339 | int tx_fifo_id, int scd_retry); | 311 | int tx_fifo_id, bool active); |
340 | int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, int sta_id, int tid); | 312 | void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int queue, int fifo, |
341 | void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, | ||
342 | enum iwl_rxon_context_id ctx, | ||
343 | int sta_id, int tid, int frame_limit, u16 ssn); | 313 | int sta_id, int tid, int frame_limit, u16 ssn); |
344 | void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, | 314 | void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, |
345 | int index, enum dma_data_direction dma_dir); | 315 | int index, enum dma_data_direction dma_dir); |
@@ -350,8 +320,6 @@ int iwl_queue_space(const struct iwl_queue *q); | |||
350 | /***************************************************** | 320 | /***************************************************** |
351 | * Error handling | 321 | * Error handling |
352 | ******************************************************/ | 322 | ******************************************************/ |
353 | int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, | ||
354 | char **buf, bool display); | ||
355 | int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); | 323 | int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display); |
356 | void iwl_dump_csr(struct iwl_trans *trans); | 324 | void iwl_dump_csr(struct iwl_trans *trans); |
357 | 325 | ||
@@ -388,91 +356,28 @@ static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) | |||
388 | iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); | 356 | iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); |
389 | } | 357 | } |
390 | 358 | ||
391 | /* | ||
392 | * we have 8 bits used like this: | ||
393 | * | ||
394 | * 7 6 5 4 3 2 1 0 | ||
395 | * | | | | | | | | | ||
396 | * | | | | | | +-+-------- AC queue (0-3) | ||
397 | * | | | | | | | ||
398 | * | +-+-+-+-+------------ HW queue ID | ||
399 | * | | ||
400 | * +---------------------- unused | ||
401 | */ | ||
402 | static inline void iwl_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq) | ||
403 | { | ||
404 | BUG_ON(ac > 3); /* only have 2 bits */ | ||
405 | BUG_ON(hwq > 31); /* only use 5 bits */ | ||
406 | |||
407 | txq->swq_id = (hwq << 2) | ac; | ||
408 | } | ||
409 | |||
410 | static inline u8 iwl_get_queue_ac(struct iwl_tx_queue *txq) | ||
411 | { | ||
412 | return txq->swq_id & 0x3; | ||
413 | } | ||
414 | |||
415 | static inline void iwl_wake_queue(struct iwl_trans *trans, | 359 | static inline void iwl_wake_queue(struct iwl_trans *trans, |
416 | struct iwl_tx_queue *txq) | 360 | struct iwl_tx_queue *txq) |
417 | { | 361 | { |
418 | u8 queue = txq->swq_id; | 362 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
419 | u8 ac = queue & 3; | 363 | |
420 | u8 hwq = (queue >> 2) & 0x1f; | 364 | if (test_and_clear_bit(txq->q.id, trans_pcie->queue_stopped)) { |
421 | struct iwl_trans_pcie *trans_pcie = | 365 | IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d\n", txq->q.id); |
422 | IWL_TRANS_GET_PCIE_TRANS(trans); | 366 | iwl_op_mode_queue_not_full(trans->op_mode, txq->q.id); |
423 | |||
424 | if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) { | ||
425 | if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) { | ||
426 | iwl_op_mode_queue_not_full(trans->op_mode, ac); | ||
427 | IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d", | ||
428 | hwq, ac); | ||
429 | } else { | ||
430 | IWL_DEBUG_TX_QUEUES(trans, | ||
431 | "Don't wake hwq %d ac %d stop count %d", | ||
432 | hwq, ac, | ||
433 | atomic_read(&trans_pcie->queue_stop_count[ac])); | ||
434 | } | ||
435 | } | 367 | } |
436 | } | 368 | } |
437 | 369 | ||
438 | static inline void iwl_stop_queue(struct iwl_trans *trans, | 370 | static inline void iwl_stop_queue(struct iwl_trans *trans, |
439 | struct iwl_tx_queue *txq) | 371 | struct iwl_tx_queue *txq) |
440 | { | 372 | { |
441 | u8 queue = txq->swq_id; | 373 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
442 | u8 ac = queue & 3; | ||
443 | u8 hwq = (queue >> 2) & 0x1f; | ||
444 | struct iwl_trans_pcie *trans_pcie = | ||
445 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
446 | |||
447 | if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) { | ||
448 | if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) { | ||
449 | iwl_op_mode_queue_full(trans->op_mode, ac); | ||
450 | IWL_DEBUG_TX_QUEUES(trans, | ||
451 | "Stop hwq %d ac %d stop count %d", | ||
452 | hwq, ac, | ||
453 | atomic_read(&trans_pcie->queue_stop_count[ac])); | ||
454 | } else { | ||
455 | IWL_DEBUG_TX_QUEUES(trans, | ||
456 | "Don't stop hwq %d ac %d stop count %d", | ||
457 | hwq, ac, | ||
458 | atomic_read(&trans_pcie->queue_stop_count[ac])); | ||
459 | } | ||
460 | } else { | ||
461 | IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped", | ||
462 | hwq); | ||
463 | } | ||
464 | } | ||
465 | |||
466 | static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie, | ||
467 | int txq_id) | ||
468 | { | ||
469 | set_bit(txq_id, &trans_pcie->txq_ctx_active_msk); | ||
470 | } | ||
471 | 374 | ||
472 | static inline void iwl_txq_ctx_deactivate(struct iwl_trans_pcie *trans_pcie, | 375 | if (!test_and_set_bit(txq->q.id, trans_pcie->queue_stopped)) { |
473 | int txq_id) | 376 | iwl_op_mode_queue_full(trans->op_mode, txq->q.id); |
474 | { | 377 | IWL_DEBUG_TX_QUEUES(trans, "Stop hwq %d\n", txq->q.id); |
475 | clear_bit(txq_id, &trans_pcie->txq_ctx_active_msk); | 378 | } else |
379 | IWL_DEBUG_TX_QUEUES(trans, "hwq %d already stopped\n", | ||
380 | txq->q.id); | ||
476 | } | 381 | } |
477 | 382 | ||
478 | static inline int iwl_queue_used(const struct iwl_queue *q, int i) | 383 | static inline int iwl_queue_used(const struct iwl_queue *q, int i) |
@@ -487,19 +392,4 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index) | |||
487 | return index & (q->n_window - 1); | 392 | return index & (q->n_window - 1); |
488 | } | 393 | } |
489 | 394 | ||
490 | #define IWL_TX_FIFO_BK 0 /* shared */ | ||
491 | #define IWL_TX_FIFO_BE 1 | ||
492 | #define IWL_TX_FIFO_VI 2 /* shared */ | ||
493 | #define IWL_TX_FIFO_VO 3 | ||
494 | #define IWL_TX_FIFO_BK_IPAN IWL_TX_FIFO_BK | ||
495 | #define IWL_TX_FIFO_BE_IPAN 4 | ||
496 | #define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI | ||
497 | #define IWL_TX_FIFO_VO_IPAN 5 | ||
498 | /* re-uses the VO FIFO, uCode will properly flush/schedule */ | ||
499 | #define IWL_TX_FIFO_AUX 5 | ||
500 | #define IWL_TX_FIFO_UNUSED -1 | ||
501 | |||
502 | /* AUX (TX during scan dwell) queue */ | ||
503 | #define IWL_AUX_QUEUE 10 | ||
504 | |||
505 | #endif /* __iwl_trans_int_pcie_h__ */ | 395 | #endif /* __iwl_trans_int_pcie_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 8b1a7988e176..ab0f3fc22b87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | |||
@@ -146,8 +146,11 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | |||
146 | q->write_actual = (q->write & ~0x7); | 146 | q->write_actual = (q->write & ~0x7); |
147 | iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, q->write_actual); | 147 | iwl_write32(trans, FH_RSCSR_CHNL0_WPTR, q->write_actual); |
148 | } else { | 148 | } else { |
149 | struct iwl_trans_pcie *trans_pcie = | ||
150 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
151 | |||
149 | /* If power-saving is in use, make sure device is awake */ | 152 | /* If power-saving is in use, make sure device is awake */ |
150 | if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { | 153 | if (test_bit(STATUS_POWER_PMI, &trans_pcie->status)) { |
151 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); | 154 | reg = iwl_read32(trans, CSR_UCODE_DRV_GP1); |
152 | 155 | ||
153 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { | 156 | if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { |
@@ -362,83 +365,96 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
362 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 365 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
363 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 366 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
364 | struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; | 367 | struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue]; |
365 | struct iwl_device_cmd *cmd; | ||
366 | unsigned long flags; | 368 | unsigned long flags; |
367 | int len, err; | 369 | bool page_stolen = false; |
368 | u16 sequence; | 370 | int max_len = PAGE_SIZE << hw_params(trans).rx_page_order; |
369 | struct iwl_rx_cmd_buffer rxcb; | 371 | u32 offset = 0; |
370 | struct iwl_rx_packet *pkt; | ||
371 | bool reclaim; | ||
372 | int index, cmd_index; | ||
373 | 372 | ||
374 | if (WARN_ON(!rxb)) | 373 | if (WARN_ON(!rxb)) |
375 | return; | 374 | return; |
376 | 375 | ||
377 | dma_unmap_page(trans->dev, rxb->page_dma, | 376 | dma_unmap_page(trans->dev, rxb->page_dma, max_len, DMA_FROM_DEVICE); |
378 | PAGE_SIZE << hw_params(trans).rx_page_order, | ||
379 | DMA_FROM_DEVICE); | ||
380 | |||
381 | rxcb._page = rxb->page; | ||
382 | pkt = rxb_addr(&rxcb); | ||
383 | 377 | ||
384 | IWL_DEBUG_RX(trans, "%s, 0x%02x\n", | 378 | while (offset + sizeof(u32) + sizeof(struct iwl_cmd_header) < max_len) { |
385 | get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); | 379 | struct iwl_rx_packet *pkt; |
380 | struct iwl_device_cmd *cmd; | ||
381 | u16 sequence; | ||
382 | bool reclaim; | ||
383 | int index, cmd_index, err, len; | ||
384 | struct iwl_rx_cmd_buffer rxcb = { | ||
385 | ._offset = offset, | ||
386 | ._page = rxb->page, | ||
387 | ._page_stolen = false, | ||
388 | }; | ||
386 | 389 | ||
390 | pkt = rxb_addr(&rxcb); | ||
387 | 391 | ||
388 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 392 | if (pkt->len_n_flags == cpu_to_le32(FH_RSCSR_FRAME_INVALID)) |
389 | len += sizeof(u32); /* account for status word */ | 393 | break; |
390 | trace_iwlwifi_dev_rx(trans->dev, pkt, len); | ||
391 | |||
392 | /* Reclaim a command buffer only if this packet is a response | ||
393 | * to a (driver-originated) command. | ||
394 | * If the packet (e.g. Rx frame) originated from uCode, | ||
395 | * there is no command buffer to reclaim. | ||
396 | * Ucode should set SEQ_RX_FRAME bit if ucode-originated, | ||
397 | * but apparently a few don't get set; catch them here. */ | ||
398 | reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME); | ||
399 | if (reclaim) { | ||
400 | int i; | ||
401 | 394 | ||
402 | for (i = 0; i < trans_pcie->n_no_reclaim_cmds; i++) { | 395 | IWL_DEBUG_RX(trans, "cmd at offset %d: %s (0x%.2x)\n", |
403 | if (trans_pcie->no_reclaim_cmds[i] == pkt->hdr.cmd) { | 396 | rxcb._offset, get_cmd_string(pkt->hdr.cmd), |
404 | reclaim = false; | 397 | pkt->hdr.cmd); |
405 | break; | 398 | |
399 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
400 | len += sizeof(u32); /* account for status word */ | ||
401 | trace_iwlwifi_dev_rx(trans->dev, pkt, len); | ||
402 | |||
403 | /* Reclaim a command buffer only if this packet is a response | ||
404 | * to a (driver-originated) command. | ||
405 | * If the packet (e.g. Rx frame) originated from uCode, | ||
406 | * there is no command buffer to reclaim. | ||
407 | * Ucode should set SEQ_RX_FRAME bit if ucode-originated, | ||
408 | * but apparently a few don't get set; catch them here. */ | ||
409 | reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME); | ||
410 | if (reclaim) { | ||
411 | int i; | ||
412 | |||
413 | for (i = 0; i < trans_pcie->n_no_reclaim_cmds; i++) { | ||
414 | if (trans_pcie->no_reclaim_cmds[i] == | ||
415 | pkt->hdr.cmd) { | ||
416 | reclaim = false; | ||
417 | break; | ||
418 | } | ||
406 | } | 419 | } |
407 | } | 420 | } |
408 | } | ||
409 | 421 | ||
410 | sequence = le16_to_cpu(pkt->hdr.sequence); | 422 | sequence = le16_to_cpu(pkt->hdr.sequence); |
411 | index = SEQ_TO_INDEX(sequence); | 423 | index = SEQ_TO_INDEX(sequence); |
412 | cmd_index = get_cmd_index(&txq->q, index); | 424 | cmd_index = get_cmd_index(&txq->q, index); |
413 | 425 | ||
414 | if (reclaim) | 426 | if (reclaim) |
415 | cmd = txq->cmd[cmd_index]; | 427 | cmd = txq->cmd[cmd_index]; |
416 | else | 428 | else |
417 | cmd = NULL; | 429 | cmd = NULL; |
418 | 430 | ||
419 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); | 431 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); |
420 | 432 | ||
421 | /* | 433 | /* |
422 | * XXX: After here, we should always check rxcb._page | 434 | * After here, we should always check rxcb._page_stolen, |
423 | * against NULL before touching it or its virtual | 435 | * if it is true then one of the handlers took the page. |
424 | * memory (pkt). Because some rx_handler might have | 436 | */ |
425 | * already taken or freed the pages. | ||
426 | */ | ||
427 | 437 | ||
428 | if (reclaim) { | 438 | if (reclaim) { |
429 | /* Invoke any callbacks, transfer the buffer to caller, | 439 | /* Invoke any callbacks, transfer the buffer to caller, |
430 | * and fire off the (possibly) blocking | 440 | * and fire off the (possibly) blocking |
431 | * iwl_trans_send_cmd() | 441 | * iwl_trans_send_cmd() |
432 | * as we reclaim the driver command queue */ | 442 | * as we reclaim the driver command queue */ |
433 | if (rxcb._page) | 443 | if (!rxcb._page_stolen) |
434 | iwl_tx_cmd_complete(trans, &rxcb, err); | 444 | iwl_tx_cmd_complete(trans, &rxcb, err); |
435 | else | 445 | else |
436 | IWL_WARN(trans, "Claim null rxb?\n"); | 446 | IWL_WARN(trans, "Claim null rxb?\n"); |
447 | } | ||
448 | |||
449 | page_stolen |= rxcb._page_stolen; | ||
450 | offset += ALIGN(len, FH_RSCSR_FRAME_ALIGN); | ||
437 | } | 451 | } |
438 | 452 | ||
439 | /* page was stolen from us */ | 453 | /* page was stolen from us -- free our reference */ |
440 | if (rxcb._page == NULL) | 454 | if (page_stolen) { |
455 | __free_pages(rxb->page, hw_params(trans).rx_page_order); | ||
441 | rxb->page = NULL; | 456 | rxb->page = NULL; |
457 | } | ||
442 | 458 | ||
443 | /* Reuse the page if possible. For notification packets and | 459 | /* Reuse the page if possible. For notification packets and |
444 | * SKBs that fail to Rx correctly, add them back into the | 460 | * SKBs that fail to Rx correctly, add them back into the |
@@ -520,153 +536,6 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
520 | iwlagn_rx_queue_restock(trans); | 536 | iwlagn_rx_queue_restock(trans); |
521 | } | 537 | } |
522 | 538 | ||
523 | static const char * const desc_lookup_text[] = { | ||
524 | "OK", | ||
525 | "FAIL", | ||
526 | "BAD_PARAM", | ||
527 | "BAD_CHECKSUM", | ||
528 | "NMI_INTERRUPT_WDG", | ||
529 | "SYSASSERT", | ||
530 | "FATAL_ERROR", | ||
531 | "BAD_COMMAND", | ||
532 | "HW_ERROR_TUNE_LOCK", | ||
533 | "HW_ERROR_TEMPERATURE", | ||
534 | "ILLEGAL_CHAN_FREQ", | ||
535 | "VCC_NOT_STABLE", | ||
536 | "FH_ERROR", | ||
537 | "NMI_INTERRUPT_HOST", | ||
538 | "NMI_INTERRUPT_ACTION_PT", | ||
539 | "NMI_INTERRUPT_UNKNOWN", | ||
540 | "UCODE_VERSION_MISMATCH", | ||
541 | "HW_ERROR_ABS_LOCK", | ||
542 | "HW_ERROR_CAL_LOCK_FAIL", | ||
543 | "NMI_INTERRUPT_INST_ACTION_PT", | ||
544 | "NMI_INTERRUPT_DATA_ACTION_PT", | ||
545 | "NMI_TRM_HW_ER", | ||
546 | "NMI_INTERRUPT_TRM", | ||
547 | "NMI_INTERRUPT_BREAK_POINT", | ||
548 | "DEBUG_0", | ||
549 | "DEBUG_1", | ||
550 | "DEBUG_2", | ||
551 | "DEBUG_3", | ||
552 | }; | ||
553 | |||
554 | static struct { char *name; u8 num; } advanced_lookup[] = { | ||
555 | { "NMI_INTERRUPT_WDG", 0x34 }, | ||
556 | { "SYSASSERT", 0x35 }, | ||
557 | { "UCODE_VERSION_MISMATCH", 0x37 }, | ||
558 | { "BAD_COMMAND", 0x38 }, | ||
559 | { "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C }, | ||
560 | { "FATAL_ERROR", 0x3D }, | ||
561 | { "NMI_TRM_HW_ERR", 0x46 }, | ||
562 | { "NMI_INTERRUPT_TRM", 0x4C }, | ||
563 | { "NMI_INTERRUPT_BREAK_POINT", 0x54 }, | ||
564 | { "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C }, | ||
565 | { "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 }, | ||
566 | { "NMI_INTERRUPT_HOST", 0x66 }, | ||
567 | { "NMI_INTERRUPT_ACTION_PT", 0x7C }, | ||
568 | { "NMI_INTERRUPT_UNKNOWN", 0x84 }, | ||
569 | { "NMI_INTERRUPT_INST_ACTION_PT", 0x86 }, | ||
570 | { "ADVANCED_SYSASSERT", 0 }, | ||
571 | }; | ||
572 | |||
573 | static const char *desc_lookup(u32 num) | ||
574 | { | ||
575 | int i; | ||
576 | int max = ARRAY_SIZE(desc_lookup_text); | ||
577 | |||
578 | if (num < max) | ||
579 | return desc_lookup_text[num]; | ||
580 | |||
581 | max = ARRAY_SIZE(advanced_lookup) - 1; | ||
582 | for (i = 0; i < max; i++) { | ||
583 | if (advanced_lookup[i].num == num) | ||
584 | break; | ||
585 | } | ||
586 | return advanced_lookup[i].name; | ||
587 | } | ||
588 | |||
589 | #define ERROR_START_OFFSET (1 * sizeof(u32)) | ||
590 | #define ERROR_ELEM_SIZE (7 * sizeof(u32)) | ||
591 | |||
592 | static void iwl_dump_nic_error_log(struct iwl_trans *trans) | ||
593 | { | ||
594 | u32 base; | ||
595 | struct iwl_error_event_table table; | ||
596 | struct iwl_trans_pcie *trans_pcie = | ||
597 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
598 | |||
599 | base = trans->shrd->device_pointers.error_event_table; | ||
600 | if (trans->shrd->ucode_type == IWL_UCODE_INIT) { | ||
601 | if (!base) | ||
602 | base = trans->shrd->fw->init_errlog_ptr; | ||
603 | } else { | ||
604 | if (!base) | ||
605 | base = trans->shrd->fw->inst_errlog_ptr; | ||
606 | } | ||
607 | |||
608 | if (!iwlagn_hw_valid_rtc_data_addr(base)) { | ||
609 | IWL_ERR(trans, | ||
610 | "Not valid error log pointer 0x%08X for %s uCode\n", | ||
611 | base, | ||
612 | (trans->shrd->ucode_type == IWL_UCODE_INIT) | ||
613 | ? "Init" : "RT"); | ||
614 | return; | ||
615 | } | ||
616 | |||
617 | iwl_read_targ_mem_words(trans, base, &table, sizeof(table)); | ||
618 | |||
619 | if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) { | ||
620 | IWL_ERR(trans, "Start IWL Error Log Dump:\n"); | ||
621 | IWL_ERR(trans, "Status: 0x%08lX, count: %d\n", | ||
622 | trans->shrd->status, table.valid); | ||
623 | } | ||
624 | |||
625 | trans_pcie->isr_stats.err_code = table.error_id; | ||
626 | |||
627 | trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, | ||
628 | table.data1, table.data2, table.line, | ||
629 | table.blink1, table.blink2, table.ilink1, | ||
630 | table.ilink2, table.bcon_time, table.gp1, | ||
631 | table.gp2, table.gp3, table.ucode_ver, | ||
632 | table.hw_ver, table.brd_ver); | ||
633 | IWL_ERR(trans, "0x%08X | %-28s\n", table.error_id, | ||
634 | desc_lookup(table.error_id)); | ||
635 | IWL_ERR(trans, "0x%08X | uPc\n", table.pc); | ||
636 | IWL_ERR(trans, "0x%08X | branchlink1\n", table.blink1); | ||
637 | IWL_ERR(trans, "0x%08X | branchlink2\n", table.blink2); | ||
638 | IWL_ERR(trans, "0x%08X | interruptlink1\n", table.ilink1); | ||
639 | IWL_ERR(trans, "0x%08X | interruptlink2\n", table.ilink2); | ||
640 | IWL_ERR(trans, "0x%08X | data1\n", table.data1); | ||
641 | IWL_ERR(trans, "0x%08X | data2\n", table.data2); | ||
642 | IWL_ERR(trans, "0x%08X | line\n", table.line); | ||
643 | IWL_ERR(trans, "0x%08X | beacon time\n", table.bcon_time); | ||
644 | IWL_ERR(trans, "0x%08X | tsf low\n", table.tsf_low); | ||
645 | IWL_ERR(trans, "0x%08X | tsf hi\n", table.tsf_hi); | ||
646 | IWL_ERR(trans, "0x%08X | time gp1\n", table.gp1); | ||
647 | IWL_ERR(trans, "0x%08X | time gp2\n", table.gp2); | ||
648 | IWL_ERR(trans, "0x%08X | time gp3\n", table.gp3); | ||
649 | IWL_ERR(trans, "0x%08X | uCode version\n", table.ucode_ver); | ||
650 | IWL_ERR(trans, "0x%08X | hw version\n", table.hw_ver); | ||
651 | IWL_ERR(trans, "0x%08X | board version\n", table.brd_ver); | ||
652 | IWL_ERR(trans, "0x%08X | hcmd\n", table.hcmd); | ||
653 | |||
654 | IWL_ERR(trans, "0x%08X | isr0\n", table.isr0); | ||
655 | IWL_ERR(trans, "0x%08X | isr1\n", table.isr1); | ||
656 | IWL_ERR(trans, "0x%08X | isr2\n", table.isr2); | ||
657 | IWL_ERR(trans, "0x%08X | isr3\n", table.isr3); | ||
658 | IWL_ERR(trans, "0x%08X | isr4\n", table.isr4); | ||
659 | IWL_ERR(trans, "0x%08X | isr_pref\n", table.isr_pref); | ||
660 | IWL_ERR(trans, "0x%08X | wait_event\n", table.wait_event); | ||
661 | IWL_ERR(trans, "0x%08X | l2p_control\n", table.l2p_control); | ||
662 | IWL_ERR(trans, "0x%08X | l2p_duration\n", table.l2p_duration); | ||
663 | IWL_ERR(trans, "0x%08X | l2p_mhvalid\n", table.l2p_mhvalid); | ||
664 | IWL_ERR(trans, "0x%08X | l2p_addr_match\n", table.l2p_addr_match); | ||
665 | IWL_ERR(trans, "0x%08X | lmpm_pmg_sel\n", table.lmpm_pmg_sel); | ||
666 | IWL_ERR(trans, "0x%08X | timestamp\n", table.u_timestamp); | ||
667 | IWL_ERR(trans, "0x%08X | flow_handler\n", table.flow_handler); | ||
668 | } | ||
669 | |||
670 | /** | 539 | /** |
671 | * iwl_irq_handle_error - called for HW or SW error interrupt from card | 540 | * iwl_irq_handle_error - called for HW or SW error interrupt from card |
672 | */ | 541 | */ |
@@ -689,243 +558,12 @@ static void iwl_irq_handle_error(struct iwl_trans *trans) | |||
689 | return; | 558 | return; |
690 | } | 559 | } |
691 | 560 | ||
692 | IWL_ERR(trans, "Loaded firmware version: %s\n", | ||
693 | trans->shrd->fw->fw_version); | ||
694 | |||
695 | iwl_dump_nic_error_log(trans); | ||
696 | iwl_dump_csr(trans); | 561 | iwl_dump_csr(trans); |
697 | iwl_dump_fh(trans, NULL, false); | 562 | iwl_dump_fh(trans, NULL, false); |
698 | iwl_dump_nic_event_log(trans, false, NULL, false); | ||
699 | 563 | ||
700 | iwl_op_mode_nic_error(trans->op_mode); | 564 | iwl_op_mode_nic_error(trans->op_mode); |
701 | } | 565 | } |
702 | 566 | ||
703 | #define EVENT_START_OFFSET (4 * sizeof(u32)) | ||
704 | |||
705 | /** | ||
706 | * iwl_print_event_log - Dump error event log to syslog | ||
707 | * | ||
708 | */ | ||
709 | static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx, | ||
710 | u32 num_events, u32 mode, | ||
711 | int pos, char **buf, size_t bufsz) | ||
712 | { | ||
713 | u32 i; | ||
714 | u32 base; /* SRAM byte address of event log header */ | ||
715 | u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ | ||
716 | u32 ptr; /* SRAM byte address of log data */ | ||
717 | u32 ev, time, data; /* event log data */ | ||
718 | unsigned long reg_flags; | ||
719 | |||
720 | if (num_events == 0) | ||
721 | return pos; | ||
722 | |||
723 | base = trans->shrd->device_pointers.log_event_table; | ||
724 | if (trans->shrd->ucode_type == IWL_UCODE_INIT) { | ||
725 | if (!base) | ||
726 | base = trans->shrd->fw->init_evtlog_ptr; | ||
727 | } else { | ||
728 | if (!base) | ||
729 | base = trans->shrd->fw->inst_evtlog_ptr; | ||
730 | } | ||
731 | |||
732 | if (mode == 0) | ||
733 | event_size = 2 * sizeof(u32); | ||
734 | else | ||
735 | event_size = 3 * sizeof(u32); | ||
736 | |||
737 | ptr = base + EVENT_START_OFFSET + (start_idx * event_size); | ||
738 | |||
739 | /* Make sure device is powered up for SRAM reads */ | ||
740 | spin_lock_irqsave(&trans->reg_lock, reg_flags); | ||
741 | if (unlikely(!iwl_grab_nic_access(trans))) | ||
742 | goto out_unlock; | ||
743 | |||
744 | /* Set starting address; reads will auto-increment */ | ||
745 | iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr); | ||
746 | |||
747 | /* "time" is actually "data" for mode 0 (no timestamp). | ||
748 | * place event id # at far right for easier visual parsing. */ | ||
749 | for (i = 0; i < num_events; i++) { | ||
750 | ev = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | ||
751 | time = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | ||
752 | if (mode == 0) { | ||
753 | /* data, ev */ | ||
754 | if (bufsz) { | ||
755 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
756 | "EVT_LOG:0x%08x:%04u\n", | ||
757 | time, ev); | ||
758 | } else { | ||
759 | trace_iwlwifi_dev_ucode_event(trans->dev, 0, | ||
760 | time, ev); | ||
761 | IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n", | ||
762 | time, ev); | ||
763 | } | ||
764 | } else { | ||
765 | data = iwl_read32(trans, HBUS_TARG_MEM_RDAT); | ||
766 | if (bufsz) { | ||
767 | pos += scnprintf(*buf + pos, bufsz - pos, | ||
768 | "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
769 | time, data, ev); | ||
770 | } else { | ||
771 | IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n", | ||
772 | time, data, ev); | ||
773 | trace_iwlwifi_dev_ucode_event(trans->dev, time, | ||
774 | data, ev); | ||
775 | } | ||
776 | } | ||
777 | } | ||
778 | |||
779 | /* Allow device to power down */ | ||
780 | iwl_release_nic_access(trans); | ||
781 | out_unlock: | ||
782 | spin_unlock_irqrestore(&trans->reg_lock, reg_flags); | ||
783 | return pos; | ||
784 | } | ||
785 | |||
786 | /** | ||
787 | * iwl_print_last_event_logs - Dump the newest # of event log to syslog | ||
788 | */ | ||
789 | static int iwl_print_last_event_logs(struct iwl_trans *trans, u32 capacity, | ||
790 | u32 num_wraps, u32 next_entry, | ||
791 | u32 size, u32 mode, | ||
792 | int pos, char **buf, size_t bufsz) | ||
793 | { | ||
794 | /* | ||
795 | * display the newest DEFAULT_LOG_ENTRIES entries | ||
796 | * i.e the entries just before the next ont that uCode would fill. | ||
797 | */ | ||
798 | if (num_wraps) { | ||
799 | if (next_entry < size) { | ||
800 | pos = iwl_print_event_log(trans, | ||
801 | capacity - (size - next_entry), | ||
802 | size - next_entry, mode, | ||
803 | pos, buf, bufsz); | ||
804 | pos = iwl_print_event_log(trans, 0, | ||
805 | next_entry, mode, | ||
806 | pos, buf, bufsz); | ||
807 | } else | ||
808 | pos = iwl_print_event_log(trans, next_entry - size, | ||
809 | size, mode, pos, buf, bufsz); | ||
810 | } else { | ||
811 | if (next_entry < size) { | ||
812 | pos = iwl_print_event_log(trans, 0, next_entry, | ||
813 | mode, pos, buf, bufsz); | ||
814 | } else { | ||
815 | pos = iwl_print_event_log(trans, next_entry - size, | ||
816 | size, mode, pos, buf, bufsz); | ||
817 | } | ||
818 | } | ||
819 | return pos; | ||
820 | } | ||
821 | |||
822 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) | ||
823 | |||
824 | int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log, | ||
825 | char **buf, bool display) | ||
826 | { | ||
827 | u32 base; /* SRAM byte address of event log header */ | ||
828 | u32 capacity; /* event log capacity in # entries */ | ||
829 | u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ | ||
830 | u32 num_wraps; /* # times uCode wrapped to top of log */ | ||
831 | u32 next_entry; /* index of next entry to be written by uCode */ | ||
832 | u32 size; /* # entries that we'll print */ | ||
833 | u32 logsize; | ||
834 | int pos = 0; | ||
835 | size_t bufsz = 0; | ||
836 | |||
837 | base = trans->shrd->device_pointers.log_event_table; | ||
838 | if (trans->shrd->ucode_type == IWL_UCODE_INIT) { | ||
839 | logsize = trans->shrd->fw->init_evtlog_size; | ||
840 | if (!base) | ||
841 | base = trans->shrd->fw->init_evtlog_ptr; | ||
842 | } else { | ||
843 | logsize = trans->shrd->fw->inst_evtlog_size; | ||
844 | if (!base) | ||
845 | base = trans->shrd->fw->inst_evtlog_ptr; | ||
846 | } | ||
847 | |||
848 | if (!iwlagn_hw_valid_rtc_data_addr(base)) { | ||
849 | IWL_ERR(trans, | ||
850 | "Invalid event log pointer 0x%08X for %s uCode\n", | ||
851 | base, | ||
852 | (trans->shrd->ucode_type == IWL_UCODE_INIT) | ||
853 | ? "Init" : "RT"); | ||
854 | return -EINVAL; | ||
855 | } | ||
856 | |||
857 | /* event log header */ | ||
858 | capacity = iwl_read_targ_mem(trans, base); | ||
859 | mode = iwl_read_targ_mem(trans, base + (1 * sizeof(u32))); | ||
860 | num_wraps = iwl_read_targ_mem(trans, base + (2 * sizeof(u32))); | ||
861 | next_entry = iwl_read_targ_mem(trans, base + (3 * sizeof(u32))); | ||
862 | |||
863 | if (capacity > logsize) { | ||
864 | IWL_ERR(trans, "Log capacity %d is bogus, limit to %d " | ||
865 | "entries\n", capacity, logsize); | ||
866 | capacity = logsize; | ||
867 | } | ||
868 | |||
869 | if (next_entry > logsize) { | ||
870 | IWL_ERR(trans, "Log write index %d is bogus, limit to %d\n", | ||
871 | next_entry, logsize); | ||
872 | next_entry = logsize; | ||
873 | } | ||
874 | |||
875 | size = num_wraps ? capacity : next_entry; | ||
876 | |||
877 | /* bail out if nothing in log */ | ||
878 | if (size == 0) { | ||
879 | IWL_ERR(trans, "Start IWL Event Log Dump: nothing in log\n"); | ||
880 | return pos; | ||
881 | } | ||
882 | |||
883 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
884 | if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log) | ||
885 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) | ||
886 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; | ||
887 | #else | ||
888 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) | ||
889 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; | ||
890 | #endif | ||
891 | IWL_ERR(trans, "Start IWL Event Log Dump: display last %u entries\n", | ||
892 | size); | ||
893 | |||
894 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
895 | if (display) { | ||
896 | if (full_log) | ||
897 | bufsz = capacity * 48; | ||
898 | else | ||
899 | bufsz = size * 48; | ||
900 | *buf = kmalloc(bufsz, GFP_KERNEL); | ||
901 | if (!*buf) | ||
902 | return -ENOMEM; | ||
903 | } | ||
904 | if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) { | ||
905 | /* | ||
906 | * if uCode has wrapped back to top of log, | ||
907 | * start at the oldest entry, | ||
908 | * i.e the next one that uCode would fill. | ||
909 | */ | ||
910 | if (num_wraps) | ||
911 | pos = iwl_print_event_log(trans, next_entry, | ||
912 | capacity - next_entry, mode, | ||
913 | pos, buf, bufsz); | ||
914 | /* (then/else) start at top of log */ | ||
915 | pos = iwl_print_event_log(trans, 0, | ||
916 | next_entry, mode, pos, buf, bufsz); | ||
917 | } else | ||
918 | pos = iwl_print_last_event_logs(trans, capacity, num_wraps, | ||
919 | next_entry, size, mode, | ||
920 | pos, buf, bufsz); | ||
921 | #else | ||
922 | pos = iwl_print_last_event_logs(trans, capacity, num_wraps, | ||
923 | next_entry, size, mode, | ||
924 | pos, buf, bufsz); | ||
925 | #endif | ||
926 | return pos; | ||
927 | } | ||
928 | |||
929 | /* tasklet for iwlagn interrupt */ | 567 | /* tasklet for iwlagn interrupt */ |
930 | void iwl_irq_tasklet(struct iwl_trans *trans) | 568 | void iwl_irq_tasklet(struct iwl_trans *trans) |
931 | { | 569 | { |
@@ -963,7 +601,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
963 | if (iwl_have_debug_level(IWL_DL_ISR)) { | 601 | if (iwl_have_debug_level(IWL_DL_ISR)) { |
964 | /* just for debug */ | 602 | /* just for debug */ |
965 | inta_mask = iwl_read32(trans, CSR_INT_MASK); | 603 | inta_mask = iwl_read32(trans, CSR_INT_MASK); |
966 | IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ", | 604 | IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n", |
967 | inta, inta_mask); | 605 | inta, inta_mask); |
968 | } | 606 | } |
969 | #endif | 607 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index e92972fd6ecf..4684e2310cd8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | |||
@@ -41,43 +41,6 @@ | |||
41 | #define IWL_TX_CRC_SIZE 4 | 41 | #define IWL_TX_CRC_SIZE 4 |
42 | #define IWL_TX_DELIMITER_SIZE 4 | 42 | #define IWL_TX_DELIMITER_SIZE 4 |
43 | 43 | ||
44 | /* | ||
45 | * mac80211 queues, ACs, hardware queues, FIFOs. | ||
46 | * | ||
47 | * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues | ||
48 | * | ||
49 | * Mac80211 uses the following numbers, which we get as from it | ||
50 | * by way of skb_get_queue_mapping(skb): | ||
51 | * | ||
52 | * VO 0 | ||
53 | * VI 1 | ||
54 | * BE 2 | ||
55 | * BK 3 | ||
56 | * | ||
57 | * | ||
58 | * Regular (not A-MPDU) frames are put into hardware queues corresponding | ||
59 | * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their | ||
60 | * own queue per aggregation session (RA/TID combination), such queues are | ||
61 | * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In | ||
62 | * order to map frames to the right queue, we also need an AC->hw queue | ||
63 | * mapping. This is implemented here. | ||
64 | * | ||
65 | * Due to the way hw queues are set up (by the hw specific code), the AC->hw | ||
66 | * queue mapping is the identity mapping. | ||
67 | */ | ||
68 | |||
69 | static const u8 tid_to_ac[] = { | ||
70 | IEEE80211_AC_BE, | ||
71 | IEEE80211_AC_BK, | ||
72 | IEEE80211_AC_BK, | ||
73 | IEEE80211_AC_BE, | ||
74 | IEEE80211_AC_VI, | ||
75 | IEEE80211_AC_VI, | ||
76 | IEEE80211_AC_VO, | ||
77 | IEEE80211_AC_VO | ||
78 | }; | ||
79 | |||
80 | |||
81 | /** | 44 | /** |
82 | * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | 45 | * iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array |
83 | */ | 46 | */ |
@@ -141,8 +104,10 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq) | |||
141 | iwl_write32(trans, HBUS_TARG_WRPTR, | 104 | iwl_write32(trans, HBUS_TARG_WRPTR, |
142 | txq->q.write_ptr | (txq_id << 8)); | 105 | txq->q.write_ptr | (txq_id << 8)); |
143 | } else { | 106 | } else { |
107 | struct iwl_trans_pcie *trans_pcie = | ||
108 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
144 | /* if we're trying to save power */ | 109 | /* if we're trying to save power */ |
145 | if (test_bit(STATUS_POWER_PMI, &trans->shrd->status)) { | 110 | if (test_bit(STATUS_POWER_PMI, &trans_pcie->status)) { |
146 | /* wake up nic if it's powered down ... | 111 | /* wake up nic if it's powered down ... |
147 | * uCode will wake up, and interrupt us again, so next | 112 | * uCode will wake up, and interrupt us again, so next |
148 | * time we'll skip this part. */ | 113 | * time we'll skip this part. */ |
@@ -448,20 +413,17 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_trans *trans, u16 txq_id) | |||
448 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, | 413 | void iwl_trans_set_wr_ptrs(struct iwl_trans *trans, |
449 | int txq_id, u32 index) | 414 | int txq_id, u32 index) |
450 | { | 415 | { |
451 | IWL_DEBUG_TX_QUEUES(trans, "Q %d WrPtr: %d", txq_id, index & 0xff); | 416 | IWL_DEBUG_TX_QUEUES(trans, "Q %d WrPtr: %d\n", txq_id, index & 0xff); |
452 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, | 417 | iwl_write_direct32(trans, HBUS_TARG_WRPTR, |
453 | (index & 0xff) | (txq_id << 8)); | 418 | (index & 0xff) | (txq_id << 8)); |
454 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), index); | 419 | iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), index); |
455 | } | 420 | } |
456 | 421 | ||
457 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | 422 | void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, |
458 | struct iwl_tx_queue *txq, | 423 | struct iwl_tx_queue *txq, |
459 | int tx_fifo_id, int scd_retry) | 424 | int tx_fifo_id, bool active) |
460 | { | 425 | { |
461 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
462 | int txq_id = txq->q.id; | 426 | int txq_id = txq->q.id; |
463 | int active = | ||
464 | test_bit(txq_id, &trans_pcie->txq_ctx_active_msk) ? 1 : 0; | ||
465 | 427 | ||
466 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), | 428 | iwl_write_prph(trans, SCD_QUEUE_STATUS_BITS(txq_id), |
467 | (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | | 429 | (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | |
@@ -469,77 +431,22 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans, | |||
469 | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | | 431 | (1 << SCD_QUEUE_STTS_REG_POS_WSL) | |
470 | SCD_QUEUE_STTS_REG_MSK); | 432 | SCD_QUEUE_STTS_REG_MSK); |
471 | 433 | ||
472 | txq->sched_retry = scd_retry; | ||
473 | |||
474 | if (active) | 434 | if (active) |
475 | IWL_DEBUG_TX_QUEUES(trans, "Activate %s Queue %d on FIFO %d\n", | 435 | IWL_DEBUG_TX_QUEUES(trans, "Activate queue %d on FIFO %d\n", |
476 | scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); | 436 | txq_id, tx_fifo_id); |
477 | else | 437 | else |
478 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate %s Queue %d\n", | 438 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); |
479 | scd_retry ? "BA" : "AC/CMD", txq_id); | ||
480 | } | ||
481 | |||
482 | static inline int get_ac_from_tid(u16 tid) | ||
483 | { | ||
484 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | ||
485 | return tid_to_ac[tid]; | ||
486 | |||
487 | /* no support for TIDs 8-15 yet */ | ||
488 | return -EINVAL; | ||
489 | } | 439 | } |
490 | 440 | ||
491 | static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie, | 441 | void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, int txq_id, int fifo, |
492 | u8 ctx, u16 tid) | 442 | int sta_id, int tid, int frame_limit, u16 ssn) |
493 | { | 443 | { |
494 | const u8 *ac_to_fifo = trans_pcie->ac_to_fifo[ctx]; | 444 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
495 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | ||
496 | return ac_to_fifo[tid_to_ac[tid]]; | ||
497 | |||
498 | /* no support for TIDs 8-15 yet */ | ||
499 | return -EINVAL; | ||
500 | } | ||
501 | |||
502 | static inline bool is_agg_txqid_valid(struct iwl_trans *trans, int txq_id) | ||
503 | { | ||
504 | if (txq_id < IWLAGN_FIRST_AMPDU_QUEUE) | ||
505 | return false; | ||
506 | return txq_id < (IWLAGN_FIRST_AMPDU_QUEUE + | ||
507 | hw_params(trans).num_ampdu_queues); | ||
508 | } | ||
509 | |||
510 | void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, | ||
511 | enum iwl_rxon_context_id ctx, int sta_id, | ||
512 | int tid, int frame_limit, u16 ssn) | ||
513 | { | ||
514 | int tx_fifo, txq_id; | ||
515 | u16 ra_tid; | ||
516 | unsigned long flags; | 445 | unsigned long flags; |
446 | u16 ra_tid = BUILD_RAxTID(sta_id, tid); | ||
517 | 447 | ||
518 | struct iwl_trans_pcie *trans_pcie = | 448 | if (test_and_set_bit(txq_id, trans_pcie->queue_used)) |
519 | IWL_TRANS_GET_PCIE_TRANS(trans); | 449 | WARN_ONCE(1, "queue %d already used - expect issues", txq_id); |
520 | |||
521 | if (WARN_ON(sta_id == IWL_INVALID_STATION)) | ||
522 | return; | ||
523 | if (WARN_ON(tid >= IWL_MAX_TID_COUNT)) | ||
524 | return; | ||
525 | |||
526 | tx_fifo = get_fifo_from_tid(trans_pcie, ctx, tid); | ||
527 | if (WARN_ON(tx_fifo < 0)) { | ||
528 | IWL_ERR(trans, "txq_agg_setup, bad fifo: %d\n", tx_fifo); | ||
529 | return; | ||
530 | } | ||
531 | |||
532 | txq_id = trans_pcie->agg_txq[sta_id][tid]; | ||
533 | if (WARN_ON_ONCE(!is_agg_txqid_valid(trans, txq_id))) { | ||
534 | IWL_ERR(trans, | ||
535 | "queue number out of range: %d, must be %d to %d\n", | ||
536 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | ||
537 | IWLAGN_FIRST_AMPDU_QUEUE + | ||
538 | hw_params(trans).num_ampdu_queues - 1); | ||
539 | return; | ||
540 | } | ||
541 | |||
542 | ra_tid = BUILD_RAxTID(sta_id, tid); | ||
543 | 450 | ||
544 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 451 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
545 | 452 | ||
@@ -550,10 +457,10 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, | |||
550 | iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); | 457 | iwlagn_tx_queue_set_q2ratid(trans, ra_tid, txq_id); |
551 | 458 | ||
552 | /* Set this queue as a chain-building queue */ | 459 | /* Set this queue as a chain-building queue */ |
553 | iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, (1<<txq_id)); | 460 | iwl_set_bits_prph(trans, SCD_QUEUECHAIN_SEL, BIT(txq_id)); |
554 | 461 | ||
555 | /* enable aggregations for the queue */ | 462 | /* enable aggregations for the queue */ |
556 | iwl_set_bits_prph(trans, SCD_AGGR_SEL, (1<<txq_id)); | 463 | iwl_set_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); |
557 | 464 | ||
558 | /* Place first TFD at index corresponding to start sequence number. | 465 | /* Place first TFD at index corresponding to start sequence number. |
559 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | 466 | * Assumes that ssn_idx is valid (!= 0xFFF) */ |
@@ -563,92 +470,42 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, | |||
563 | 470 | ||
564 | /* Set up Tx window size and frame limit for this queue */ | 471 | /* Set up Tx window size and frame limit for this queue */ |
565 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + | 472 | iwl_write_targ_mem(trans, trans_pcie->scd_base_addr + |
566 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + | 473 | SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), |
567 | sizeof(u32), | 474 | ((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & |
568 | ((frame_limit << | 475 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | |
569 | SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | 476 | ((frame_limit << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & |
570 | SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | 477 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); |
571 | ((frame_limit << | ||
572 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
573 | SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
574 | 478 | ||
575 | iwl_set_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); | 479 | iwl_set_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); |
576 | 480 | ||
577 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | 481 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ |
578 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], | 482 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], |
579 | tx_fifo, 1); | 483 | fifo, true); |
580 | |||
581 | trans_pcie->txq[txq_id].sta_id = sta_id; | ||
582 | trans_pcie->txq[txq_id].tid = tid; | ||
583 | 484 | ||
584 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 485 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
585 | } | 486 | } |
586 | 487 | ||
587 | /* | 488 | void iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int txq_id) |
588 | * Find first available (lowest unused) Tx Queue, mark it "active". | ||
589 | * Called only when finding queue for aggregation. | ||
590 | * Should never return anything < 7, because they should already | ||
591 | * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) | ||
592 | */ | ||
593 | static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans) | ||
594 | { | ||
595 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
596 | int txq_id; | ||
597 | |||
598 | for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues; | ||
599 | txq_id++) | ||
600 | if (!test_and_set_bit(txq_id, | ||
601 | &trans_pcie->txq_ctx_active_msk)) | ||
602 | return txq_id; | ||
603 | return -1; | ||
604 | } | ||
605 | |||
606 | int iwl_trans_pcie_tx_agg_alloc(struct iwl_trans *trans, | ||
607 | int sta_id, int tid) | ||
608 | { | ||
609 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
610 | int txq_id; | ||
611 | |||
612 | txq_id = iwlagn_txq_ctx_activate_free(trans); | ||
613 | if (txq_id == -1) { | ||
614 | IWL_ERR(trans, "No free aggregation queue available\n"); | ||
615 | return -ENXIO; | ||
616 | } | ||
617 | |||
618 | trans_pcie->agg_txq[sta_id][tid] = txq_id; | ||
619 | iwl_set_swq_id(&trans_pcie->txq[txq_id], get_ac_from_tid(tid), txq_id); | ||
620 | |||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid) | ||
625 | { | 489 | { |
626 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 490 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
627 | u8 txq_id = trans_pcie->agg_txq[sta_id][tid]; | ||
628 | 491 | ||
629 | if (WARN_ON_ONCE(!is_agg_txqid_valid(trans, txq_id))) { | 492 | if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { |
630 | IWL_ERR(trans, | 493 | WARN_ONCE(1, "queue %d not used", txq_id); |
631 | "queue number out of range: %d, must be %d to %d\n", | 494 | return; |
632 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | ||
633 | IWLAGN_FIRST_AMPDU_QUEUE + | ||
634 | hw_params(trans).num_ampdu_queues - 1); | ||
635 | return -EINVAL; | ||
636 | } | 495 | } |
637 | 496 | ||
638 | iwlagn_tx_queue_stop_scheduler(trans, txq_id); | 497 | iwlagn_tx_queue_stop_scheduler(trans, txq_id); |
639 | 498 | ||
640 | iwl_clear_bits_prph(trans, SCD_AGGR_SEL, (1 << txq_id)); | 499 | iwl_clear_bits_prph(trans, SCD_AGGR_SEL, BIT(txq_id)); |
641 | 500 | ||
642 | trans_pcie->agg_txq[sta_id][tid] = 0; | ||
643 | trans_pcie->txq[txq_id].q.read_ptr = 0; | 501 | trans_pcie->txq[txq_id].q.read_ptr = 0; |
644 | trans_pcie->txq[txq_id].q.write_ptr = 0; | 502 | trans_pcie->txq[txq_id].q.write_ptr = 0; |
645 | /* supposes that ssn_idx is valid (!= 0xFFF) */ | ||
646 | iwl_trans_set_wr_ptrs(trans, txq_id, 0); | 503 | iwl_trans_set_wr_ptrs(trans, txq_id, 0); |
647 | 504 | ||
648 | iwl_clear_bits_prph(trans, SCD_INTERRUPT_MASK, (1 << txq_id)); | 505 | iwl_clear_bits_prph(trans, SCD_INTERRUPT_MASK, BIT(txq_id)); |
649 | iwl_txq_ctx_deactivate(trans_pcie, txq_id); | 506 | |
650 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], 0, 0); | 507 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[txq_id], |
651 | return 0; | 508 | 0, false); |
652 | } | 509 | } |
653 | 510 | ||
654 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 511 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
@@ -681,11 +538,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
681 | int trace_idx; | 538 | int trace_idx; |
682 | #endif | 539 | #endif |
683 | 540 | ||
684 | if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) { | ||
685 | IWL_WARN(trans, "fw recovery, no hcmd send\n"); | ||
686 | return -EIO; | ||
687 | } | ||
688 | |||
689 | copy_size = sizeof(out_cmd->hdr); | 541 | copy_size = sizeof(out_cmd->hdr); |
690 | cmd_size = sizeof(out_cmd->hdr); | 542 | cmd_size = sizeof(out_cmd->hdr); |
691 | 543 | ||
@@ -966,12 +818,6 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
966 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", | 818 | IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n", |
967 | get_cmd_string(cmd->id)); | 819 | get_cmd_string(cmd->id)); |
968 | 820 | ||
969 | if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) { | ||
970 | IWL_ERR(trans, "Command %s failed: FW Error\n", | ||
971 | get_cmd_string(cmd->id)); | ||
972 | return -EIO; | ||
973 | } | ||
974 | |||
975 | if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE, | 821 | if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE, |
976 | &trans->shrd->status))) { | 822 | &trans->shrd->status))) { |
977 | IWL_ERR(trans, "Command %s: a command is already active!\n", | 823 | IWL_ERR(trans, "Command %s: a command is already active!\n", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 4d7b30d3e648..9f62283504e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | |||
@@ -180,7 +180,6 @@ static void iwl_trans_rx_hw_init(struct iwl_trans *trans, | |||
180 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | 180 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | |
181 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | 181 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | |
182 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | 182 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | |
183 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | | ||
184 | rb_size| | 183 | rb_size| |
185 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | 184 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| |
186 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | 185 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); |
@@ -370,21 +369,13 @@ error: | |||
370 | } | 369 | } |
371 | 370 | ||
372 | static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, | 371 | static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq, |
373 | int slots_num, u32 txq_id) | 372 | int slots_num, u32 txq_id) |
374 | { | 373 | { |
375 | int ret; | 374 | int ret; |
376 | 375 | ||
377 | txq->need_update = 0; | 376 | txq->need_update = 0; |
378 | memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num); | 377 | memset(txq->meta, 0, sizeof(txq->meta[0]) * slots_num); |
379 | 378 | ||
380 | /* | ||
381 | * For the default queues 0-3, set up the swq_id | ||
382 | * already -- all others need to get one later | ||
383 | * (if they need one at all). | ||
384 | */ | ||
385 | if (txq_id < 4) | ||
386 | iwl_set_swq_id(txq, txq_id, txq_id); | ||
387 | |||
388 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise | 379 | /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise |
389 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ | 380 | * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ |
390 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); | 381 | BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); |
@@ -895,59 +886,6 @@ static int iwl_prepare_card_hw(struct iwl_trans *trans) | |||
895 | return ret; | 886 | return ret; |
896 | } | 887 | } |
897 | 888 | ||
898 | #define IWL_AC_UNSET -1 | ||
899 | |||
900 | struct queue_to_fifo_ac { | ||
901 | s8 fifo, ac; | ||
902 | }; | ||
903 | |||
904 | static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = { | ||
905 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
906 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
907 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
908 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
909 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
910 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
911 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
912 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
913 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
914 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
915 | { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, | ||
916 | }; | ||
917 | |||
918 | static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { | ||
919 | { IWL_TX_FIFO_VO, IEEE80211_AC_VO, }, | ||
920 | { IWL_TX_FIFO_VI, IEEE80211_AC_VI, }, | ||
921 | { IWL_TX_FIFO_BE, IEEE80211_AC_BE, }, | ||
922 | { IWL_TX_FIFO_BK, IEEE80211_AC_BK, }, | ||
923 | { IWL_TX_FIFO_BK_IPAN, IEEE80211_AC_BK, }, | ||
924 | { IWL_TX_FIFO_BE_IPAN, IEEE80211_AC_BE, }, | ||
925 | { IWL_TX_FIFO_VI_IPAN, IEEE80211_AC_VI, }, | ||
926 | { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, | ||
927 | { IWL_TX_FIFO_BE_IPAN, 2, }, | ||
928 | { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, | ||
929 | { IWL_TX_FIFO_AUX, IWL_AC_UNSET, }, | ||
930 | }; | ||
931 | |||
932 | static const u8 iwlagn_bss_ac_to_fifo[] = { | ||
933 | IWL_TX_FIFO_VO, | ||
934 | IWL_TX_FIFO_VI, | ||
935 | IWL_TX_FIFO_BE, | ||
936 | IWL_TX_FIFO_BK, | ||
937 | }; | ||
938 | static const u8 iwlagn_bss_ac_to_queue[] = { | ||
939 | 0, 1, 2, 3, | ||
940 | }; | ||
941 | static const u8 iwlagn_pan_ac_to_fifo[] = { | ||
942 | IWL_TX_FIFO_VO_IPAN, | ||
943 | IWL_TX_FIFO_VI_IPAN, | ||
944 | IWL_TX_FIFO_BE_IPAN, | ||
945 | IWL_TX_FIFO_BK_IPAN, | ||
946 | }; | ||
947 | static const u8 iwlagn_pan_ac_to_queue[] = { | ||
948 | 7, 6, 5, 4, | ||
949 | }; | ||
950 | |||
951 | /* | 889 | /* |
952 | * ucode | 890 | * ucode |
953 | */ | 891 | */ |
@@ -1028,19 +966,8 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | |||
1028 | const struct fw_img *fw) | 966 | const struct fw_img *fw) |
1029 | { | 967 | { |
1030 | int ret; | 968 | int ret; |
1031 | struct iwl_trans_pcie *trans_pcie = | ||
1032 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1033 | bool hw_rfkill; | 969 | bool hw_rfkill; |
1034 | 970 | ||
1035 | trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue; | ||
1036 | trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue; | ||
1037 | |||
1038 | trans_pcie->ac_to_fifo[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_fifo; | ||
1039 | trans_pcie->ac_to_fifo[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_fifo; | ||
1040 | |||
1041 | trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0; | ||
1042 | trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE; | ||
1043 | |||
1044 | /* This may fail if AMT took ownership of the device */ | 971 | /* This may fail if AMT took ownership of the device */ |
1045 | if (iwl_prepare_card_hw(trans)) { | 972 | if (iwl_prepare_card_hw(trans)) { |
1046 | IWL_WARN(trans, "Exit HW not ready\n"); | 973 | IWL_WARN(trans, "Exit HW not ready\n"); |
@@ -1098,9 +1025,7 @@ static void iwl_trans_txq_set_sched(struct iwl_trans *trans, u32 mask) | |||
1098 | 1025 | ||
1099 | static void iwl_tx_start(struct iwl_trans *trans) | 1026 | static void iwl_tx_start(struct iwl_trans *trans) |
1100 | { | 1027 | { |
1101 | const struct queue_to_fifo_ac *queue_to_fifo; | 1028 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1102 | struct iwl_trans_pcie *trans_pcie = | ||
1103 | IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1104 | u32 a; | 1029 | u32 a; |
1105 | unsigned long flags; | 1030 | unsigned long flags; |
1106 | int i, chan; | 1031 | int i, chan; |
@@ -1166,41 +1091,19 @@ static void iwl_tx_start(struct iwl_trans *trans) | |||
1166 | /* Activate all Tx DMA/FIFO channels */ | 1091 | /* Activate all Tx DMA/FIFO channels */ |
1167 | iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); | 1092 | iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7)); |
1168 | 1093 | ||
1169 | /* map queues to FIFOs */ | ||
1170 | if (trans->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS)) | ||
1171 | queue_to_fifo = iwlagn_ipan_queue_to_tx_fifo; | ||
1172 | else | ||
1173 | queue_to_fifo = iwlagn_default_queue_to_tx_fifo; | ||
1174 | |||
1175 | iwl_trans_set_wr_ptrs(trans, trans_pcie->cmd_queue, 0); | 1094 | iwl_trans_set_wr_ptrs(trans, trans_pcie->cmd_queue, 0); |
1176 | 1095 | ||
1177 | /* make sure all queue are not stopped */ | 1096 | /* make sure all queue are not stopped/used */ |
1178 | memset(&trans_pcie->queue_stopped[0], 0, | 1097 | memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped)); |
1179 | sizeof(trans_pcie->queue_stopped)); | 1098 | memset(trans_pcie->queue_used, 0, sizeof(trans_pcie->queue_used)); |
1180 | for (i = 0; i < 4; i++) | ||
1181 | atomic_set(&trans_pcie->queue_stop_count[i], 0); | ||
1182 | 1099 | ||
1183 | /* reset to 0 to enable all the queue first */ | 1100 | for (i = 0; i < trans_pcie->n_q_to_fifo; i++) { |
1184 | trans_pcie->txq_ctx_active_msk = 0; | 1101 | int fifo = trans_pcie->setup_q_to_fifo[i]; |
1185 | 1102 | ||
1186 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) < | 1103 | set_bit(i, trans_pcie->queue_used); |
1187 | IWLAGN_FIRST_AMPDU_QUEUE); | ||
1188 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) < | ||
1189 | IWLAGN_FIRST_AMPDU_QUEUE); | ||
1190 | 1104 | ||
1191 | for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) { | ||
1192 | int fifo = queue_to_fifo[i].fifo; | ||
1193 | int ac = queue_to_fifo[i].ac; | ||
1194 | |||
1195 | iwl_txq_ctx_activate(trans_pcie, i); | ||
1196 | |||
1197 | if (fifo == IWL_TX_FIFO_UNUSED) | ||
1198 | continue; | ||
1199 | |||
1200 | if (ac != IWL_AC_UNSET) | ||
1201 | iwl_set_swq_id(&trans_pcie->txq[i], ac, i); | ||
1202 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], | 1105 | iwl_trans_tx_queue_set_status(trans, &trans_pcie->txq[i], |
1203 | fifo, 0); | 1106 | fifo, true); |
1204 | } | 1107 | } |
1205 | 1108 | ||
1206 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 1109 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
@@ -1325,70 +1228,32 @@ static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans) | |||
1325 | } | 1228 | } |
1326 | 1229 | ||
1327 | static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | 1230 | static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, |
1328 | struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, | 1231 | struct iwl_device_cmd *dev_cmd, int txq_id) |
1329 | u8 sta_id, u8 tid) | ||
1330 | { | 1232 | { |
1331 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1233 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1332 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1234 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1333 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1334 | struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; | 1235 | struct iwl_tx_cmd *tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; |
1335 | struct iwl_cmd_meta *out_meta; | 1236 | struct iwl_cmd_meta *out_meta; |
1336 | struct iwl_tx_queue *txq; | 1237 | struct iwl_tx_queue *txq; |
1337 | struct iwl_queue *q; | 1238 | struct iwl_queue *q; |
1338 | |||
1339 | dma_addr_t phys_addr = 0; | 1239 | dma_addr_t phys_addr = 0; |
1340 | dma_addr_t txcmd_phys; | 1240 | dma_addr_t txcmd_phys; |
1341 | dma_addr_t scratch_phys; | 1241 | dma_addr_t scratch_phys; |
1342 | u16 len, firstlen, secondlen; | 1242 | u16 len, firstlen, secondlen; |
1343 | u8 wait_write_ptr = 0; | 1243 | u8 wait_write_ptr = 0; |
1344 | u8 txq_id; | ||
1345 | bool is_agg = false; | ||
1346 | __le16 fc = hdr->frame_control; | 1244 | __le16 fc = hdr->frame_control; |
1347 | u8 hdr_len = ieee80211_hdrlen(fc); | 1245 | u8 hdr_len = ieee80211_hdrlen(fc); |
1348 | u16 __maybe_unused wifi_seq; | 1246 | u16 __maybe_unused wifi_seq; |
1349 | 1247 | ||
1350 | /* | ||
1351 | * Send this frame after DTIM -- there's a special queue | ||
1352 | * reserved for this for contexts that support AP mode. | ||
1353 | */ | ||
1354 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | ||
1355 | txq_id = trans_pcie->mcast_queue[ctx]; | ||
1356 | |||
1357 | /* | ||
1358 | * The microcode will clear the more data | ||
1359 | * bit in the last frame it transmits. | ||
1360 | */ | ||
1361 | hdr->frame_control |= | ||
1362 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
1363 | } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
1364 | txq_id = IWL_AUX_QUEUE; | ||
1365 | else | ||
1366 | txq_id = | ||
1367 | trans_pcie->ac_to_queue[ctx][skb_get_queue_mapping(skb)]; | ||
1368 | |||
1369 | /* aggregation is on for this <sta,tid> */ | ||
1370 | if (info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
1371 | WARN_ON(tid >= IWL_MAX_TID_COUNT); | ||
1372 | txq_id = trans_pcie->agg_txq[sta_id][tid]; | ||
1373 | is_agg = true; | ||
1374 | } | ||
1375 | |||
1376 | txq = &trans_pcie->txq[txq_id]; | 1248 | txq = &trans_pcie->txq[txq_id]; |
1377 | q = &txq->q; | 1249 | q = &txq->q; |
1378 | 1250 | ||
1379 | spin_lock(&txq->lock); | 1251 | if (unlikely(!test_bit(txq_id, trans_pcie->queue_used))) { |
1252 | WARN_ON_ONCE(1); | ||
1253 | return -EINVAL; | ||
1254 | } | ||
1380 | 1255 | ||
1381 | /* In AGG mode, the index in the ring must correspond to the WiFi | 1256 | spin_lock(&txq->lock); |
1382 | * sequence number. This is a HW requirements to help the SCD to parse | ||
1383 | * the BA. | ||
1384 | * Check here that the packets are in the right place on the ring. | ||
1385 | */ | ||
1386 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1387 | wifi_seq = SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); | ||
1388 | WARN_ONCE(is_agg && ((wifi_seq & 0xff) != q->write_ptr), | ||
1389 | "Q: %d WiFi Seq %d tfdNum %d", | ||
1390 | txq_id, wifi_seq, q->write_ptr); | ||
1391 | #endif | ||
1392 | 1257 | ||
1393 | /* Set up driver data for this TFD */ | 1258 | /* Set up driver data for this TFD */ |
1394 | txq->skbs[q->write_ptr] = skb; | 1259 | txq->skbs[q->write_ptr] = skb; |
@@ -1565,8 +1430,8 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans) | |||
1565 | iwl_enable_rfkill_int(trans); | 1430 | iwl_enable_rfkill_int(trans); |
1566 | } | 1431 | } |
1567 | 1432 | ||
1568 | static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, | 1433 | static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, |
1569 | int txq_id, int ssn, struct sk_buff_head *skbs) | 1434 | struct sk_buff_head *skbs) |
1570 | { | 1435 | { |
1571 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1436 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1572 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | 1437 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; |
@@ -1578,33 +1443,15 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid, | |||
1578 | 1443 | ||
1579 | txq->time_stamp = jiffies; | 1444 | txq->time_stamp = jiffies; |
1580 | 1445 | ||
1581 | if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE && | ||
1582 | tid != IWL_TID_NON_QOS && | ||
1583 | txq_id != trans_pcie->agg_txq[sta_id][tid])) { | ||
1584 | /* | ||
1585 | * FIXME: this is a uCode bug which need to be addressed, | ||
1586 | * log the information and return for now. | ||
1587 | * Since it is can possibly happen very often and in order | ||
1588 | * not to fill the syslog, don't use IWL_ERR or IWL_WARN | ||
1589 | */ | ||
1590 | IWL_DEBUG_TX_QUEUES(trans, "Bad queue mapping txq_id %d, " | ||
1591 | "agg_txq[sta_id[tid] %d", txq_id, | ||
1592 | trans_pcie->agg_txq[sta_id][tid]); | ||
1593 | spin_unlock(&txq->lock); | ||
1594 | return 1; | ||
1595 | } | ||
1596 | |||
1597 | if (txq->q.read_ptr != tfd_num) { | 1446 | if (txq->q.read_ptr != tfd_num) { |
1598 | IWL_DEBUG_TX_REPLY(trans, "[Q %d | AC %d] %d -> %d (%d)\n", | 1447 | IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", |
1599 | txq_id, iwl_get_queue_ac(txq), txq->q.read_ptr, | 1448 | txq_id, txq->q.read_ptr, tfd_num, ssn); |
1600 | tfd_num, ssn); | ||
1601 | freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); | 1449 | freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); |
1602 | if (iwl_queue_space(&txq->q) > txq->q.low_mark) | 1450 | if (iwl_queue_space(&txq->q) > txq->q.low_mark) |
1603 | iwl_wake_queue(trans, txq); | 1451 | iwl_wake_queue(trans, txq); |
1604 | } | 1452 | } |
1605 | 1453 | ||
1606 | spin_unlock(&txq->lock); | 1454 | spin_unlock(&txq->lock); |
1607 | return 0; | ||
1608 | } | 1455 | } |
1609 | 1456 | ||
1610 | static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) | 1457 | static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val) |
@@ -1623,7 +1470,7 @@ static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs) | |||
1623 | } | 1470 | } |
1624 | 1471 | ||
1625 | static void iwl_trans_pcie_configure(struct iwl_trans *trans, | 1472 | static void iwl_trans_pcie_configure(struct iwl_trans *trans, |
1626 | const struct iwl_trans_config *trans_cfg) | 1473 | const struct iwl_trans_config *trans_cfg) |
1627 | { | 1474 | { |
1628 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1475 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
1629 | 1476 | ||
@@ -1635,6 +1482,17 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, | |||
1635 | if (trans_pcie->n_no_reclaim_cmds) | 1482 | if (trans_pcie->n_no_reclaim_cmds) |
1636 | memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds, | 1483 | memcpy(trans_pcie->no_reclaim_cmds, trans_cfg->no_reclaim_cmds, |
1637 | trans_pcie->n_no_reclaim_cmds * sizeof(u8)); | 1484 | trans_pcie->n_no_reclaim_cmds * sizeof(u8)); |
1485 | |||
1486 | trans_pcie->n_q_to_fifo = trans_cfg->n_queue_to_fifo; | ||
1487 | |||
1488 | if (WARN_ON(trans_pcie->n_q_to_fifo > IWL_MAX_HW_QUEUES)) | ||
1489 | trans_pcie->n_q_to_fifo = IWL_MAX_HW_QUEUES; | ||
1490 | |||
1491 | /* at least the command queue must be mapped */ | ||
1492 | WARN_ON(!trans_pcie->n_q_to_fifo); | ||
1493 | |||
1494 | memcpy(trans_pcie->setup_q_to_fifo, trans_cfg->queue_to_fifo, | ||
1495 | trans_pcie->n_q_to_fifo * sizeof(u8)); | ||
1638 | } | 1496 | } |
1639 | 1497 | ||
1640 | static void iwl_trans_pcie_free(struct iwl_trans *trans) | 1498 | static void iwl_trans_pcie_free(struct iwl_trans *trans) |
@@ -1660,6 +1518,16 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans) | |||
1660 | kfree(trans); | 1518 | kfree(trans); |
1661 | } | 1519 | } |
1662 | 1520 | ||
1521 | static void iwl_trans_pcie_set_pmi(struct iwl_trans *trans, bool state) | ||
1522 | { | ||
1523 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
1524 | |||
1525 | if (state) | ||
1526 | set_bit(STATUS_POWER_PMI, &trans_pcie->status); | ||
1527 | else | ||
1528 | clear_bit(STATUS_POWER_PMI, &trans_pcie->status); | ||
1529 | } | ||
1530 | |||
1663 | #ifdef CONFIG_PM_SLEEP | 1531 | #ifdef CONFIG_PM_SLEEP |
1664 | static int iwl_trans_pcie_suspend(struct iwl_trans *trans) | 1532 | static int iwl_trans_pcie_suspend(struct iwl_trans *trans) |
1665 | { | 1533 | { |
@@ -1952,18 +1820,10 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
1952 | txq = &trans_pcie->txq[cnt]; | 1820 | txq = &trans_pcie->txq[cnt]; |
1953 | q = &txq->q; | 1821 | q = &txq->q; |
1954 | pos += scnprintf(buf + pos, bufsz - pos, | 1822 | pos += scnprintf(buf + pos, bufsz - pos, |
1955 | "hwq %.2d: read=%u write=%u stop=%d" | 1823 | "hwq %.2d: read=%u write=%u use=%d stop=%d\n", |
1956 | " swq_id=%#.2x (ac %d/hwq %d)\n", | ||
1957 | cnt, q->read_ptr, q->write_ptr, | 1824 | cnt, q->read_ptr, q->write_ptr, |
1958 | !!test_bit(cnt, trans_pcie->queue_stopped), | 1825 | !!test_bit(cnt, trans_pcie->queue_used), |
1959 | txq->swq_id, txq->swq_id & 3, | 1826 | !!test_bit(cnt, trans_pcie->queue_stopped)); |
1960 | (txq->swq_id >> 2) & 0x1f); | ||
1961 | if (cnt >= 4) | ||
1962 | continue; | ||
1963 | /* for the ACs, display the stop count too */ | ||
1964 | pos += scnprintf(buf + pos, bufsz - pos, | ||
1965 | " stop-count: %d\n", | ||
1966 | atomic_read(&trans_pcie->queue_stop_count[cnt])); | ||
1967 | } | 1827 | } |
1968 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1828 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1969 | kfree(buf); | 1829 | kfree(buf); |
@@ -1997,44 +1857,6 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1997 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1857 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1998 | } | 1858 | } |
1999 | 1859 | ||
2000 | static ssize_t iwl_dbgfs_log_event_read(struct file *file, | ||
2001 | char __user *user_buf, | ||
2002 | size_t count, loff_t *ppos) | ||
2003 | { | ||
2004 | struct iwl_trans *trans = file->private_data; | ||
2005 | char *buf; | ||
2006 | int pos = 0; | ||
2007 | ssize_t ret = -ENOMEM; | ||
2008 | |||
2009 | ret = pos = iwl_dump_nic_event_log(trans, true, &buf, true); | ||
2010 | if (buf) { | ||
2011 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
2012 | kfree(buf); | ||
2013 | } | ||
2014 | return ret; | ||
2015 | } | ||
2016 | |||
2017 | static ssize_t iwl_dbgfs_log_event_write(struct file *file, | ||
2018 | const char __user *user_buf, | ||
2019 | size_t count, loff_t *ppos) | ||
2020 | { | ||
2021 | struct iwl_trans *trans = file->private_data; | ||
2022 | u32 event_log_flag; | ||
2023 | char buf[8]; | ||
2024 | int buf_size; | ||
2025 | |||
2026 | memset(buf, 0, sizeof(buf)); | ||
2027 | buf_size = min(count, sizeof(buf) - 1); | ||
2028 | if (copy_from_user(buf, user_buf, buf_size)) | ||
2029 | return -EFAULT; | ||
2030 | if (sscanf(buf, "%d", &event_log_flag) != 1) | ||
2031 | return -EFAULT; | ||
2032 | if (event_log_flag == 1) | ||
2033 | iwl_dump_nic_event_log(trans, true, NULL, false); | ||
2034 | |||
2035 | return count; | ||
2036 | } | ||
2037 | |||
2038 | static ssize_t iwl_dbgfs_interrupt_read(struct file *file, | 1860 | static ssize_t iwl_dbgfs_interrupt_read(struct file *file, |
2039 | char __user *user_buf, | 1861 | char __user *user_buf, |
2040 | size_t count, loff_t *ppos) { | 1862 | size_t count, loff_t *ppos) { |
@@ -2161,7 +1983,6 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, | |||
2161 | return ret; | 1983 | return ret; |
2162 | } | 1984 | } |
2163 | 1985 | ||
2164 | DEBUGFS_READ_WRITE_FILE_OPS(log_event); | ||
2165 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 1986 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); |
2166 | DEBUGFS_READ_FILE_OPS(fh_reg); | 1987 | DEBUGFS_READ_FILE_OPS(fh_reg); |
2167 | DEBUGFS_READ_FILE_OPS(rx_queue); | 1988 | DEBUGFS_READ_FILE_OPS(rx_queue); |
@@ -2177,7 +1998,6 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | |||
2177 | { | 1998 | { |
2178 | DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); | 1999 | DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); |
2179 | DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); | 2000 | DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); |
2180 | DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); | ||
2181 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); | 2001 | DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); |
2182 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); | 2002 | DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); |
2183 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); | 2003 | DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); |
@@ -2205,7 +2025,6 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
2205 | .reclaim = iwl_trans_pcie_reclaim, | 2025 | .reclaim = iwl_trans_pcie_reclaim, |
2206 | 2026 | ||
2207 | .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, | 2027 | .tx_agg_disable = iwl_trans_pcie_tx_agg_disable, |
2208 | .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, | ||
2209 | .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, | 2028 | .tx_agg_setup = iwl_trans_pcie_tx_agg_setup, |
2210 | 2029 | ||
2211 | .free = iwl_trans_pcie_free, | 2030 | .free = iwl_trans_pcie_free, |
@@ -2223,6 +2042,7 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
2223 | .write32 = iwl_trans_pcie_write32, | 2042 | .write32 = iwl_trans_pcie_write32, |
2224 | .read32 = iwl_trans_pcie_read32, | 2043 | .read32 = iwl_trans_pcie_read32, |
2225 | .configure = iwl_trans_pcie_configure, | 2044 | .configure = iwl_trans_pcie_configure, |
2045 | .set_pmi = iwl_trans_pcie_set_pmi, | ||
2226 | }; | 2046 | }; |
2227 | 2047 | ||
2228 | struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, | 2048 | struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 0c81cbaa8088..66c54c1b404e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -162,6 +162,8 @@ struct iwl_cmd_header { | |||
162 | 162 | ||
163 | 163 | ||
164 | #define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */ | 164 | #define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */ |
165 | #define FH_RSCSR_FRAME_INVALID 0x55550000 | ||
166 | #define FH_RSCSR_FRAME_ALIGN 0x40 | ||
165 | 167 | ||
166 | struct iwl_rx_packet { | 168 | struct iwl_rx_packet { |
167 | /* | 169 | /* |
@@ -260,27 +262,42 @@ static inline void iwl_free_resp(struct iwl_host_cmd *cmd) | |||
260 | 262 | ||
261 | struct iwl_rx_cmd_buffer { | 263 | struct iwl_rx_cmd_buffer { |
262 | struct page *_page; | 264 | struct page *_page; |
265 | int _offset; | ||
266 | bool _page_stolen; | ||
263 | }; | 267 | }; |
264 | 268 | ||
265 | static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r) | 269 | static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r) |
266 | { | 270 | { |
267 | return page_address(r->_page); | 271 | return (void *)((unsigned long)page_address(r->_page) + r->_offset); |
272 | } | ||
273 | |||
274 | static inline int rxb_offset(struct iwl_rx_cmd_buffer *r) | ||
275 | { | ||
276 | return r->_offset; | ||
268 | } | 277 | } |
269 | 278 | ||
270 | static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) | 279 | static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) |
271 | { | 280 | { |
272 | struct page *p = r->_page; | 281 | r->_page_stolen = true; |
273 | r->_page = NULL; | 282 | get_page(r->_page); |
274 | return p; | 283 | return r->_page; |
275 | } | 284 | } |
276 | 285 | ||
277 | #define MAX_NO_RECLAIM_CMDS 6 | 286 | #define MAX_NO_RECLAIM_CMDS 6 |
278 | 287 | ||
288 | /* | ||
289 | * Maximum number of HW queues the transport layer | ||
290 | * currently supports | ||
291 | */ | ||
292 | #define IWL_MAX_HW_QUEUES 32 | ||
293 | |||
279 | /** | 294 | /** |
280 | * struct iwl_trans_config - transport configuration | 295 | * struct iwl_trans_config - transport configuration |
281 | * | 296 | * |
282 | * @op_mode: pointer to the upper layer. | 297 | * @op_mode: pointer to the upper layer. |
283 | * Must be set before any other call. | 298 | * @queue_to_fifo: queue to FIFO mapping to set up by |
299 | * default | ||
300 | * @n_queue_to_fifo: number of queues to set up | ||
284 | * @cmd_queue: the index of the command queue. | 301 | * @cmd_queue: the index of the command queue. |
285 | * Must be set before start_fw. | 302 | * Must be set before start_fw. |
286 | * @no_reclaim_cmds: Some devices erroneously don't set the | 303 | * @no_reclaim_cmds: Some devices erroneously don't set the |
@@ -291,6 +308,9 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r) | |||
291 | */ | 308 | */ |
292 | struct iwl_trans_config { | 309 | struct iwl_trans_config { |
293 | struct iwl_op_mode *op_mode; | 310 | struct iwl_op_mode *op_mode; |
311 | const u8 *queue_to_fifo; | ||
312 | u8 n_queue_to_fifo; | ||
313 | |||
294 | u8 cmd_queue; | 314 | u8 cmd_queue; |
295 | const u8 *no_reclaim_cmds; | 315 | const u8 *no_reclaim_cmds; |
296 | int n_no_reclaim_cmds; | 316 | int n_no_reclaim_cmds; |
@@ -322,8 +342,6 @@ struct iwl_trans_config { | |||
322 | * Must be atomic | 342 | * Must be atomic |
323 | * @reclaim: free packet until ssn. Returns a list of freed packets. | 343 | * @reclaim: free packet until ssn. Returns a list of freed packets. |
324 | * Must be atomic | 344 | * Must be atomic |
325 | * @tx_agg_alloc: allocate resources for a TX BA session | ||
326 | * Must be atomic | ||
327 | * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is | 345 | * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is |
328 | * ready and a successful ADDBA response has been received. | 346 | * ready and a successful ADDBA response has been received. |
329 | * May sleep | 347 | * May sleep |
@@ -346,6 +364,7 @@ struct iwl_trans_config { | |||
346 | * @configure: configure parameters required by the transport layer from | 364 | * @configure: configure parameters required by the transport layer from |
347 | * the op_mode. May be called several times before start_fw, can't be | 365 | * the op_mode. May be called several times before start_fw, can't be |
348 | * called after that. | 366 | * called after that. |
367 | * @set_pmi: set the power pmi state | ||
349 | */ | 368 | */ |
350 | struct iwl_trans_ops { | 369 | struct iwl_trans_ops { |
351 | 370 | ||
@@ -360,18 +379,13 @@ struct iwl_trans_ops { | |||
360 | int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); | 379 | int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd); |
361 | 380 | ||
362 | int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, | 381 | int (*tx)(struct iwl_trans *trans, struct sk_buff *skb, |
363 | struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, | 382 | struct iwl_device_cmd *dev_cmd, int queue); |
364 | u8 sta_id, u8 tid); | 383 | void (*reclaim)(struct iwl_trans *trans, int queue, int ssn, |
365 | int (*reclaim)(struct iwl_trans *trans, int sta_id, int tid, | 384 | struct sk_buff_head *skbs); |
366 | int txq_id, int ssn, struct sk_buff_head *skbs); | 385 | |
367 | 386 | void (*tx_agg_setup)(struct iwl_trans *trans, int queue, int fifo, | |
368 | int (*tx_agg_disable)(struct iwl_trans *trans, | 387 | int sta_id, int tid, int frame_limit, u16 ssn); |
369 | int sta_id, int tid); | 388 | void (*tx_agg_disable)(struct iwl_trans *trans, int queue); |
370 | int (*tx_agg_alloc)(struct iwl_trans *trans, | ||
371 | int sta_id, int tid); | ||
372 | void (*tx_agg_setup)(struct iwl_trans *trans, | ||
373 | enum iwl_rxon_context_id ctx, int sta_id, int tid, | ||
374 | int frame_limit, u16 ssn); | ||
375 | 389 | ||
376 | void (*free)(struct iwl_trans *trans); | 390 | void (*free)(struct iwl_trans *trans); |
377 | 391 | ||
@@ -387,6 +401,7 @@ struct iwl_trans_ops { | |||
387 | u32 (*read32)(struct iwl_trans *trans, u32 ofs); | 401 | u32 (*read32)(struct iwl_trans *trans, u32 ofs); |
388 | void (*configure)(struct iwl_trans *trans, | 402 | void (*configure)(struct iwl_trans *trans, |
389 | const struct iwl_trans_config *trans_cfg); | 403 | const struct iwl_trans_config *trans_cfg); |
404 | void (*set_pmi)(struct iwl_trans *trans, bool state); | ||
390 | }; | 405 | }; |
391 | 406 | ||
392 | /** | 407 | /** |
@@ -507,55 +522,42 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | |||
507 | } | 522 | } |
508 | 523 | ||
509 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, | 524 | static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb, |
510 | struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, | 525 | struct iwl_device_cmd *dev_cmd, int queue) |
511 | u8 sta_id, u8 tid) | ||
512 | { | ||
513 | if (trans->state != IWL_TRANS_FW_ALIVE) | ||
514 | IWL_ERR(trans, "%s bad state = %d", __func__, trans->state); | ||
515 | |||
516 | return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id, tid); | ||
517 | } | ||
518 | |||
519 | static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id, | ||
520 | int tid, int txq_id, int ssn, | ||
521 | struct sk_buff_head *skbs) | ||
522 | { | 526 | { |
523 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 527 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, |
524 | "%s bad state = %d", __func__, trans->state); | 528 | "%s bad state = %d", __func__, trans->state); |
525 | 529 | ||
526 | return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, skbs); | 530 | return trans->ops->tx(trans, skb, dev_cmd, queue); |
527 | } | 531 | } |
528 | 532 | ||
529 | static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans, | 533 | static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, |
530 | int sta_id, int tid) | 534 | int ssn, struct sk_buff_head *skbs) |
531 | { | 535 | { |
532 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 536 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, |
533 | "%s bad state = %d", __func__, trans->state); | 537 | "%s bad state = %d", __func__, trans->state); |
534 | 538 | ||
535 | return trans->ops->tx_agg_disable(trans, sta_id, tid); | 539 | trans->ops->reclaim(trans, queue, ssn, skbs); |
536 | } | 540 | } |
537 | 541 | ||
538 | static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans, | 542 | static inline void iwl_trans_tx_agg_disable(struct iwl_trans *trans, int queue) |
539 | int sta_id, int tid) | ||
540 | { | 543 | { |
541 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 544 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, |
542 | "%s bad state = %d", __func__, trans->state); | 545 | "%s bad state = %d", __func__, trans->state); |
543 | 546 | ||
544 | return trans->ops->tx_agg_alloc(trans, sta_id, tid); | 547 | trans->ops->tx_agg_disable(trans, queue); |
545 | } | 548 | } |
546 | 549 | ||
547 | 550 | static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, int queue, | |
548 | static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, | 551 | int fifo, int sta_id, int tid, |
549 | enum iwl_rxon_context_id ctx, | 552 | int frame_limit, u16 ssn) |
550 | int sta_id, int tid, | ||
551 | int frame_limit, u16 ssn) | ||
552 | { | 553 | { |
553 | might_sleep(); | 554 | might_sleep(); |
554 | 555 | ||
555 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, | 556 | WARN_ONCE(trans->state != IWL_TRANS_FW_ALIVE, |
556 | "%s bad state = %d", __func__, trans->state); | 557 | "%s bad state = %d", __func__, trans->state); |
557 | 558 | ||
558 | trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn); | 559 | trans->ops->tx_agg_setup(trans, queue, fifo, sta_id, tid, |
560 | frame_limit, ssn); | ||
559 | } | 561 | } |
560 | 562 | ||
561 | static inline void iwl_trans_free(struct iwl_trans *trans) | 563 | static inline void iwl_trans_free(struct iwl_trans *trans) |
@@ -611,6 +613,11 @@ static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs) | |||
611 | return trans->ops->read32(trans, ofs); | 613 | return trans->ops->read32(trans, ofs); |
612 | } | 614 | } |
613 | 615 | ||
616 | static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state) | ||
617 | { | ||
618 | trans->ops->set_pmi(trans, state); | ||
619 | } | ||
620 | |||
614 | /***************************************************** | 621 | /***************************************************** |
615 | * Transport layers implementations + their allocation function | 622 | * Transport layers implementations + their allocation function |
616 | ******************************************************/ | 623 | ******************************************************/ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 252828728837..ba7c9f883cb6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c | |||
@@ -40,37 +40,6 @@ | |||
40 | #include "iwl-fh.h" | 40 | #include "iwl-fh.h" |
41 | #include "iwl-op-mode.h" | 41 | #include "iwl-op-mode.h" |
42 | 42 | ||
43 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | ||
44 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, | ||
45 | 0, COEX_UNASSOC_IDLE_FLAGS}, | ||
46 | {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP, | ||
47 | 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, | ||
48 | {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP, | ||
49 | 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, | ||
50 | {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP, | ||
51 | 0, COEX_CALIBRATION_FLAGS}, | ||
52 | {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP, | ||
53 | 0, COEX_PERIODIC_CALIBRATION_FLAGS}, | ||
54 | {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP, | ||
55 | 0, COEX_CONNECTION_ESTAB_FLAGS}, | ||
56 | {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP, | ||
57 | 0, COEX_ASSOCIATED_IDLE_FLAGS}, | ||
58 | {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP, | ||
59 | 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, | ||
60 | {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP, | ||
61 | 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, | ||
62 | {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP, | ||
63 | 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, | ||
64 | {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS}, | ||
65 | {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS}, | ||
66 | {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP, | ||
67 | 0, COEX_STAND_ALONE_DEBUG_FLAGS}, | ||
68 | {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP, | ||
69 | 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, | ||
70 | {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS}, | ||
71 | {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS} | ||
72 | }; | ||
73 | |||
74 | /****************************************************************************** | 43 | /****************************************************************************** |
75 | * | 44 | * |
76 | * uCode download functions | 45 | * uCode download functions |
@@ -174,24 +143,6 @@ static int iwl_send_calib_cfg(struct iwl_priv *priv) | |||
174 | return iwl_dvm_send_cmd(priv, &cmd); | 143 | return iwl_dvm_send_cmd(priv, &cmd); |
175 | } | 144 | } |
176 | 145 | ||
177 | int iwlagn_rx_calib_result(struct iwl_priv *priv, | ||
178 | struct iwl_rx_cmd_buffer *rxb, | ||
179 | struct iwl_device_cmd *cmd) | ||
180 | { | ||
181 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
182 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->data; | ||
183 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
184 | |||
185 | /* reduce the size of the length field itself */ | ||
186 | len -= 4; | ||
187 | |||
188 | if (iwl_calib_set(priv, hdr, len)) | ||
189 | IWL_ERR(priv, "Failed to record calibration data %d\n", | ||
190 | hdr->op_code); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | int iwl_init_alive_start(struct iwl_priv *priv) | 146 | int iwl_init_alive_start(struct iwl_priv *priv) |
196 | { | 147 | { |
197 | int ret; | 148 | int ret; |
@@ -233,25 +184,9 @@ static int iwl_send_wimax_coex(struct iwl_priv *priv) | |||
233 | { | 184 | { |
234 | struct iwl_wimax_coex_cmd coex_cmd; | 185 | struct iwl_wimax_coex_cmd coex_cmd; |
235 | 186 | ||
236 | if (cfg(priv)->base_params->support_wimax_coexist) { | 187 | /* coexistence is disabled */ |
237 | /* UnMask wake up src at associated sleep */ | 188 | memset(&coex_cmd, 0, sizeof(coex_cmd)); |
238 | coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK; | ||
239 | 189 | ||
240 | /* UnMask wake up src at unassociated sleep */ | ||
241 | coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK; | ||
242 | memcpy(coex_cmd.sta_prio, cu_priorities, | ||
243 | sizeof(struct iwl_wimax_coex_event_entry) * | ||
244 | COEX_NUM_OF_EVENTS); | ||
245 | |||
246 | /* enabling the coexistence feature */ | ||
247 | coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK; | ||
248 | |||
249 | /* enabling the priorities tables */ | ||
250 | coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK; | ||
251 | } else { | ||
252 | /* coexistence is disabled */ | ||
253 | memset(&coex_cmd, 0, sizeof(coex_cmd)); | ||
254 | } | ||
255 | return iwl_dvm_send_cmd_pdu(priv, | 190 | return iwl_dvm_send_cmd_pdu(priv, |
256 | COEX_PRIORITY_TABLE_CMD, CMD_SYNC, | 191 | COEX_PRIORITY_TABLE_CMD, CMD_SYNC, |
257 | sizeof(coex_cmd), &coex_cmd); | 192 | sizeof(coex_cmd), &coex_cmd); |
@@ -417,9 +352,8 @@ struct iwl_alive_data { | |||
417 | u8 subtype; | 352 | u8 subtype; |
418 | }; | 353 | }; |
419 | 354 | ||
420 | static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | 355 | static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, |
421 | struct iwl_rx_packet *pkt, | 356 | struct iwl_rx_packet *pkt, void *data) |
422 | void *data) | ||
423 | { | 357 | { |
424 | struct iwl_priv *priv = | 358 | struct iwl_priv *priv = |
425 | container_of(notif_wait, struct iwl_priv, notif_wait); | 359 | container_of(notif_wait, struct iwl_priv, notif_wait); |
@@ -433,13 +367,15 @@ static void iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, | |||
433 | palive->is_valid, palive->ver_type, | 367 | palive->is_valid, palive->ver_type, |
434 | palive->ver_subtype); | 368 | palive->ver_subtype); |
435 | 369 | ||
436 | priv->shrd->device_pointers.error_event_table = | 370 | priv->device_pointers.error_event_table = |
437 | le32_to_cpu(palive->error_event_table_ptr); | 371 | le32_to_cpu(palive->error_event_table_ptr); |
438 | priv->shrd->device_pointers.log_event_table = | 372 | priv->device_pointers.log_event_table = |
439 | le32_to_cpu(palive->log_event_table_ptr); | 373 | le32_to_cpu(palive->log_event_table_ptr); |
440 | 374 | ||
441 | alive_data->subtype = palive->ver_subtype; | 375 | alive_data->subtype = palive->ver_subtype; |
442 | alive_data->valid = palive->is_valid == UCODE_VALID_OK; | 376 | alive_data->valid = palive->is_valid == UCODE_VALID_OK; |
377 | |||
378 | return true; | ||
443 | } | 379 | } |
444 | 380 | ||
445 | #define UCODE_ALIVE_TIMEOUT HZ | 381 | #define UCODE_ALIVE_TIMEOUT HZ |
@@ -453,9 +389,10 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
453 | const struct fw_img *fw; | 389 | const struct fw_img *fw; |
454 | int ret; | 390 | int ret; |
455 | enum iwl_ucode_type old_type; | 391 | enum iwl_ucode_type old_type; |
392 | static const u8 alive_cmd[] = { REPLY_ALIVE }; | ||
456 | 393 | ||
457 | old_type = priv->shrd->ucode_type; | 394 | old_type = priv->cur_ucode; |
458 | priv->shrd->ucode_type = ucode_type; | 395 | priv->cur_ucode = ucode_type; |
459 | fw = iwl_get_ucode_image(priv, ucode_type); | 396 | fw = iwl_get_ucode_image(priv, ucode_type); |
460 | 397 | ||
461 | priv->ucode_loaded = false; | 398 | priv->ucode_loaded = false; |
@@ -463,12 +400,13 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
463 | if (!fw) | 400 | if (!fw) |
464 | return -EINVAL; | 401 | return -EINVAL; |
465 | 402 | ||
466 | iwl_init_notification_wait(&priv->notif_wait, &alive_wait, REPLY_ALIVE, | 403 | iwl_init_notification_wait(&priv->notif_wait, &alive_wait, |
467 | iwl_alive_fn, &alive_data); | 404 | alive_cmd, ARRAY_SIZE(alive_cmd), |
405 | iwl_alive_fn, &alive_data); | ||
468 | 406 | ||
469 | ret = iwl_trans_start_fw(trans(priv), fw); | 407 | ret = iwl_trans_start_fw(trans(priv), fw); |
470 | if (ret) { | 408 | if (ret) { |
471 | priv->shrd->ucode_type = old_type; | 409 | priv->cur_ucode = old_type; |
472 | iwl_remove_notification(&priv->notif_wait, &alive_wait); | 410 | iwl_remove_notification(&priv->notif_wait, &alive_wait); |
473 | return ret; | 411 | return ret; |
474 | } | 412 | } |
@@ -480,13 +418,13 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
480 | ret = iwl_wait_notification(&priv->notif_wait, &alive_wait, | 418 | ret = iwl_wait_notification(&priv->notif_wait, &alive_wait, |
481 | UCODE_ALIVE_TIMEOUT); | 419 | UCODE_ALIVE_TIMEOUT); |
482 | if (ret) { | 420 | if (ret) { |
483 | priv->shrd->ucode_type = old_type; | 421 | priv->cur_ucode = old_type; |
484 | return ret; | 422 | return ret; |
485 | } | 423 | } |
486 | 424 | ||
487 | if (!alive_data.valid) { | 425 | if (!alive_data.valid) { |
488 | IWL_ERR(priv, "Loaded ucode is not valid!\n"); | 426 | IWL_ERR(priv, "Loaded ucode is not valid!\n"); |
489 | priv->shrd->ucode_type = old_type; | 427 | priv->cur_ucode = old_type; |
490 | return -EIO; | 428 | return -EIO; |
491 | } | 429 | } |
492 | 430 | ||
@@ -498,7 +436,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
498 | if (ucode_type != IWL_UCODE_WOWLAN) { | 436 | if (ucode_type != IWL_UCODE_WOWLAN) { |
499 | ret = iwl_verify_ucode(priv, ucode_type); | 437 | ret = iwl_verify_ucode(priv, ucode_type); |
500 | if (ret) { | 438 | if (ret) { |
501 | priv->shrd->ucode_type = old_type; | 439 | priv->cur_ucode = old_type; |
502 | return ret; | 440 | return ret; |
503 | } | 441 | } |
504 | 442 | ||
@@ -510,7 +448,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
510 | if (ret) { | 448 | if (ret) { |
511 | IWL_WARN(priv, | 449 | IWL_WARN(priv, |
512 | "Could not complete ALIVE transition: %d\n", ret); | 450 | "Could not complete ALIVE transition: %d\n", ret); |
513 | priv->shrd->ucode_type = old_type; | 451 | priv->cur_ucode = old_type; |
514 | return ret; | 452 | return ret; |
515 | } | 453 | } |
516 | 454 | ||
@@ -519,9 +457,38 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | |||
519 | return 0; | 457 | return 0; |
520 | } | 458 | } |
521 | 459 | ||
460 | static bool iwlagn_wait_calib(struct iwl_notif_wait_data *notif_wait, | ||
461 | struct iwl_rx_packet *pkt, void *data) | ||
462 | { | ||
463 | struct iwl_priv *priv = data; | ||
464 | struct iwl_calib_hdr *hdr; | ||
465 | int len; | ||
466 | |||
467 | if (pkt->hdr.cmd != CALIBRATION_RES_NOTIFICATION) { | ||
468 | WARN_ON(pkt->hdr.cmd != CALIBRATION_COMPLETE_NOTIFICATION); | ||
469 | return true; | ||
470 | } | ||
471 | |||
472 | hdr = (struct iwl_calib_hdr *)pkt->data; | ||
473 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
474 | |||
475 | /* reduce the size by the length field itself */ | ||
476 | len -= sizeof(__le32); | ||
477 | |||
478 | if (iwl_calib_set(priv, hdr, len)) | ||
479 | IWL_ERR(priv, "Failed to record calibration data %d\n", | ||
480 | hdr->op_code); | ||
481 | |||
482 | return false; | ||
483 | } | ||
484 | |||
522 | int iwl_run_init_ucode(struct iwl_priv *priv) | 485 | int iwl_run_init_ucode(struct iwl_priv *priv) |
523 | { | 486 | { |
524 | struct iwl_notification_wait calib_wait; | 487 | struct iwl_notification_wait calib_wait; |
488 | static const u8 calib_complete[] = { | ||
489 | CALIBRATION_RES_NOTIFICATION, | ||
490 | CALIBRATION_COMPLETE_NOTIFICATION | ||
491 | }; | ||
525 | int ret; | 492 | int ret; |
526 | 493 | ||
527 | lockdep_assert_held(&priv->mutex); | 494 | lockdep_assert_held(&priv->mutex); |
@@ -534,8 +501,8 @@ int iwl_run_init_ucode(struct iwl_priv *priv) | |||
534 | return 0; | 501 | return 0; |
535 | 502 | ||
536 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, | 503 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, |
537 | CALIBRATION_COMPLETE_NOTIFICATION, | 504 | calib_complete, ARRAY_SIZE(calib_complete), |
538 | NULL, NULL); | 505 | iwlagn_wait_calib, priv); |
539 | 506 | ||
540 | /* Will also start the device */ | 507 | /* Will also start the device */ |
541 | ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); | 508 | ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 538783f51989..2d913644d92b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -637,6 +637,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
637 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 637 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
638 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 638 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
639 | struct ieee80211_rx_status rx_status; | 639 | struct ieee80211_rx_status rx_status; |
640 | struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); | ||
640 | 641 | ||
641 | if (data->idle) { | 642 | if (data->idle) { |
642 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); | 643 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); |
@@ -671,6 +672,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
671 | spin_lock(&hwsim_radio_lock); | 672 | spin_lock(&hwsim_radio_lock); |
672 | list_for_each_entry(data2, &hwsim_radios, list) { | 673 | list_for_each_entry(data2, &hwsim_radios, list) { |
673 | struct sk_buff *nskb; | 674 | struct sk_buff *nskb; |
675 | struct ieee80211_mgmt *mgmt; | ||
674 | 676 | ||
675 | if (data == data2) | 677 | if (data == data2) |
676 | continue; | 678 | continue; |
@@ -688,8 +690,17 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
688 | 690 | ||
689 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) | 691 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) |
690 | ack = true; | 692 | ack = true; |
693 | |||
694 | /* set bcn timestamp relative to receiver mactime */ | ||
691 | rx_status.mactime = | 695 | rx_status.mactime = |
692 | le64_to_cpu(__mac80211_hwsim_get_tsf(data2)); | 696 | le64_to_cpu(__mac80211_hwsim_get_tsf(data2)); |
697 | mgmt = (struct ieee80211_mgmt *) nskb->data; | ||
698 | if (ieee80211_is_beacon(mgmt->frame_control) || | ||
699 | ieee80211_is_probe_resp(mgmt->frame_control)) | ||
700 | mgmt->u.beacon.timestamp = cpu_to_le64( | ||
701 | rx_status.mactime + | ||
702 | 24 * 8 * 10 / txrate->bitrate); | ||
703 | |||
693 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 704 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
694 | ieee80211_rx_irqsafe(data2->hw, nskb); | 705 | ieee80211_rx_irqsafe(data2->hw, nskb); |
695 | } | 706 | } |
@@ -703,12 +714,6 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
703 | bool ack; | 714 | bool ack; |
704 | struct ieee80211_tx_info *txi; | 715 | struct ieee80211_tx_info *txi; |
705 | u32 _pid; | 716 | u32 _pid; |
706 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; | ||
707 | struct mac80211_hwsim_data *data = hw->priv; | ||
708 | |||
709 | if (ieee80211_is_beacon(mgmt->frame_control) || | ||
710 | ieee80211_is_probe_resp(mgmt->frame_control)) | ||
711 | mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data); | ||
712 | 717 | ||
713 | mac80211_hwsim_monitor_rx(hw, skb); | 718 | mac80211_hwsim_monitor_rx(hw, skb); |
714 | 719 | ||
@@ -805,11 +810,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
805 | struct ieee80211_vif *vif) | 810 | struct ieee80211_vif *vif) |
806 | { | 811 | { |
807 | struct ieee80211_hw *hw = arg; | 812 | struct ieee80211_hw *hw = arg; |
808 | struct mac80211_hwsim_data *data = hw->priv; | ||
809 | struct sk_buff *skb; | 813 | struct sk_buff *skb; |
810 | struct ieee80211_tx_info *info; | 814 | struct ieee80211_tx_info *info; |
811 | u32 _pid; | 815 | u32 _pid; |
812 | struct ieee80211_mgmt *mgmt; | ||
813 | 816 | ||
814 | hwsim_check_magic(vif); | 817 | hwsim_check_magic(vif); |
815 | 818 | ||
@@ -823,9 +826,6 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
823 | return; | 826 | return; |
824 | info = IEEE80211_SKB_CB(skb); | 827 | info = IEEE80211_SKB_CB(skb); |
825 | 828 | ||
826 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
827 | mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data); | ||
828 | |||
829 | mac80211_hwsim_monitor_rx(hw, skb); | 829 | mac80211_hwsim_monitor_rx(hw, skb); |
830 | 830 | ||
831 | /* wmediumd mode check */ | 831 | /* wmediumd mode check */ |
@@ -1450,7 +1450,7 @@ DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group, | |||
1450 | hwsim_fops_group_read, hwsim_fops_group_write, | 1450 | hwsim_fops_group_read, hwsim_fops_group_write, |
1451 | "%llx\n"); | 1451 | "%llx\n"); |
1452 | 1452 | ||
1453 | struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr( | 1453 | static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr( |
1454 | struct mac_address *addr) | 1454 | struct mac_address *addr) |
1455 | { | 1455 | { |
1456 | struct mac80211_hwsim_data *data; | 1456 | struct mac80211_hwsim_data *data; |
@@ -1795,9 +1795,11 @@ static int __init init_mac80211_hwsim(void) | |||
1795 | IEEE80211_HW_SIGNAL_DBM | | 1795 | IEEE80211_HW_SIGNAL_DBM | |
1796 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | 1796 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | |
1797 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 1797 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
1798 | IEEE80211_HW_AMPDU_AGGREGATION; | 1798 | IEEE80211_HW_AMPDU_AGGREGATION | |
1799 | IEEE80211_HW_WANT_MONITOR_VIF; | ||
1799 | 1800 | ||
1800 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; | 1801 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
1802 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | ||
1801 | 1803 | ||
1802 | /* ask mac80211 to reserve space for magic */ | 1804 | /* ask mac80211 to reserve space for magic */ |
1803 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 1805 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index a5e182b5e944..fe8ebfebcc0e 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -350,25 +350,26 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
350 | ret_len += sizeof(struct mwifiex_ie_types_htcap); | 350 | ret_len += sizeof(struct mwifiex_ie_types_htcap); |
351 | } | 351 | } |
352 | 352 | ||
353 | if (bss_desc->bcn_ht_info) { | 353 | if (bss_desc->bcn_ht_oper) { |
354 | if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { | 354 | if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { |
355 | ht_info = (struct mwifiex_ie_types_htinfo *) *buffer; | 355 | ht_info = (struct mwifiex_ie_types_htinfo *) *buffer; |
356 | memset(ht_info, 0, | 356 | memset(ht_info, 0, |
357 | sizeof(struct mwifiex_ie_types_htinfo)); | 357 | sizeof(struct mwifiex_ie_types_htinfo)); |
358 | ht_info->header.type = | 358 | ht_info->header.type = |
359 | cpu_to_le16(WLAN_EID_HT_INFORMATION); | 359 | cpu_to_le16(WLAN_EID_HT_OPERATION); |
360 | ht_info->header.len = | 360 | ht_info->header.len = |
361 | cpu_to_le16(sizeof(struct ieee80211_ht_info)); | 361 | cpu_to_le16( |
362 | sizeof(struct ieee80211_ht_operation)); | ||
362 | 363 | ||
363 | memcpy((u8 *) ht_info + | 364 | memcpy((u8 *) ht_info + |
364 | sizeof(struct mwifiex_ie_types_header), | 365 | sizeof(struct mwifiex_ie_types_header), |
365 | (u8 *) bss_desc->bcn_ht_info + | 366 | (u8 *) bss_desc->bcn_ht_oper + |
366 | sizeof(struct ieee_types_header), | 367 | sizeof(struct ieee_types_header), |
367 | le16_to_cpu(ht_info->header.len)); | 368 | le16_to_cpu(ht_info->header.len)); |
368 | 369 | ||
369 | if (!(sband->ht_cap.cap & | 370 | if (!(sband->ht_cap.cap & |
370 | IEEE80211_HT_CAP_SUP_WIDTH_20_40)) | 371 | IEEE80211_HT_CAP_SUP_WIDTH_20_40)) |
371 | ht_info->ht_info.ht_param &= | 372 | ht_info->ht_oper.ht_param &= |
372 | ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY | | 373 | ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY | |
373 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET); | 374 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET); |
374 | 375 | ||
@@ -385,16 +386,16 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | |||
385 | sizeof(struct mwifiex_ie_types_chan_list_param_set) - | 386 | sizeof(struct mwifiex_ie_types_chan_list_param_set) - |
386 | sizeof(struct mwifiex_ie_types_header)); | 387 | sizeof(struct mwifiex_ie_types_header)); |
387 | chan_list->chan_scan_param[0].chan_number = | 388 | chan_list->chan_scan_param[0].chan_number = |
388 | bss_desc->bcn_ht_info->control_chan; | 389 | bss_desc->bcn_ht_oper->primary_chan; |
389 | chan_list->chan_scan_param[0].radio_type = | 390 | chan_list->chan_scan_param[0].radio_type = |
390 | mwifiex_band_to_radio_type((u8) bss_desc->bss_band); | 391 | mwifiex_band_to_radio_type((u8) bss_desc->bss_band); |
391 | 392 | ||
392 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && | 393 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && |
393 | bss_desc->bcn_ht_info->ht_param & | 394 | bss_desc->bcn_ht_oper->ht_param & |
394 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) | 395 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) |
395 | SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. | 396 | SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. |
396 | radio_type, | 397 | radio_type, |
397 | (bss_desc->bcn_ht_info->ht_param & | 398 | (bss_desc->bcn_ht_oper->ht_param & |
398 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); | 399 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); |
399 | 400 | ||
400 | *buffer += sizeof(struct mwifiex_ie_types_chan_list_param_set); | 401 | *buffer += sizeof(struct mwifiex_ie_types_chan_list_param_set); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 65050384c42b..c7e89188c350 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -516,25 +516,23 @@ static int | |||
516 | mwifiex_dump_station_info(struct mwifiex_private *priv, | 516 | mwifiex_dump_station_info(struct mwifiex_private *priv, |
517 | struct station_info *sinfo) | 517 | struct station_info *sinfo) |
518 | { | 518 | { |
519 | struct mwifiex_ds_get_signal signal; | ||
520 | struct mwifiex_rate_cfg rate; | 519 | struct mwifiex_rate_cfg rate; |
521 | int ret = 0; | ||
522 | 520 | ||
523 | sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES | | 521 | sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES | |
524 | STATION_INFO_RX_PACKETS | | 522 | STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS | |
525 | STATION_INFO_TX_PACKETS | 523 | STATION_INFO_TX_BITRATE | |
526 | | STATION_INFO_SIGNAL | STATION_INFO_TX_BITRATE; | 524 | STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; |
527 | 525 | ||
528 | /* Get signal information from the firmware */ | 526 | /* Get signal information from the firmware */ |
529 | memset(&signal, 0, sizeof(struct mwifiex_ds_get_signal)); | 527 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO, |
530 | if (mwifiex_get_signal_info(priv, &signal)) { | 528 | HostCmd_ACT_GEN_GET, 0, NULL)) { |
531 | dev_err(priv->adapter->dev, "getting signal information\n"); | 529 | dev_err(priv->adapter->dev, "failed to get signal information\n"); |
532 | ret = -EFAULT; | 530 | return -EFAULT; |
533 | } | 531 | } |
534 | 532 | ||
535 | if (mwifiex_drv_get_data_rate(priv, &rate)) { | 533 | if (mwifiex_drv_get_data_rate(priv, &rate)) { |
536 | dev_err(priv->adapter->dev, "getting data rate\n"); | 534 | dev_err(priv->adapter->dev, "getting data rate\n"); |
537 | ret = -EFAULT; | 535 | return -EFAULT; |
538 | } | 536 | } |
539 | 537 | ||
540 | /* Get DTIM period information from firmware */ | 538 | /* Get DTIM period information from firmware */ |
@@ -557,11 +555,12 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
557 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | 555 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
558 | } | 556 | } |
559 | 557 | ||
558 | sinfo->signal_avg = priv->bcn_rssi_avg; | ||
560 | sinfo->rx_bytes = priv->stats.rx_bytes; | 559 | sinfo->rx_bytes = priv->stats.rx_bytes; |
561 | sinfo->tx_bytes = priv->stats.tx_bytes; | 560 | sinfo->tx_bytes = priv->stats.tx_bytes; |
562 | sinfo->rx_packets = priv->stats.rx_packets; | 561 | sinfo->rx_packets = priv->stats.rx_packets; |
563 | sinfo->tx_packets = priv->stats.tx_packets; | 562 | sinfo->tx_packets = priv->stats.tx_packets; |
564 | sinfo->signal = priv->qual_level; | 563 | sinfo->signal = priv->bcn_rssi_avg; |
565 | /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */ | 564 | /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */ |
566 | sinfo->txrate.legacy = rate.rate * 5; | 565 | sinfo->txrate.legacy = rate.rate * 5; |
567 | 566 | ||
@@ -581,7 +580,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
581 | priv->curr_bss_params.bss_descriptor.beacon_period; | 580 | priv->curr_bss_params.bss_descriptor.beacon_period; |
582 | } | 581 | } |
583 | 582 | ||
584 | return ret; | 583 | return 0; |
585 | } | 584 | } |
586 | 585 | ||
587 | /* | 586 | /* |
@@ -604,6 +603,23 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
604 | return mwifiex_dump_station_info(priv, sinfo); | 603 | return mwifiex_dump_station_info(priv, sinfo); |
605 | } | 604 | } |
606 | 605 | ||
606 | /* | ||
607 | * CFG802.11 operation handler to dump station information. | ||
608 | */ | ||
609 | static int | ||
610 | mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | ||
611 | int idx, u8 *mac, struct station_info *sinfo) | ||
612 | { | ||
613 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
614 | |||
615 | if (!priv->media_connected || idx) | ||
616 | return -ENOENT; | ||
617 | |||
618 | memcpy(mac, priv->cfg_bssid, ETH_ALEN); | ||
619 | |||
620 | return mwifiex_dump_station_info(priv, sinfo); | ||
621 | } | ||
622 | |||
607 | /* Supported rates to be advertised to the cfg80211 */ | 623 | /* Supported rates to be advertised to the cfg80211 */ |
608 | 624 | ||
609 | static struct ieee80211_rate mwifiex_rates[] = { | 625 | static struct ieee80211_rate mwifiex_rates[] = { |
@@ -750,6 +766,45 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, | |||
750 | } | 766 | } |
751 | 767 | ||
752 | /* | 768 | /* |
769 | * CFG802.11 operation handler for connection quality monitoring. | ||
770 | * | ||
771 | * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI | ||
772 | * events to FW. | ||
773 | */ | ||
774 | static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, | ||
775 | struct net_device *dev, | ||
776 | s32 rssi_thold, u32 rssi_hyst) | ||
777 | { | ||
778 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
779 | struct mwifiex_ds_misc_subsc_evt subsc_evt; | ||
780 | |||
781 | priv->cqm_rssi_thold = rssi_thold; | ||
782 | priv->cqm_rssi_hyst = rssi_hyst; | ||
783 | |||
784 | memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt)); | ||
785 | subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; | ||
786 | |||
787 | /* Subscribe/unsubscribe low and high rssi events */ | ||
788 | if (rssi_thold && rssi_hyst) { | ||
789 | subsc_evt.action = HostCmd_ACT_BITWISE_SET; | ||
790 | subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold); | ||
791 | subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold); | ||
792 | subsc_evt.bcn_l_rssi_cfg.evt_freq = 1; | ||
793 | subsc_evt.bcn_h_rssi_cfg.evt_freq = 1; | ||
794 | return mwifiex_send_cmd_sync(priv, | ||
795 | HostCmd_CMD_802_11_SUBSCRIBE_EVENT, | ||
796 | 0, 0, &subsc_evt); | ||
797 | } else { | ||
798 | subsc_evt.action = HostCmd_ACT_BITWISE_CLR; | ||
799 | return mwifiex_send_cmd_sync(priv, | ||
800 | HostCmd_CMD_802_11_SUBSCRIBE_EVENT, | ||
801 | 0, 0, &subsc_evt); | ||
802 | } | ||
803 | |||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | /* | ||
753 | * CFG802.11 operation handler for disconnection request. | 808 | * CFG802.11 operation handler for disconnection request. |
754 | * | 809 | * |
755 | * This function does not work when there is already a disconnection | 810 | * This function does not work when there is already a disconnection |
@@ -1340,6 +1395,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
1340 | .connect = mwifiex_cfg80211_connect, | 1395 | .connect = mwifiex_cfg80211_connect, |
1341 | .disconnect = mwifiex_cfg80211_disconnect, | 1396 | .disconnect = mwifiex_cfg80211_disconnect, |
1342 | .get_station = mwifiex_cfg80211_get_station, | 1397 | .get_station = mwifiex_cfg80211_get_station, |
1398 | .dump_station = mwifiex_cfg80211_dump_station, | ||
1343 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, | 1399 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, |
1344 | .set_channel = mwifiex_cfg80211_set_channel, | 1400 | .set_channel = mwifiex_cfg80211_set_channel, |
1345 | .join_ibss = mwifiex_cfg80211_join_ibss, | 1401 | .join_ibss = mwifiex_cfg80211_join_ibss, |
@@ -1350,6 +1406,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
1350 | .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, | 1406 | .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, |
1351 | .set_tx_power = mwifiex_cfg80211_set_tx_power, | 1407 | .set_tx_power = mwifiex_cfg80211_set_tx_power, |
1352 | .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, | 1408 | .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, |
1409 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, | ||
1353 | }; | 1410 | }; |
1354 | 1411 | ||
1355 | /* | 1412 | /* |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index e98fc5af73dc..bb26114bdb96 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -92,10 +92,12 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
92 | #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) | 92 | #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) |
93 | #define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) | 93 | #define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) |
94 | #define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) | 94 | #define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) |
95 | #define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4) | ||
95 | #define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) | 96 | #define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) |
96 | #define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) | 97 | #define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) |
97 | #define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) | 98 | #define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) |
98 | #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) | 99 | #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) |
100 | #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) | ||
99 | #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) | 101 | #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) |
100 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) | 102 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) |
101 | #define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) | 103 | #define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) |
@@ -194,6 +196,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
194 | #define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e | 196 | #define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e |
195 | #define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c | 197 | #define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c |
196 | #define HostCmd_CMD_WMM_GET_STATUS 0x0071 | 198 | #define HostCmd_CMD_WMM_GET_STATUS 0x0071 |
199 | #define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075 | ||
197 | #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f | 200 | #define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f |
198 | #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 | 201 | #define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 |
199 | #define HostCmd_CMD_VERSION_EXT 0x0097 | 202 | #define HostCmd_CMD_VERSION_EXT 0x0097 |
@@ -228,6 +231,8 @@ enum ENH_PS_MODES { | |||
228 | #define HostCmd_RET_BIT 0x8000 | 231 | #define HostCmd_RET_BIT 0x8000 |
229 | #define HostCmd_ACT_GEN_GET 0x0000 | 232 | #define HostCmd_ACT_GEN_GET 0x0000 |
230 | #define HostCmd_ACT_GEN_SET 0x0001 | 233 | #define HostCmd_ACT_GEN_SET 0x0001 |
234 | #define HostCmd_ACT_BITWISE_SET 0x0002 | ||
235 | #define HostCmd_ACT_BITWISE_CLR 0x0003 | ||
231 | #define HostCmd_RESULT_OK 0x0000 | 236 | #define HostCmd_RESULT_OK 0x0000 |
232 | 237 | ||
233 | #define HostCmd_ACT_MAC_RX_ON 0x0001 | 238 | #define HostCmd_ACT_MAC_RX_ON 0x0001 |
@@ -1007,7 +1012,7 @@ struct ieee_types_wmm_parameter { | |||
1007 | struct ieee_types_vendor_header vend_hdr; | 1012 | struct ieee_types_vendor_header vend_hdr; |
1008 | u8 qos_info_bitmap; | 1013 | u8 qos_info_bitmap; |
1009 | u8 reserved; | 1014 | u8 reserved; |
1010 | struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_MAX_QUEUES]; | 1015 | struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS]; |
1011 | } __packed; | 1016 | } __packed; |
1012 | 1017 | ||
1013 | struct ieee_types_wmm_info { | 1018 | struct ieee_types_wmm_info { |
@@ -1028,7 +1033,7 @@ struct ieee_types_wmm_info { | |||
1028 | 1033 | ||
1029 | struct host_cmd_ds_wmm_get_status { | 1034 | struct host_cmd_ds_wmm_get_status { |
1030 | u8 queue_status_tlv[sizeof(struct mwifiex_ie_types_wmm_queue_status) * | 1035 | u8 queue_status_tlv[sizeof(struct mwifiex_ie_types_wmm_queue_status) * |
1031 | IEEE80211_MAX_QUEUES]; | 1036 | IEEE80211_NUM_ACS]; |
1032 | u8 wmm_param_tlv[sizeof(struct ieee_types_wmm_parameter) + 2]; | 1037 | u8 wmm_param_tlv[sizeof(struct ieee_types_wmm_parameter) + 2]; |
1033 | } __packed; | 1038 | } __packed; |
1034 | 1039 | ||
@@ -1045,7 +1050,7 @@ struct mwifiex_ie_types_htcap { | |||
1045 | 1050 | ||
1046 | struct mwifiex_ie_types_htinfo { | 1051 | struct mwifiex_ie_types_htinfo { |
1047 | struct mwifiex_ie_types_header header; | 1052 | struct mwifiex_ie_types_header header; |
1048 | struct ieee80211_ht_info ht_info; | 1053 | struct ieee80211_ht_operation ht_oper; |
1049 | } __packed; | 1054 | } __packed; |
1050 | 1055 | ||
1051 | struct mwifiex_ie_types_2040bssco { | 1056 | struct mwifiex_ie_types_2040bssco { |
@@ -1146,6 +1151,17 @@ struct host_cmd_ds_pcie_details { | |||
1146 | u32 sleep_cookie_addr_hi; | 1151 | u32 sleep_cookie_addr_hi; |
1147 | } __packed; | 1152 | } __packed; |
1148 | 1153 | ||
1154 | struct mwifiex_ie_types_rssi_threshold { | ||
1155 | struct mwifiex_ie_types_header header; | ||
1156 | u8 abs_value; | ||
1157 | u8 evt_freq; | ||
1158 | } __packed; | ||
1159 | |||
1160 | struct host_cmd_ds_802_11_subsc_evt { | ||
1161 | __le16 action; | ||
1162 | __le16 events; | ||
1163 | } __packed; | ||
1164 | |||
1149 | struct host_cmd_ds_command { | 1165 | struct host_cmd_ds_command { |
1150 | __le16 command; | 1166 | __le16 command; |
1151 | __le16 size; | 1167 | __le16 size; |
@@ -1195,6 +1211,7 @@ struct host_cmd_ds_command { | |||
1195 | struct host_cmd_ds_set_bss_mode bss_mode; | 1211 | struct host_cmd_ds_set_bss_mode bss_mode; |
1196 | struct host_cmd_ds_pcie_details pcie_host_spec; | 1212 | struct host_cmd_ds_pcie_details pcie_host_spec; |
1197 | struct host_cmd_ds_802_11_eeprom_access eeprom; | 1213 | struct host_cmd_ds_802_11_eeprom_access eeprom; |
1214 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; | ||
1198 | } params; | 1215 | } params; |
1199 | } __packed; | 1216 | } __packed; |
1200 | 1217 | ||
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 7ca4e8234f3e..99c06649f94c 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -85,34 +85,6 @@ struct mwifiex_ds_get_stats { | |||
85 | u32 wep_icv_error[4]; | 85 | u32 wep_icv_error[4]; |
86 | }; | 86 | }; |
87 | 87 | ||
88 | #define BCN_RSSI_AVG_MASK 0x00000002 | ||
89 | #define BCN_NF_AVG_MASK 0x00000200 | ||
90 | #define ALL_RSSI_INFO_MASK 0x00000fff | ||
91 | |||
92 | struct mwifiex_ds_get_signal { | ||
93 | /* | ||
94 | * Bit0: Last Beacon RSSI, Bit1: Average Beacon RSSI, | ||
95 | * Bit2: Last Data RSSI, Bit3: Average Data RSSI, | ||
96 | * Bit4: Last Beacon SNR, Bit5: Average Beacon SNR, | ||
97 | * Bit6: Last Data SNR, Bit7: Average Data SNR, | ||
98 | * Bit8: Last Beacon NF, Bit9: Average Beacon NF, | ||
99 | * Bit10: Last Data NF, Bit11: Average Data NF | ||
100 | */ | ||
101 | u16 selector; | ||
102 | s16 bcn_rssi_last; | ||
103 | s16 bcn_rssi_avg; | ||
104 | s16 data_rssi_last; | ||
105 | s16 data_rssi_avg; | ||
106 | s16 bcn_snr_last; | ||
107 | s16 bcn_snr_avg; | ||
108 | s16 data_snr_last; | ||
109 | s16 data_snr_avg; | ||
110 | s16 bcn_nf_last; | ||
111 | s16 bcn_nf_avg; | ||
112 | s16 data_nf_last; | ||
113 | s16 data_nf_avg; | ||
114 | }; | ||
115 | |||
116 | #define MWIFIEX_MAX_VER_STR_LEN 128 | 88 | #define MWIFIEX_MAX_VER_STR_LEN 128 |
117 | 89 | ||
118 | struct mwifiex_ver_ext { | 90 | struct mwifiex_ver_ext { |
@@ -308,6 +280,27 @@ struct mwifiex_ds_misc_cmd { | |||
308 | u8 cmd[MWIFIEX_SIZE_OF_CMD_BUFFER]; | 280 | u8 cmd[MWIFIEX_SIZE_OF_CMD_BUFFER]; |
309 | }; | 281 | }; |
310 | 282 | ||
283 | #define BITMASK_BCN_RSSI_LOW BIT(0) | ||
284 | #define BITMASK_BCN_RSSI_HIGH BIT(4) | ||
285 | |||
286 | enum subsc_evt_rssi_state { | ||
287 | EVENT_HANDLED, | ||
288 | RSSI_LOW_RECVD, | ||
289 | RSSI_HIGH_RECVD | ||
290 | }; | ||
291 | |||
292 | struct subsc_evt_cfg { | ||
293 | u8 abs_value; | ||
294 | u8 evt_freq; | ||
295 | }; | ||
296 | |||
297 | struct mwifiex_ds_misc_subsc_evt { | ||
298 | u16 action; | ||
299 | u16 events; | ||
300 | struct subsc_evt_cfg bcn_l_rssi_cfg; | ||
301 | struct subsc_evt_cfg bcn_h_rssi_cfg; | ||
302 | }; | ||
303 | |||
311 | #define MWIFIEX_MAX_VSIE_LEN (256) | 304 | #define MWIFIEX_MAX_VSIE_LEN (256) |
312 | #define MWIFIEX_MAX_VSIE_NUM (8) | 305 | #define MWIFIEX_MAX_VSIE_NUM (8) |
313 | #define MWIFIEX_VSIE_MASK_SCAN 0x01 | 306 | #define MWIFIEX_VSIE_MASK_SCAN 0x01 |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 8f9382b9c3ca..bca8b6d52273 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -932,20 +932,20 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, | |||
932 | /* Fill HT INFORMATION */ | 932 | /* Fill HT INFORMATION */ |
933 | ht_info = (struct mwifiex_ie_types_htinfo *) pos; | 933 | ht_info = (struct mwifiex_ie_types_htinfo *) pos; |
934 | memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo)); | 934 | memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo)); |
935 | ht_info->header.type = cpu_to_le16(WLAN_EID_HT_INFORMATION); | 935 | ht_info->header.type = cpu_to_le16(WLAN_EID_HT_OPERATION); |
936 | ht_info->header.len = | 936 | ht_info->header.len = |
937 | cpu_to_le16(sizeof(struct ieee80211_ht_info)); | 937 | cpu_to_le16(sizeof(struct ieee80211_ht_operation)); |
938 | 938 | ||
939 | ht_info->ht_info.control_chan = | 939 | ht_info->ht_oper.primary_chan = |
940 | (u8) priv->curr_bss_params.bss_descriptor.channel; | 940 | (u8) priv->curr_bss_params.bss_descriptor.channel; |
941 | if (adapter->sec_chan_offset) { | 941 | if (adapter->sec_chan_offset) { |
942 | ht_info->ht_info.ht_param = adapter->sec_chan_offset; | 942 | ht_info->ht_oper.ht_param = adapter->sec_chan_offset; |
943 | ht_info->ht_info.ht_param |= | 943 | ht_info->ht_oper.ht_param |= |
944 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; | 944 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; |
945 | } | 945 | } |
946 | ht_info->ht_info.operation_mode = | 946 | ht_info->ht_oper.operation_mode = |
947 | cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | 947 | cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); |
948 | ht_info->ht_info.basic_set[0] = 0xff; | 948 | ht_info->ht_oper.basic_set[0] = 0xff; |
949 | pos += sizeof(struct mwifiex_ie_types_htinfo); | 949 | pos += sizeof(struct mwifiex_ie_types_htinfo); |
950 | cmd_append_size += | 950 | cmd_append_size += |
951 | sizeof(struct mwifiex_ie_types_htinfo); | 951 | sizeof(struct mwifiex_ie_types_htinfo); |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 35225e9b1080..fcccf6b1373f 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -201,10 +201,10 @@ struct mwifiex_wmm_desc { | |||
201 | u32 packets_out[MAX_NUM_TID]; | 201 | u32 packets_out[MAX_NUM_TID]; |
202 | /* spin lock to protect ra_list */ | 202 | /* spin lock to protect ra_list */ |
203 | spinlock_t ra_list_spinlock; | 203 | spinlock_t ra_list_spinlock; |
204 | struct mwifiex_wmm_ac_status ac_status[IEEE80211_MAX_QUEUES]; | 204 | struct mwifiex_wmm_ac_status ac_status[IEEE80211_NUM_ACS]; |
205 | enum mwifiex_wmm_ac_e ac_down_graded_vals[IEEE80211_MAX_QUEUES]; | 205 | enum mwifiex_wmm_ac_e ac_down_graded_vals[IEEE80211_NUM_ACS]; |
206 | u32 drv_pkt_delay_max; | 206 | u32 drv_pkt_delay_max; |
207 | u8 queue_priority[IEEE80211_MAX_QUEUES]; | 207 | u8 queue_priority[IEEE80211_NUM_ACS]; |
208 | u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ | 208 | u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ |
209 | /* Number of transmit packets queued */ | 209 | /* Number of transmit packets queued */ |
210 | atomic_t tx_pkts_queued; | 210 | atomic_t tx_pkts_queued; |
@@ -269,7 +269,7 @@ struct mwifiex_bssdescriptor { | |||
269 | u8 disable_11n; | 269 | u8 disable_11n; |
270 | struct ieee80211_ht_cap *bcn_ht_cap; | 270 | struct ieee80211_ht_cap *bcn_ht_cap; |
271 | u16 ht_cap_offset; | 271 | u16 ht_cap_offset; |
272 | struct ieee80211_ht_info *bcn_ht_info; | 272 | struct ieee80211_ht_operation *bcn_ht_oper; |
273 | u16 ht_info_offset; | 273 | u16 ht_info_offset; |
274 | u8 *bcn_bss_co_2040; | 274 | u8 *bcn_bss_co_2040; |
275 | u16 bss_co_2040_offset; | 275 | u16 bss_co_2040_offset; |
@@ -448,7 +448,6 @@ struct mwifiex_private { | |||
448 | struct dentry *dfs_dev_dir; | 448 | struct dentry *dfs_dev_dir; |
449 | #endif | 449 | #endif |
450 | u8 nick_name[16]; | 450 | u8 nick_name[16]; |
451 | u8 qual_level, qual_noise; | ||
452 | u16 current_key_index; | 451 | u16 current_key_index; |
453 | struct semaphore async_sem; | 452 | struct semaphore async_sem; |
454 | u8 scan_pending_on_block; | 453 | u8 scan_pending_on_block; |
@@ -459,6 +458,9 @@ struct mwifiex_private { | |||
459 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | 458 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; |
460 | struct wps wps; | 459 | struct wps wps; |
461 | u8 scan_block; | 460 | u8 scan_block; |
461 | s32 cqm_rssi_thold; | ||
462 | u32 cqm_rssi_hyst; | ||
463 | u8 subsc_evt_rssi_state; | ||
462 | }; | 464 | }; |
463 | 465 | ||
464 | enum mwifiex_ba_status { | 466 | enum mwifiex_ba_status { |
@@ -896,8 +898,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
896 | int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); | 898 | int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); |
897 | int mwifiex_enable_hs(struct mwifiex_adapter *adapter); | 899 | int mwifiex_enable_hs(struct mwifiex_adapter *adapter); |
898 | int mwifiex_disable_auto_ds(struct mwifiex_private *priv); | 900 | int mwifiex_disable_auto_ds(struct mwifiex_private *priv); |
899 | int mwifiex_get_signal_info(struct mwifiex_private *priv, | ||
900 | struct mwifiex_ds_get_signal *signal); | ||
901 | int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, | 901 | int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, |
902 | struct mwifiex_rate_cfg *rate); | 902 | struct mwifiex_rate_cfg *rate); |
903 | int mwifiex_request_scan(struct mwifiex_private *priv, | 903 | int mwifiex_request_scan(struct mwifiex_private *priv, |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index aff9cd763f2b..ef84a1a6742f 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1221,9 +1221,9 @@ mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | |||
1221 | sizeof(struct ieee_types_header) - | 1221 | sizeof(struct ieee_types_header) - |
1222 | bss_entry->beacon_buf); | 1222 | bss_entry->beacon_buf); |
1223 | break; | 1223 | break; |
1224 | case WLAN_EID_HT_INFORMATION: | 1224 | case WLAN_EID_HT_OPERATION: |
1225 | bss_entry->bcn_ht_info = (struct ieee80211_ht_info *) | 1225 | bss_entry->bcn_ht_oper = |
1226 | (current_ptr + | 1226 | (struct ieee80211_ht_operation *)(current_ptr + |
1227 | sizeof(struct ieee_types_header)); | 1227 | sizeof(struct ieee_types_header)); |
1228 | bss_entry->ht_info_offset = (u16) (current_ptr + | 1228 | bss_entry->ht_info_offset = (u16) (current_ptr + |
1229 | sizeof(struct ieee_types_header) - | 1229 | sizeof(struct ieee_types_header) - |
@@ -1493,7 +1493,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid, | |||
1493 | priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL; | 1493 | priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL; |
1494 | priv->curr_bss_params.bss_descriptor.ht_cap_offset = | 1494 | priv->curr_bss_params.bss_descriptor.ht_cap_offset = |
1495 | 0; | 1495 | 0; |
1496 | priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL; | 1496 | priv->curr_bss_params.bss_descriptor.bcn_ht_oper = NULL; |
1497 | priv->curr_bss_params.bss_descriptor.ht_info_offset = | 1497 | priv->curr_bss_params.bss_descriptor.ht_info_offset = |
1498 | 0; | 1498 | 0; |
1499 | priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = | 1499 | priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = |
@@ -1667,8 +1667,9 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1667 | 1667 | ||
1668 | memcpy(bssid, bcn_param->bssid, ETH_ALEN); | 1668 | memcpy(bssid, bcn_param->bssid, ETH_ALEN); |
1669 | 1669 | ||
1670 | rssi = (s32) (bcn_param->rssi); | 1670 | rssi = (s32) bcn_param->rssi; |
1671 | dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", rssi); | 1671 | rssi = (-rssi) * 100; /* Convert dBm to mBm */ |
1672 | dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi); | ||
1672 | 1673 | ||
1673 | beacon_period = le16_to_cpu(bcn_param->beacon_period); | 1674 | beacon_period = le16_to_cpu(bcn_param->beacon_period); |
1674 | 1675 | ||
@@ -2019,8 +2020,8 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv) | |||
2019 | (curr_bss->beacon_buf + | 2020 | (curr_bss->beacon_buf + |
2020 | curr_bss->ht_cap_offset); | 2021 | curr_bss->ht_cap_offset); |
2021 | 2022 | ||
2022 | if (curr_bss->bcn_ht_info) | 2023 | if (curr_bss->bcn_ht_oper) |
2023 | curr_bss->bcn_ht_info = (struct ieee80211_ht_info *) | 2024 | curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *) |
2024 | (curr_bss->beacon_buf + | 2025 | (curr_bss->beacon_buf + |
2025 | curr_bss->ht_info_offset); | 2026 | curr_bss->ht_info_offset); |
2026 | 2027 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index a3fb322205b0..0ead152e3d1e 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h | |||
@@ -193,7 +193,7 @@ | |||
193 | a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+(MAX_PORT - \ | 193 | a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+(MAX_PORT - \ |
194 | a->mp_end_port))); \ | 194 | a->mp_end_port))); \ |
195 | a->mpa_tx.pkt_cnt++; \ | 195 | a->mpa_tx.pkt_cnt++; \ |
196 | } while (0); | 196 | } while (0) |
197 | 197 | ||
198 | /* SDIO Tx aggregation limit ? */ | 198 | /* SDIO Tx aggregation limit ? */ |
199 | #define MP_TX_AGGR_PKT_LIMIT_REACHED(a) \ | 199 | #define MP_TX_AGGR_PKT_LIMIT_REACHED(a) \ |
@@ -211,7 +211,7 @@ | |||
211 | a->mpa_tx.buf_len = 0; \ | 211 | a->mpa_tx.buf_len = 0; \ |
212 | a->mpa_tx.ports = 0; \ | 212 | a->mpa_tx.ports = 0; \ |
213 | a->mpa_tx.start_port = 0; \ | 213 | a->mpa_tx.start_port = 0; \ |
214 | } while (0); | 214 | } while (0) |
215 | 215 | ||
216 | /* SDIO Rx aggregation limit ? */ | 216 | /* SDIO Rx aggregation limit ? */ |
217 | #define MP_RX_AGGR_PKT_LIMIT_REACHED(a) \ | 217 | #define MP_RX_AGGR_PKT_LIMIT_REACHED(a) \ |
@@ -242,7 +242,7 @@ | |||
242 | a->mpa_rx.skb_arr[a->mpa_rx.pkt_cnt] = skb; \ | 242 | a->mpa_rx.skb_arr[a->mpa_rx.pkt_cnt] = skb; \ |
243 | a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = skb->len; \ | 243 | a->mpa_rx.len_arr[a->mpa_rx.pkt_cnt] = skb->len; \ |
244 | a->mpa_rx.pkt_cnt++; \ | 244 | a->mpa_rx.pkt_cnt++; \ |
245 | } while (0); | 245 | } while (0) |
246 | 246 | ||
247 | /* Reset SDIO Rx aggregation buffer parameters */ | 247 | /* Reset SDIO Rx aggregation buffer parameters */ |
248 | #define MP_RX_AGGR_BUF_RESET(a) do { \ | 248 | #define MP_RX_AGGR_BUF_RESET(a) do { \ |
@@ -250,7 +250,7 @@ | |||
250 | a->mpa_rx.buf_len = 0; \ | 250 | a->mpa_rx.buf_len = 0; \ |
251 | a->mpa_rx.ports = 0; \ | 251 | a->mpa_rx.ports = 0; \ |
252 | a->mpa_rx.start_port = 0; \ | 252 | a->mpa_rx.start_port = 0; \ |
253 | } while (0); | 253 | } while (0) |
254 | 254 | ||
255 | 255 | ||
256 | /* data structure for SDIO MPA TX */ | 256 | /* data structure for SDIO MPA TX */ |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 6c8e4594b48b..e90c34d9c63d 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -907,6 +907,101 @@ mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv, | |||
907 | } | 907 | } |
908 | 908 | ||
909 | /* | 909 | /* |
910 | * This function prepares command for event subscription, configuration | ||
911 | * and query. Events can be subscribed or unsubscribed. Current subscribed | ||
912 | * events can be queried. Also, current subscribed events are reported in | ||
913 | * every FW response. | ||
914 | */ | ||
915 | static int | ||
916 | mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv, | ||
917 | struct host_cmd_ds_command *cmd, | ||
918 | struct mwifiex_ds_misc_subsc_evt *subsc_evt_cfg) | ||
919 | { | ||
920 | struct host_cmd_ds_802_11_subsc_evt *subsc_evt = &cmd->params.subsc_evt; | ||
921 | struct mwifiex_ie_types_rssi_threshold *rssi_tlv; | ||
922 | u16 event_bitmap; | ||
923 | u8 *pos; | ||
924 | |||
925 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT); | ||
926 | cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt) + | ||
927 | S_DS_GEN); | ||
928 | |||
929 | subsc_evt->action = cpu_to_le16(subsc_evt_cfg->action); | ||
930 | dev_dbg(priv->adapter->dev, "cmd: action: %d\n", subsc_evt_cfg->action); | ||
931 | |||
932 | /*For query requests, no configuration TLV structures are to be added.*/ | ||
933 | if (subsc_evt_cfg->action == HostCmd_ACT_GEN_GET) | ||
934 | return 0; | ||
935 | |||
936 | subsc_evt->events = cpu_to_le16(subsc_evt_cfg->events); | ||
937 | |||
938 | event_bitmap = subsc_evt_cfg->events; | ||
939 | dev_dbg(priv->adapter->dev, "cmd: event bitmap : %16x\n", | ||
940 | event_bitmap); | ||
941 | |||
942 | if (((subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR) || | ||
943 | (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_SET)) && | ||
944 | (event_bitmap == 0)) { | ||
945 | dev_dbg(priv->adapter->dev, "Error: No event specified " | ||
946 | "for bitwise action type\n"); | ||
947 | return -EINVAL; | ||
948 | } | ||
949 | |||
950 | /* | ||
951 | * Append TLV structures for each of the specified events for | ||
952 | * subscribing or re-configuring. This is not required for | ||
953 | * bitwise unsubscribing request. | ||
954 | */ | ||
955 | if (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR) | ||
956 | return 0; | ||
957 | |||
958 | pos = ((u8 *)subsc_evt) + | ||
959 | sizeof(struct host_cmd_ds_802_11_subsc_evt); | ||
960 | |||
961 | if (event_bitmap & BITMASK_BCN_RSSI_LOW) { | ||
962 | rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos; | ||
963 | |||
964 | rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_LOW); | ||
965 | rssi_tlv->header.len = | ||
966 | cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) - | ||
967 | sizeof(struct mwifiex_ie_types_header)); | ||
968 | rssi_tlv->abs_value = subsc_evt_cfg->bcn_l_rssi_cfg.abs_value; | ||
969 | rssi_tlv->evt_freq = subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq; | ||
970 | |||
971 | dev_dbg(priv->adapter->dev, "Cfg Beacon Low Rssi event, " | ||
972 | "RSSI:-%d dBm, Freq:%d\n", | ||
973 | subsc_evt_cfg->bcn_l_rssi_cfg.abs_value, | ||
974 | subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq); | ||
975 | |||
976 | pos += sizeof(struct mwifiex_ie_types_rssi_threshold); | ||
977 | le16_add_cpu(&cmd->size, | ||
978 | sizeof(struct mwifiex_ie_types_rssi_threshold)); | ||
979 | } | ||
980 | |||
981 | if (event_bitmap & BITMASK_BCN_RSSI_HIGH) { | ||
982 | rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos; | ||
983 | |||
984 | rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH); | ||
985 | rssi_tlv->header.len = | ||
986 | cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) - | ||
987 | sizeof(struct mwifiex_ie_types_header)); | ||
988 | rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value; | ||
989 | rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq; | ||
990 | |||
991 | dev_dbg(priv->adapter->dev, "Cfg Beacon Low Rssi event, " | ||
992 | "RSSI:-%d dBm, Freq:%d\n", | ||
993 | subsc_evt_cfg->bcn_h_rssi_cfg.abs_value, | ||
994 | subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq); | ||
995 | |||
996 | pos += sizeof(struct mwifiex_ie_types_rssi_threshold); | ||
997 | le16_add_cpu(&cmd->size, | ||
998 | sizeof(struct mwifiex_ie_types_rssi_threshold)); | ||
999 | } | ||
1000 | |||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | /* | ||
910 | * This function prepares the commands before sending them to the firmware. | 1005 | * This function prepares the commands before sending them to the firmware. |
911 | * | 1006 | * |
912 | * This is a generic function which calls specific command preparation | 1007 | * This is a generic function which calls specific command preparation |
@@ -1086,6 +1181,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1086 | case HostCmd_CMD_PCIE_DESC_DETAILS: | 1181 | case HostCmd_CMD_PCIE_DESC_DETAILS: |
1087 | ret = mwifiex_cmd_pcie_host_spec(priv, cmd_ptr, cmd_action); | 1182 | ret = mwifiex_cmd_pcie_host_spec(priv, cmd_ptr, cmd_action); |
1088 | break; | 1183 | break; |
1184 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: | ||
1185 | ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); | ||
1186 | break; | ||
1089 | default: | 1187 | default: |
1090 | dev_err(priv->adapter->dev, | 1188 | dev_err(priv->adapter->dev, |
1091 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); | 1189 | "PREP_CMD: unknown cmd- %#x\n", cmd_no); |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 4da19ed0f078..3aa54243dea9 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -119,11 +119,11 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, | |||
119 | * calculated SNR values. | 119 | * calculated SNR values. |
120 | */ | 120 | */ |
121 | static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, | 121 | static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, |
122 | struct host_cmd_ds_command *resp, | 122 | struct host_cmd_ds_command *resp) |
123 | struct mwifiex_ds_get_signal *signal) | ||
124 | { | 123 | { |
125 | struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = | 124 | struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = |
126 | &resp->params.rssi_info_rsp; | 125 | &resp->params.rssi_info_rsp; |
126 | struct mwifiex_ds_misc_subsc_evt subsc_evt; | ||
127 | 127 | ||
128 | priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); | 128 | priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); |
129 | priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); | 129 | priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); |
@@ -137,34 +137,29 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, | |||
137 | priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); | 137 | priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); |
138 | priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg); | 138 | priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg); |
139 | 139 | ||
140 | /* Need to indicate IOCTL complete */ | 140 | if (priv->subsc_evt_rssi_state == EVENT_HANDLED) |
141 | if (signal) { | 141 | return 0; |
142 | memset(signal, 0, sizeof(*signal)); | 142 | |
143 | 143 | /* Resubscribe low and high rssi events with new thresholds */ | |
144 | signal->selector = ALL_RSSI_INFO_MASK; | 144 | memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt)); |
145 | 145 | subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; | |
146 | /* RSSI */ | 146 | subsc_evt.action = HostCmd_ACT_BITWISE_SET; |
147 | signal->bcn_rssi_last = priv->bcn_rssi_last; | 147 | if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) { |
148 | signal->bcn_rssi_avg = priv->bcn_rssi_avg; | 148 | subsc_evt.bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg - |
149 | signal->data_rssi_last = priv->data_rssi_last; | 149 | priv->cqm_rssi_hyst); |
150 | signal->data_rssi_avg = priv->data_rssi_avg; | 150 | subsc_evt.bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); |
151 | 151 | } else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) { | |
152 | /* SNR */ | 152 | subsc_evt.bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); |
153 | signal->bcn_snr_last = | 153 | subsc_evt.bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg + |
154 | CAL_SNR(priv->bcn_rssi_last, priv->bcn_nf_last); | 154 | priv->cqm_rssi_hyst); |
155 | signal->bcn_snr_avg = | ||
156 | CAL_SNR(priv->bcn_rssi_avg, priv->bcn_nf_avg); | ||
157 | signal->data_snr_last = | ||
158 | CAL_SNR(priv->data_rssi_last, priv->data_nf_last); | ||
159 | signal->data_snr_avg = | ||
160 | CAL_SNR(priv->data_rssi_avg, priv->data_nf_avg); | ||
161 | |||
162 | /* NF */ | ||
163 | signal->bcn_nf_last = priv->bcn_nf_last; | ||
164 | signal->bcn_nf_avg = priv->bcn_nf_avg; | ||
165 | signal->data_nf_last = priv->data_nf_last; | ||
166 | signal->data_nf_avg = priv->data_nf_avg; | ||
167 | } | 155 | } |
156 | subsc_evt.bcn_l_rssi_cfg.evt_freq = 1; | ||
157 | subsc_evt.bcn_h_rssi_cfg.evt_freq = 1; | ||
158 | |||
159 | priv->subsc_evt_rssi_state = EVENT_HANDLED; | ||
160 | |||
161 | mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT, | ||
162 | 0, 0, &subsc_evt); | ||
168 | 163 | ||
169 | return 0; | 164 | return 0; |
170 | } | 165 | } |
@@ -785,6 +780,28 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, | |||
785 | } | 780 | } |
786 | 781 | ||
787 | /* | 782 | /* |
783 | * This function handles the command response for subscribe event command. | ||
784 | */ | ||
785 | static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv, | ||
786 | struct host_cmd_ds_command *resp, | ||
787 | struct mwifiex_ds_misc_subsc_evt *sub_event) | ||
788 | { | ||
789 | struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event = | ||
790 | (struct host_cmd_ds_802_11_subsc_evt *)&resp->params.subsc_evt; | ||
791 | |||
792 | /* For every subscribe event command (Get/Set/Clear), FW reports the | ||
793 | * current set of subscribed events*/ | ||
794 | dev_dbg(priv->adapter->dev, "Bitmap of currently subscribed events: %16x\n", | ||
795 | le16_to_cpu(cmd_sub_event->events)); | ||
796 | |||
797 | /*Return the subscribed event info for a Get request*/ | ||
798 | if (sub_event) | ||
799 | sub_event->events = le16_to_cpu(cmd_sub_event->events); | ||
800 | |||
801 | return 0; | ||
802 | } | ||
803 | |||
804 | /* | ||
788 | * This function handles the command responses. | 805 | * This function handles the command responses. |
789 | * | 806 | * |
790 | * This is a generic function, which calls command specific | 807 | * This is a generic function, which calls command specific |
@@ -853,7 +870,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
853 | ret = mwifiex_ret_get_log(priv, resp, data_buf); | 870 | ret = mwifiex_ret_get_log(priv, resp, data_buf); |
854 | break; | 871 | break; |
855 | case HostCmd_CMD_RSSI_INFO: | 872 | case HostCmd_CMD_RSSI_INFO: |
856 | ret = mwifiex_ret_802_11_rssi_info(priv, resp, data_buf); | 873 | ret = mwifiex_ret_802_11_rssi_info(priv, resp); |
857 | break; | 874 | break; |
858 | case HostCmd_CMD_802_11_SNMP_MIB: | 875 | case HostCmd_CMD_802_11_SNMP_MIB: |
859 | ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf); | 876 | ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf); |
@@ -924,6 +941,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
924 | break; | 941 | break; |
925 | case HostCmd_CMD_PCIE_DESC_DETAILS: | 942 | case HostCmd_CMD_PCIE_DESC_DETAILS: |
926 | break; | 943 | break; |
944 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: | ||
945 | ret = mwifiex_ret_subsc_evt(priv, resp, data_buf); | ||
946 | break; | ||
927 | default: | 947 | default: |
928 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 948 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
929 | resp->command); | 949 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index cc531b536a56..f6bbb9307f86 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
@@ -128,9 +128,6 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv) | |||
128 | mwifiex_stop_net_dev_queue(priv->netdev, adapter); | 128 | mwifiex_stop_net_dev_queue(priv->netdev, adapter); |
129 | if (netif_carrier_ok(priv->netdev)) | 129 | if (netif_carrier_ok(priv->netdev)) |
130 | netif_carrier_off(priv->netdev); | 130 | netif_carrier_off(priv->netdev); |
131 | /* Reset wireless stats signal info */ | ||
132 | priv->qual_level = 0; | ||
133 | priv->qual_noise = 0; | ||
134 | } | 131 | } |
135 | 132 | ||
136 | /* | 133 | /* |
@@ -317,6 +314,12 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
317 | break; | 314 | break; |
318 | 315 | ||
319 | case EVENT_RSSI_LOW: | 316 | case EVENT_RSSI_LOW: |
317 | cfg80211_cqm_rssi_notify(priv->netdev, | ||
318 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | ||
319 | GFP_KERNEL); | ||
320 | mwifiex_send_cmd_async(priv, HostCmd_CMD_RSSI_INFO, | ||
321 | HostCmd_ACT_GEN_GET, 0, NULL); | ||
322 | priv->subsc_evt_rssi_state = RSSI_LOW_RECVD; | ||
320 | dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n"); | 323 | dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n"); |
321 | break; | 324 | break; |
322 | case EVENT_SNR_LOW: | 325 | case EVENT_SNR_LOW: |
@@ -326,6 +329,12 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
326 | dev_dbg(adapter->dev, "event: MAX_FAIL\n"); | 329 | dev_dbg(adapter->dev, "event: MAX_FAIL\n"); |
327 | break; | 330 | break; |
328 | case EVENT_RSSI_HIGH: | 331 | case EVENT_RSSI_HIGH: |
332 | cfg80211_cqm_rssi_notify(priv->netdev, | ||
333 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | ||
334 | GFP_KERNEL); | ||
335 | mwifiex_send_cmd_async(priv, HostCmd_CMD_RSSI_INFO, | ||
336 | HostCmd_ACT_GEN_GET, 0, NULL); | ||
337 | priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD; | ||
329 | dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n"); | 338 | dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n"); |
330 | break; | 339 | break; |
331 | case EVENT_SNR_HIGH: | 340 | case EVENT_SNR_HIGH: |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index d7b11defafe0..8ba58d935328 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -1185,39 +1185,6 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, | |||
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | /* | 1187 | /* |
1188 | * Sends IOCTL request to get signal information. | ||
1189 | * | ||
1190 | * This function allocates the IOCTL request buffer, fills it | ||
1191 | * with requisite parameters and calls the IOCTL handler. | ||
1192 | */ | ||
1193 | int mwifiex_get_signal_info(struct mwifiex_private *priv, | ||
1194 | struct mwifiex_ds_get_signal *signal) | ||
1195 | { | ||
1196 | int status; | ||
1197 | |||
1198 | signal->selector = ALL_RSSI_INFO_MASK; | ||
1199 | |||
1200 | /* Signal info can be obtained only if connected */ | ||
1201 | if (!priv->media_connected) { | ||
1202 | dev_dbg(priv->adapter->dev, | ||
1203 | "info: Can not get signal in disconnected state\n"); | ||
1204 | return -1; | ||
1205 | } | ||
1206 | |||
1207 | status = mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO, | ||
1208 | HostCmd_ACT_GEN_GET, 0, signal); | ||
1209 | |||
1210 | if (!status) { | ||
1211 | if (signal->selector & BCN_RSSI_AVG_MASK) | ||
1212 | priv->qual_level = signal->bcn_rssi_avg; | ||
1213 | if (signal->selector & BCN_NF_AVG_MASK) | ||
1214 | priv->qual_noise = signal->bcn_nf_avg; | ||
1215 | } | ||
1216 | |||
1217 | return status; | ||
1218 | } | ||
1219 | |||
1220 | /* | ||
1221 | * Sends IOCTL request to set encoding parameters. | 1188 | * Sends IOCTL request to set encoding parameters. |
1222 | * | 1189 | * |
1223 | * This function allocates the IOCTL request buffer, fills it | 1190 | * This function allocates the IOCTL request buffer, fills it |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index ee8af1f047c8..7cffea795ad2 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -796,11 +796,14 @@ int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) | |||
796 | dev_err(pdev, "Cannot register device (%d).\n", err); | 796 | dev_err(pdev, "Cannot register device (%d).\n", err); |
797 | return err; | 797 | return err; |
798 | } | 798 | } |
799 | priv->registered = true; | ||
799 | 800 | ||
800 | #ifdef CONFIG_P54_LEDS | 801 | #ifdef CONFIG_P54_LEDS |
801 | err = p54_init_leds(priv); | 802 | err = p54_init_leds(priv); |
802 | if (err) | 803 | if (err) { |
804 | p54_unregister_common(dev); | ||
803 | return err; | 805 | return err; |
806 | } | ||
804 | #endif /* CONFIG_P54_LEDS */ | 807 | #endif /* CONFIG_P54_LEDS */ |
805 | 808 | ||
806 | dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy)); | 809 | dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy)); |
@@ -840,7 +843,11 @@ void p54_unregister_common(struct ieee80211_hw *dev) | |||
840 | p54_unregister_leds(priv); | 843 | p54_unregister_leds(priv); |
841 | #endif /* CONFIG_P54_LEDS */ | 844 | #endif /* CONFIG_P54_LEDS */ |
842 | 845 | ||
843 | ieee80211_unregister_hw(dev); | 846 | if (priv->registered) { |
847 | priv->registered = false; | ||
848 | ieee80211_unregister_hw(dev); | ||
849 | } | ||
850 | |||
844 | mutex_destroy(&priv->conf_mutex); | 851 | mutex_destroy(&priv->conf_mutex); |
845 | mutex_destroy(&priv->eeprom_mutex); | 852 | mutex_destroy(&priv->eeprom_mutex); |
846 | } | 853 | } |
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 452fa3a64aa1..40b401ed6845 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h | |||
@@ -173,6 +173,7 @@ struct p54_common { | |||
173 | struct sk_buff_head tx_pending; | 173 | struct sk_buff_head tx_pending; |
174 | struct sk_buff_head tx_queue; | 174 | struct sk_buff_head tx_queue; |
175 | struct mutex conf_mutex; | 175 | struct mutex conf_mutex; |
176 | bool registered; | ||
176 | 177 | ||
177 | /* memory management (as seen by the firmware) */ | 178 | /* memory management (as seen by the firmware) */ |
178 | u32 rx_start; | 179 | u32 rx_start; |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index f4d28c39aac7..bac3d03f5786 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -117,21 +117,18 @@ static const struct { | |||
117 | u32 intf; | 117 | u32 intf; |
118 | enum p54u_hw_type type; | 118 | enum p54u_hw_type type; |
119 | const char *fw; | 119 | const char *fw; |
120 | const char *fw_legacy; | ||
121 | char hw[20]; | 120 | char hw[20]; |
122 | } p54u_fwlist[__NUM_P54U_HWTYPES] = { | 121 | } p54u_fwlist[__NUM_P54U_HWTYPES] = { |
123 | { | 122 | { |
124 | .type = P54U_NET2280, | 123 | .type = P54U_NET2280, |
125 | .intf = FW_LM86, | 124 | .intf = FW_LM86, |
126 | .fw = "isl3886usb", | 125 | .fw = "isl3886usb", |
127 | .fw_legacy = "isl3890usb", | ||
128 | .hw = "ISL3886 + net2280", | 126 | .hw = "ISL3886 + net2280", |
129 | }, | 127 | }, |
130 | { | 128 | { |
131 | .type = P54U_3887, | 129 | .type = P54U_3887, |
132 | .intf = FW_LM87, | 130 | .intf = FW_LM87, |
133 | .fw = "isl3887usb", | 131 | .fw = "isl3887usb", |
134 | .fw_legacy = "isl3887usb_bare", | ||
135 | .hw = "ISL3887", | 132 | .hw = "ISL3887", |
136 | }, | 133 | }, |
137 | }; | 134 | }; |
@@ -208,6 +205,16 @@ static void p54u_free_urbs(struct ieee80211_hw *dev) | |||
208 | usb_kill_anchored_urbs(&priv->submitted); | 205 | usb_kill_anchored_urbs(&priv->submitted); |
209 | } | 206 | } |
210 | 207 | ||
208 | static void p54u_stop(struct ieee80211_hw *dev) | ||
209 | { | ||
210 | /* | ||
211 | * TODO: figure out how to reliably stop the 3887 and net2280 so | ||
212 | * the hardware is still usable next time we want to start it. | ||
213 | * until then, we just stop listening to the hardware.. | ||
214 | */ | ||
215 | p54u_free_urbs(dev); | ||
216 | } | ||
217 | |||
211 | static int p54u_init_urbs(struct ieee80211_hw *dev) | 218 | static int p54u_init_urbs(struct ieee80211_hw *dev) |
212 | { | 219 | { |
213 | struct p54u_priv *priv = dev->priv; | 220 | struct p54u_priv *priv = dev->priv; |
@@ -257,6 +264,16 @@ static int p54u_init_urbs(struct ieee80211_hw *dev) | |||
257 | return ret; | 264 | return ret; |
258 | } | 265 | } |
259 | 266 | ||
267 | static int p54u_open(struct ieee80211_hw *dev) | ||
268 | { | ||
269 | /* | ||
270 | * TODO: Because we don't know how to reliably stop the 3887 and | ||
271 | * the isl3886+net2280, other than brutally cut off all | ||
272 | * communications. We have to reinitialize the urbs on every start. | ||
273 | */ | ||
274 | return p54u_init_urbs(dev); | ||
275 | } | ||
276 | |||
260 | static __le32 p54u_lm87_chksum(const __le32 *data, size_t length) | 277 | static __le32 p54u_lm87_chksum(const __le32 *data, size_t length) |
261 | { | 278 | { |
262 | u32 chk = 0; | 279 | u32 chk = 0; |
@@ -836,70 +853,137 @@ fail: | |||
836 | return err; | 853 | return err; |
837 | } | 854 | } |
838 | 855 | ||
839 | static int p54u_load_firmware(struct ieee80211_hw *dev) | 856 | static int p54_find_type(struct p54u_priv *priv) |
840 | { | 857 | { |
841 | struct p54u_priv *priv = dev->priv; | 858 | int i; |
842 | int err, i; | ||
843 | |||
844 | BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES); | ||
845 | 859 | ||
846 | for (i = 0; i < __NUM_P54U_HWTYPES; i++) | 860 | for (i = 0; i < __NUM_P54U_HWTYPES; i++) |
847 | if (p54u_fwlist[i].type == priv->hw_type) | 861 | if (p54u_fwlist[i].type == priv->hw_type) |
848 | break; | 862 | break; |
849 | |||
850 | if (i == __NUM_P54U_HWTYPES) | 863 | if (i == __NUM_P54U_HWTYPES) |
851 | return -EOPNOTSUPP; | 864 | return -EOPNOTSUPP; |
852 | 865 | ||
853 | err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev); | 866 | return i; |
854 | if (err) { | 867 | } |
855 | dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s " | ||
856 | "(%d)!\n", p54u_fwlist[i].fw, err); | ||
857 | 868 | ||
858 | err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy, | 869 | static int p54u_start_ops(struct p54u_priv *priv) |
859 | &priv->udev->dev); | 870 | { |
860 | if (err) | 871 | struct ieee80211_hw *dev = priv->common.hw; |
861 | return err; | 872 | int ret; |
862 | } | ||
863 | 873 | ||
864 | err = p54_parse_firmware(dev, priv->fw); | 874 | ret = p54_parse_firmware(dev, priv->fw); |
865 | if (err) | 875 | if (ret) |
866 | goto out; | 876 | goto err_out; |
877 | |||
878 | ret = p54_find_type(priv); | ||
879 | if (ret < 0) | ||
880 | goto err_out; | ||
867 | 881 | ||
868 | if (priv->common.fw_interface != p54u_fwlist[i].intf) { | 882 | if (priv->common.fw_interface != p54u_fwlist[ret].intf) { |
869 | dev_err(&priv->udev->dev, "wrong firmware, please get " | 883 | dev_err(&priv->udev->dev, "wrong firmware, please get " |
870 | "a firmware for \"%s\" and try again.\n", | 884 | "a firmware for \"%s\" and try again.\n", |
871 | p54u_fwlist[i].hw); | 885 | p54u_fwlist[ret].hw); |
872 | err = -EINVAL; | 886 | ret = -ENODEV; |
887 | goto err_out; | ||
873 | } | 888 | } |
874 | 889 | ||
875 | out: | 890 | ret = priv->upload_fw(dev); |
876 | if (err) | 891 | if (ret) |
877 | release_firmware(priv->fw); | 892 | goto err_out; |
878 | 893 | ||
879 | return err; | 894 | ret = p54u_open(dev); |
895 | if (ret) | ||
896 | goto err_out; | ||
897 | |||
898 | ret = p54_read_eeprom(dev); | ||
899 | if (ret) | ||
900 | goto err_stop; | ||
901 | |||
902 | p54u_stop(dev); | ||
903 | |||
904 | ret = p54_register_common(dev, &priv->udev->dev); | ||
905 | if (ret) | ||
906 | goto err_stop; | ||
907 | |||
908 | return 0; | ||
909 | |||
910 | err_stop: | ||
911 | p54u_stop(dev); | ||
912 | |||
913 | err_out: | ||
914 | /* | ||
915 | * p54u_disconnect will do the rest of the | ||
916 | * cleanup | ||
917 | */ | ||
918 | return ret; | ||
880 | } | 919 | } |
881 | 920 | ||
882 | static int p54u_open(struct ieee80211_hw *dev) | 921 | static void p54u_load_firmware_cb(const struct firmware *firmware, |
922 | void *context) | ||
883 | { | 923 | { |
884 | struct p54u_priv *priv = dev->priv; | 924 | struct p54u_priv *priv = context; |
925 | struct usb_device *udev = priv->udev; | ||
885 | int err; | 926 | int err; |
886 | 927 | ||
887 | err = p54u_init_urbs(dev); | 928 | complete(&priv->fw_wait_load); |
888 | if (err) { | 929 | if (firmware) { |
889 | return err; | 930 | priv->fw = firmware; |
931 | err = p54u_start_ops(priv); | ||
932 | } else { | ||
933 | err = -ENOENT; | ||
934 | dev_err(&udev->dev, "Firmware not found.\n"); | ||
890 | } | 935 | } |
891 | 936 | ||
892 | priv->common.open = p54u_init_urbs; | 937 | if (err) { |
938 | struct device *parent = priv->udev->dev.parent; | ||
893 | 939 | ||
894 | return 0; | 940 | dev_err(&udev->dev, "failed to initialize device (%d)\n", err); |
941 | |||
942 | if (parent) | ||
943 | device_lock(parent); | ||
944 | |||
945 | device_release_driver(&udev->dev); | ||
946 | /* | ||
947 | * At this point p54u_disconnect has already freed | ||
948 | * the "priv" context. Do not use it anymore! | ||
949 | */ | ||
950 | priv = NULL; | ||
951 | |||
952 | if (parent) | ||
953 | device_unlock(parent); | ||
954 | } | ||
955 | |||
956 | usb_put_dev(udev); | ||
895 | } | 957 | } |
896 | 958 | ||
897 | static void p54u_stop(struct ieee80211_hw *dev) | 959 | static int p54u_load_firmware(struct ieee80211_hw *dev, |
960 | struct usb_interface *intf) | ||
898 | { | 961 | { |
899 | /* TODO: figure out how to reliably stop the 3887 and net2280 so | 962 | struct usb_device *udev = interface_to_usbdev(intf); |
900 | the hardware is still usable next time we want to start it. | 963 | struct p54u_priv *priv = dev->priv; |
901 | until then, we just stop listening to the hardware.. */ | 964 | struct device *device = &udev->dev; |
902 | p54u_free_urbs(dev); | 965 | int err, i; |
966 | |||
967 | BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES); | ||
968 | |||
969 | init_completion(&priv->fw_wait_load); | ||
970 | i = p54_find_type(priv); | ||
971 | if (i < 0) | ||
972 | return i; | ||
973 | |||
974 | dev_info(&priv->udev->dev, "Loading firmware file %s\n", | ||
975 | p54u_fwlist[i].fw); | ||
976 | |||
977 | usb_get_dev(udev); | ||
978 | err = request_firmware_nowait(THIS_MODULE, 1, p54u_fwlist[i].fw, | ||
979 | device, GFP_KERNEL, priv, | ||
980 | p54u_load_firmware_cb); | ||
981 | if (err) { | ||
982 | dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s " | ||
983 | "(%d)!\n", p54u_fwlist[i].fw, err); | ||
984 | } | ||
985 | |||
986 | return err; | ||
903 | } | 987 | } |
904 | 988 | ||
905 | static int __devinit p54u_probe(struct usb_interface *intf, | 989 | static int __devinit p54u_probe(struct usb_interface *intf, |
@@ -969,33 +1053,7 @@ static int __devinit p54u_probe(struct usb_interface *intf, | |||
969 | priv->common.tx = p54u_tx_net2280; | 1053 | priv->common.tx = p54u_tx_net2280; |
970 | priv->upload_fw = p54u_upload_firmware_net2280; | 1054 | priv->upload_fw = p54u_upload_firmware_net2280; |
971 | } | 1055 | } |
972 | err = p54u_load_firmware(dev); | 1056 | err = p54u_load_firmware(dev, intf); |
973 | if (err) | ||
974 | goto err_free_dev; | ||
975 | |||
976 | err = priv->upload_fw(dev); | ||
977 | if (err) | ||
978 | goto err_free_fw; | ||
979 | |||
980 | p54u_open(dev); | ||
981 | err = p54_read_eeprom(dev); | ||
982 | p54u_stop(dev); | ||
983 | if (err) | ||
984 | goto err_free_fw; | ||
985 | |||
986 | err = p54_register_common(dev, &udev->dev); | ||
987 | if (err) | ||
988 | goto err_free_fw; | ||
989 | |||
990 | return 0; | ||
991 | |||
992 | err_free_fw: | ||
993 | release_firmware(priv->fw); | ||
994 | |||
995 | err_free_dev: | ||
996 | p54_free_common(dev); | ||
997 | usb_set_intfdata(intf, NULL); | ||
998 | usb_put_dev(udev); | ||
999 | return err; | 1057 | return err; |
1000 | } | 1058 | } |
1001 | 1059 | ||
@@ -1007,9 +1065,10 @@ static void __devexit p54u_disconnect(struct usb_interface *intf) | |||
1007 | if (!dev) | 1065 | if (!dev) |
1008 | return; | 1066 | return; |
1009 | 1067 | ||
1068 | priv = dev->priv; | ||
1069 | wait_for_completion(&priv->fw_wait_load); | ||
1010 | p54_unregister_common(dev); | 1070 | p54_unregister_common(dev); |
1011 | 1071 | ||
1012 | priv = dev->priv; | ||
1013 | usb_put_dev(interface_to_usbdev(intf)); | 1072 | usb_put_dev(interface_to_usbdev(intf)); |
1014 | release_firmware(priv->fw); | 1073 | release_firmware(priv->fw); |
1015 | p54_free_common(dev); | 1074 | p54_free_common(dev); |
diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h index ed4034ade59a..d273be7272b9 100644 --- a/drivers/net/wireless/p54/p54usb.h +++ b/drivers/net/wireless/p54/p54usb.h | |||
@@ -143,6 +143,9 @@ struct p54u_priv { | |||
143 | struct sk_buff_head rx_queue; | 143 | struct sk_buff_head rx_queue; |
144 | struct usb_anchor submitted; | 144 | struct usb_anchor submitted; |
145 | const struct firmware *fw; | 145 | const struct firmware *fw; |
146 | |||
147 | /* asynchronous firmware callback */ | ||
148 | struct completion fw_wait_load; | ||
146 | }; | 149 | }; |
147 | 150 | ||
148 | #endif /* P54USB_H */ | 151 | #endif /* P54USB_H */ |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index a08a6f0e4dd1..7c8f118c2b09 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -914,8 +914,7 @@ void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
914 | txhdr->hw_queue = queue; | 914 | txhdr->hw_queue = queue; |
915 | txhdr->backlog = priv->tx_stats[queue].len - 1; | 915 | txhdr->backlog = priv->tx_stats[queue].len - 1; |
916 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); | 916 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); |
917 | txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ? | 917 | txhdr->tx_antenna = 2 & priv->tx_diversity_mask; |
918 | 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask; | ||
919 | if (priv->rxhw == 5) { | 918 | if (priv->rxhw == 5) { |
920 | txhdr->longbow.cts_rate = cts_rate; | 919 | txhdr->longbow.cts_rate = cts_rate; |
921 | txhdr->longbow.output_power = cpu_to_le16(priv->output_power); | 920 | txhdr->longbow.output_power = cpu_to_le16(priv->output_power); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 471f87cab4ab..5583214721e0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -692,6 +692,8 @@ enum rt2x00_state_flags { | |||
692 | */ | 692 | */ |
693 | CONFIG_CHANNEL_HT40, | 693 | CONFIG_CHANNEL_HT40, |
694 | CONFIG_POWERSAVING, | 694 | CONFIG_POWERSAVING, |
695 | CONFIG_HT_DISABLED, | ||
696 | CONFIG_QOS_DISABLED, | ||
695 | 697 | ||
696 | /* | 698 | /* |
697 | * Mark we currently are sequentially reading TX_STA_FIFO register | 699 | * Mark we currently are sequentially reading TX_STA_FIFO register |
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 293676bfa571..e7361d913e8e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -217,6 +217,11 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | |||
217 | libconf.conf = conf; | 217 | libconf.conf = conf; |
218 | 218 | ||
219 | if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { | 219 | if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { |
220 | if (!conf_is_ht(conf)) | ||
221 | set_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags); | ||
222 | else | ||
223 | clear_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags); | ||
224 | |||
220 | if (conf_is_ht40(conf)) { | 225 | if (conf_is_ht40(conf)) { |
221 | set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); | 226 | set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); |
222 | hw_value = rt2x00ht_center_channel(rt2x00dev, conf); | 227 | hw_value = rt2x00ht_center_channel(rt2x00dev, conf); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index fc9901e027c1..90cc5e772650 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1062,11 +1062,6 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) | |||
1062 | 1062 | ||
1063 | set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags); | 1063 | set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags); |
1064 | 1064 | ||
1065 | /* | ||
1066 | * Register the extra components. | ||
1067 | */ | ||
1068 | rt2x00rfkill_register(rt2x00dev); | ||
1069 | |||
1070 | return 0; | 1065 | return 0; |
1071 | } | 1066 | } |
1072 | 1067 | ||
@@ -1210,6 +1205,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1210 | rt2x00link_register(rt2x00dev); | 1205 | rt2x00link_register(rt2x00dev); |
1211 | rt2x00leds_register(rt2x00dev); | 1206 | rt2x00leds_register(rt2x00dev); |
1212 | rt2x00debug_register(rt2x00dev); | 1207 | rt2x00debug_register(rt2x00dev); |
1208 | rt2x00rfkill_register(rt2x00dev); | ||
1213 | 1209 | ||
1214 | return 0; | 1210 | return 0; |
1215 | 1211 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index ca585e34d00e..8679d781a264 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c | |||
@@ -124,17 +124,15 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, | |||
124 | 124 | ||
125 | void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) | 125 | void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) |
126 | { | 126 | { |
127 | char dev_name[16]; | 127 | char name[36]; |
128 | char name[32]; | ||
129 | int retval; | 128 | int retval; |
130 | unsigned long on_period; | 129 | unsigned long on_period; |
131 | unsigned long off_period; | 130 | unsigned long off_period; |
132 | 131 | const char *phy_name = wiphy_name(rt2x00dev->hw->wiphy); | |
133 | snprintf(dev_name, sizeof(dev_name), "%s-%s", | ||
134 | rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy)); | ||
135 | 132 | ||
136 | if (rt2x00dev->led_radio.flags & LED_INITIALIZED) { | 133 | if (rt2x00dev->led_radio.flags & LED_INITIALIZED) { |
137 | snprintf(name, sizeof(name), "%s::radio", dev_name); | 134 | snprintf(name, sizeof(name), "%s-%s::radio", |
135 | rt2x00dev->ops->name, phy_name); | ||
138 | 136 | ||
139 | retval = rt2x00leds_register_led(rt2x00dev, | 137 | retval = rt2x00leds_register_led(rt2x00dev, |
140 | &rt2x00dev->led_radio, | 138 | &rt2x00dev->led_radio, |
@@ -144,7 +142,8 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) | |||
144 | } | 142 | } |
145 | 143 | ||
146 | if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) { | 144 | if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) { |
147 | snprintf(name, sizeof(name), "%s::assoc", dev_name); | 145 | snprintf(name, sizeof(name), "%s-%s::assoc", |
146 | rt2x00dev->ops->name, phy_name); | ||
148 | 147 | ||
149 | retval = rt2x00leds_register_led(rt2x00dev, | 148 | retval = rt2x00leds_register_led(rt2x00dev, |
150 | &rt2x00dev->led_assoc, | 149 | &rt2x00dev->led_assoc, |
@@ -154,7 +153,8 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) | |||
154 | } | 153 | } |
155 | 154 | ||
156 | if (rt2x00dev->led_qual.flags & LED_INITIALIZED) { | 155 | if (rt2x00dev->led_qual.flags & LED_INITIALIZED) { |
157 | snprintf(name, sizeof(name), "%s::quality", dev_name); | 156 | snprintf(name, sizeof(name), "%s-%s::quality", |
157 | rt2x00dev->ops->name, phy_name); | ||
158 | 158 | ||
159 | retval = rt2x00leds_register_led(rt2x00dev, | 159 | retval = rt2x00leds_register_led(rt2x00dev, |
160 | &rt2x00dev->led_qual, | 160 | &rt2x00dev->led_qual, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 2df2eb6d3e06..b49773ef72f2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -709,9 +709,19 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
709 | rt2x00dev->intf_associated--; | 709 | rt2x00dev->intf_associated--; |
710 | 710 | ||
711 | rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); | 711 | rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); |
712 | |||
713 | clear_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags); | ||
712 | } | 714 | } |
713 | 715 | ||
714 | /* | 716 | /* |
717 | * Check for access point which do not support 802.11e . We have to | ||
718 | * generate data frames sequence number in S/W for such AP, because | ||
719 | * of H/W bug. | ||
720 | */ | ||
721 | if (changes & BSS_CHANGED_QOS && !bss_conf->qos) | ||
722 | set_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags); | ||
723 | |||
724 | /* | ||
715 | * When the erp information has changed, we should perform | 725 | * When the erp information has changed, we should perform |
716 | * additional configuration steps. For all other changes we are done. | 726 | * additional configuration steps. For all other changes we are done. |
717 | */ | 727 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 9b1b2b7a7807..8ecf409476cd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -213,8 +213,19 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, | |||
213 | 213 | ||
214 | __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); | 214 | __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); |
215 | 215 | ||
216 | if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags)) | 216 | if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags)) { |
217 | return; | 217 | /* |
218 | * rt2800 has a H/W (or F/W) bug, device incorrectly increase | ||
219 | * seqno on retransmited data (non-QOS) frames. To workaround | ||
220 | * the problem let's generate seqno in software if QOS is | ||
221 | * disabled. | ||
222 | */ | ||
223 | if (test_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags)) | ||
224 | __clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); | ||
225 | else | ||
226 | /* H/W will generate sequence number */ | ||
227 | return; | ||
228 | } | ||
218 | 229 | ||
219 | /* | 230 | /* |
220 | * The hardware is not able to insert a sequence number. Assign a | 231 | * The hardware is not able to insert a sequence number. Assign a |
@@ -320,14 +331,6 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev, | |||
320 | txdesc->u.ht.wcid = sta_priv->wcid; | 331 | txdesc->u.ht.wcid = sta_priv->wcid; |
321 | } | 332 | } |
322 | 333 | ||
323 | txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ | ||
324 | |||
325 | /* | ||
326 | * Only one STBC stream is supported for now. | ||
327 | */ | ||
328 | if (tx_info->flags & IEEE80211_TX_CTL_STBC) | ||
329 | txdesc->u.ht.stbc = 1; | ||
330 | |||
331 | /* | 334 | /* |
332 | * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the | 335 | * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the |
333 | * mcs rate to be used | 336 | * mcs rate to be used |
@@ -351,6 +354,24 @@ static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev, | |||
351 | txdesc->u.ht.mcs |= 0x08; | 354 | txdesc->u.ht.mcs |= 0x08; |
352 | } | 355 | } |
353 | 356 | ||
357 | if (test_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags)) { | ||
358 | if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) | ||
359 | txdesc->u.ht.txop = TXOP_SIFS; | ||
360 | else | ||
361 | txdesc->u.ht.txop = TXOP_BACKOFF; | ||
362 | |||
363 | /* Left zero on all other settings. */ | ||
364 | return; | ||
365 | } | ||
366 | |||
367 | txdesc->u.ht.ba_size = 7; /* FIXME: What value is needed? */ | ||
368 | |||
369 | /* | ||
370 | * Only one STBC stream is supported for now. | ||
371 | */ | ||
372 | if (tx_info->flags & IEEE80211_TX_CTL_STBC) | ||
373 | txdesc->u.ht.stbc = 1; | ||
374 | |||
354 | /* | 375 | /* |
355 | * This frame is eligible for an AMPDU, however, don't aggregate | 376 | * This frame is eligible for an AMPDU, however, don't aggregate |
356 | * frames that are intended to probe a specific tx rate. | 377 | * frames that are intended to probe a specific tx rate. |
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 510023554e5f..e54488db0e10 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -838,7 +838,10 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw, | |||
838 | __le16 fc = hdr->frame_control; | 838 | __le16 fc = hdr->frame_control; |
839 | 839 | ||
840 | txrate = ieee80211_get_tx_rate(hw, info); | 840 | txrate = ieee80211_get_tx_rate(hw, info); |
841 | tcb_desc->hw_rate = txrate->hw_value; | 841 | if (txrate) |
842 | tcb_desc->hw_rate = txrate->hw_value; | ||
843 | else | ||
844 | tcb_desc->hw_rate = 0; | ||
842 | 845 | ||
843 | if (ieee80211_is_data(fc)) { | 846 | if (ieee80211_is_data(fc)) { |
844 | /* | 847 | /* |
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c index 5c7d57947d23..3d8cc4a0c86d 100644 --- a/drivers/net/wireless/rtlwifi/cam.c +++ b/drivers/net/wireless/rtlwifi/cam.c | |||
@@ -328,10 +328,9 @@ void rtl_cam_del_entry(struct ieee80211_hw *hw, u8 *sta_addr) | |||
328 | RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, "sta_addr is NULL\n"); | 328 | RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, "sta_addr is NULL\n"); |
329 | } | 329 | } |
330 | 330 | ||
331 | if ((sta_addr[0]|sta_addr[1]|sta_addr[2]|sta_addr[3]|\ | 331 | if (is_zero_ether_addr(sta_addr)) { |
332 | sta_addr[4]|sta_addr[5]) == 0) { | ||
333 | RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, | 332 | RT_TRACE(rtlpriv, COMP_SEC, DBG_EMERG, |
334 | "sta_addr is 00:00:00:00:00:00\n"); | 333 | "sta_addr is %pM\n", sta_addr); |
335 | return; | 334 | return; |
336 | } | 335 | } |
337 | /* Does STA already exist? */ | 336 | /* Does STA already exist? */ |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 07dd38efe62a..288b035a3579 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -912,8 +912,13 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) | |||
912 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); | 912 | memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc)); |
913 | ring = &rtlpci->tx_ring[BEACON_QUEUE]; | 913 | ring = &rtlpci->tx_ring[BEACON_QUEUE]; |
914 | pskb = __skb_dequeue(&ring->queue); | 914 | pskb = __skb_dequeue(&ring->queue); |
915 | if (pskb) | 915 | if (pskb) { |
916 | struct rtl_tx_desc *entry = &ring->desc[ring->idx]; | ||
917 | pci_unmap_single(rtlpci->pdev, rtlpriv->cfg->ops->get_desc( | ||
918 | (u8 *) entry, true, HW_DESC_TXBUFF_ADDR), | ||
919 | pskb->len, PCI_DMA_TODEVICE); | ||
916 | kfree_skb(pskb); | 920 | kfree_skb(pskb); |
921 | } | ||
917 | 922 | ||
918 | /*NB: the beacon data buffer must be 32-bit aligned. */ | 923 | /*NB: the beacon data buffer must be 32-bit aligned. */ |
919 | pskb = ieee80211_beacon_get(hw, mac->vif); | 924 | pskb = ieee80211_beacon_get(hw, mac->vif); |
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c index c66f08a0524a..d5cbf01da8ac 100644 --- a/drivers/net/wireless/rtlwifi/rc.c +++ b/drivers/net/wireless/rtlwifi/rc.c | |||
@@ -225,8 +225,7 @@ static void rtl_rate_init(void *ppriv, | |||
225 | static void rtl_rate_update(void *ppriv, | 225 | static void rtl_rate_update(void *ppriv, |
226 | struct ieee80211_supported_band *sband, | 226 | struct ieee80211_supported_band *sband, |
227 | struct ieee80211_sta *sta, void *priv_sta, | 227 | struct ieee80211_sta *sta, void *priv_sta, |
228 | u32 changed, | 228 | u32 changed) |
229 | enum nl80211_channel_type oper_chan_type) | ||
230 | { | 229 | { |
231 | } | 230 | } |
232 | 231 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index efb9ab270403..c4adb9777365 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h | |||
@@ -530,12 +530,7 @@ | |||
530 | SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) | 530 | SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) |
531 | 531 | ||
532 | #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ | 532 | #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ |
533 | do { \ | 533 | memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) |
534 | if (_size > TX_DESC_NEXT_DESC_OFFSET) \ | ||
535 | memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ | ||
536 | else \ | ||
537 | memset(__pdesc, 0, _size); \ | ||
538 | } while (0); | ||
539 | 534 | ||
540 | struct rx_fwinfo_92c { | 535 | struct rx_fwinfo_92c { |
541 | u8 gain_trsw[4]; | 536 | u8 gain_trsw[4]; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index 4898c502974d..480862c07f92 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c | |||
@@ -91,7 +91,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) | |||
91 | u8 tid; | 91 | u8 tid; |
92 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 92 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
93 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 93 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
94 | static int header_print; | ||
95 | 94 | ||
96 | rtlpriv->dm.dm_initialgain_enable = true; | 95 | rtlpriv->dm.dm_initialgain_enable = true; |
97 | rtlpriv->dm.dm_flag = 0; | 96 | rtlpriv->dm.dm_flag = 0; |
@@ -171,10 +170,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) | |||
171 | for (tid = 0; tid < 8; tid++) | 170 | for (tid = 0; tid < 8; tid++) |
172 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); | 171 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); |
173 | 172 | ||
174 | /* Only load firmware for first MAC */ | ||
175 | if (header_print) | ||
176 | return 0; | ||
177 | |||
178 | /* for firmware buf */ | 173 | /* for firmware buf */ |
179 | rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); | 174 | rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); |
180 | if (!rtlpriv->rtlhal.pfirmware) { | 175 | if (!rtlpriv->rtlhal.pfirmware) { |
@@ -186,7 +181,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) | |||
186 | rtlpriv->max_fw_size = 0x8000; | 181 | rtlpriv->max_fw_size = 0x8000; |
187 | pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); | 182 | pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); |
188 | pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); | 183 | pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); |
189 | header_print++; | ||
190 | 184 | ||
191 | /* request fw */ | 185 | /* request fw */ |
192 | err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, | 186 | err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h index 0dc736c2723b..057a52431b00 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h | |||
@@ -530,12 +530,8 @@ | |||
530 | SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) | 530 | SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val) |
531 | 531 | ||
532 | #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ | 532 | #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ |
533 | do { \ | 533 | memset((void *)__pdesc, 0, \ |
534 | if (_size > TX_DESC_NEXT_DESC_OFFSET) \ | 534 | min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) |
535 | memset((void *)__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ | ||
536 | else \ | ||
537 | memset((void *)__pdesc, 0, _size); \ | ||
538 | } while (0); | ||
539 | 535 | ||
540 | /* For 92D early mode */ | 536 | /* For 92D early mode */ |
541 | #define SET_EARLYMODE_PKTNUM(__paddr, __value) \ | 537 | #define SET_EARLYMODE_PKTNUM(__paddr, __value) \ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h index d1b0a1e14971..20afec62ce05 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h | |||
@@ -252,12 +252,7 @@ | |||
252 | * the desc is cleared. */ | 252 | * the desc is cleared. */ |
253 | #define TX_DESC_NEXT_DESC_OFFSET 36 | 253 | #define TX_DESC_NEXT_DESC_OFFSET 36 |
254 | #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ | 254 | #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ |
255 | do { \ | 255 | memset(__pdesc, 0, min_t(size_t, _size, TX_DESC_NEXT_DESC_OFFSET)) |
256 | if (_size > TX_DESC_NEXT_DESC_OFFSET) \ | ||
257 | memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ | ||
258 | else \ | ||
259 | memset(__pdesc, 0, _size); \ | ||
260 | } while (0); | ||
261 | 256 | ||
262 | /* Rx Desc */ | 257 | /* Rx Desc */ |
263 | #define RX_STATUS_DESC_SIZE 24 | 258 | #define RX_STATUS_DESC_SIZE 24 |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/rtlwifi/rtl8192se/fw.h index b4afff626437..d53f4332464d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.h | |||
@@ -345,7 +345,7 @@ enum fw_h2c_cmd { | |||
345 | do { \ | 345 | do { \ |
346 | udelay(1000); \ | 346 | udelay(1000); \ |
347 | rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \ | 347 | rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \ |
348 | } while (0); | 348 | } while (0) |
349 | 349 | ||
350 | #define FW_CMD_IO_UPDATE(rtlpriv, _val) \ | 350 | #define FW_CMD_IO_UPDATE(rtlpriv, _val) \ |
351 | rtlpriv->rtlhal.fwcmd_iomap = _val; | 351 | rtlpriv->rtlhal.fwcmd_iomap = _val; |
@@ -354,13 +354,13 @@ enum fw_h2c_cmd { | |||
354 | do { \ | 354 | do { \ |
355 | rtl_write_word(rtlpriv, LBUS_MON_ADDR, (u16)_val); \ | 355 | rtl_write_word(rtlpriv, LBUS_MON_ADDR, (u16)_val); \ |
356 | FW_CMD_IO_UPDATE(rtlpriv, _val); \ | 356 | FW_CMD_IO_UPDATE(rtlpriv, _val); \ |
357 | } while (0); | 357 | } while (0) |
358 | 358 | ||
359 | #define FW_CMD_PARA_SET(rtlpriv, _val) \ | 359 | #define FW_CMD_PARA_SET(rtlpriv, _val) \ |
360 | do { \ | 360 | do { \ |
361 | rtl_write_dword(rtlpriv, LBUS_ADDR_MASK, _val); \ | 361 | rtl_write_dword(rtlpriv, LBUS_ADDR_MASK, _val); \ |
362 | rtlpriv->rtlhal.fwcmd_ioparam = _val; \ | 362 | rtlpriv->rtlhal.fwcmd_ioparam = _val; \ |
363 | } while (0); | 363 | } while (0) |
364 | 364 | ||
365 | #define FW_CMD_IO_QUERY(rtlpriv) \ | 365 | #define FW_CMD_IO_QUERY(rtlpriv) \ |
366 | (u16)(rtlpriv->rtlhal.fwcmd_iomap) | 366 | (u16)(rtlpriv->rtlhal.fwcmd_iomap) |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 2e1e352864bb..d04dbda13f5a 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -124,46 +124,38 @@ static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request, | |||
124 | return status; | 124 | return status; |
125 | } | 125 | } |
126 | 126 | ||
127 | static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len) | 127 | static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) |
128 | { | 128 | { |
129 | struct device *dev = rtlpriv->io.dev; | ||
130 | struct usb_device *udev = to_usb_device(dev); | ||
129 | u8 request; | 131 | u8 request; |
130 | u16 wvalue; | 132 | u16 wvalue; |
131 | u16 index; | 133 | u16 index; |
132 | u32 *data; | 134 | __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; |
133 | u32 ret; | ||
134 | 135 | ||
135 | data = kmalloc(sizeof(u32), GFP_KERNEL); | ||
136 | if (!data) | ||
137 | return -ENOMEM; | ||
138 | request = REALTEK_USB_VENQT_CMD_REQ; | 136 | request = REALTEK_USB_VENQT_CMD_REQ; |
139 | index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ | 137 | index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ |
140 | 138 | ||
141 | wvalue = (u16)addr; | 139 | wvalue = (u16)addr; |
142 | _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); | 140 | _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); |
143 | ret = le32_to_cpu(*data); | 141 | if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) |
144 | kfree(data); | 142 | rtlpriv->usb_data_index = 0; |
145 | return ret; | 143 | return le32_to_cpu(*data); |
146 | } | 144 | } |
147 | 145 | ||
148 | static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr) | 146 | static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr) |
149 | { | 147 | { |
150 | struct device *dev = rtlpriv->io.dev; | 148 | return (u8)_usb_read_sync(rtlpriv, addr, 1); |
151 | |||
152 | return (u8)_usb_read_sync(to_usb_device(dev), addr, 1); | ||
153 | } | 149 | } |
154 | 150 | ||
155 | static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr) | 151 | static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr) |
156 | { | 152 | { |
157 | struct device *dev = rtlpriv->io.dev; | 153 | return (u16)_usb_read_sync(rtlpriv, addr, 2); |
158 | |||
159 | return (u16)_usb_read_sync(to_usb_device(dev), addr, 2); | ||
160 | } | 154 | } |
161 | 155 | ||
162 | static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr) | 156 | static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr) |
163 | { | 157 | { |
164 | struct device *dev = rtlpriv->io.dev; | 158 | return _usb_read_sync(rtlpriv, addr, 4); |
165 | |||
166 | return _usb_read_sync(to_usb_device(dev), addr, 4); | ||
167 | } | 159 | } |
168 | 160 | ||
169 | static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val, | 161 | static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val, |
@@ -955,6 +947,11 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, | |||
955 | return -ENOMEM; | 947 | return -ENOMEM; |
956 | } | 948 | } |
957 | rtlpriv = hw->priv; | 949 | rtlpriv = hw->priv; |
950 | rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32), | ||
951 | GFP_KERNEL); | ||
952 | if (!rtlpriv->usb_data) | ||
953 | return -ENOMEM; | ||
954 | rtlpriv->usb_data_index = 0; | ||
958 | init_completion(&rtlpriv->firmware_loading_complete); | 955 | init_completion(&rtlpriv->firmware_loading_complete); |
959 | SET_IEEE80211_DEV(hw, &intf->dev); | 956 | SET_IEEE80211_DEV(hw, &intf->dev); |
960 | udev = interface_to_usbdev(intf); | 957 | udev = interface_to_usbdev(intf); |
@@ -1025,6 +1022,7 @@ void rtl_usb_disconnect(struct usb_interface *intf) | |||
1025 | /* rtl_deinit_rfkill(hw); */ | 1022 | /* rtl_deinit_rfkill(hw); */ |
1026 | rtl_usb_deinit(hw); | 1023 | rtl_usb_deinit(hw); |
1027 | rtl_deinit_core(hw); | 1024 | rtl_deinit_core(hw); |
1025 | kfree(rtlpriv->usb_data); | ||
1028 | rtlpriv->cfg->ops->deinit_sw_leds(hw); | 1026 | rtlpriv->cfg->ops->deinit_sw_leds(hw); |
1029 | rtlpriv->cfg->ops->deinit_sw_vars(hw); | 1027 | rtlpriv->cfg->ops->deinit_sw_vars(hw); |
1030 | _rtl_usb_io_handler_release(hw); | 1028 | _rtl_usb_io_handler_release(hw); |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index b591614c3b9b..521398803099 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -67,7 +67,7 @@ | |||
67 | #define QOS_QUEUE_NUM 4 | 67 | #define QOS_QUEUE_NUM 4 |
68 | #define RTL_MAC80211_NUM_QUEUE 5 | 68 | #define RTL_MAC80211_NUM_QUEUE 5 |
69 | #define REALTEK_USB_VENQT_MAX_BUF_SIZE 254 | 69 | #define REALTEK_USB_VENQT_MAX_BUF_SIZE 254 |
70 | 70 | #define RTL_USB_MAX_RX_COUNT 100 | |
71 | #define QBSS_LOAD_SIZE 5 | 71 | #define QBSS_LOAD_SIZE 5 |
72 | #define MAX_WMMELE_LENGTH 64 | 72 | #define MAX_WMMELE_LENGTH 64 |
73 | 73 | ||
@@ -1629,6 +1629,10 @@ struct rtl_priv { | |||
1629 | interface or hardware */ | 1629 | interface or hardware */ |
1630 | unsigned long status; | 1630 | unsigned long status; |
1631 | 1631 | ||
1632 | /* data buffer pointer for USB reads */ | ||
1633 | __le32 *usb_data; | ||
1634 | int usb_data_index; | ||
1635 | |||
1632 | /*This must be the last item so | 1636 | /*This must be the last item so |
1633 | that it points to the data allocated | 1637 | that it points to the data allocated |
1634 | beyond this structure like: | 1638 | beyond this structure like: |
@@ -1954,37 +1958,35 @@ static inline void rtl_write_dword(struct rtl_priv *rtlpriv, | |||
1954 | static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, | 1958 | static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, |
1955 | u32 regaddr, u32 bitmask) | 1959 | u32 regaddr, u32 bitmask) |
1956 | { | 1960 | { |
1957 | return ((struct rtl_priv *)(hw)->priv)->cfg->ops->get_bbreg(hw, | 1961 | struct rtl_priv *rtlpriv = hw->priv; |
1958 | regaddr, | 1962 | |
1959 | bitmask); | 1963 | return rtlpriv->cfg->ops->get_bbreg(hw, regaddr, bitmask); |
1960 | } | 1964 | } |
1961 | 1965 | ||
1962 | static inline void rtl_set_bbreg(struct ieee80211_hw *hw, u32 regaddr, | 1966 | static inline void rtl_set_bbreg(struct ieee80211_hw *hw, u32 regaddr, |
1963 | u32 bitmask, u32 data) | 1967 | u32 bitmask, u32 data) |
1964 | { | 1968 | { |
1965 | ((struct rtl_priv *)(hw)->priv)->cfg->ops->set_bbreg(hw, | 1969 | struct rtl_priv *rtlpriv = hw->priv; |
1966 | regaddr, bitmask, | ||
1967 | data); | ||
1968 | 1970 | ||
1971 | rtlpriv->cfg->ops->set_bbreg(hw, regaddr, bitmask, data); | ||
1969 | } | 1972 | } |
1970 | 1973 | ||
1971 | static inline u32 rtl_get_rfreg(struct ieee80211_hw *hw, | 1974 | static inline u32 rtl_get_rfreg(struct ieee80211_hw *hw, |
1972 | enum radio_path rfpath, u32 regaddr, | 1975 | enum radio_path rfpath, u32 regaddr, |
1973 | u32 bitmask) | 1976 | u32 bitmask) |
1974 | { | 1977 | { |
1975 | return ((struct rtl_priv *)(hw)->priv)->cfg->ops->get_rfreg(hw, | 1978 | struct rtl_priv *rtlpriv = hw->priv; |
1976 | rfpath, | 1979 | |
1977 | regaddr, | 1980 | return rtlpriv->cfg->ops->get_rfreg(hw, rfpath, regaddr, bitmask); |
1978 | bitmask); | ||
1979 | } | 1981 | } |
1980 | 1982 | ||
1981 | static inline void rtl_set_rfreg(struct ieee80211_hw *hw, | 1983 | static inline void rtl_set_rfreg(struct ieee80211_hw *hw, |
1982 | enum radio_path rfpath, u32 regaddr, | 1984 | enum radio_path rfpath, u32 regaddr, |
1983 | u32 bitmask, u32 data) | 1985 | u32 bitmask, u32 data) |
1984 | { | 1986 | { |
1985 | ((struct rtl_priv *)(hw)->priv)->cfg->ops->set_rfreg(hw, | 1987 | struct rtl_priv *rtlpriv = hw->priv; |
1986 | rfpath, regaddr, | 1988 | |
1987 | bitmask, data); | 1989 | rtlpriv->cfg->ops->set_rfreg(hw, rfpath, regaddr, bitmask, data); |
1988 | } | 1990 | } |
1989 | 1991 | ||
1990 | static inline bool is_hal_stop(struct rtl_hal *rtlhal) | 1992 | static inline bool is_hal_stop(struct rtl_hal *rtlhal) |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 39002363611e..362ff1a7067e 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -232,7 +232,7 @@ static struct conf_drv_settings default_conf = { | |||
232 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | 232 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
233 | }, | 233 | }, |
234 | [1] = { | 234 | [1] = { |
235 | .ie = WLAN_EID_HT_INFORMATION, | 235 | .ie = WLAN_EID_HT_OPERATION, |
236 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | 236 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, |
237 | }, | 237 | }, |
238 | }, | 238 | }, |
@@ -5242,7 +5242,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5242 | wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - | 5242 | wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - |
5243 | sizeof(struct ieee80211_header); | 5243 | sizeof(struct ieee80211_header); |
5244 | 5244 | ||
5245 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | 5245 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD | |
5246 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | ||
5246 | 5247 | ||
5247 | /* make sure all our channels fit in the scanned_ch bitmask */ | 5248 | /* make sure all our channels fit in the scanned_ch bitmask */ |
5248 | BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + | 5249 | BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 210e2c325534..db84e2f6b289 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -640,9 +640,9 @@ struct ieee80211_rann_ie { | |||
640 | u8 rann_hopcount; | 640 | u8 rann_hopcount; |
641 | u8 rann_ttl; | 641 | u8 rann_ttl; |
642 | u8 rann_addr[6]; | 642 | u8 rann_addr[6]; |
643 | u32 rann_seq; | 643 | __le32 rann_seq; |
644 | u32 rann_interval; | 644 | __le32 rann_interval; |
645 | u32 rann_metric; | 645 | __le32 rann_metric; |
646 | } __attribute__ ((packed)); | 646 | } __attribute__ ((packed)); |
647 | 647 | ||
648 | enum ieee80211_rann_flags { | 648 | enum ieee80211_rann_flags { |
@@ -1007,13 +1007,13 @@ enum ieee80211_min_mpdu_spacing { | |||
1007 | }; | 1007 | }; |
1008 | 1008 | ||
1009 | /** | 1009 | /** |
1010 | * struct ieee80211_ht_info - HT information | 1010 | * struct ieee80211_ht_operation - HT operation IE |
1011 | * | 1011 | * |
1012 | * This structure is the "HT information element" as | 1012 | * This structure is the "HT operation element" as |
1013 | * described in 802.11n D5.0 7.3.2.58 | 1013 | * described in 802.11n-2009 7.3.2.57 |
1014 | */ | 1014 | */ |
1015 | struct ieee80211_ht_info { | 1015 | struct ieee80211_ht_operation { |
1016 | u8 control_chan; | 1016 | u8 primary_chan; |
1017 | u8 ht_param; | 1017 | u8 ht_param; |
1018 | __le16 operation_mode; | 1018 | __le16 operation_mode; |
1019 | __le16 stbc_param; | 1019 | __le16 stbc_param; |
@@ -1027,8 +1027,6 @@ struct ieee80211_ht_info { | |||
1027 | #define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 | 1027 | #define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 |
1028 | #define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 | 1028 | #define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 |
1029 | #define IEEE80211_HT_PARAM_RIFS_MODE 0x08 | 1029 | #define IEEE80211_HT_PARAM_RIFS_MODE 0x08 |
1030 | #define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 | ||
1031 | #define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 | ||
1032 | 1030 | ||
1033 | /* for operation_mode */ | 1031 | /* for operation_mode */ |
1034 | #define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 | 1032 | #define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 |
@@ -1301,7 +1299,7 @@ enum ieee80211_eid { | |||
1301 | WLAN_EID_EXT_SUPP_RATES = 50, | 1299 | WLAN_EID_EXT_SUPP_RATES = 50, |
1302 | 1300 | ||
1303 | WLAN_EID_HT_CAPABILITY = 45, | 1301 | WLAN_EID_HT_CAPABILITY = 45, |
1304 | WLAN_EID_HT_INFORMATION = 61, | 1302 | WLAN_EID_HT_OPERATION = 61, |
1305 | 1303 | ||
1306 | WLAN_EID_RSN = 48, | 1304 | WLAN_EID_RSN = 48, |
1307 | WLAN_EID_MMIE = 76, | 1305 | WLAN_EID_MMIE = 76, |
@@ -1441,6 +1439,18 @@ enum ieee80211_tdls_actioncode { | |||
1441 | #define WLAN_TDLS_SNAP_RFTYPE 0x2 | 1439 | #define WLAN_TDLS_SNAP_RFTYPE 0x2 |
1442 | 1440 | ||
1443 | /** | 1441 | /** |
1442 | * enum - mesh synchronization method identifier | ||
1443 | * | ||
1444 | * @IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET: the default synchronization method | ||
1445 | * @IEEE80211_SYNC_METHOD_VENDOR: a vendor specific synchronization method | ||
1446 | * that will be specified in a vendor specific information element | ||
1447 | */ | ||
1448 | enum { | ||
1449 | IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET = 1, | ||
1450 | IEEE80211_SYNC_METHOD_VENDOR = 255, | ||
1451 | }; | ||
1452 | |||
1453 | /** | ||
1444 | * enum - mesh path selection protocol identifier | 1454 | * enum - mesh path selection protocol identifier |
1445 | * | 1455 | * |
1446 | * @IEEE80211_PATH_PROTOCOL_HWMP: the default path selection protocol | 1456 | * @IEEE80211_PATH_PROTOCOL_HWMP: the default path selection protocol |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index e474f6e780cc..1335084b1c69 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -548,6 +548,11 @@ | |||
548 | * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether | 548 | * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether |
549 | * No Acknowledgement Policy should be applied. | 549 | * No Acknowledgement Policy should be applied. |
550 | * | 550 | * |
551 | * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels | ||
552 | * independently of the userspace SME, send this event indicating | ||
553 | * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with | ||
554 | * %NL80211_ATTR_WIPHY_CHANNEL_TYPE. | ||
555 | * | ||
551 | * @NL80211_CMD_MAX: highest used command number | 556 | * @NL80211_CMD_MAX: highest used command number |
552 | * @__NL80211_CMD_AFTER_LAST: internal use | 557 | * @__NL80211_CMD_AFTER_LAST: internal use |
553 | */ | 558 | */ |
@@ -689,6 +694,8 @@ enum nl80211_commands { | |||
689 | 694 | ||
690 | NL80211_CMD_SET_NOACK_MAP, | 695 | NL80211_CMD_SET_NOACK_MAP, |
691 | 696 | ||
697 | NL80211_CMD_CH_SWITCH_NOTIFY, | ||
698 | |||
692 | /* add new commands above here */ | 699 | /* add new commands above here */ |
693 | 700 | ||
694 | /* used to define NL80211_CMD_MAX below */ | 701 | /* used to define NL80211_CMD_MAX below */ |
@@ -1685,6 +1692,7 @@ enum nl80211_sta_bss_param { | |||
1685 | * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected | 1692 | * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected |
1686 | * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. | 1693 | * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. |
1687 | * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) | 1694 | * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) |
1695 | * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64) | ||
1688 | * @__NL80211_STA_INFO_AFTER_LAST: internal | 1696 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
1689 | * @NL80211_STA_INFO_MAX: highest possible station info attribute | 1697 | * @NL80211_STA_INFO_MAX: highest possible station info attribute |
1690 | */ | 1698 | */ |
@@ -1708,6 +1716,7 @@ enum nl80211_sta_info { | |||
1708 | NL80211_STA_INFO_CONNECTED_TIME, | 1716 | NL80211_STA_INFO_CONNECTED_TIME, |
1709 | NL80211_STA_INFO_STA_FLAGS, | 1717 | NL80211_STA_INFO_STA_FLAGS, |
1710 | NL80211_STA_INFO_BEACON_LOSS, | 1718 | NL80211_STA_INFO_BEACON_LOSS, |
1719 | NL80211_STA_INFO_T_OFFSET, | ||
1711 | 1720 | ||
1712 | /* keep last */ | 1721 | /* keep last */ |
1713 | __NL80211_STA_INFO_AFTER_LAST, | 1722 | __NL80211_STA_INFO_AFTER_LAST, |
@@ -2142,6 +2151,9 @@ enum nl80211_mntr_flags { | |||
2142 | * | 2151 | * |
2143 | * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute | 2152 | * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute |
2144 | * | 2153 | * |
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) | ||
2156 | * | ||
2145 | * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use | 2157 | * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use |
2146 | */ | 2158 | */ |
2147 | enum nl80211_meshconf_params { | 2159 | enum nl80211_meshconf_params { |
@@ -2166,6 +2178,7 @@ enum nl80211_meshconf_params { | |||
2166 | NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, | 2178 | NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, |
2167 | NL80211_MESHCONF_FORWARDING, | 2179 | NL80211_MESHCONF_FORWARDING, |
2168 | NL80211_MESHCONF_RSSI_THRESHOLD, | 2180 | NL80211_MESHCONF_RSSI_THRESHOLD, |
2181 | NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, | ||
2169 | 2182 | ||
2170 | /* keep last */ | 2183 | /* keep last */ |
2171 | __NL80211_MESHCONF_ATTR_AFTER_LAST, | 2184 | __NL80211_MESHCONF_ATTR_AFTER_LAST, |
@@ -2205,6 +2218,11 @@ enum nl80211_meshconf_params { | |||
2205 | * complete (unsecured) mesh peering without the need of a userspace daemon. | 2218 | * complete (unsecured) mesh peering without the need of a userspace daemon. |
2206 | * | 2219 | * |
2207 | * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number | 2220 | * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number |
2221 | * | ||
2222 | * @NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC: Enable this option to use a | ||
2223 | * vendor specific synchronization method or disable it to use the default | ||
2224 | * neighbor offset synchronization | ||
2225 | * | ||
2208 | * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use | 2226 | * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use |
2209 | */ | 2227 | */ |
2210 | enum nl80211_mesh_setup_params { | 2228 | enum nl80211_mesh_setup_params { |
@@ -2214,6 +2232,7 @@ enum nl80211_mesh_setup_params { | |||
2214 | NL80211_MESH_SETUP_IE, | 2232 | NL80211_MESH_SETUP_IE, |
2215 | NL80211_MESH_SETUP_USERSPACE_AUTH, | 2233 | NL80211_MESH_SETUP_USERSPACE_AUTH, |
2216 | NL80211_MESH_SETUP_USERSPACE_AMPE, | 2234 | NL80211_MESH_SETUP_USERSPACE_AMPE, |
2235 | NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, | ||
2217 | 2236 | ||
2218 | /* keep last */ | 2237 | /* keep last */ |
2219 | __NL80211_MESH_SETUP_ATTR_AFTER_LAST, | 2238 | __NL80211_MESH_SETUP_ATTR_AFTER_LAST, |
@@ -2223,7 +2242,7 @@ enum nl80211_mesh_setup_params { | |||
2223 | /** | 2242 | /** |
2224 | * enum nl80211_txq_attr - TX queue parameter attributes | 2243 | * enum nl80211_txq_attr - TX queue parameter attributes |
2225 | * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved | 2244 | * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved |
2226 | * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*) | 2245 | * @NL80211_TXQ_ATTR_AC: AC identifier (NL80211_AC_*) |
2227 | * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning | 2246 | * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning |
2228 | * disabled | 2247 | * disabled |
2229 | * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form | 2248 | * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form |
@@ -2236,7 +2255,7 @@ enum nl80211_mesh_setup_params { | |||
2236 | */ | 2255 | */ |
2237 | enum nl80211_txq_attr { | 2256 | enum nl80211_txq_attr { |
2238 | __NL80211_TXQ_ATTR_INVALID, | 2257 | __NL80211_TXQ_ATTR_INVALID, |
2239 | NL80211_TXQ_ATTR_QUEUE, | 2258 | NL80211_TXQ_ATTR_AC, |
2240 | NL80211_TXQ_ATTR_TXOP, | 2259 | NL80211_TXQ_ATTR_TXOP, |
2241 | NL80211_TXQ_ATTR_CWMIN, | 2260 | NL80211_TXQ_ATTR_CWMIN, |
2242 | NL80211_TXQ_ATTR_CWMAX, | 2261 | NL80211_TXQ_ATTR_CWMAX, |
@@ -2247,13 +2266,21 @@ enum nl80211_txq_attr { | |||
2247 | NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 | 2266 | NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 |
2248 | }; | 2267 | }; |
2249 | 2268 | ||
2250 | enum nl80211_txq_q { | 2269 | enum nl80211_ac { |
2251 | NL80211_TXQ_Q_VO, | 2270 | NL80211_AC_VO, |
2252 | NL80211_TXQ_Q_VI, | 2271 | NL80211_AC_VI, |
2253 | NL80211_TXQ_Q_BE, | 2272 | NL80211_AC_BE, |
2254 | NL80211_TXQ_Q_BK | 2273 | NL80211_AC_BK, |
2274 | NL80211_NUM_ACS | ||
2255 | }; | 2275 | }; |
2256 | 2276 | ||
2277 | /* backward compat */ | ||
2278 | #define NL80211_TXQ_ATTR_QUEUE NL80211_TXQ_ATTR_AC | ||
2279 | #define NL80211_TXQ_Q_VO NL80211_AC_VO | ||
2280 | #define NL80211_TXQ_Q_VI NL80211_AC_VI | ||
2281 | #define NL80211_TXQ_Q_BE NL80211_AC_BE | ||
2282 | #define NL80211_TXQ_Q_BK NL80211_AC_BK | ||
2283 | |||
2257 | enum nl80211_channel_type { | 2284 | enum nl80211_channel_type { |
2258 | NL80211_CHAN_NO_HT, | 2285 | NL80211_CHAN_NO_HT, |
2259 | NL80211_CHAN_HT20, | 2286 | NL80211_CHAN_HT20, |
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 344b0f972828..d47e523c9d83 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -92,6 +92,7 @@ enum { | |||
92 | HCI_SERVICE_CACHE, | 92 | HCI_SERVICE_CACHE, |
93 | HCI_LINK_KEYS, | 93 | HCI_LINK_KEYS, |
94 | HCI_DEBUG_KEYS, | 94 | HCI_DEBUG_KEYS, |
95 | HCI_UNREGISTER, | ||
95 | 96 | ||
96 | HCI_LE_SCAN, | 97 | HCI_LE_SCAN, |
97 | HCI_SSP_ENABLED, | 98 | HCI_SSP_ENABLED, |
@@ -1327,8 +1328,8 @@ struct sockaddr_hci { | |||
1327 | #define HCI_DEV_NONE 0xffff | 1328 | #define HCI_DEV_NONE 0xffff |
1328 | 1329 | ||
1329 | #define HCI_CHANNEL_RAW 0 | 1330 | #define HCI_CHANNEL_RAW 0 |
1330 | #define HCI_CHANNEL_CONTROL 1 | ||
1331 | #define HCI_CHANNEL_MONITOR 2 | 1331 | #define HCI_CHANNEL_MONITOR 2 |
1332 | #define HCI_CHANNEL_CONTROL 3 | ||
1332 | 1333 | ||
1333 | struct hci_filter { | 1334 | struct hci_filter { |
1334 | unsigned long type_mask; | 1335 | unsigned long type_mask; |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index daefaac51131..6822d2595aff 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -427,7 +427,7 @@ enum { | |||
427 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) | 427 | static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) |
428 | { | 428 | { |
429 | struct hci_dev *hdev = conn->hdev; | 429 | struct hci_dev *hdev = conn->hdev; |
430 | return (test_bit(HCI_SSP_ENABLED, &hdev->flags) && | 430 | return (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && |
431 | test_bit(HCI_CONN_SSP_ENABLED, &conn->flags)); | 431 | test_bit(HCI_CONN_SSP_ENABLED, &conn->flags)); |
432 | } | 432 | } |
433 | 433 | ||
@@ -907,11 +907,13 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, | |||
907 | 907 | ||
908 | static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) | 908 | static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) |
909 | { | 909 | { |
910 | u8 field_len; | 910 | size_t parsed = 0; |
911 | size_t parsed; | ||
912 | 911 | ||
913 | for (parsed = 0; parsed < data_len - 1; parsed += field_len) { | 912 | if (data_len < 2) |
914 | field_len = data[0]; | 913 | return false; |
914 | |||
915 | while (parsed < data_len - 1) { | ||
916 | u8 field_len = data[0]; | ||
915 | 917 | ||
916 | if (field_len == 0) | 918 | if (field_len == 0) |
917 | break; | 919 | break; |
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index ffc1377e092e..ebfd91fc20f8 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h | |||
@@ -117,7 +117,7 @@ struct mgmt_mode { | |||
117 | #define MGMT_OP_SET_DISCOVERABLE 0x0006 | 117 | #define MGMT_OP_SET_DISCOVERABLE 0x0006 |
118 | struct mgmt_cp_set_discoverable { | 118 | struct mgmt_cp_set_discoverable { |
119 | __u8 val; | 119 | __u8 val; |
120 | __u16 timeout; | 120 | __le16 timeout; |
121 | } __packed; | 121 | } __packed; |
122 | #define MGMT_SET_DISCOVERABLE_SIZE 3 | 122 | #define MGMT_SET_DISCOVERABLE_SIZE 3 |
123 | 123 | ||
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 83d800c31e3c..a587867375b2 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -521,6 +521,7 @@ struct station_parameters { | |||
521 | * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled | 521 | * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled |
522 | * @STATION_INFO_STA_FLAGS: @sta_flags filled | 522 | * @STATION_INFO_STA_FLAGS: @sta_flags filled |
523 | * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled | 523 | * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled |
524 | * @STATION_INFO_T_OFFSET: @t_offset filled | ||
524 | */ | 525 | */ |
525 | enum station_info_flags { | 526 | enum station_info_flags { |
526 | STATION_INFO_INACTIVE_TIME = 1<<0, | 527 | STATION_INFO_INACTIVE_TIME = 1<<0, |
@@ -542,7 +543,8 @@ enum station_info_flags { | |||
542 | STATION_INFO_CONNECTED_TIME = 1<<16, | 543 | STATION_INFO_CONNECTED_TIME = 1<<16, |
543 | STATION_INFO_ASSOC_REQ_IES = 1<<17, | 544 | STATION_INFO_ASSOC_REQ_IES = 1<<17, |
544 | STATION_INFO_STA_FLAGS = 1<<18, | 545 | STATION_INFO_STA_FLAGS = 1<<18, |
545 | STATION_INFO_BEACON_LOSS_COUNT = 1<<19 | 546 | STATION_INFO_BEACON_LOSS_COUNT = 1<<19, |
547 | STATION_INFO_T_OFFSET = 1<<20, | ||
546 | }; | 548 | }; |
547 | 549 | ||
548 | /** | 550 | /** |
@@ -643,6 +645,7 @@ struct sta_bss_parameters { | |||
643 | * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets. | 645 | * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets. |
644 | * @sta_flags: station flags mask & values | 646 | * @sta_flags: station flags mask & values |
645 | * @beacon_loss_count: Number of times beacon loss event has triggered. | 647 | * @beacon_loss_count: Number of times beacon loss event has triggered. |
648 | * @t_offset: Time offset of the station relative to this host. | ||
646 | */ | 649 | */ |
647 | struct station_info { | 650 | struct station_info { |
648 | u32 filled; | 651 | u32 filled; |
@@ -671,6 +674,7 @@ struct station_info { | |||
671 | size_t assoc_req_ies_len; | 674 | size_t assoc_req_ies_len; |
672 | 675 | ||
673 | u32 beacon_loss_count; | 676 | u32 beacon_loss_count; |
677 | s64 t_offset; | ||
674 | 678 | ||
675 | /* | 679 | /* |
676 | * Note: Add a new enum station_info_flags value for each new field and | 680 | * Note: Add a new enum station_info_flags value for each new field and |
@@ -798,6 +802,8 @@ struct mesh_config { | |||
798 | /* ttl used in path selection information elements */ | 802 | /* ttl used in path selection information elements */ |
799 | u8 element_ttl; | 803 | u8 element_ttl; |
800 | bool auto_open_plinks; | 804 | bool auto_open_plinks; |
805 | /* neighbor offset synchronization */ | ||
806 | u32 dot11MeshNbrOffsetMaxNeighbor; | ||
801 | /* HWMP parameters */ | 807 | /* HWMP parameters */ |
802 | u8 dot11MeshHWMPmaxPREQretries; | 808 | u8 dot11MeshHWMPmaxPREQretries; |
803 | u32 path_refresh_time; | 809 | u32 path_refresh_time; |
@@ -821,6 +827,7 @@ struct mesh_config { | |||
821 | * struct mesh_setup - 802.11s mesh setup configuration | 827 | * struct mesh_setup - 802.11s mesh setup configuration |
822 | * @mesh_id: the mesh ID | 828 | * @mesh_id: the mesh ID |
823 | * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes | 829 | * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes |
830 | * @sync_method: which synchronization method to use | ||
824 | * @path_sel_proto: which path selection protocol to use | 831 | * @path_sel_proto: which path selection protocol to use |
825 | * @path_metric: which metric to use | 832 | * @path_metric: which metric to use |
826 | * @ie: vendor information elements (optional) | 833 | * @ie: vendor information elements (optional) |
@@ -834,8 +841,9 @@ struct mesh_config { | |||
834 | struct mesh_setup { | 841 | struct mesh_setup { |
835 | const u8 *mesh_id; | 842 | const u8 *mesh_id; |
836 | u8 mesh_id_len; | 843 | u8 mesh_id_len; |
837 | u8 path_sel_proto; | 844 | u8 sync_method; |
838 | u8 path_metric; | 845 | u8 path_sel_proto; |
846 | u8 path_metric; | ||
839 | const u8 *ie; | 847 | const u8 *ie; |
840 | u8 ie_len; | 848 | u8 ie_len; |
841 | bool is_authenticated; | 849 | bool is_authenticated; |
@@ -845,7 +853,7 @@ struct mesh_setup { | |||
845 | 853 | ||
846 | /** | 854 | /** |
847 | * struct ieee80211_txq_params - TX queue parameters | 855 | * struct ieee80211_txq_params - TX queue parameters |
848 | * @queue: TX queue identifier (NL80211_TXQ_Q_*) | 856 | * @ac: AC identifier |
849 | * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled | 857 | * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled |
850 | * @cwmin: Minimum contention window [a value of the form 2^n-1 in the range | 858 | * @cwmin: Minimum contention window [a value of the form 2^n-1 in the range |
851 | * 1..32767] | 859 | * 1..32767] |
@@ -854,7 +862,7 @@ struct mesh_setup { | |||
854 | * @aifs: Arbitration interframe space [0..255] | 862 | * @aifs: Arbitration interframe space [0..255] |
855 | */ | 863 | */ |
856 | struct ieee80211_txq_params { | 864 | struct ieee80211_txq_params { |
857 | enum nl80211_txq_q queue; | 865 | enum nl80211_ac ac; |
858 | u16 txop; | 866 | u16 txop; |
859 | u16 cwmin; | 867 | u16 cwmin; |
860 | u16 cwmax; | 868 | u16 cwmax; |
@@ -1336,6 +1344,9 @@ struct cfg80211_gtk_rekey_data { | |||
1336 | * be %NULL or contain the enabled Wake-on-Wireless triggers that are | 1344 | * be %NULL or contain the enabled Wake-on-Wireless triggers that are |
1337 | * configured for the device. | 1345 | * configured for the device. |
1338 | * @resume: wiphy device needs to be resumed | 1346 | * @resume: wiphy device needs to be resumed |
1347 | * @set_wakeup: Called when WoWLAN is enabled/disabled, use this callback | ||
1348 | * to call device_set_wakeup_enable() to enable/disable wakeup from | ||
1349 | * the device. | ||
1339 | * | 1350 | * |
1340 | * @add_virtual_intf: create a new virtual interface with the given name, | 1351 | * @add_virtual_intf: create a new virtual interface with the given name, |
1341 | * must set the struct wireless_dev's iftype. Beware: You must create | 1352 | * must set the struct wireless_dev's iftype. Beware: You must create |
@@ -1507,6 +1518,7 @@ struct cfg80211_gtk_rekey_data { | |||
1507 | struct cfg80211_ops { | 1518 | struct cfg80211_ops { |
1508 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); | 1519 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); |
1509 | int (*resume)(struct wiphy *wiphy); | 1520 | int (*resume)(struct wiphy *wiphy); |
1521 | void (*set_wakeup)(struct wiphy *wiphy, bool enabled); | ||
1510 | 1522 | ||
1511 | struct net_device * (*add_virtual_intf)(struct wiphy *wiphy, | 1523 | struct net_device * (*add_virtual_intf)(struct wiphy *wiphy, |
1512 | char *name, | 1524 | char *name, |
@@ -3343,6 +3355,17 @@ int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, | |||
3343 | enum nl80211_channel_type channel_type); | 3355 | enum nl80211_channel_type channel_type); |
3344 | 3356 | ||
3345 | /* | 3357 | /* |
3358 | * cfg80211_ch_switch_notify - update wdev channel and notify userspace | ||
3359 | * @dev: the device which switched channels | ||
3360 | * @freq: new channel frequency (in MHz) | ||
3361 | * @type: channel type | ||
3362 | * | ||
3363 | * Acquires wdev_lock, so must only be called from sleepable driver context! | ||
3364 | */ | ||
3365 | void cfg80211_ch_switch_notify(struct net_device *dev, int freq, | ||
3366 | enum nl80211_channel_type type); | ||
3367 | |||
3368 | /* | ||
3346 | * cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units) | 3369 | * cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units) |
3347 | * @rate: given rate_info to calculate bitrate from | 3370 | * @rate: given rate_info to calculate bitrate from |
3348 | * | 3371 | * |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 87d203ff7a8a..32cd5171fa22 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -95,9 +95,11 @@ struct device; | |||
95 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. | 95 | * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. |
96 | */ | 96 | */ |
97 | enum ieee80211_max_queues { | 97 | enum ieee80211_max_queues { |
98 | IEEE80211_MAX_QUEUES = 4, | 98 | IEEE80211_MAX_QUEUES = 16, |
99 | }; | 99 | }; |
100 | 100 | ||
101 | #define IEEE80211_INVAL_HW_QUEUE 0xff | ||
102 | |||
101 | /** | 103 | /** |
102 | * enum ieee80211_ac_numbers - AC numbers as used in mac80211 | 104 | * enum ieee80211_ac_numbers - AC numbers as used in mac80211 |
103 | * @IEEE80211_AC_VO: voice | 105 | * @IEEE80211_AC_VO: voice |
@@ -244,7 +246,7 @@ enum ieee80211_rssi_event { | |||
244 | * @channel_type: Channel type for this BSS -- the hardware might be | 246 | * @channel_type: Channel type for this BSS -- the hardware might be |
245 | * configured for HT40+ while this BSS only uses no-HT, for | 247 | * configured for HT40+ while this BSS only uses no-HT, for |
246 | * example. | 248 | * example. |
247 | * @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info). | 249 | * @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation. |
248 | * This field is only valid when the channel type is one of the HT types. | 250 | * This field is only valid when the channel type is one of the HT types. |
249 | * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value | 251 | * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value |
250 | * implies disabled | 252 | * implies disabled |
@@ -522,7 +524,7 @@ struct ieee80211_tx_rate { | |||
522 | * | 524 | * |
523 | * @flags: transmit info flags, defined above | 525 | * @flags: transmit info flags, defined above |
524 | * @band: the band to transmit on (use for checking for races) | 526 | * @band: the band to transmit on (use for checking for races) |
525 | * @antenna_sel_tx: antenna to use, 0 for automatic diversity | 527 | * @hw_queue: HW queue to put the frame on, skb_get_queue_mapping() gives the AC |
526 | * @ack_frame_id: internal frame ID for TX status, used internally | 528 | * @ack_frame_id: internal frame ID for TX status, used internally |
527 | * @control: union for control data | 529 | * @control: union for control data |
528 | * @status: union for status data | 530 | * @status: union for status data |
@@ -538,7 +540,7 @@ struct ieee80211_tx_info { | |||
538 | u32 flags; | 540 | u32 flags; |
539 | u8 band; | 541 | u8 band; |
540 | 542 | ||
541 | u8 antenna_sel_tx; | 543 | u8 hw_queue; |
542 | 544 | ||
543 | u16 ack_frame_id; | 545 | u16 ack_frame_id; |
544 | 546 | ||
@@ -564,7 +566,8 @@ struct ieee80211_tx_info { | |||
564 | u8 ampdu_ack_len; | 566 | u8 ampdu_ack_len; |
565 | int ack_signal; | 567 | int ack_signal; |
566 | u8 ampdu_len; | 568 | u8 ampdu_len; |
567 | /* 15 bytes free */ | 569 | u8 antenna; |
570 | /* 14 bytes free */ | ||
568 | } status; | 571 | } status; |
569 | struct { | 572 | struct { |
570 | struct ieee80211_tx_rate driver_rates[ | 573 | struct ieee80211_tx_rate driver_rates[ |
@@ -888,6 +891,8 @@ enum ieee80211_vif_flags { | |||
888 | * these need to be set (or cleared) when the interface is added | 891 | * these need to be set (or cleared) when the interface is added |
889 | * or, if supported by the driver, the interface type is changed | 892 | * or, if supported by the driver, the interface type is changed |
890 | * at runtime, mac80211 will never touch this field | 893 | * at runtime, mac80211 will never touch this field |
894 | * @hw_queue: hardware queue for each AC | ||
895 | * @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only | ||
891 | * @drv_priv: data area for driver use, will always be aligned to | 896 | * @drv_priv: data area for driver use, will always be aligned to |
892 | * sizeof(void *). | 897 | * sizeof(void *). |
893 | */ | 898 | */ |
@@ -896,7 +901,12 @@ struct ieee80211_vif { | |||
896 | struct ieee80211_bss_conf bss_conf; | 901 | struct ieee80211_bss_conf bss_conf; |
897 | u8 addr[ETH_ALEN]; | 902 | u8 addr[ETH_ALEN]; |
898 | bool p2p; | 903 | bool p2p; |
904 | |||
905 | u8 cab_queue; | ||
906 | u8 hw_queue[IEEE80211_NUM_ACS]; | ||
907 | |||
899 | u32 driver_flags; | 908 | u32 driver_flags; |
909 | |||
900 | /* must be last */ | 910 | /* must be last */ |
901 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | 911 | u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); |
902 | }; | 912 | }; |
@@ -1174,6 +1184,15 @@ enum sta_notify_cmd { | |||
1174 | * @IEEE80211_HW_SCAN_WHILE_IDLE: The device can do hw scan while | 1184 | * @IEEE80211_HW_SCAN_WHILE_IDLE: The device can do hw scan while |
1175 | * being idle (i.e. mac80211 doesn't have to go idle-off during the | 1185 | * being idle (i.e. mac80211 doesn't have to go idle-off during the |
1176 | * the scan). | 1186 | * the scan). |
1187 | * | ||
1188 | * @IEEE80211_HW_WANT_MONITOR_VIF: The driver would like to be informed of | ||
1189 | * a virtual monitor interface when monitor interfaces are the only | ||
1190 | * active interfaces. | ||
1191 | * | ||
1192 | * @IEEE80211_HW_QUEUE_CONTROL: The driver wants to control per-interface | ||
1193 | * queue mapping in order to use different queues (not just one per AC) | ||
1194 | * for different virtual interfaces. See the doc section on HW queue | ||
1195 | * control for more details. | ||
1177 | */ | 1196 | */ |
1178 | enum ieee80211_hw_flags { | 1197 | enum ieee80211_hw_flags { |
1179 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | 1198 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, |
@@ -1190,13 +1209,13 @@ enum ieee80211_hw_flags { | |||
1190 | IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11, | 1209 | IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11, |
1191 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12, | 1210 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12, |
1192 | IEEE80211_HW_MFP_CAPABLE = 1<<13, | 1211 | IEEE80211_HW_MFP_CAPABLE = 1<<13, |
1193 | /* reuse bit 14 */ | 1212 | IEEE80211_HW_WANT_MONITOR_VIF = 1<<14, |
1194 | IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15, | 1213 | IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15, |
1195 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, | 1214 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, |
1196 | IEEE80211_HW_SUPPORTS_UAPSD = 1<<17, | 1215 | IEEE80211_HW_SUPPORTS_UAPSD = 1<<17, |
1197 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, | 1216 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, |
1198 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, | 1217 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, |
1199 | /* reuse bit 20 */ | 1218 | IEEE80211_HW_QUEUE_CONTROL = 1<<20, |
1200 | IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, | 1219 | IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, |
1201 | IEEE80211_HW_AP_LINK_PS = 1<<22, | 1220 | IEEE80211_HW_AP_LINK_PS = 1<<22, |
1202 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, | 1221 | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, |
@@ -1266,6 +1285,9 @@ enum ieee80211_hw_flags { | |||
1266 | * @max_tx_aggregation_subframes: maximum number of subframes in an | 1285 | * @max_tx_aggregation_subframes: maximum number of subframes in an |
1267 | * aggregate an HT driver will transmit, used by the peer as a | 1286 | * aggregate an HT driver will transmit, used by the peer as a |
1268 | * hint to size its reorder buffer. | 1287 | * hint to size its reorder buffer. |
1288 | * | ||
1289 | * @offchannel_tx_hw_queue: HW queue ID to use for offchannel TX | ||
1290 | * (if %IEEE80211_HW_QUEUE_CONTROL is set) | ||
1269 | */ | 1291 | */ |
1270 | struct ieee80211_hw { | 1292 | struct ieee80211_hw { |
1271 | struct ieee80211_conf conf; | 1293 | struct ieee80211_conf conf; |
@@ -1286,6 +1308,7 @@ struct ieee80211_hw { | |||
1286 | u8 max_rate_tries; | 1308 | u8 max_rate_tries; |
1287 | u8 max_rx_aggregation_subframes; | 1309 | u8 max_rx_aggregation_subframes; |
1288 | u8 max_tx_aggregation_subframes; | 1310 | u8 max_tx_aggregation_subframes; |
1311 | u8 offchannel_tx_hw_queue; | ||
1289 | }; | 1312 | }; |
1290 | 1313 | ||
1291 | /** | 1314 | /** |
@@ -1327,7 +1350,7 @@ static inline struct ieee80211_rate * | |||
1327 | ieee80211_get_tx_rate(const struct ieee80211_hw *hw, | 1350 | ieee80211_get_tx_rate(const struct ieee80211_hw *hw, |
1328 | const struct ieee80211_tx_info *c) | 1351 | const struct ieee80211_tx_info *c) |
1329 | { | 1352 | { |
1330 | if (WARN_ON(c->control.rates[0].idx < 0)) | 1353 | if (WARN_ON_ONCE(c->control.rates[0].idx < 0)) |
1331 | return NULL; | 1354 | return NULL; |
1332 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx]; | 1355 | return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx]; |
1333 | } | 1356 | } |
@@ -1694,6 +1717,61 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
1694 | */ | 1717 | */ |
1695 | 1718 | ||
1696 | /** | 1719 | /** |
1720 | * DOC: HW queue control | ||
1721 | * | ||
1722 | * Before HW queue control was introduced, mac80211 only had a single static | ||
1723 | * assignment of per-interface AC software queues to hardware queues. This | ||
1724 | * was problematic for a few reasons: | ||
1725 | * 1) off-channel transmissions might get stuck behind other frames | ||
1726 | * 2) multiple virtual interfaces couldn't be handled correctly | ||
1727 | * 3) after-DTIM frames could get stuck behind other frames | ||
1728 | * | ||
1729 | * To solve this, hardware typically uses multiple different queues for all | ||
1730 | * the different usages, and this needs to be propagated into mac80211 so it | ||
1731 | * won't have the same problem with the software queues. | ||
1732 | * | ||
1733 | * Therefore, mac80211 now offers the %IEEE80211_HW_QUEUE_CONTROL capability | ||
1734 | * flag that tells it that the driver implements its own queue control. To do | ||
1735 | * so, the driver will set up the various queues in each &struct ieee80211_vif | ||
1736 | * and the offchannel queue in &struct ieee80211_hw. In response, mac80211 will | ||
1737 | * use those queue IDs in the hw_queue field of &struct ieee80211_tx_info and | ||
1738 | * if necessary will queue the frame on the right software queue that mirrors | ||
1739 | * the hardware queue. | ||
1740 | * Additionally, the driver has to then use these HW queue IDs for the queue | ||
1741 | * management functions (ieee80211_stop_queue() et al.) | ||
1742 | * | ||
1743 | * The driver is free to set up the queue mappings as needed, multiple virtual | ||
1744 | * interfaces may map to the same hardware queues if needed. The setup has to | ||
1745 | * happen during add_interface or change_interface callbacks. For example, a | ||
1746 | * driver supporting station+station and station+AP modes might decide to have | ||
1747 | * 10 hardware queues to handle different scenarios: | ||
1748 | * | ||
1749 | * 4 AC HW queues for 1st vif: 0, 1, 2, 3 | ||
1750 | * 4 AC HW queues for 2nd vif: 4, 5, 6, 7 | ||
1751 | * after-DTIM queue for AP: 8 | ||
1752 | * off-channel queue: 9 | ||
1753 | * | ||
1754 | * It would then set up the hardware like this: | ||
1755 | * hw.offchannel_tx_hw_queue = 9 | ||
1756 | * | ||
1757 | * and the first virtual interface that is added as follows: | ||
1758 | * vif.hw_queue[IEEE80211_AC_VO] = 0 | ||
1759 | * vif.hw_queue[IEEE80211_AC_VI] = 1 | ||
1760 | * vif.hw_queue[IEEE80211_AC_BE] = 2 | ||
1761 | * vif.hw_queue[IEEE80211_AC_BK] = 3 | ||
1762 | * vif.cab_queue = 8 // if AP mode, otherwise %IEEE80211_INVAL_HW_QUEUE | ||
1763 | * and the second virtual interface with 4-7. | ||
1764 | * | ||
1765 | * If queue 6 gets full, for example, mac80211 would only stop the second | ||
1766 | * virtual interface's BE queue since virtual interface queues are per AC. | ||
1767 | * | ||
1768 | * Note that the vif.cab_queue value should be set to %IEEE80211_INVAL_HW_QUEUE | ||
1769 | * whenever the queue is not used (i.e. the interface is not in AP mode) if the | ||
1770 | * queue could potentially be shared since mac80211 will look at cab_queue when | ||
1771 | * a queue is stopped/woken even if the interface is not in AP mode. | ||
1772 | */ | ||
1773 | |||
1774 | /** | ||
1697 | * enum ieee80211_filter_flags - hardware filter flags | 1775 | * enum ieee80211_filter_flags - hardware filter flags |
1698 | * | 1776 | * |
1699 | * These flags determine what the filter in hardware should be | 1777 | * These flags determine what the filter in hardware should be |
@@ -1780,6 +1858,18 @@ enum ieee80211_frame_release_type { | |||
1780 | }; | 1858 | }; |
1781 | 1859 | ||
1782 | /** | 1860 | /** |
1861 | * enum ieee80211_rate_control_changed - flags to indicate what changed | ||
1862 | * | ||
1863 | * @IEEE80211_RC_BW_CHANGED: The bandwidth that can be used to transmit | ||
1864 | * to this station changed. | ||
1865 | * @IEEE80211_RC_SMPS_CHANGED: The SMPS state of the station changed. | ||
1866 | */ | ||
1867 | enum ieee80211_rate_control_changed { | ||
1868 | IEEE80211_RC_BW_CHANGED = BIT(0), | ||
1869 | IEEE80211_RC_SMPS_CHANGED = BIT(1), | ||
1870 | }; | ||
1871 | |||
1872 | /** | ||
1783 | * struct ieee80211_ops - callbacks from mac80211 to the driver | 1873 | * struct ieee80211_ops - callbacks from mac80211 to the driver |
1784 | * | 1874 | * |
1785 | * This structure contains various callbacks that the driver may | 1875 | * This structure contains various callbacks that the driver may |
@@ -1980,6 +2070,14 @@ enum ieee80211_frame_release_type { | |||
1980 | * up the list of states. | 2070 | * up the list of states. |
1981 | * The callback can sleep. | 2071 | * The callback can sleep. |
1982 | * | 2072 | * |
2073 | * @sta_rc_update: Notifies the driver of changes to the bitrates that can be | ||
2074 | * used to transmit to the station. The changes are advertised with bits | ||
2075 | * from &enum ieee80211_rate_control_changed and the values are reflected | ||
2076 | * in the station data. This callback should only be used when the driver | ||
2077 | * uses hardware rate control (%IEEE80211_HW_HAS_RATE_CONTROL) since | ||
2078 | * otherwise the rate control algorithm is notified directly. | ||
2079 | * Must be atomic. | ||
2080 | * | ||
1983 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), | 2081 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), |
1984 | * bursting) for a hardware TX queue. | 2082 | * bursting) for a hardware TX queue. |
1985 | * Returns a negative error code on failure. | 2083 | * Returns a negative error code on failure. |
@@ -2135,6 +2233,7 @@ struct ieee80211_ops { | |||
2135 | #ifdef CONFIG_PM | 2233 | #ifdef CONFIG_PM |
2136 | int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); | 2234 | int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); |
2137 | int (*resume)(struct ieee80211_hw *hw); | 2235 | int (*resume)(struct ieee80211_hw *hw); |
2236 | void (*set_wakeup)(struct ieee80211_hw *hw, bool enabled); | ||
2138 | #endif | 2237 | #endif |
2139 | int (*add_interface)(struct ieee80211_hw *hw, | 2238 | int (*add_interface)(struct ieee80211_hw *hw, |
2140 | struct ieee80211_vif *vif); | 2239 | struct ieee80211_vif *vif); |
@@ -2196,8 +2295,12 @@ struct ieee80211_ops { | |||
2196 | struct ieee80211_sta *sta, | 2295 | struct ieee80211_sta *sta, |
2197 | enum ieee80211_sta_state old_state, | 2296 | enum ieee80211_sta_state old_state, |
2198 | enum ieee80211_sta_state new_state); | 2297 | enum ieee80211_sta_state new_state); |
2298 | void (*sta_rc_update)(struct ieee80211_hw *hw, | ||
2299 | struct ieee80211_vif *vif, | ||
2300 | struct ieee80211_sta *sta, | ||
2301 | u32 changed); | ||
2199 | int (*conf_tx)(struct ieee80211_hw *hw, | 2302 | int (*conf_tx)(struct ieee80211_hw *hw, |
2200 | struct ieee80211_vif *vif, u16 queue, | 2303 | struct ieee80211_vif *vif, u16 ac, |
2201 | const struct ieee80211_tx_queue_params *params); | 2304 | const struct ieee80211_tx_queue_params *params); |
2202 | u64 (*get_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | 2305 | u64 (*get_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
2203 | void (*set_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2306 | void (*set_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
@@ -3512,19 +3615,6 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn); | |||
3512 | /* Rate control API */ | 3615 | /* Rate control API */ |
3513 | 3616 | ||
3514 | /** | 3617 | /** |
3515 | * enum rate_control_changed - flags to indicate which parameter changed | ||
3516 | * | ||
3517 | * @IEEE80211_RC_HT_CHANGED: The HT parameters of the operating channel have | ||
3518 | * changed, rate control algorithm can update its internal state if needed. | ||
3519 | * @IEEE80211_RC_SMPS_CHANGED: The SMPS state of the station changed, the rate | ||
3520 | * control algorithm needs to adjust accordingly. | ||
3521 | */ | ||
3522 | enum rate_control_changed { | ||
3523 | IEEE80211_RC_HT_CHANGED = BIT(0), | ||
3524 | IEEE80211_RC_SMPS_CHANGED = BIT(1), | ||
3525 | }; | ||
3526 | |||
3527 | /** | ||
3528 | * struct ieee80211_tx_rate_control - rate control information for/from RC algo | 3618 | * struct ieee80211_tx_rate_control - rate control information for/from RC algo |
3529 | * | 3619 | * |
3530 | * @hw: The hardware the algorithm is invoked for. | 3620 | * @hw: The hardware the algorithm is invoked for. |
@@ -3569,9 +3659,8 @@ struct rate_control_ops { | |||
3569 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, | 3659 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, |
3570 | struct ieee80211_sta *sta, void *priv_sta); | 3660 | struct ieee80211_sta *sta, void *priv_sta); |
3571 | void (*rate_update)(void *priv, struct ieee80211_supported_band *sband, | 3661 | void (*rate_update)(void *priv, struct ieee80211_supported_band *sband, |
3572 | struct ieee80211_sta *sta, | 3662 | struct ieee80211_sta *sta, void *priv_sta, |
3573 | void *priv_sta, u32 changed, | 3663 | u32 changed); |
3574 | enum nl80211_channel_type oper_chan_type); | ||
3575 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, | 3664 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, |
3576 | void *priv_sta); | 3665 | void *priv_sta); |
3577 | 3666 | ||
@@ -3706,8 +3795,9 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, | |||
3706 | 3795 | ||
3707 | void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); | 3796 | void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); |
3708 | 3797 | ||
3709 | int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb); | 3798 | int ieee80211_add_srates_ie(struct ieee80211_vif *vif, |
3799 | struct sk_buff *skb, bool need_basic); | ||
3710 | 3800 | ||
3711 | int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, | 3801 | int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, |
3712 | struct sk_buff *skb); | 3802 | struct sk_buff *skb, bool need_basic); |
3713 | #endif /* MAC80211_H */ | 3803 | #endif /* MAC80211_H */ |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index e33af63a884a..92a857e3786d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -665,6 +665,11 @@ int hci_dev_open(__u16 dev) | |||
665 | 665 | ||
666 | hci_req_lock(hdev); | 666 | hci_req_lock(hdev); |
667 | 667 | ||
668 | if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) { | ||
669 | ret = -ENODEV; | ||
670 | goto done; | ||
671 | } | ||
672 | |||
668 | if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) { | 673 | if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) { |
669 | ret = -ERFKILL; | 674 | ret = -ERFKILL; |
670 | goto done; | 675 | goto done; |
@@ -1849,6 +1854,8 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
1849 | 1854 | ||
1850 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); | 1855 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); |
1851 | 1856 | ||
1857 | set_bit(HCI_UNREGISTER, &hdev->dev_flags); | ||
1858 | |||
1852 | write_lock(&hci_dev_list_lock); | 1859 | write_lock(&hci_dev_list_lock); |
1853 | list_del(&hdev->list); | 1860 | list_del(&hdev->list); |
1854 | write_unlock(&hci_dev_list_lock); | 1861 | write_unlock(&hci_dev_list_lock); |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b8e17e4dac8b..94552b33d528 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -1308,6 +1308,7 @@ static void l2cap_monitor_timeout(struct work_struct *work) | |||
1308 | if (chan->retry_count >= chan->remote_max_tx) { | 1308 | if (chan->retry_count >= chan->remote_max_tx) { |
1309 | l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); | 1309 | l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED); |
1310 | l2cap_chan_unlock(chan); | 1310 | l2cap_chan_unlock(chan); |
1311 | l2cap_chan_put(chan); | ||
1311 | return; | 1312 | return; |
1312 | } | 1313 | } |
1313 | 1314 | ||
@@ -1316,6 +1317,7 @@ static void l2cap_monitor_timeout(struct work_struct *work) | |||
1316 | 1317 | ||
1317 | l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); | 1318 | l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); |
1318 | l2cap_chan_unlock(chan); | 1319 | l2cap_chan_unlock(chan); |
1320 | l2cap_chan_put(chan); | ||
1319 | } | 1321 | } |
1320 | 1322 | ||
1321 | static void l2cap_retrans_timeout(struct work_struct *work) | 1323 | static void l2cap_retrans_timeout(struct work_struct *work) |
@@ -1335,6 +1337,7 @@ static void l2cap_retrans_timeout(struct work_struct *work) | |||
1335 | l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); | 1337 | l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL); |
1336 | 1338 | ||
1337 | l2cap_chan_unlock(chan); | 1339 | l2cap_chan_unlock(chan); |
1340 | l2cap_chan_put(chan); | ||
1338 | } | 1341 | } |
1339 | 1342 | ||
1340 | static void l2cap_drop_acked_frames(struct l2cap_chan *chan) | 1343 | static void l2cap_drop_acked_frames(struct l2cap_chan *chan) |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index c4fe583b0af6..29122ed28ea9 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -82,7 +82,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
82 | } | 82 | } |
83 | 83 | ||
84 | if (la.l2_cid) | 84 | if (la.l2_cid) |
85 | err = l2cap_add_scid(chan, la.l2_cid); | 85 | err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid)); |
86 | else | 86 | else |
87 | err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm); | 87 | err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm); |
88 | 88 | ||
@@ -123,7 +123,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
123 | if (la.l2_cid && la.l2_psm) | 123 | if (la.l2_cid && la.l2_psm) |
124 | return -EINVAL; | 124 | return -EINVAL; |
125 | 125 | ||
126 | err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr); | 126 | err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), |
127 | &la.l2_bdaddr); | ||
127 | if (err) | 128 | if (err) |
128 | return err; | 129 | return err; |
129 | 130 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7fcff8887131..4ef275c69675 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -2523,13 +2523,18 @@ static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev, | |||
2523 | 2523 | ||
2524 | if (cp->val) { | 2524 | if (cp->val) { |
2525 | type = PAGE_SCAN_TYPE_INTERLACED; | 2525 | type = PAGE_SCAN_TYPE_INTERLACED; |
2526 | acp.interval = 0x0024; /* 22.5 msec page scan interval */ | 2526 | |
2527 | /* 22.5 msec page scan interval */ | ||
2528 | acp.interval = __constant_cpu_to_le16(0x0024); | ||
2527 | } else { | 2529 | } else { |
2528 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | 2530 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ |
2529 | acp.interval = 0x0800; /* default 1.28 sec page scan */ | 2531 | |
2532 | /* default 1.28 sec page scan */ | ||
2533 | acp.interval = __constant_cpu_to_le16(0x0800); | ||
2530 | } | 2534 | } |
2531 | 2535 | ||
2532 | acp.window = 0x0012; /* default 11.25 msec page scan window */ | 2536 | /* default 11.25 msec page scan window */ |
2537 | acp.window = __constant_cpu_to_le16(0x0012); | ||
2533 | 2538 | ||
2534 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), | 2539 | err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), |
2535 | &acp); | 2540 | &acp); |
@@ -2936,7 +2941,7 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
2936 | name, name_len); | 2941 | name, name_len); |
2937 | 2942 | ||
2938 | if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0) | 2943 | if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0) |
2939 | eir_len = eir_append_data(&ev->eir[eir_len], eir_len, | 2944 | eir_len = eir_append_data(ev->eir, eir_len, |
2940 | EIR_CLASS_OF_DEV, dev_class, 3); | 2945 | EIR_CLASS_OF_DEV, dev_class, 3); |
2941 | 2946 | ||
2942 | put_unaligned_le16(eir_len, &ev->eir_len); | 2947 | put_unaligned_le16(eir_len, &ev->eir_len); |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 96ddb72760b9..8d249d705980 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -225,6 +225,17 @@ config MAC80211_VERBOSE_MHWMP_DEBUG | |||
225 | 225 | ||
226 | Do not select this option. | 226 | Do not select this option. |
227 | 227 | ||
228 | config MAC80211_VERBOSE_MESH_SYNC_DEBUG | ||
229 | bool "Verbose mesh mesh synchronization debugging" | ||
230 | depends on MAC80211_DEBUG_MENU | ||
231 | depends on MAC80211_MESH | ||
232 | ---help--- | ||
233 | Selecting this option causes mac80211 to print out very verbose mesh | ||
234 | synchronization debugging messages (when mac80211 is taking part in a | ||
235 | mesh network). | ||
236 | |||
237 | Do not select this option. | ||
238 | |||
228 | config MAC80211_VERBOSE_TDLS_DEBUG | 239 | config MAC80211_VERBOSE_TDLS_DEBUG |
229 | bool "Verbose TDLS debugging" | 240 | bool "Verbose TDLS debugging" |
230 | depends on MAC80211_DEBUG_MENU | 241 | depends on MAC80211_DEBUG_MENU |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 1be7a454aa77..3e9d931bba35 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -38,7 +38,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ | |||
38 | mesh.o \ | 38 | mesh.o \ |
39 | mesh_pathtbl.o \ | 39 | mesh_pathtbl.o \ |
40 | mesh_plink.o \ | 40 | mesh_plink.o \ |
41 | mesh_hwmp.o | 41 | mesh_hwmp.o \ |
42 | mesh_sync.o | ||
42 | 43 | ||
43 | mac80211-$(CONFIG_PM) += pm.o | 44 | mac80211-$(CONFIG_PM) += pm.o |
44 | 45 | ||
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 64d3ce5ea1a0..a070d4f460ea 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -142,6 +142,18 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
142 | u8 *timer_to_id = ptid - *ptid; | 142 | u8 *timer_to_id = ptid - *ptid; |
143 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | 143 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, |
144 | timer_to_tid[0]); | 144 | timer_to_tid[0]); |
145 | struct tid_ampdu_rx *tid_rx; | ||
146 | unsigned long timeout; | ||
147 | |||
148 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]); | ||
149 | if (!tid_rx) | ||
150 | return; | ||
151 | |||
152 | timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout); | ||
153 | if (time_is_after_jiffies(timeout)) { | ||
154 | mod_timer(&tid_rx->session_timer, timeout); | ||
155 | return; | ||
156 | } | ||
145 | 157 | ||
146 | #ifdef CONFIG_MAC80211_HT_DEBUG | 158 | #ifdef CONFIG_MAC80211_HT_DEBUG |
147 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 159 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
@@ -291,7 +303,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
291 | /* rx timer */ | 303 | /* rx timer */ |
292 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; | 304 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; |
293 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 305 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
294 | init_timer(&tid_agg_rx->session_timer); | 306 | init_timer_deferrable(&tid_agg_rx->session_timer); |
295 | 307 | ||
296 | /* rx reorder timer */ | 308 | /* rx reorder timer */ |
297 | tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; | 309 | tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; |
@@ -335,8 +347,10 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
335 | /* activate it for RX */ | 347 | /* activate it for RX */ |
336 | rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); | 348 | rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx); |
337 | 349 | ||
338 | if (timeout) | 350 | if (timeout) { |
339 | mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); | 351 | mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout)); |
352 | tid_agg_rx->last_rx = jiffies; | ||
353 | } | ||
340 | 354 | ||
341 | end: | 355 | end: |
342 | mutex_unlock(&sta->ampdu_mlme.mtx); | 356 | mutex_unlock(&sta->ampdu_mlme.mtx); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 76be61744198..5b7053c58732 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -286,25 +286,25 @@ static inline int ieee80211_ac_from_tid(int tid) | |||
286 | * a global "agg_queue_stop" refcount. | 286 | * a global "agg_queue_stop" refcount. |
287 | */ | 287 | */ |
288 | static void __acquires(agg_queue) | 288 | static void __acquires(agg_queue) |
289 | ieee80211_stop_queue_agg(struct ieee80211_local *local, int tid) | 289 | ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) |
290 | { | 290 | { |
291 | int queue = ieee80211_ac_from_tid(tid); | 291 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; |
292 | 292 | ||
293 | if (atomic_inc_return(&local->agg_queue_stop[queue]) == 1) | 293 | if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1) |
294 | ieee80211_stop_queue_by_reason( | 294 | ieee80211_stop_queue_by_reason( |
295 | &local->hw, queue, | 295 | &sdata->local->hw, queue, |
296 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | 296 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); |
297 | __acquire(agg_queue); | 297 | __acquire(agg_queue); |
298 | } | 298 | } |
299 | 299 | ||
300 | static void __releases(agg_queue) | 300 | static void __releases(agg_queue) |
301 | ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | 301 | ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) |
302 | { | 302 | { |
303 | int queue = ieee80211_ac_from_tid(tid); | 303 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; |
304 | 304 | ||
305 | if (atomic_dec_return(&local->agg_queue_stop[queue]) == 0) | 305 | if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0) |
306 | ieee80211_wake_queue_by_reason( | 306 | ieee80211_wake_queue_by_reason( |
307 | &local->hw, queue, | 307 | &sdata->local->hw, queue, |
308 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | 308 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); |
309 | __release(agg_queue); | 309 | __release(agg_queue); |
310 | } | 310 | } |
@@ -314,13 +314,14 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | |||
314 | * requires a call to ieee80211_agg_splice_finish later | 314 | * requires a call to ieee80211_agg_splice_finish later |
315 | */ | 315 | */ |
316 | static void __acquires(agg_queue) | 316 | static void __acquires(agg_queue) |
317 | ieee80211_agg_splice_packets(struct ieee80211_local *local, | 317 | ieee80211_agg_splice_packets(struct ieee80211_sub_if_data *sdata, |
318 | struct tid_ampdu_tx *tid_tx, u16 tid) | 318 | struct tid_ampdu_tx *tid_tx, u16 tid) |
319 | { | 319 | { |
320 | int queue = ieee80211_ac_from_tid(tid); | 320 | struct ieee80211_local *local = sdata->local; |
321 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; | ||
321 | unsigned long flags; | 322 | unsigned long flags; |
322 | 323 | ||
323 | ieee80211_stop_queue_agg(local, tid); | 324 | ieee80211_stop_queue_agg(sdata, tid); |
324 | 325 | ||
325 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" | 326 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" |
326 | " from the pending queue\n", tid)) | 327 | " from the pending queue\n", tid)) |
@@ -336,9 +337,9 @@ ieee80211_agg_splice_packets(struct ieee80211_local *local, | |||
336 | } | 337 | } |
337 | 338 | ||
338 | static void __releases(agg_queue) | 339 | static void __releases(agg_queue) |
339 | ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | 340 | ieee80211_agg_splice_finish(struct ieee80211_sub_if_data *sdata, u16 tid) |
340 | { | 341 | { |
341 | ieee80211_wake_queue_agg(local, tid); | 342 | ieee80211_wake_queue_agg(sdata, tid); |
342 | } | 343 | } |
343 | 344 | ||
344 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | 345 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
@@ -376,9 +377,9 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
376 | " tid %d\n", tid); | 377 | " tid %d\n", tid); |
377 | #endif | 378 | #endif |
378 | spin_lock_bh(&sta->lock); | 379 | spin_lock_bh(&sta->lock); |
379 | ieee80211_agg_splice_packets(local, tid_tx, tid); | 380 | ieee80211_agg_splice_packets(sdata, tid_tx, tid); |
380 | ieee80211_assign_tid_tx(sta, tid, NULL); | 381 | ieee80211_assign_tid_tx(sta, tid, NULL); |
381 | ieee80211_agg_splice_finish(local, tid); | 382 | ieee80211_agg_splice_finish(sdata, tid); |
382 | spin_unlock_bh(&sta->lock); | 383 | spin_unlock_bh(&sta->lock); |
383 | 384 | ||
384 | kfree_rcu(tid_tx, rcu_head); | 385 | kfree_rcu(tid_tx, rcu_head); |
@@ -417,6 +418,18 @@ static void sta_tx_agg_session_timer_expired(unsigned long data) | |||
417 | u8 *timer_to_id = ptid - *ptid; | 418 | u8 *timer_to_id = ptid - *ptid; |
418 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | 419 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, |
419 | timer_to_tid[0]); | 420 | timer_to_tid[0]); |
421 | struct tid_ampdu_tx *tid_tx; | ||
422 | unsigned long timeout; | ||
423 | |||
424 | tid_tx = rcu_dereference_protected_tid_tx(sta, *ptid); | ||
425 | if (!tid_tx) | ||
426 | return; | ||
427 | |||
428 | timeout = tid_tx->last_tx + TU_TO_JIFFIES(tid_tx->timeout); | ||
429 | if (time_is_after_jiffies(timeout)) { | ||
430 | mod_timer(&tid_tx->session_timer, timeout); | ||
431 | return; | ||
432 | } | ||
420 | 433 | ||
421 | #ifdef CONFIG_MAC80211_HT_DEBUG | 434 | #ifdef CONFIG_MAC80211_HT_DEBUG |
422 | printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); | 435 | printk(KERN_DEBUG "tx session timer expired on tid %d\n", (u16)*ptid); |
@@ -542,7 +555,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
542 | /* tx timer */ | 555 | /* tx timer */ |
543 | tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; | 556 | tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; |
544 | tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 557 | tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; |
545 | init_timer(&tid_tx->session_timer); | 558 | init_timer_deferrable(&tid_tx->session_timer); |
546 | 559 | ||
547 | /* assign a dialog token */ | 560 | /* assign a dialog token */ |
548 | sta->ampdu_mlme.dialog_token_allocator++; | 561 | sta->ampdu_mlme.dialog_token_allocator++; |
@@ -586,14 +599,14 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
586 | */ | 599 | */ |
587 | spin_lock_bh(&sta->lock); | 600 | spin_lock_bh(&sta->lock); |
588 | 601 | ||
589 | ieee80211_agg_splice_packets(local, tid_tx, tid); | 602 | ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid); |
590 | /* | 603 | /* |
591 | * Now mark as operational. This will be visible | 604 | * Now mark as operational. This will be visible |
592 | * in the TX path, and lets it go lock-free in | 605 | * in the TX path, and lets it go lock-free in |
593 | * the common case. | 606 | * the common case. |
594 | */ | 607 | */ |
595 | set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); | 608 | set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); |
596 | ieee80211_agg_splice_finish(local, tid); | 609 | ieee80211_agg_splice_finish(sta->sdata, tid); |
597 | 610 | ||
598 | spin_unlock_bh(&sta->lock); | 611 | spin_unlock_bh(&sta->lock); |
599 | } | 612 | } |
@@ -778,12 +791,12 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
778 | * more. | 791 | * more. |
779 | */ | 792 | */ |
780 | 793 | ||
781 | ieee80211_agg_splice_packets(local, tid_tx, tid); | 794 | ieee80211_agg_splice_packets(sta->sdata, tid_tx, tid); |
782 | 795 | ||
783 | /* future packets must not find the tid_tx struct any more */ | 796 | /* future packets must not find the tid_tx struct any more */ |
784 | ieee80211_assign_tid_tx(sta, tid, NULL); | 797 | ieee80211_assign_tid_tx(sta, tid, NULL); |
785 | 798 | ||
786 | ieee80211_agg_splice_finish(local, tid); | 799 | ieee80211_agg_splice_finish(sta->sdata, tid); |
787 | 800 | ||
788 | kfree_rcu(tid_tx, rcu_head); | 801 | kfree_rcu(tid_tx, rcu_head); |
789 | 802 | ||
@@ -884,9 +897,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
884 | 897 | ||
885 | sta->ampdu_mlme.addba_req_num[tid] = 0; | 898 | sta->ampdu_mlme.addba_req_num[tid] = 0; |
886 | 899 | ||
887 | if (tid_tx->timeout) | 900 | if (tid_tx->timeout) { |
888 | mod_timer(&tid_tx->session_timer, | 901 | mod_timer(&tid_tx->session_timer, |
889 | TU_TO_EXP_TIME(tid_tx->timeout)); | 902 | TU_TO_EXP_TIME(tid_tx->timeout)); |
903 | tid_tx->last_tx = jiffies; | ||
904 | } | ||
890 | 905 | ||
891 | } else { | 906 | } else { |
892 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, | 907 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR, |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 677d65929780..355735491252 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -412,6 +412,10 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
412 | sinfo->llid = le16_to_cpu(sta->llid); | 412 | sinfo->llid = le16_to_cpu(sta->llid); |
413 | sinfo->plid = le16_to_cpu(sta->plid); | 413 | sinfo->plid = le16_to_cpu(sta->plid); |
414 | sinfo->plink_state = sta->plink_state; | 414 | sinfo->plink_state = sta->plink_state; |
415 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | ||
416 | sinfo->filled |= STATION_INFO_T_OFFSET; | ||
417 | sinfo->t_offset = sta->t_offset; | ||
418 | } | ||
415 | #endif | 419 | #endif |
416 | } | 420 | } |
417 | 421 | ||
@@ -640,6 +644,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
640 | 644 | ||
641 | ieee80211_bss_info_change_notify(sdata, changed); | 645 | ieee80211_bss_info_change_notify(sdata, changed); |
642 | 646 | ||
647 | netif_carrier_on(dev); | ||
648 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
649 | netif_carrier_on(vlan->dev); | ||
650 | |||
643 | return 0; | 651 | return 0; |
644 | } | 652 | } |
645 | 653 | ||
@@ -665,7 +673,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
665 | 673 | ||
666 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | 674 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) |
667 | { | 675 | { |
668 | struct ieee80211_sub_if_data *sdata; | 676 | struct ieee80211_sub_if_data *sdata, *vlan; |
669 | struct beacon_data *old; | 677 | struct beacon_data *old; |
670 | 678 | ||
671 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 679 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -674,6 +682,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
674 | if (!old) | 682 | if (!old) |
675 | return -ENOENT; | 683 | return -ENOENT; |
676 | 684 | ||
685 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
686 | netif_carrier_off(vlan->dev); | ||
687 | netif_carrier_off(dev); | ||
688 | |||
677 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); | 689 | RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); |
678 | 690 | ||
679 | kfree_rcu(old, rcu_head); | 691 | kfree_rcu(old, rcu_head); |
@@ -1235,6 +1247,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1235 | /* now copy the rest of the setup parameters */ | 1247 | /* now copy the rest of the setup parameters */ |
1236 | ifmsh->mesh_id_len = setup->mesh_id_len; | 1248 | ifmsh->mesh_id_len = setup->mesh_id_len; |
1237 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | 1249 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); |
1250 | ifmsh->mesh_sp_id = setup->sync_method; | ||
1238 | ifmsh->mesh_pp_id = setup->path_sel_proto; | 1251 | ifmsh->mesh_pp_id = setup->path_sel_proto; |
1239 | ifmsh->mesh_pm_id = setup->path_metric; | 1252 | ifmsh->mesh_pm_id = setup->path_metric; |
1240 | ifmsh->security = IEEE80211_MESH_SEC_NONE; | 1253 | ifmsh->security = IEEE80211_MESH_SEC_NONE; |
@@ -1279,6 +1292,9 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, | |||
1279 | conf->dot11MeshTTL = nconf->element_ttl; | 1292 | conf->dot11MeshTTL = nconf->element_ttl; |
1280 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) | 1293 | if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) |
1281 | conf->auto_open_plinks = nconf->auto_open_plinks; | 1294 | conf->auto_open_plinks = nconf->auto_open_plinks; |
1295 | if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask)) | ||
1296 | conf->dot11MeshNbrOffsetMaxNeighbor = | ||
1297 | nconf->dot11MeshNbrOffsetMaxNeighbor; | ||
1282 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) | 1298 | if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask)) |
1283 | conf->dot11MeshHWMPmaxPREQretries = | 1299 | conf->dot11MeshHWMPmaxPREQretries = |
1284 | nconf->dot11MeshHWMPmaxPREQretries; | 1300 | nconf->dot11MeshHWMPmaxPREQretries; |
@@ -1437,6 +1453,9 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1437 | if (!local->ops->conf_tx) | 1453 | if (!local->ops->conf_tx) |
1438 | return -EOPNOTSUPP; | 1454 | return -EOPNOTSUPP; |
1439 | 1455 | ||
1456 | if (local->hw.queues < IEEE80211_NUM_ACS) | ||
1457 | return -EOPNOTSUPP; | ||
1458 | |||
1440 | memset(&p, 0, sizeof(p)); | 1459 | memset(&p, 0, sizeof(p)); |
1441 | p.aifs = params->aifs; | 1460 | p.aifs = params->aifs; |
1442 | p.cw_max = params->cwmax; | 1461 | p.cw_max = params->cwmax; |
@@ -1449,14 +1468,11 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1449 | */ | 1468 | */ |
1450 | p.uapsd = false; | 1469 | p.uapsd = false; |
1451 | 1470 | ||
1452 | if (params->queue >= local->hw.queues) | 1471 | sdata->tx_conf[params->ac] = p; |
1453 | return -EINVAL; | 1472 | if (drv_conf_tx(local, sdata, params->ac, &p)) { |
1454 | |||
1455 | sdata->tx_conf[params->queue] = p; | ||
1456 | if (drv_conf_tx(local, sdata, params->queue, &p)) { | ||
1457 | wiphy_debug(local->hw.wiphy, | 1473 | wiphy_debug(local->hw.wiphy, |
1458 | "failed to set TX queue parameters for queue %d\n", | 1474 | "failed to set TX queue parameters for AC %d\n", |
1459 | params->queue); | 1475 | params->ac); |
1460 | return -EINVAL; | 1476 | return -EINVAL; |
1461 | } | 1477 | } |
1462 | 1478 | ||
@@ -2090,6 +2106,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2090 | 2106 | ||
2091 | IEEE80211_SKB_CB(skb)->flags = flags; | 2107 | IEEE80211_SKB_CB(skb)->flags = flags; |
2092 | 2108 | ||
2109 | if (flags & IEEE80211_TX_CTL_TX_OFFCHAN) | ||
2110 | IEEE80211_SKB_CB(skb)->hw_queue = | ||
2111 | local->hw.offchannel_tx_hw_queue; | ||
2112 | |||
2093 | skb->dev = sdata->dev; | 2113 | skb->dev = sdata->dev; |
2094 | 2114 | ||
2095 | *cookie = (unsigned long) skb; | 2115 | *cookie = (unsigned long) skb; |
@@ -2131,6 +2151,8 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
2131 | /* modify cookie to prevent API mismatches */ | 2151 | /* modify cookie to prevent API mismatches */ |
2132 | *cookie ^= 2; | 2152 | *cookie ^= 2; |
2133 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; | 2153 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; |
2154 | IEEE80211_SKB_CB(skb)->hw_queue = | ||
2155 | local->hw.offchannel_tx_hw_queue; | ||
2134 | local->hw_roc_skb = skb; | 2156 | local->hw_roc_skb = skb; |
2135 | local->hw_roc_skb_for_status = skb; | 2157 | local->hw_roc_skb_for_status = skb; |
2136 | mutex_unlock(&local->mtx); | 2158 | mutex_unlock(&local->mtx); |
@@ -2350,8 +2372,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2350 | tf->u.setup_req.capability = | 2372 | tf->u.setup_req.capability = |
2351 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2373 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2352 | 2374 | ||
2353 | ieee80211_add_srates_ie(&sdata->vif, skb); | 2375 | ieee80211_add_srates_ie(&sdata->vif, skb, false); |
2354 | ieee80211_add_ext_srates_ie(&sdata->vif, skb); | 2376 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); |
2355 | ieee80211_tdls_add_ext_capab(skb); | 2377 | ieee80211_tdls_add_ext_capab(skb); |
2356 | break; | 2378 | break; |
2357 | case WLAN_TDLS_SETUP_RESPONSE: | 2379 | case WLAN_TDLS_SETUP_RESPONSE: |
@@ -2364,8 +2386,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2364 | tf->u.setup_resp.capability = | 2386 | tf->u.setup_resp.capability = |
2365 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2387 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2366 | 2388 | ||
2367 | ieee80211_add_srates_ie(&sdata->vif, skb); | 2389 | ieee80211_add_srates_ie(&sdata->vif, skb, false); |
2368 | ieee80211_add_ext_srates_ie(&sdata->vif, skb); | 2390 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); |
2369 | ieee80211_tdls_add_ext_capab(skb); | 2391 | ieee80211_tdls_add_ext_capab(skb); |
2370 | break; | 2392 | break; |
2371 | case WLAN_TDLS_SETUP_CONFIRM: | 2393 | case WLAN_TDLS_SETUP_CONFIRM: |
@@ -2425,8 +2447,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2425 | mgmt->u.action.u.tdls_discover_resp.capability = | 2447 | mgmt->u.action.u.tdls_discover_resp.capability = |
2426 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2448 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2427 | 2449 | ||
2428 | ieee80211_add_srates_ie(&sdata->vif, skb); | 2450 | ieee80211_add_srates_ie(&sdata->vif, skb, false); |
2429 | ieee80211_add_ext_srates_ie(&sdata->vif, skb); | 2451 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, false); |
2430 | ieee80211_tdls_add_ext_capab(skb); | 2452 | ieee80211_tdls_add_ext_capab(skb); |
2431 | break; | 2453 | break; |
2432 | default: | 2454 | default: |
@@ -2673,6 +2695,13 @@ ieee80211_wiphy_get_channel(struct wiphy *wiphy) | |||
2673 | return local->oper_channel; | 2695 | return local->oper_channel; |
2674 | } | 2696 | } |
2675 | 2697 | ||
2698 | #ifdef CONFIG_PM | ||
2699 | static void ieee80211_set_wakeup(struct wiphy *wiphy, bool enabled) | ||
2700 | { | ||
2701 | drv_set_wakeup(wiphy_priv(wiphy), enabled); | ||
2702 | } | ||
2703 | #endif | ||
2704 | |||
2676 | struct cfg80211_ops mac80211_config_ops = { | 2705 | struct cfg80211_ops mac80211_config_ops = { |
2677 | .add_virtual_intf = ieee80211_add_iface, | 2706 | .add_virtual_intf = ieee80211_add_iface, |
2678 | .del_virtual_intf = ieee80211_del_iface, | 2707 | .del_virtual_intf = ieee80211_del_iface, |
@@ -2741,4 +2770,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2741 | .probe_client = ieee80211_probe_client, | 2770 | .probe_client = ieee80211_probe_client, |
2742 | .get_channel = ieee80211_wiphy_get_channel, | 2771 | .get_channel = ieee80211_wiphy_get_channel, |
2743 | .set_noack_map = ieee80211_set_noack_map, | 2772 | .set_noack_map = ieee80211_set_noack_map, |
2773 | #ifdef CONFIG_PM | ||
2774 | .set_wakeup = ieee80211_set_wakeup, | ||
2775 | #endif | ||
2744 | }; | 2776 | }; |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index e00ce8c3e28e..c76cf7230c7d 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -135,29 +135,3 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
135 | 135 | ||
136 | return result; | 136 | return result; |
137 | } | 137 | } |
138 | |||
139 | /* | ||
140 | * ieee80211_get_tx_channel_type returns the channel type we should | ||
141 | * use for packet transmission, given the channel capability and | ||
142 | * whatever regulatory flags we have been given. | ||
143 | */ | ||
144 | enum nl80211_channel_type ieee80211_get_tx_channel_type( | ||
145 | struct ieee80211_local *local, | ||
146 | enum nl80211_channel_type channel_type) | ||
147 | { | ||
148 | switch (channel_type) { | ||
149 | case NL80211_CHAN_HT40PLUS: | ||
150 | if (local->hw.conf.channel->flags & | ||
151 | IEEE80211_CHAN_NO_HT40PLUS) | ||
152 | return NL80211_CHAN_HT20; | ||
153 | break; | ||
154 | case NL80211_CHAN_HT40MINUS: | ||
155 | if (local->hw.conf.channel->flags & | ||
156 | IEEE80211_CHAN_NO_HT40MINUS) | ||
157 | return NL80211_CHAN_HT20; | ||
158 | break; | ||
159 | default: | ||
160 | break; | ||
161 | } | ||
162 | return channel_type; | ||
163 | } | ||
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 30f99c344847..e7af5227e322 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -424,6 +424,7 @@ static ssize_t ieee80211_if_parse_tsf( | |||
424 | struct ieee80211_local *local = sdata->local; | 424 | struct ieee80211_local *local = sdata->local; |
425 | unsigned long long tsf; | 425 | unsigned long long tsf; |
426 | int ret; | 426 | int ret; |
427 | int tsf_is_delta = 0; | ||
427 | 428 | ||
428 | if (strncmp(buf, "reset", 5) == 0) { | 429 | if (strncmp(buf, "reset", 5) == 0) { |
429 | if (local->ops->reset_tsf) { | 430 | if (local->ops->reset_tsf) { |
@@ -431,9 +432,20 @@ static ssize_t ieee80211_if_parse_tsf( | |||
431 | wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); | 432 | wiphy_info(local->hw.wiphy, "debugfs reset TSF\n"); |
432 | } | 433 | } |
433 | } else { | 434 | } else { |
435 | if (buflen > 10 && buf[1] == '=') { | ||
436 | if (buf[0] == '+') | ||
437 | tsf_is_delta = 1; | ||
438 | else if (buf[0] == '-') | ||
439 | tsf_is_delta = -1; | ||
440 | else | ||
441 | return -EINVAL; | ||
442 | buf += 2; | ||
443 | } | ||
434 | ret = kstrtoull(buf, 10, &tsf); | 444 | ret = kstrtoull(buf, 10, &tsf); |
435 | if (ret < 0) | 445 | if (ret < 0) |
436 | return -EINVAL; | 446 | return -EINVAL; |
447 | if (tsf_is_delta) | ||
448 | tsf = drv_get_tsf(local, sdata) + tsf_is_delta * tsf; | ||
437 | if (local->ops->set_tsf) { | 449 | if (local->ops->set_tsf) { |
438 | drv_set_tsf(local, sdata, tsf); | 450 | drv_set_tsf(local, sdata, tsf); |
439 | wiphy_info(local->hw.wiphy, | 451 | wiphy_info(local->hw.wiphy, |
@@ -499,26 +511,23 @@ IEEE80211_IF_FILE(dot11MeshForwarding, u.mesh.mshcfg.dot11MeshForwarding, DEC); | |||
499 | IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC); | 511 | IEEE80211_IF_FILE(rssi_threshold, u.mesh.mshcfg.rssi_threshold, DEC); |
500 | #endif | 512 | #endif |
501 | 513 | ||
502 | |||
503 | #define DEBUGFS_ADD(name) \ | ||
504 | debugfs_create_file(#name, 0400, sdata->debugfs.dir, \ | ||
505 | sdata, &name##_ops); | ||
506 | |||
507 | #define DEBUGFS_ADD_MODE(name, mode) \ | 514 | #define DEBUGFS_ADD_MODE(name, mode) \ |
508 | debugfs_create_file(#name, mode, sdata->debugfs.dir, \ | 515 | debugfs_create_file(#name, mode, sdata->debugfs.dir, \ |
509 | sdata, &name##_ops); | 516 | sdata, &name##_ops); |
510 | 517 | ||
511 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | 518 | #define DEBUGFS_ADD(name) DEBUGFS_ADD_MODE(name, 0400) |
519 | |||
520 | static void add_common_files(struct ieee80211_sub_if_data *sdata) | ||
512 | { | 521 | { |
513 | DEBUGFS_ADD(drop_unencrypted); | 522 | DEBUGFS_ADD(drop_unencrypted); |
514 | DEBUGFS_ADD(flags); | ||
515 | DEBUGFS_ADD(state); | ||
516 | DEBUGFS_ADD(channel_type); | ||
517 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | 523 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); |
518 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | 524 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); |
519 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | 525 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); |
520 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | 526 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); |
527 | } | ||
521 | 528 | ||
529 | static void add_sta_files(struct ieee80211_sub_if_data *sdata) | ||
530 | { | ||
522 | DEBUGFS_ADD(bssid); | 531 | DEBUGFS_ADD(bssid); |
523 | DEBUGFS_ADD(aid); | 532 | DEBUGFS_ADD(aid); |
524 | DEBUGFS_ADD(last_beacon); | 533 | DEBUGFS_ADD(last_beacon); |
@@ -531,15 +540,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
531 | 540 | ||
532 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 541 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
533 | { | 542 | { |
534 | DEBUGFS_ADD(drop_unencrypted); | ||
535 | DEBUGFS_ADD(flags); | ||
536 | DEBUGFS_ADD(state); | ||
537 | DEBUGFS_ADD(channel_type); | ||
538 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | ||
539 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | ||
540 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
541 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
542 | |||
543 | DEBUGFS_ADD(num_sta_authorized); | 543 | DEBUGFS_ADD(num_sta_authorized); |
544 | DEBUGFS_ADD(num_sta_ps); | 544 | DEBUGFS_ADD(num_sta_ps); |
545 | DEBUGFS_ADD(dtim_count); | 545 | DEBUGFS_ADD(dtim_count); |
@@ -549,48 +549,14 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
549 | 549 | ||
550 | static void add_ibss_files(struct ieee80211_sub_if_data *sdata) | 550 | static void add_ibss_files(struct ieee80211_sub_if_data *sdata) |
551 | { | 551 | { |
552 | DEBUGFS_ADD(channel_type); | ||
553 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | ||
554 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | ||
555 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
556 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
557 | |||
558 | DEBUGFS_ADD_MODE(tsf, 0600); | 552 | DEBUGFS_ADD_MODE(tsf, 0600); |
559 | } | 553 | } |
560 | 554 | ||
561 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) | 555 | static void add_wds_files(struct ieee80211_sub_if_data *sdata) |
562 | { | 556 | { |
563 | DEBUGFS_ADD(drop_unencrypted); | ||
564 | DEBUGFS_ADD(flags); | ||
565 | DEBUGFS_ADD(state); | ||
566 | DEBUGFS_ADD(channel_type); | ||
567 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | ||
568 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | ||
569 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
570 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
571 | |||
572 | DEBUGFS_ADD(peer); | 557 | DEBUGFS_ADD(peer); |
573 | } | 558 | } |
574 | 559 | ||
575 | static void add_vlan_files(struct ieee80211_sub_if_data *sdata) | ||
576 | { | ||
577 | DEBUGFS_ADD(drop_unencrypted); | ||
578 | DEBUGFS_ADD(flags); | ||
579 | DEBUGFS_ADD(state); | ||
580 | DEBUGFS_ADD(channel_type); | ||
581 | DEBUGFS_ADD(rc_rateidx_mask_2ghz); | ||
582 | DEBUGFS_ADD(rc_rateidx_mask_5ghz); | ||
583 | DEBUGFS_ADD(rc_rateidx_mcs_mask_2ghz); | ||
584 | DEBUGFS_ADD(rc_rateidx_mcs_mask_5ghz); | ||
585 | } | ||
586 | |||
587 | static void add_monitor_files(struct ieee80211_sub_if_data *sdata) | ||
588 | { | ||
589 | DEBUGFS_ADD(flags); | ||
590 | DEBUGFS_ADD(state); | ||
591 | DEBUGFS_ADD(channel_type); | ||
592 | } | ||
593 | |||
594 | #ifdef CONFIG_MAC80211_MESH | 560 | #ifdef CONFIG_MAC80211_MESH |
595 | 561 | ||
596 | static void add_mesh_files(struct ieee80211_sub_if_data *sdata) | 562 | static void add_mesh_files(struct ieee80211_sub_if_data *sdata) |
@@ -651,6 +617,13 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
651 | if (!sdata->debugfs.dir) | 617 | if (!sdata->debugfs.dir) |
652 | return; | 618 | return; |
653 | 619 | ||
620 | DEBUGFS_ADD(flags); | ||
621 | DEBUGFS_ADD(state); | ||
622 | DEBUGFS_ADD(channel_type); | ||
623 | |||
624 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | ||
625 | add_common_files(sdata); | ||
626 | |||
654 | switch (sdata->vif.type) { | 627 | switch (sdata->vif.type) { |
655 | case NL80211_IFTYPE_MESH_POINT: | 628 | case NL80211_IFTYPE_MESH_POINT: |
656 | #ifdef CONFIG_MAC80211_MESH | 629 | #ifdef CONFIG_MAC80211_MESH |
@@ -671,12 +644,6 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
671 | case NL80211_IFTYPE_WDS: | 644 | case NL80211_IFTYPE_WDS: |
672 | add_wds_files(sdata); | 645 | add_wds_files(sdata); |
673 | break; | 646 | break; |
674 | case NL80211_IFTYPE_MONITOR: | ||
675 | add_monitor_files(sdata); | ||
676 | break; | ||
677 | case NL80211_IFTYPE_AP_VLAN: | ||
678 | add_vlan_files(sdata); | ||
679 | break; | ||
680 | default: | 647 | default: |
681 | break; | 648 | break; |
682 | } | 649 | } |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 832b2da5e4cd..5ccec2c1e9f6 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -63,7 +63,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" | 63 | test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" |
64 | 64 | ||
65 | int res = scnprintf(buf, sizeof(buf), | 65 | int res = scnprintf(buf, sizeof(buf), |
66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", | 66 | "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", |
67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), | 67 | TEST(AUTH), TEST(ASSOC), TEST(PS_STA), |
68 | TEST(PS_DRIVER), TEST(AUTHORIZED), | 68 | TEST(PS_DRIVER), TEST(AUTHORIZED), |
69 | TEST(SHORT_PREAMBLE), | 69 | TEST(SHORT_PREAMBLE), |
@@ -71,7 +71,8 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, | |||
71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), | 71 | TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL), |
72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), | 72 | TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), |
73 | TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), | 73 | TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), |
74 | TEST(INSERTED), TEST(RATE_CONTROL)); | 74 | TEST(INSERTED), TEST(RATE_CONTROL), |
75 | TEST(TOFFSET_KNOWN)); | ||
75 | #undef TEST | 76 | #undef TEST |
76 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); | 77 | return simple_read_from_buffer(userbuf, count, ppos, buf, res); |
77 | } | 78 | } |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index af4691fed645..4a0e559cb26b 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -7,7 +7,9 @@ | |||
7 | 7 | ||
8 | static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) | 8 | static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) |
9 | { | 9 | { |
10 | WARN_ON(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER)); | 10 | WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), |
11 | "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", | ||
12 | sdata->dev->name, sdata->flags); | ||
11 | } | 13 | } |
12 | 14 | ||
13 | static inline struct ieee80211_sub_if_data * | 15 | static inline struct ieee80211_sub_if_data * |
@@ -89,6 +91,19 @@ static inline int drv_resume(struct ieee80211_local *local) | |||
89 | trace_drv_return_int(local, ret); | 91 | trace_drv_return_int(local, ret); |
90 | return ret; | 92 | return ret; |
91 | } | 93 | } |
94 | |||
95 | static inline void drv_set_wakeup(struct ieee80211_local *local, | ||
96 | bool enabled) | ||
97 | { | ||
98 | might_sleep(); | ||
99 | |||
100 | if (!local->ops->set_wakeup) | ||
101 | return; | ||
102 | |||
103 | trace_drv_set_wakeup(local, enabled); | ||
104 | local->ops->set_wakeup(&local->hw, enabled); | ||
105 | trace_drv_return_void(local); | ||
106 | } | ||
92 | #endif | 107 | #endif |
93 | 108 | ||
94 | static inline int drv_add_interface(struct ieee80211_local *local, | 109 | static inline int drv_add_interface(struct ieee80211_local *local, |
@@ -99,7 +114,8 @@ static inline int drv_add_interface(struct ieee80211_local *local, | |||
99 | might_sleep(); | 114 | might_sleep(); |
100 | 115 | ||
101 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 116 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
102 | sdata->vif.type == NL80211_IFTYPE_MONITOR)) | 117 | (sdata->vif.type == NL80211_IFTYPE_MONITOR && |
118 | !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)))) | ||
103 | return -EINVAL; | 119 | return -EINVAL; |
104 | 120 | ||
105 | trace_drv_add_interface(local, sdata); | 121 | trace_drv_add_interface(local, sdata); |
@@ -474,8 +490,23 @@ int drv_sta_state(struct ieee80211_local *local, | |||
474 | return ret; | 490 | return ret; |
475 | } | 491 | } |
476 | 492 | ||
493 | static inline void drv_sta_rc_update(struct ieee80211_local *local, | ||
494 | struct ieee80211_sub_if_data *sdata, | ||
495 | struct ieee80211_sta *sta, u32 changed) | ||
496 | { | ||
497 | sdata = get_bss_sdata(sdata); | ||
498 | check_sdata_in_driver(sdata); | ||
499 | |||
500 | trace_drv_sta_rc_update(local, sdata, sta, changed); | ||
501 | if (local->ops->sta_rc_update) | ||
502 | local->ops->sta_rc_update(&local->hw, &sdata->vif, | ||
503 | sta, changed); | ||
504 | |||
505 | trace_drv_return_void(local); | ||
506 | } | ||
507 | |||
477 | static inline int drv_conf_tx(struct ieee80211_local *local, | 508 | static inline int drv_conf_tx(struct ieee80211_local *local, |
478 | struct ieee80211_sub_if_data *sdata, u16 queue, | 509 | struct ieee80211_sub_if_data *sdata, u16 ac, |
479 | const struct ieee80211_tx_queue_params *params) | 510 | const struct ieee80211_tx_queue_params *params) |
480 | { | 511 | { |
481 | int ret = -EOPNOTSUPP; | 512 | int ret = -EOPNOTSUPP; |
@@ -484,10 +515,10 @@ static inline int drv_conf_tx(struct ieee80211_local *local, | |||
484 | 515 | ||
485 | check_sdata_in_driver(sdata); | 516 | check_sdata_in_driver(sdata); |
486 | 517 | ||
487 | trace_drv_conf_tx(local, sdata, queue, params); | 518 | trace_drv_conf_tx(local, sdata, ac, params); |
488 | if (local->ops->conf_tx) | 519 | if (local->ops->conf_tx) |
489 | ret = local->ops->conf_tx(&local->hw, &sdata->vif, | 520 | ret = local->ops->conf_tx(&local->hw, &sdata->vif, |
490 | queue, params); | 521 | ac, params); |
491 | trace_drv_return_int(local, ret); | 522 | trace_drv_return_int(local, ret); |
492 | return ret; | 523 | return ret; |
493 | } | 524 | } |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 21d6f5290a1c..7c0754bed61b 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -171,6 +171,20 @@ DEFINE_EVENT(local_only_evt, drv_resume, | |||
171 | TP_ARGS(local) | 171 | TP_ARGS(local) |
172 | ); | 172 | ); |
173 | 173 | ||
174 | TRACE_EVENT(drv_set_wakeup, | ||
175 | TP_PROTO(struct ieee80211_local *local, bool enabled), | ||
176 | TP_ARGS(local, enabled), | ||
177 | TP_STRUCT__entry( | ||
178 | LOCAL_ENTRY | ||
179 | __field(bool, enabled) | ||
180 | ), | ||
181 | TP_fast_assign( | ||
182 | LOCAL_ASSIGN; | ||
183 | __entry->enabled = enabled; | ||
184 | ), | ||
185 | TP_printk(LOCAL_PR_FMT " enabled:%d", LOCAL_PR_ARG, __entry->enabled) | ||
186 | ); | ||
187 | |||
174 | DEFINE_EVENT(local_only_evt, drv_stop, | 188 | DEFINE_EVENT(local_only_evt, drv_stop, |
175 | TP_PROTO(struct ieee80211_local *local), | 189 | TP_PROTO(struct ieee80211_local *local), |
176 | TP_ARGS(local) | 190 | TP_ARGS(local) |
@@ -624,6 +638,34 @@ TRACE_EVENT(drv_sta_state, | |||
624 | ) | 638 | ) |
625 | ); | 639 | ); |
626 | 640 | ||
641 | TRACE_EVENT(drv_sta_rc_update, | ||
642 | TP_PROTO(struct ieee80211_local *local, | ||
643 | struct ieee80211_sub_if_data *sdata, | ||
644 | struct ieee80211_sta *sta, | ||
645 | u32 changed), | ||
646 | |||
647 | TP_ARGS(local, sdata, sta, changed), | ||
648 | |||
649 | TP_STRUCT__entry( | ||
650 | LOCAL_ENTRY | ||
651 | VIF_ENTRY | ||
652 | STA_ENTRY | ||
653 | __field(u32, changed) | ||
654 | ), | ||
655 | |||
656 | TP_fast_assign( | ||
657 | LOCAL_ASSIGN; | ||
658 | VIF_ASSIGN; | ||
659 | STA_ASSIGN; | ||
660 | __entry->changed = changed; | ||
661 | ), | ||
662 | |||
663 | TP_printk( | ||
664 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " changed: 0x%x", | ||
665 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->changed | ||
666 | ) | ||
667 | ); | ||
668 | |||
627 | TRACE_EVENT(drv_sta_add, | 669 | TRACE_EVENT(drv_sta_add, |
628 | TP_PROTO(struct ieee80211_local *local, | 670 | TP_PROTO(struct ieee80211_local *local, |
629 | struct ieee80211_sub_if_data *sdata, | 671 | struct ieee80211_sub_if_data *sdata, |
@@ -677,15 +719,14 @@ TRACE_EVENT(drv_sta_remove, | |||
677 | TRACE_EVENT(drv_conf_tx, | 719 | TRACE_EVENT(drv_conf_tx, |
678 | TP_PROTO(struct ieee80211_local *local, | 720 | TP_PROTO(struct ieee80211_local *local, |
679 | struct ieee80211_sub_if_data *sdata, | 721 | struct ieee80211_sub_if_data *sdata, |
680 | u16 queue, | 722 | u16 ac, const struct ieee80211_tx_queue_params *params), |
681 | const struct ieee80211_tx_queue_params *params), | ||
682 | 723 | ||
683 | TP_ARGS(local, sdata, queue, params), | 724 | TP_ARGS(local, sdata, ac, params), |
684 | 725 | ||
685 | TP_STRUCT__entry( | 726 | TP_STRUCT__entry( |
686 | LOCAL_ENTRY | 727 | LOCAL_ENTRY |
687 | VIF_ENTRY | 728 | VIF_ENTRY |
688 | __field(u16, queue) | 729 | __field(u16, ac) |
689 | __field(u16, txop) | 730 | __field(u16, txop) |
690 | __field(u16, cw_min) | 731 | __field(u16, cw_min) |
691 | __field(u16, cw_max) | 732 | __field(u16, cw_max) |
@@ -696,7 +737,7 @@ TRACE_EVENT(drv_conf_tx, | |||
696 | TP_fast_assign( | 737 | TP_fast_assign( |
697 | LOCAL_ASSIGN; | 738 | LOCAL_ASSIGN; |
698 | VIF_ASSIGN; | 739 | VIF_ASSIGN; |
699 | __entry->queue = queue; | 740 | __entry->ac = ac; |
700 | __entry->txop = params->txop; | 741 | __entry->txop = params->txop; |
701 | __entry->cw_max = params->cw_max; | 742 | __entry->cw_max = params->cw_max; |
702 | __entry->cw_min = params->cw_min; | 743 | __entry->cw_min = params->cw_min; |
@@ -705,8 +746,8 @@ TRACE_EVENT(drv_conf_tx, | |||
705 | ), | 746 | ), |
706 | 747 | ||
707 | TP_printk( | 748 | TP_printk( |
708 | LOCAL_PR_FMT VIF_PR_FMT " queue:%d", | 749 | LOCAL_PR_FMT VIF_PR_FMT " AC:%d", |
709 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->queue | 750 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->ac |
710 | ) | 751 | ) |
711 | ); | 752 | ); |
712 | 753 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index f25fff7607d8..9b603366943c 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -19,15 +19,6 @@ | |||
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "rate.h" | 20 | #include "rate.h" |
21 | 21 | ||
22 | bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata) | ||
23 | { | ||
24 | const __le16 flg = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
25 | if ((sdata->u.mgd.ht_capa_mask.cap_info & flg) && | ||
26 | !(sdata->u.mgd.ht_capa.cap_info & flg)) | ||
27 | return true; | ||
28 | return false; | ||
29 | } | ||
30 | |||
31 | static void __check_htcap_disable(struct ieee80211_sub_if_data *sdata, | 22 | static void __check_htcap_disable(struct ieee80211_sub_if_data *sdata, |
32 | struct ieee80211_sta_ht_cap *ht_cap, | 23 | struct ieee80211_sta_ht_cap *ht_cap, |
33 | u16 flag) | 24 | u16 flag) |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 33fd8d9f714e..49a207980338 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -160,16 +160,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
160 | if (channel_type && sband->ht_cap.ht_supported) { | 160 | if (channel_type && sband->ht_cap.ht_supported) { |
161 | pos = skb_put(skb, 4 + | 161 | pos = skb_put(skb, 4 + |
162 | sizeof(struct ieee80211_ht_cap) + | 162 | sizeof(struct ieee80211_ht_cap) + |
163 | sizeof(struct ieee80211_ht_info)); | 163 | sizeof(struct ieee80211_ht_operation)); |
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_info(pos, | 166 | pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, |
167 | &sband->ht_cap, | 167 | chan, channel_type); |
168 | chan, | ||
169 | channel_type); | ||
170 | } | 168 | } |
171 | 169 | ||
172 | if (local->hw.queues >= 4) { | 170 | if (local->hw.queues >= IEEE80211_NUM_ACS) { |
173 | pos = skb_put(skb, 9); | 171 | pos = skb_put(skb, 9); |
174 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | 172 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; |
175 | *pos++ = 7; /* len */ | 173 | *pos++ = 7; /* len */ |
@@ -410,7 +408,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
410 | 408 | ||
411 | if (elems->supp_rates) { | 409 | if (elems->supp_rates) { |
412 | supp_rates = ieee80211_sta_get_rates(local, elems, | 410 | supp_rates = ieee80211_sta_get_rates(local, elems, |
413 | band); | 411 | band, NULL); |
414 | if (sta) { | 412 | if (sta) { |
415 | u32 prev_rates; | 413 | u32 prev_rates; |
416 | 414 | ||
@@ -441,13 +439,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
441 | if (sta && elems->wmm_info) | 439 | if (sta && elems->wmm_info) |
442 | set_sta_flag(sta, WLAN_STA_WME); | 440 | set_sta_flag(sta, WLAN_STA_WME); |
443 | 441 | ||
444 | if (sta && elems->ht_info_elem && elems->ht_cap_elem && | 442 | if (sta && elems->ht_operation && elems->ht_cap_elem && |
445 | sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { | 443 | sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { |
446 | /* we both use HT */ | 444 | /* we both use HT */ |
447 | struct ieee80211_sta_ht_cap sta_ht_cap_new; | 445 | struct ieee80211_sta_ht_cap sta_ht_cap_new; |
448 | enum nl80211_channel_type channel_type = | 446 | enum nl80211_channel_type channel_type = |
449 | ieee80211_ht_info_to_channel_type( | 447 | ieee80211_ht_oper_to_channel_type( |
450 | elems->ht_info_elem); | 448 | elems->ht_operation); |
451 | 449 | ||
452 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 450 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
453 | elems->ht_cap_elem, | 451 | elems->ht_cap_elem, |
@@ -560,7 +558,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
560 | sdata->name, mgmt->bssid); | 558 | sdata->name, mgmt->bssid); |
561 | #endif | 559 | #endif |
562 | ieee80211_sta_join_ibss(sdata, bss); | 560 | ieee80211_sta_join_ibss(sdata, bss); |
563 | supp_rates = ieee80211_sta_get_rates(local, elems, band); | 561 | supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); |
564 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 562 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
565 | supp_rates, true); | 563 | supp_rates, true); |
566 | rcu_read_unlock(); | 564 | rcu_read_unlock(); |
@@ -1063,7 +1061,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1063 | 4 /* IBSS params */ + | 1061 | 4 /* IBSS params */ + |
1064 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | 1062 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + |
1065 | 2 + sizeof(struct ieee80211_ht_cap) + | 1063 | 2 + sizeof(struct ieee80211_ht_cap) + |
1066 | 2 + sizeof(struct ieee80211_ht_info) + | 1064 | 2 + sizeof(struct ieee80211_ht_operation) + |
1067 | params->ie_len); | 1065 | params->ie_len); |
1068 | if (!skb) | 1066 | if (!skb) |
1069 | return -ENOMEM; | 1067 | return -ENOMEM; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index d9798a307f20..4be11ea3dfc4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -52,7 +52,8 @@ struct ieee80211_local; | |||
52 | * increased memory use (about 2 kB of RAM per entry). */ | 52 | * increased memory use (about 2 kB of RAM per entry). */ |
53 | #define IEEE80211_FRAGMENT_MAX 4 | 53 | #define IEEE80211_FRAGMENT_MAX 4 |
54 | 54 | ||
55 | #define TU_TO_EXP_TIME(x) (jiffies + usecs_to_jiffies((x) * 1024)) | 55 | #define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024)) |
56 | #define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x)) | ||
56 | 57 | ||
57 | #define IEEE80211_DEFAULT_UAPSD_QUEUES \ | 58 | #define IEEE80211_DEFAULT_UAPSD_QUEUES \ |
58 | (IEEE80211_WMM_IE_STA_QOSINFO_AC_BK | \ | 59 | (IEEE80211_WMM_IE_STA_QOSINFO_AC_BK | \ |
@@ -378,6 +379,7 @@ enum ieee80211_sta_flags { | |||
378 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), | 379 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
379 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | 380 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), |
380 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), | 381 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), |
382 | IEEE80211_STA_DISABLE_40MHZ = BIT(10), | ||
381 | }; | 383 | }; |
382 | 384 | ||
383 | struct ieee80211_mgd_auth_data { | 385 | struct ieee80211_mgd_auth_data { |
@@ -397,7 +399,7 @@ struct ieee80211_mgd_auth_data { | |||
397 | struct ieee80211_mgd_assoc_data { | 399 | struct ieee80211_mgd_assoc_data { |
398 | struct cfg80211_bss *bss; | 400 | struct cfg80211_bss *bss; |
399 | const u8 *supp_rates; | 401 | const u8 *supp_rates; |
400 | const u8 *ht_information_ie; | 402 | const u8 *ht_operation_ie; |
401 | 403 | ||
402 | unsigned long timeout; | 404 | unsigned long timeout; |
403 | int tries; | 405 | int tries; |
@@ -552,6 +554,24 @@ struct ieee80211_if_ibss { | |||
552 | } state; | 554 | } state; |
553 | }; | 555 | }; |
554 | 556 | ||
557 | /** | ||
558 | * struct ieee80211_mesh_sync_ops - Extensible synchronization framework interface | ||
559 | * | ||
560 | * these declarations define the interface, which enables | ||
561 | * vendor-specific mesh synchronization | ||
562 | * | ||
563 | */ | ||
564 | struct ieee802_11_elems; | ||
565 | struct ieee80211_mesh_sync_ops { | ||
566 | void (*rx_bcn_presp)(struct ieee80211_sub_if_data *sdata, | ||
567 | u16 stype, | ||
568 | struct ieee80211_mgmt *mgmt, | ||
569 | struct ieee802_11_elems *elems, | ||
570 | struct ieee80211_rx_status *rx_status); | ||
571 | void (*adjust_tbtt)(struct ieee80211_sub_if_data *sdata); | ||
572 | /* add other framework functions here */ | ||
573 | }; | ||
574 | |||
555 | struct ieee80211_if_mesh { | 575 | struct ieee80211_if_mesh { |
556 | struct timer_list housekeeping_timer; | 576 | struct timer_list housekeeping_timer; |
557 | struct timer_list mesh_path_timer; | 577 | struct timer_list mesh_path_timer; |
@@ -600,6 +620,11 @@ struct ieee80211_if_mesh { | |||
600 | IEEE80211_MESH_SEC_AUTHED = 0x1, | 620 | IEEE80211_MESH_SEC_AUTHED = 0x1, |
601 | IEEE80211_MESH_SEC_SECURED = 0x2, | 621 | IEEE80211_MESH_SEC_SECURED = 0x2, |
602 | } security; | 622 | } security; |
623 | /* Extensible Synchronization Framework */ | ||
624 | struct ieee80211_mesh_sync_ops *sync_ops; | ||
625 | s64 sync_offset_clockdrift_max; | ||
626 | spinlock_t sync_offset_lock; | ||
627 | bool adjusting_tbtt; | ||
603 | }; | 628 | }; |
604 | 629 | ||
605 | #ifdef CONFIG_MAC80211_MESH | 630 | #ifdef CONFIG_MAC80211_MESH |
@@ -666,12 +691,6 @@ struct ieee80211_sub_if_data { | |||
666 | 691 | ||
667 | char name[IFNAMSIZ]; | 692 | char name[IFNAMSIZ]; |
668 | 693 | ||
669 | /* | ||
670 | * keep track of whether the HT opmode (stored in | ||
671 | * vif.bss_info.ht_operation_mode) is valid. | ||
672 | */ | ||
673 | bool ht_opmode_valid; | ||
674 | |||
675 | /* to detect idle changes */ | 694 | /* to detect idle changes */ |
676 | bool old_idle; | 695 | bool old_idle; |
677 | 696 | ||
@@ -691,7 +710,7 @@ struct ieee80211_sub_if_data { | |||
691 | __be16 control_port_protocol; | 710 | __be16 control_port_protocol; |
692 | bool control_port_no_encrypt; | 711 | bool control_port_no_encrypt; |
693 | 712 | ||
694 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_MAX_QUEUES]; | 713 | struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS]; |
695 | 714 | ||
696 | struct work_struct work; | 715 | struct work_struct work; |
697 | struct sk_buff_head skb_queue; | 716 | struct sk_buff_head skb_queue; |
@@ -761,7 +780,6 @@ enum queue_stop_reason { | |||
761 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, | 780 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
762 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, | 781 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
763 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 782 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
764 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE, | ||
765 | }; | 783 | }; |
766 | 784 | ||
767 | #ifdef CONFIG_MAC80211_LEDS | 785 | #ifdef CONFIG_MAC80211_LEDS |
@@ -1082,6 +1100,9 @@ struct ieee80211_local { | |||
1082 | struct net_device napi_dev; | 1100 | struct net_device napi_dev; |
1083 | 1101 | ||
1084 | struct napi_struct napi; | 1102 | struct napi_struct napi; |
1103 | |||
1104 | /* virtual monitor interface */ | ||
1105 | struct ieee80211_sub_if_data __rcu *monitor_sdata; | ||
1085 | }; | 1106 | }; |
1086 | 1107 | ||
1087 | static inline struct ieee80211_sub_if_data * | 1108 | static inline struct ieee80211_sub_if_data * |
@@ -1117,7 +1138,7 @@ struct ieee802_11_elems { | |||
1117 | u8 *wmm_info; | 1138 | u8 *wmm_info; |
1118 | u8 *wmm_param; | 1139 | u8 *wmm_param; |
1119 | struct ieee80211_ht_cap *ht_cap_elem; | 1140 | struct ieee80211_ht_cap *ht_cap_elem; |
1120 | struct ieee80211_ht_info *ht_info_elem; | 1141 | struct ieee80211_ht_operation *ht_operation; |
1121 | struct ieee80211_meshconf_ie *mesh_config; | 1142 | struct ieee80211_meshconf_ie *mesh_config; |
1122 | u8 *mesh_id; | 1143 | u8 *mesh_id; |
1123 | u8 *peering; | 1144 | u8 *peering; |
@@ -1299,7 +1320,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1299 | struct net_device *dev); | 1320 | struct net_device *dev); |
1300 | 1321 | ||
1301 | /* HT */ | 1322 | /* HT */ |
1302 | bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata); | ||
1303 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | 1323 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, |
1304 | struct ieee80211_sta_ht_cap *ht_cap); | 1324 | struct ieee80211_sta_ht_cap *ht_cap); |
1305 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | 1325 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, |
@@ -1429,13 +1449,17 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | |||
1429 | enum queue_stop_reason reason); | 1449 | enum queue_stop_reason reason); |
1430 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1450 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, |
1431 | enum queue_stop_reason reason); | 1451 | enum queue_stop_reason reason); |
1452 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); | ||
1432 | void ieee80211_add_pending_skb(struct ieee80211_local *local, | 1453 | void ieee80211_add_pending_skb(struct ieee80211_local *local, |
1433 | struct sk_buff *skb); | 1454 | struct sk_buff *skb); |
1434 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, | ||
1435 | struct sk_buff_head *skbs); | ||
1436 | void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | 1455 | void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, |
1437 | struct sk_buff_head *skbs, | 1456 | struct sk_buff_head *skbs, |
1438 | void (*fn)(void *data), void *data); | 1457 | void (*fn)(void *data), void *data); |
1458 | static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, | ||
1459 | struct sk_buff_head *skbs) | ||
1460 | { | ||
1461 | ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); | ||
1462 | } | ||
1439 | 1463 | ||
1440 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1464 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1441 | u16 transaction, u16 auth_alg, | 1465 | u16 transaction, u16 auth_alg, |
@@ -1460,7 +1484,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
1460 | const u8 *supp_rates); | 1484 | const u8 *supp_rates); |
1461 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1485 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
1462 | struct ieee802_11_elems *elems, | 1486 | struct ieee802_11_elems *elems, |
1463 | enum ieee80211_band band); | 1487 | enum ieee80211_band band, u32 *basic_rates); |
1464 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | 1488 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, |
1465 | enum ieee80211_smps_mode smps_mode); | 1489 | enum ieee80211_smps_mode smps_mode); |
1466 | void ieee80211_recalc_smps(struct ieee80211_local *local); | 1490 | void ieee80211_recalc_smps(struct ieee80211_local *local); |
@@ -1470,10 +1494,9 @@ size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | |||
1470 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); | 1494 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); |
1471 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1495 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1472 | u16 cap); | 1496 | u16 cap); |
1473 | u8 *ieee80211_ie_build_ht_info(u8 *pos, | 1497 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1474 | struct ieee80211_sta_ht_cap *ht_cap, | 1498 | struct ieee80211_channel *channel, |
1475 | struct ieee80211_channel *channel, | 1499 | enum nl80211_channel_type channel_type); |
1476 | enum nl80211_channel_type channel_type); | ||
1477 | 1500 | ||
1478 | /* internal work items */ | 1501 | /* internal work items */ |
1479 | void ieee80211_work_init(struct ieee80211_local *local); | 1502 | void ieee80211_work_init(struct ieee80211_local *local); |
@@ -1501,10 +1524,7 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local, | |||
1501 | struct ieee80211_sub_if_data *sdata, | 1524 | struct ieee80211_sub_if_data *sdata, |
1502 | enum nl80211_channel_type chantype); | 1525 | enum nl80211_channel_type chantype); |
1503 | enum nl80211_channel_type | 1526 | enum nl80211_channel_type |
1504 | ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info); | 1527 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); |
1505 | enum nl80211_channel_type ieee80211_get_tx_channel_type( | ||
1506 | struct ieee80211_local *local, | ||
1507 | enum nl80211_channel_type channel_type); | ||
1508 | 1528 | ||
1509 | #ifdef CONFIG_MAC80211_NOINLINE | 1529 | #ifdef CONFIG_MAC80211_NOINLINE |
1510 | #define debug_noinline noinline | 1530 | #define debug_noinline noinline |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 401c01f0731e..6e85faed053d 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -149,6 +149,34 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata, | |||
149 | return 0; | 149 | return 0; |
150 | } | 150 | } |
151 | 151 | ||
152 | static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata) | ||
153 | { | ||
154 | int n_queues = sdata->local->hw.queues; | ||
155 | int i; | ||
156 | |||
157 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | ||
158 | if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == | ||
159 | IEEE80211_INVAL_HW_QUEUE)) | ||
160 | return -EINVAL; | ||
161 | if (WARN_ON_ONCE(sdata->vif.hw_queue[i] >= | ||
162 | n_queues)) | ||
163 | return -EINVAL; | ||
164 | } | ||
165 | |||
166 | if (sdata->vif.type != NL80211_IFTYPE_AP) { | ||
167 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | if (WARN_ON_ONCE(sdata->vif.cab_queue == IEEE80211_INVAL_HW_QUEUE)) | ||
172 | return -EINVAL; | ||
173 | |||
174 | if (WARN_ON_ONCE(sdata->vif.cab_queue >= n_queues)) | ||
175 | return -EINVAL; | ||
176 | |||
177 | return 0; | ||
178 | } | ||
179 | |||
152 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | 180 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, |
153 | const int offset) | 181 | const int offset) |
154 | { | 182 | { |
@@ -169,6 +197,81 @@ void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | |||
169 | #undef ADJUST | 197 | #undef ADJUST |
170 | } | 198 | } |
171 | 199 | ||
200 | static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | ||
201 | { | ||
202 | struct ieee80211_local *local = sdata->local; | ||
203 | int i; | ||
204 | |||
205 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | ||
206 | if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | ||
207 | sdata->vif.hw_queue[i] = IEEE80211_INVAL_HW_QUEUE; | ||
208 | else | ||
209 | sdata->vif.hw_queue[i] = i; | ||
210 | } | ||
211 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; | ||
212 | } | ||
213 | |||
214 | static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | ||
215 | { | ||
216 | struct ieee80211_sub_if_data *sdata; | ||
217 | int ret; | ||
218 | |||
219 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | ||
220 | return 0; | ||
221 | |||
222 | if (local->monitor_sdata) | ||
223 | return 0; | ||
224 | |||
225 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); | ||
226 | if (!sdata) | ||
227 | return -ENOMEM; | ||
228 | |||
229 | /* set up data */ | ||
230 | sdata->local = local; | ||
231 | sdata->vif.type = NL80211_IFTYPE_MONITOR; | ||
232 | snprintf(sdata->name, IFNAMSIZ, "%s-monitor", | ||
233 | wiphy_name(local->hw.wiphy)); | ||
234 | |||
235 | ieee80211_set_default_queues(sdata); | ||
236 | |||
237 | ret = drv_add_interface(local, sdata); | ||
238 | if (WARN_ON(ret)) { | ||
239 | /* ok .. stupid driver, it asked for this! */ | ||
240 | kfree(sdata); | ||
241 | return ret; | ||
242 | } | ||
243 | |||
244 | ret = ieee80211_check_queues(sdata); | ||
245 | if (ret) { | ||
246 | kfree(sdata); | ||
247 | return ret; | ||
248 | } | ||
249 | |||
250 | rcu_assign_pointer(local->monitor_sdata, sdata); | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | ||
256 | { | ||
257 | struct ieee80211_sub_if_data *sdata; | ||
258 | |||
259 | if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | ||
260 | return; | ||
261 | |||
262 | sdata = rtnl_dereference(local->monitor_sdata); | ||
263 | |||
264 | if (!sdata) | ||
265 | return; | ||
266 | |||
267 | rcu_assign_pointer(local->monitor_sdata, NULL); | ||
268 | synchronize_net(); | ||
269 | |||
270 | drv_remove_interface(local, sdata); | ||
271 | |||
272 | kfree(sdata); | ||
273 | } | ||
274 | |||
172 | /* | 275 | /* |
173 | * NOTE: Be very careful when changing this function, it must NOT return | 276 | * NOTE: Be very careful when changing this function, it must NOT return |
174 | * an error on interface type changes that have been pre-checked, so most | 277 | * an error on interface type changes that have been pre-checked, so most |
@@ -246,15 +349,18 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
246 | memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); | 349 | memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); |
247 | 350 | ||
248 | if (!is_valid_ether_addr(dev->dev_addr)) { | 351 | if (!is_valid_ether_addr(dev->dev_addr)) { |
249 | if (!local->open_count) | 352 | res = -EADDRNOTAVAIL; |
250 | drv_stop(local); | 353 | goto err_stop; |
251 | return -EADDRNOTAVAIL; | ||
252 | } | 354 | } |
253 | } | 355 | } |
254 | 356 | ||
255 | switch (sdata->vif.type) { | 357 | switch (sdata->vif.type) { |
256 | case NL80211_IFTYPE_AP_VLAN: | 358 | case NL80211_IFTYPE_AP_VLAN: |
257 | /* no need to tell driver */ | 359 | /* no need to tell driver, but set carrier */ |
360 | if (rtnl_dereference(sdata->bss->beacon)) | ||
361 | netif_carrier_on(dev); | ||
362 | else | ||
363 | netif_carrier_off(dev); | ||
258 | break; | 364 | break; |
259 | case NL80211_IFTYPE_MONITOR: | 365 | case NL80211_IFTYPE_MONITOR: |
260 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | 366 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { |
@@ -262,6 +368,12 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
262 | break; | 368 | break; |
263 | } | 369 | } |
264 | 370 | ||
371 | if (local->monitors == 0 && local->open_count == 0) { | ||
372 | res = ieee80211_add_virtual_monitor(local); | ||
373 | if (res) | ||
374 | goto err_stop; | ||
375 | } | ||
376 | |||
265 | /* must be before the call to ieee80211_configure_filter */ | 377 | /* must be before the call to ieee80211_configure_filter */ |
266 | local->monitors++; | 378 | local->monitors++; |
267 | if (local->monitors == 1) { | 379 | if (local->monitors == 1) { |
@@ -276,9 +388,14 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
276 | break; | 388 | break; |
277 | default: | 389 | default: |
278 | if (coming_up) { | 390 | if (coming_up) { |
391 | ieee80211_del_virtual_monitor(local); | ||
392 | |||
279 | res = drv_add_interface(local, sdata); | 393 | res = drv_add_interface(local, sdata); |
280 | if (res) | 394 | if (res) |
281 | goto err_stop; | 395 | goto err_stop; |
396 | res = ieee80211_check_queues(sdata); | ||
397 | if (res) | ||
398 | goto err_del_interface; | ||
282 | } | 399 | } |
283 | 400 | ||
284 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 401 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
@@ -294,7 +411,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
294 | ieee80211_bss_info_change_notify(sdata, changed); | 411 | ieee80211_bss_info_change_notify(sdata, changed); |
295 | 412 | ||
296 | if (sdata->vif.type == NL80211_IFTYPE_STATION || | 413 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
297 | sdata->vif.type == NL80211_IFTYPE_ADHOC) | 414 | sdata->vif.type == NL80211_IFTYPE_ADHOC || |
415 | sdata->vif.type == NL80211_IFTYPE_AP) | ||
298 | netif_carrier_off(dev); | 416 | netif_carrier_off(dev); |
299 | else | 417 | else |
300 | netif_carrier_on(dev); | 418 | netif_carrier_on(dev); |
@@ -366,6 +484,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
366 | sdata->bss = NULL; | 484 | sdata->bss = NULL; |
367 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 485 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
368 | list_del(&sdata->u.vlan.list); | 486 | list_del(&sdata->u.vlan.list); |
487 | /* might already be clear but that doesn't matter */ | ||
369 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); | 488 | clear_bit(SDATA_STATE_RUNNING, &sdata->state); |
370 | return res; | 489 | return res; |
371 | } | 490 | } |
@@ -506,6 +625,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
506 | if (local->monitors == 0) { | 625 | if (local->monitors == 0) { |
507 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; | 626 | local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR; |
508 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; | 627 | hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR; |
628 | ieee80211_del_virtual_monitor(local); | ||
509 | } | 629 | } |
510 | 630 | ||
511 | ieee80211_adjust_monitor_flags(sdata, -1); | 631 | ieee80211_adjust_monitor_flags(sdata, -1); |
@@ -579,6 +699,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
579 | } | 699 | } |
580 | } | 700 | } |
581 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 701 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
702 | |||
703 | if (local->monitors == local->open_count && local->monitors > 0) | ||
704 | ieee80211_add_virtual_monitor(local); | ||
582 | } | 705 | } |
583 | 706 | ||
584 | static int ieee80211_stop(struct net_device *dev) | 707 | static int ieee80211_stop(struct net_device *dev) |
@@ -676,7 +799,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, | |||
676 | struct ieee80211_hdr *hdr; | 799 | struct ieee80211_hdr *hdr; |
677 | struct ieee80211_radiotap_header *rtap = (void *)skb->data; | 800 | struct ieee80211_radiotap_header *rtap = (void *)skb->data; |
678 | 801 | ||
679 | if (local->hw.queues < 4) | 802 | if (local->hw.queues < IEEE80211_NUM_ACS) |
680 | return 0; | 803 | return 0; |
681 | 804 | ||
682 | if (skb->len < 4 || | 805 | if (skb->len < 4 || |
@@ -970,6 +1093,13 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
970 | if (ret) | 1093 | if (ret) |
971 | type = sdata->vif.type; | 1094 | type = sdata->vif.type; |
972 | 1095 | ||
1096 | /* | ||
1097 | * Ignore return value here, there's not much we can do since | ||
1098 | * the driver changed the interface type internally already. | ||
1099 | * The warnings will hopefully make driver authors fix it :-) | ||
1100 | */ | ||
1101 | ieee80211_check_queues(sdata); | ||
1102 | |||
973 | ieee80211_setup_sdata(sdata, type); | 1103 | ieee80211_setup_sdata(sdata, type); |
974 | 1104 | ||
975 | err = ieee80211_do_open(sdata->dev, false); | 1105 | err = ieee80211_do_open(sdata->dev, false); |
@@ -1133,11 +1263,15 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1133 | struct net_device *ndev; | 1263 | struct net_device *ndev; |
1134 | struct ieee80211_sub_if_data *sdata = NULL; | 1264 | struct ieee80211_sub_if_data *sdata = NULL; |
1135 | int ret, i; | 1265 | int ret, i; |
1266 | int txqs = 1; | ||
1136 | 1267 | ||
1137 | ASSERT_RTNL(); | 1268 | ASSERT_RTNL(); |
1138 | 1269 | ||
1270 | if (local->hw.queues >= IEEE80211_NUM_ACS) | ||
1271 | txqs = IEEE80211_NUM_ACS; | ||
1272 | |||
1139 | ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, | 1273 | ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, |
1140 | name, ieee80211_if_setup, local->hw.queues, 1); | 1274 | name, ieee80211_if_setup, txqs, 1); |
1141 | if (!ndev) | 1275 | if (!ndev) |
1142 | return -ENOMEM; | 1276 | return -ENOMEM; |
1143 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); | 1277 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); |
@@ -1192,6 +1326,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1192 | sizeof(sdata->rc_rateidx_mcs_mask[i])); | 1326 | sizeof(sdata->rc_rateidx_mcs_mask[i])); |
1193 | } | 1327 | } |
1194 | 1328 | ||
1329 | ieee80211_set_default_queues(sdata); | ||
1330 | |||
1195 | /* setup type-dependent data */ | 1331 | /* setup type-dependent data */ |
1196 | ieee80211_setup_sdata(sdata, type); | 1332 | ieee80211_setup_sdata(sdata, type); |
1197 | 1333 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 16336480c631..ac79d5e8e0d0 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -557,8 +557,10 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
557 | WIPHY_FLAG_4ADDR_AP | | 557 | WIPHY_FLAG_4ADDR_AP | |
558 | WIPHY_FLAG_4ADDR_STATION | | 558 | WIPHY_FLAG_4ADDR_STATION | |
559 | WIPHY_FLAG_REPORTS_OBSS | | 559 | WIPHY_FLAG_REPORTS_OBSS | |
560 | WIPHY_FLAG_OFFCHAN_TX | | 560 | WIPHY_FLAG_OFFCHAN_TX; |
561 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 561 | |
562 | if (ops->remain_on_channel) | ||
563 | wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | ||
562 | 564 | ||
563 | wiphy->features = NL80211_FEATURE_SK_TX_STATUS | | 565 | wiphy->features = NL80211_FEATURE_SK_TX_STATUS | |
564 | NL80211_FEATURE_HT_IBSS; | 566 | NL80211_FEATURE_HT_IBSS; |
@@ -589,6 +591,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
589 | local->hw.max_report_rates = 0; | 591 | local->hw.max_report_rates = 0; |
590 | local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; | 592 | local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; |
591 | local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; | 593 | local->hw.max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF; |
594 | local->hw.offchannel_tx_hw_queue = IEEE80211_INVAL_HW_QUEUE; | ||
592 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 595 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
593 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 596 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
594 | local->user_power_level = -1; | 597 | local->user_power_level = -1; |
@@ -685,6 +688,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
685 | WLAN_CIPHER_SUITE_AES_CMAC | 688 | WLAN_CIPHER_SUITE_AES_CMAC |
686 | }; | 689 | }; |
687 | 690 | ||
691 | if (hw->flags & IEEE80211_HW_QUEUE_CONTROL && | ||
692 | (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE || | ||
693 | local->hw.offchannel_tx_hw_queue >= local->hw.queues)) | ||
694 | return -EINVAL; | ||
695 | |||
688 | if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) | 696 | if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) |
689 | #ifdef CONFIG_PM | 697 | #ifdef CONFIG_PM |
690 | && (!local->ops->suspend || !local->ops->resume) | 698 | && (!local->ops->suspend || !local->ops->resume) |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e5fbb7cf3562..133c118526fb 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -13,9 +13,6 @@ | |||
13 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
14 | #include "mesh.h" | 14 | #include "mesh.h" |
15 | 15 | ||
16 | #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 | ||
17 | #define MESHCONF_CAPAB_FORWARDING 0x08 | ||
18 | |||
19 | #define TMR_RUNNING_HK 0 | 16 | #define TMR_RUNNING_HK 0 |
20 | #define TMR_RUNNING_MP 1 | 17 | #define TMR_RUNNING_MP 1 |
21 | #define TMR_RUNNING_MPR 2 | 18 | #define TMR_RUNNING_MPR 2 |
@@ -69,11 +66,13 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data) | |||
69 | * | 66 | * |
70 | * @ie: information elements of a management frame from the mesh peer | 67 | * @ie: information elements of a management frame from the mesh peer |
71 | * @sdata: local mesh subif | 68 | * @sdata: local mesh subif |
69 | * @basic_rates: BSSBasicRateSet of the peer candidate | ||
72 | * | 70 | * |
73 | * This function checks if the mesh configuration of a mesh point matches the | 71 | * This function checks if the mesh configuration of a mesh point matches the |
74 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. | 72 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. |
75 | */ | 73 | */ |
76 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) | 74 | bool mesh_matches_local(struct ieee802_11_elems *ie, |
75 | struct ieee80211_sub_if_data *sdata, u32 basic_rates) | ||
77 | { | 76 | { |
78 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 77 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
79 | struct ieee80211_local *local = sdata->local; | 78 | struct ieee80211_local *local = sdata->local; |
@@ -97,10 +96,13 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat | |||
97 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) | 96 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) |
98 | goto mismatch; | 97 | goto mismatch; |
99 | 98 | ||
99 | if (sdata->vif.bss_conf.basic_rates != basic_rates) | ||
100 | goto mismatch; | ||
101 | |||
100 | /* disallow peering with mismatched channel types for now */ | 102 | /* disallow peering with mismatched channel types for now */ |
101 | if (ie->ht_info_elem && | 103 | if (ie->ht_operation && |
102 | (local->_oper_channel_type != | 104 | (local->_oper_channel_type != |
103 | ieee80211_ht_info_to_channel_type(ie->ht_info_elem))) | 105 | ieee80211_ht_oper_to_channel_type(ie->ht_operation))) |
104 | goto mismatch; | 106 | goto mismatch; |
105 | 107 | ||
106 | return true; | 108 | return true; |
@@ -251,8 +253,10 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
251 | /* Mesh capability */ | 253 | /* Mesh capability */ |
252 | ifmsh->accepting_plinks = mesh_plink_availables(sdata); | 254 | ifmsh->accepting_plinks = mesh_plink_availables(sdata); |
253 | *pos = MESHCONF_CAPAB_FORWARDING; | 255 | *pos = MESHCONF_CAPAB_FORWARDING; |
254 | *pos++ |= ifmsh->accepting_plinks ? | 256 | *pos |= ifmsh->accepting_plinks ? |
255 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 257 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
258 | *pos++ |= ifmsh->adjusting_tbtt ? | ||
259 | MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; | ||
256 | *pos++ = 0x00; | 260 | *pos++ = 0x00; |
257 | 261 | ||
258 | return 0; | 262 | return 0; |
@@ -371,7 +375,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, | |||
371 | return 0; | 375 | return 0; |
372 | } | 376 | } |
373 | 377 | ||
374 | int mesh_add_ht_info_ie(struct sk_buff *skb, | 378 | int mesh_add_ht_oper_ie(struct sk_buff *skb, |
375 | struct ieee80211_sub_if_data *sdata) | 379 | struct ieee80211_sub_if_data *sdata) |
376 | { | 380 | { |
377 | struct ieee80211_local *local = sdata->local; | 381 | struct ieee80211_local *local = sdata->local; |
@@ -385,11 +389,11 @@ int mesh_add_ht_info_ie(struct sk_buff *skb, | |||
385 | if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT) | 389 | if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT) |
386 | return 0; | 390 | return 0; |
387 | 391 | ||
388 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_info)) | 392 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_operation)) |
389 | return -ENOMEM; | 393 | return -ENOMEM; |
390 | 394 | ||
391 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_info)); | 395 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); |
392 | ieee80211_ie_build_ht_info(pos, ht_cap, channel, channel_type); | 396 | ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type); |
393 | 397 | ||
394 | return 0; | 398 | return 0; |
395 | } | 399 | } |
@@ -573,14 +577,21 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
573 | ieee80211_configure_filter(local); | 577 | ieee80211_configure_filter(local); |
574 | 578 | ||
575 | ifmsh->mesh_cc_id = 0; /* Disabled */ | 579 | ifmsh->mesh_cc_id = 0; /* Disabled */ |
576 | ifmsh->mesh_sp_id = 0; /* Neighbor Offset */ | ||
577 | ifmsh->mesh_auth_id = 0; /* Disabled */ | 580 | ifmsh->mesh_auth_id = 0; /* Disabled */ |
581 | /* register sync ops from extensible synchronization framework */ | ||
582 | ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id); | ||
583 | ifmsh->adjusting_tbtt = false; | ||
584 | ifmsh->sync_offset_clockdrift_max = 0; | ||
578 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); | 585 | set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags); |
579 | ieee80211_mesh_root_setup(ifmsh); | 586 | ieee80211_mesh_root_setup(ifmsh); |
580 | ieee80211_queue_work(&local->hw, &sdata->work); | 587 | ieee80211_queue_work(&local->hw, &sdata->work); |
581 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; | 588 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; |
589 | sdata->vif.bss_conf.basic_rates = | ||
590 | ieee80211_mandatory_rates(sdata->local, | ||
591 | sdata->local->hw.conf.channel->band); | ||
582 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | | 592 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
583 | BSS_CHANGED_BEACON_ENABLED | | 593 | BSS_CHANGED_BEACON_ENABLED | |
594 | BSS_CHANGED_BASIC_RATES | | ||
584 | BSS_CHANGED_BEACON_INT); | 595 | BSS_CHANGED_BEACON_INT); |
585 | } | 596 | } |
586 | 597 | ||
@@ -616,9 +627,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
616 | struct ieee80211_rx_status *rx_status) | 627 | struct ieee80211_rx_status *rx_status) |
617 | { | 628 | { |
618 | struct ieee80211_local *local = sdata->local; | 629 | struct ieee80211_local *local = sdata->local; |
630 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
619 | struct ieee802_11_elems elems; | 631 | struct ieee802_11_elems elems; |
620 | struct ieee80211_channel *channel; | 632 | struct ieee80211_channel *channel; |
621 | u32 supp_rates = 0; | 633 | u32 supp_rates = 0, basic_rates = 0; |
622 | size_t baselen; | 634 | size_t baselen; |
623 | int freq; | 635 | int freq; |
624 | enum ieee80211_band band = rx_status->band; | 636 | enum ieee80211_band band = rx_status->band; |
@@ -649,11 +661,16 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
649 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 661 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
650 | return; | 662 | return; |
651 | 663 | ||
664 | supp_rates = ieee80211_sta_get_rates(local, &elems, | ||
665 | band, &basic_rates); | ||
666 | |||
652 | if (elems.mesh_id && elems.mesh_config && | 667 | if (elems.mesh_id && elems.mesh_config && |
653 | mesh_matches_local(&elems, sdata)) { | 668 | mesh_matches_local(&elems, sdata, basic_rates)) |
654 | supp_rates = ieee80211_sta_get_rates(local, &elems, band); | ||
655 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems); | 669 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, &elems); |
656 | } | 670 | |
671 | if (ifmsh->sync_ops) | ||
672 | ifmsh->sync_ops->rx_bcn_presp(sdata, | ||
673 | stype, mgmt, &elems, rx_status); | ||
657 | } | 674 | } |
658 | 675 | ||
659 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | 676 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, |
@@ -721,6 +738,9 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
721 | 738 | ||
722 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) | 739 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) |
723 | ieee80211_mesh_rootpath(sdata); | 740 | ieee80211_mesh_rootpath(sdata); |
741 | |||
742 | if (test_and_clear_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags)) | ||
743 | mesh_sync_adjust_tbtt(sdata); | ||
724 | } | 744 | } |
725 | 745 | ||
726 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | 746 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) |
@@ -761,4 +781,5 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
761 | (unsigned long) sdata); | 781 | (unsigned long) sdata); |
762 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); | 782 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
763 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); | 783 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
784 | spin_lock_init(&ifmsh->sync_offset_lock); | ||
764 | } | 785 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 8d53b71378e3..4ad738988801 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -19,6 +19,20 @@ | |||
19 | /* Data structures */ | 19 | /* Data structures */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * enum mesh_config_capab_flags - mesh config IE capability flags | ||
23 | * | ||
24 | * @MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish | ||
25 | * additional mesh peerings with other mesh STAs | ||
26 | * @MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs | ||
27 | * @MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure is ongoing | ||
28 | */ | ||
29 | enum mesh_config_capab_flags { | ||
30 | MESHCONF_CAPAB_ACCEPT_PLINKS = BIT(0), | ||
31 | MESHCONF_CAPAB_FORWARDING = BIT(3), | ||
32 | MESHCONF_CAPAB_TBTT_ADJUSTING = BIT(5), | ||
33 | }; | ||
34 | |||
35 | /** | ||
22 | * enum mesh_path_flags - mac80211 mesh path flags | 36 | * enum mesh_path_flags - mac80211 mesh path flags |
23 | * | 37 | * |
24 | * | 38 | * |
@@ -56,12 +70,15 @@ enum mesh_path_flags { | |||
56 | * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to | 70 | * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to |
57 | * grow | 71 | * grow |
58 | * @MESH_WORK_ROOT: the mesh root station needs to send a frame | 72 | * @MESH_WORK_ROOT: the mesh root station needs to send a frame |
73 | * @MESH_WORK_DRIFT_ADJUST: time to compensate for clock drift relative to other | ||
74 | * mesh nodes | ||
59 | */ | 75 | */ |
60 | enum mesh_deferred_task_flags { | 76 | enum mesh_deferred_task_flags { |
61 | MESH_WORK_HOUSEKEEPING, | 77 | MESH_WORK_HOUSEKEEPING, |
62 | MESH_WORK_GROW_MPATH_TABLE, | 78 | MESH_WORK_GROW_MPATH_TABLE, |
63 | MESH_WORK_GROW_MPP_TABLE, | 79 | MESH_WORK_GROW_MPP_TABLE, |
64 | MESH_WORK_ROOT, | 80 | MESH_WORK_ROOT, |
81 | MESH_WORK_DRIFT_ADJUST, | ||
65 | }; | 82 | }; |
66 | 83 | ||
67 | /** | 84 | /** |
@@ -86,6 +103,7 @@ enum mesh_deferred_task_flags { | |||
86 | * mpath itself. No need to take this lock when adding or removing | 103 | * mpath itself. No need to take this lock when adding or removing |
87 | * an mpath to a hash bucket on a path table. | 104 | * an mpath to a hash bucket on a path table. |
88 | * @rann_snd_addr: the RANN sender address | 105 | * @rann_snd_addr: the RANN sender address |
106 | * @rann_metric: the aggregated path metric towards the root node | ||
89 | * @is_root: the destination station of this path is a root node | 107 | * @is_root: the destination station of this path is a root node |
90 | * @is_gate: the destination station of this path is a mesh gate | 108 | * @is_gate: the destination station of this path is a mesh gate |
91 | * | 109 | * |
@@ -112,6 +130,7 @@ struct mesh_path { | |||
112 | enum mesh_path_flags flags; | 130 | enum mesh_path_flags flags; |
113 | spinlock_t state_lock; | 131 | spinlock_t state_lock; |
114 | u8 rann_snd_addr[ETH_ALEN]; | 132 | u8 rann_snd_addr[ETH_ALEN]; |
133 | u32 rann_metric; | ||
115 | bool is_root; | 134 | bool is_root; |
116 | bool is_gate; | 135 | bool is_gate; |
117 | }; | 136 | }; |
@@ -204,7 +223,7 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | |||
204 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | 223 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, |
205 | struct ieee80211_sub_if_data *sdata); | 224 | struct ieee80211_sub_if_data *sdata); |
206 | bool mesh_matches_local(struct ieee802_11_elems *ie, | 225 | bool mesh_matches_local(struct ieee802_11_elems *ie, |
207 | struct ieee80211_sub_if_data *sdata); | 226 | struct ieee80211_sub_if_data *sdata, u32 basic_rates); |
208 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); | 227 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
209 | void mesh_mgmt_ies_add(struct sk_buff *skb, | 228 | void mesh_mgmt_ies_add(struct sk_buff *skb, |
210 | struct ieee80211_sub_if_data *sdata); | 229 | struct ieee80211_sub_if_data *sdata); |
@@ -220,7 +239,7 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
220 | struct ieee80211_sub_if_data *sdata); | 239 | struct ieee80211_sub_if_data *sdata); |
221 | int mesh_add_ht_cap_ie(struct sk_buff *skb, | 240 | int mesh_add_ht_cap_ie(struct sk_buff *skb, |
222 | struct ieee80211_sub_if_data *sdata); | 241 | struct ieee80211_sub_if_data *sdata); |
223 | int mesh_add_ht_info_ie(struct sk_buff *skb, | 242 | int mesh_add_ht_oper_ie(struct sk_buff *skb, |
224 | struct ieee80211_sub_if_data *sdata); | 243 | struct ieee80211_sub_if_data *sdata); |
225 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | 244 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); |
226 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | 245 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); |
@@ -232,6 +251,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); | |||
232 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); | 251 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); |
233 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); | 252 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); |
234 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); | 253 | void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); |
254 | struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method); | ||
235 | 255 | ||
236 | /* Mesh paths */ | 256 | /* Mesh paths */ |
237 | int mesh_nexthop_lookup(struct sk_buff *skb, | 257 | int mesh_nexthop_lookup(struct sk_buff *skb, |
@@ -325,6 +345,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata); | |||
325 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata); | 345 | void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata); |
326 | void mesh_plink_quiesce(struct sta_info *sta); | 346 | void mesh_plink_quiesce(struct sta_info *sta); |
327 | void mesh_plink_restart(struct sta_info *sta); | 347 | void mesh_plink_restart(struct sta_info *sta); |
348 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); | ||
328 | #else | 349 | #else |
329 | #define mesh_allocated 0 | 350 | #define mesh_allocated 0 |
330 | static inline void | 351 | static inline void |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 1c6f3d02aebf..a80da3784a25 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -86,8 +86,8 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae) | |||
86 | #define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0) | 86 | #define PERR_IE_TARGET_RCODE(x) u16_field_get(x, 13, 0) |
87 | 87 | ||
88 | #define MSEC_TO_TU(x) (x*1000/1024) | 88 | #define MSEC_TO_TU(x) (x*1000/1024) |
89 | #define SN_GT(x, y) ((long) (y) - (long) (x) < 0) | 89 | #define SN_GT(x, y) ((s32)(y - x) < 0) |
90 | #define SN_LT(x, y) ((long) (x) - (long) (y) < 0) | 90 | #define SN_LT(x, y) ((s32)(x - y) < 0) |
91 | 91 | ||
92 | #define net_traversal_jiffies(s) \ | 92 | #define net_traversal_jiffies(s) \ |
93 | msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) | 93 | msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) |
@@ -732,11 +732,12 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
732 | struct ieee80211_rann_ie *rann) | 732 | struct ieee80211_rann_ie *rann) |
733 | { | 733 | { |
734 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 734 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
735 | struct ieee80211_local *local = sdata->local; | ||
736 | struct sta_info *sta; | ||
735 | struct mesh_path *mpath; | 737 | struct mesh_path *mpath; |
736 | u8 ttl, flags, hopcount; | 738 | u8 ttl, flags, hopcount; |
737 | u8 *orig_addr; | 739 | u8 *orig_addr; |
738 | u32 orig_sn, metric; | 740 | u32 orig_sn, metric, metric_txsta, interval; |
739 | u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; | ||
740 | bool root_is_gate; | 741 | bool root_is_gate; |
741 | 742 | ||
742 | ttl = rann->rann_ttl; | 743 | ttl = rann->rann_ttl; |
@@ -748,10 +749,11 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
748 | flags = rann->rann_flags; | 749 | flags = rann->rann_flags; |
749 | root_is_gate = !!(flags & RANN_FLAG_IS_GATE); | 750 | root_is_gate = !!(flags & RANN_FLAG_IS_GATE); |
750 | orig_addr = rann->rann_addr; | 751 | orig_addr = rann->rann_addr; |
751 | orig_sn = rann->rann_seq; | 752 | orig_sn = le32_to_cpu(rann->rann_seq); |
753 | interval = le32_to_cpu(rann->rann_interval); | ||
752 | hopcount = rann->rann_hopcount; | 754 | hopcount = rann->rann_hopcount; |
753 | hopcount++; | 755 | hopcount++; |
754 | metric = rann->rann_metric; | 756 | metric = le32_to_cpu(rann->rann_metric); |
755 | 757 | ||
756 | /* Ignore our own RANNs */ | 758 | /* Ignore our own RANNs */ |
757 | if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0) | 759 | if (compare_ether_addr(orig_addr, sdata->vif.addr) == 0) |
@@ -761,6 +763,14 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
761 | orig_addr, mgmt->sa, root_is_gate); | 763 | orig_addr, mgmt->sa, root_is_gate); |
762 | 764 | ||
763 | rcu_read_lock(); | 765 | rcu_read_lock(); |
766 | sta = sta_info_get(sdata, mgmt->sa); | ||
767 | if (!sta) { | ||
768 | rcu_read_unlock(); | ||
769 | return; | ||
770 | } | ||
771 | |||
772 | metric_txsta = airtime_link_metric_get(local, sta); | ||
773 | |||
764 | mpath = mesh_path_lookup(orig_addr, sdata); | 774 | mpath = mesh_path_lookup(orig_addr, sdata); |
765 | if (!mpath) { | 775 | if (!mpath) { |
766 | mesh_path_add(orig_addr, sdata); | 776 | mesh_path_add(orig_addr, sdata); |
@@ -780,14 +790,16 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
780 | mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); | 790 | mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); |
781 | } | 791 | } |
782 | 792 | ||
783 | if (mpath->sn < orig_sn && ifmsh->mshcfg.dot11MeshForwarding) { | 793 | if ((SN_LT(mpath->sn, orig_sn) || (mpath->sn == orig_sn && |
794 | metric < mpath->rann_metric)) && ifmsh->mshcfg.dot11MeshForwarding) { | ||
784 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, | 795 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, |
785 | cpu_to_le32(orig_sn), | 796 | cpu_to_le32(orig_sn), |
786 | 0, NULL, 0, broadcast_addr, | 797 | 0, NULL, 0, broadcast_addr, |
787 | hopcount, ttl, cpu_to_le32(interval), | 798 | hopcount, ttl, cpu_to_le32(interval), |
788 | cpu_to_le32(metric + mpath->metric), | 799 | cpu_to_le32(metric + metric_txsta), |
789 | 0, sdata); | 800 | 0, sdata); |
790 | mpath->sn = orig_sn; | 801 | mpath->sn = orig_sn; |
802 | mpath->rann_metric = metric + metric_txsta; | ||
791 | } | 803 | } |
792 | 804 | ||
793 | /* Using individually addressed PREQ for root node */ | 805 | /* Using individually addressed PREQ for root node */ |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 4e53c4cbca9e..9c836e774fbd 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -187,7 +187,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
187 | 2 + sdata->u.mesh.mesh_id_len + | 187 | 2 + sdata->u.mesh.mesh_id_len + |
188 | 2 + sizeof(struct ieee80211_meshconf_ie) + | 188 | 2 + sizeof(struct ieee80211_meshconf_ie) + |
189 | 2 + sizeof(struct ieee80211_ht_cap) + | 189 | 2 + sizeof(struct ieee80211_ht_cap) + |
190 | 2 + sizeof(struct ieee80211_ht_info) + | 190 | 2 + sizeof(struct ieee80211_ht_operation) + |
191 | 2 + 8 + /* peering IE */ | 191 | 2 + 8 + /* peering IE */ |
192 | sdata->u.mesh.ie_len); | 192 | sdata->u.mesh.ie_len); |
193 | if (!skb) | 193 | if (!skb) |
@@ -212,8 +212,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
212 | pos = skb_put(skb, 2); | 212 | pos = skb_put(skb, 2); |
213 | memcpy(pos + 2, &plid, 2); | 213 | memcpy(pos + 2, &plid, 2); |
214 | } | 214 | } |
215 | if (ieee80211_add_srates_ie(&sdata->vif, skb) || | 215 | if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || |
216 | ieee80211_add_ext_srates_ie(&sdata->vif, skb) || | 216 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || |
217 | mesh_add_rsn_ie(skb, sdata) || | 217 | mesh_add_rsn_ie(skb, sdata) || |
218 | mesh_add_meshid_ie(skb, sdata) || | 218 | mesh_add_meshid_ie(skb, sdata) || |
219 | mesh_add_meshconf_ie(skb, sdata)) | 219 | mesh_add_meshconf_ie(skb, sdata)) |
@@ -263,7 +263,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
263 | 263 | ||
264 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { | 264 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { |
265 | if (mesh_add_ht_cap_ie(skb, sdata) || | 265 | if (mesh_add_ht_cap_ie(skb, sdata) || |
266 | mesh_add_ht_info_ie(skb, sdata)) | 266 | mesh_add_ht_oper_ie(skb, sdata)) |
267 | return -1; | 267 | return -1; |
268 | } | 268 | } |
269 | 269 | ||
@@ -465,6 +465,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
465 | bool deactivated, matches_local = true; | 465 | bool deactivated, matches_local = true; |
466 | u8 ie_len; | 466 | u8 ie_len; |
467 | u8 *baseaddr; | 467 | u8 *baseaddr; |
468 | u32 rates, basic_rates = 0; | ||
468 | __le16 plid, llid, reason; | 469 | __le16 plid, llid, reason; |
469 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 470 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
470 | static const char *mplstates[] = { | 471 | static const char *mplstates[] = { |
@@ -559,8 +560,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
559 | 560 | ||
560 | /* Now we will figure out the appropriate event... */ | 561 | /* Now we will figure out the appropriate event... */ |
561 | event = PLINK_UNDEFINED; | 562 | event = PLINK_UNDEFINED; |
563 | rates = ieee80211_sta_get_rates(local, &elems, | ||
564 | rx_status->band, &basic_rates); | ||
565 | |||
562 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && | 566 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && |
563 | (!mesh_matches_local(&elems, sdata))) { | 567 | (!mesh_matches_local(&elems, sdata, basic_rates))) { |
564 | matches_local = false; | 568 | matches_local = false; |
565 | switch (ftype) { | 569 | switch (ftype) { |
566 | case WLAN_SP_MESH_PEERING_OPEN: | 570 | case WLAN_SP_MESH_PEERING_OPEN: |
@@ -583,7 +587,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
583 | return; | 587 | return; |
584 | } else if (!sta) { | 588 | } else if (!sta) { |
585 | /* ftype == WLAN_SP_MESH_PEERING_OPEN */ | 589 | /* ftype == WLAN_SP_MESH_PEERING_OPEN */ |
586 | u32 rates; | ||
587 | 590 | ||
588 | rcu_read_unlock(); | 591 | rcu_read_unlock(); |
589 | 592 | ||
@@ -591,8 +594,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
591 | mpl_dbg("Mesh plink error: no more free plinks\n"); | 594 | mpl_dbg("Mesh plink error: no more free plinks\n"); |
592 | return; | 595 | return; |
593 | } | 596 | } |
594 | |||
595 | rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); | ||
596 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems); | 597 | sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems); |
597 | if (!sta) { | 598 | if (!sta) { |
598 | mpl_dbg("Mesh plink error: plink table full\n"); | 599 | mpl_dbg("Mesh plink error: plink table full\n"); |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c new file mode 100644 index 000000000000..f78b0139856f --- /dev/null +++ b/net/mac80211/mesh_sync.c | |||
@@ -0,0 +1,296 @@ | |||
1 | /* | ||
2 | * Copyright 2011-2012, Pavel Zubarev <pavel.zubarev@gmail.com> | ||
3 | * Copyright 2011-2012, Marco Porsch <marco.porsch@s2005.tu-chemnitz.de> | ||
4 | * Copyright 2011-2012, cozybit Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include "ieee80211_i.h" | ||
12 | #include "mesh.h" | ||
13 | #include "driver-ops.h" | ||
14 | |||
15 | #ifdef CONFIG_MAC80211_VERBOSE_MESH_SYNC_DEBUG | ||
16 | #define msync_dbg(fmt, args...) \ | ||
17 | printk(KERN_DEBUG "Mesh sync (%s): " fmt "\n", sdata->name, ##args) | ||
18 | #else | ||
19 | #define msync_dbg(fmt, args...) do { (void)(0); } while (0) | ||
20 | #endif | ||
21 | |||
22 | /* This is not in the standard. It represents a tolerable tbtt drift below | ||
23 | * which we do no TSF adjustment. | ||
24 | */ | ||
25 | #define TBTT_MINIMUM_ADJUSTMENT 10 | ||
26 | |||
27 | struct sync_method { | ||
28 | u8 method; | ||
29 | struct ieee80211_mesh_sync_ops ops; | ||
30 | }; | ||
31 | |||
32 | /** | ||
33 | * mesh_peer_tbtt_adjusting - check if an mp is currently adjusting its TBTT | ||
34 | * | ||
35 | * @ie: information elements of a management frame from the mesh peer | ||
36 | */ | ||
37 | static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) | ||
38 | { | ||
39 | return (ie->mesh_config->meshconf_cap & | ||
40 | MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; | ||
41 | } | ||
42 | |||
43 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | ||
44 | { | ||
45 | struct ieee80211_local *local = sdata->local; | ||
46 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
47 | /* sdata->vif.bss_conf.beacon_int in 1024us units, 0.04% */ | ||
48 | u64 beacon_int_fraction = sdata->vif.bss_conf.beacon_int * 1024 / 2500; | ||
49 | u64 tsf; | ||
50 | u64 tsfdelta; | ||
51 | |||
52 | spin_lock_bh(&ifmsh->sync_offset_lock); | ||
53 | |||
54 | if (ifmsh->sync_offset_clockdrift_max < beacon_int_fraction) { | ||
55 | msync_dbg("TBTT : max clockdrift=%lld; adjusting", | ||
56 | (long long) ifmsh->sync_offset_clockdrift_max); | ||
57 | tsfdelta = -ifmsh->sync_offset_clockdrift_max; | ||
58 | ifmsh->sync_offset_clockdrift_max = 0; | ||
59 | } else { | ||
60 | msync_dbg("TBTT : max clockdrift=%lld; adjusting by %llu", | ||
61 | (long long) ifmsh->sync_offset_clockdrift_max, | ||
62 | (unsigned long long) beacon_int_fraction); | ||
63 | tsfdelta = -beacon_int_fraction; | ||
64 | ifmsh->sync_offset_clockdrift_max -= beacon_int_fraction; | ||
65 | } | ||
66 | |||
67 | tsf = drv_get_tsf(local, sdata); | ||
68 | if (tsf != -1ULL) | ||
69 | drv_set_tsf(local, sdata, tsf + tsfdelta); | ||
70 | spin_unlock_bh(&ifmsh->sync_offset_lock); | ||
71 | } | ||
72 | |||
73 | static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | ||
74 | u16 stype, | ||
75 | struct ieee80211_mgmt *mgmt, | ||
76 | struct ieee802_11_elems *elems, | ||
77 | struct ieee80211_rx_status *rx_status) | ||
78 | { | ||
79 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
80 | struct ieee80211_local *local = sdata->local; | ||
81 | struct sta_info *sta; | ||
82 | u64 t_t, t_r; | ||
83 | |||
84 | WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); | ||
85 | |||
86 | /* standard mentions only beacons */ | ||
87 | if (stype != IEEE80211_STYPE_BEACON) | ||
88 | return; | ||
89 | |||
90 | /* The current tsf is a first approximation for the timestamp | ||
91 | * for the received beacon. Further down we try to get a | ||
92 | * better value from the rx_status->mactime field if | ||
93 | * available. Also we have to call drv_get_tsf() before | ||
94 | * entering the rcu-read section.*/ | ||
95 | t_r = drv_get_tsf(local, sdata); | ||
96 | |||
97 | rcu_read_lock(); | ||
98 | sta = sta_info_get(sdata, mgmt->sa); | ||
99 | if (!sta) | ||
100 | goto no_sync; | ||
101 | |||
102 | /* check offset sync conditions (13.13.2.2.1) | ||
103 | * | ||
104 | * TODO also sync to | ||
105 | * dot11MeshNbrOffsetMaxNeighbor non-peer non-MBSS neighbors | ||
106 | */ | ||
107 | |||
108 | if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { | ||
109 | clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); | ||
110 | msync_dbg("STA %pM : is adjusting TBTT", sta->sta.addr); | ||
111 | goto no_sync; | ||
112 | } | ||
113 | |||
114 | if (rx_status->flag & RX_FLAG_MACTIME_MPDU && rx_status->mactime) { | ||
115 | /* | ||
116 | * The mactime is defined as the time the first data symbol | ||
117 | * of the frame hits the PHY, and the timestamp of the beacon | ||
118 | * is defined as "the time that the data symbol containing the | ||
119 | * first bit of the timestamp is transmitted to the PHY plus | ||
120 | * the transmitting STA's delays through its local PHY from the | ||
121 | * MAC-PHY interface to its interface with the WM" (802.11 | ||
122 | * 11.1.2) | ||
123 | * | ||
124 | * T_r, in 13.13.2.2.2, is just defined as "the frame reception | ||
125 | * time" but we unless we interpret that time to be the same | ||
126 | * time of the beacon timestamp, the offset calculation will be | ||
127 | * off. Below we adjust t_r to be "the time at which the first | ||
128 | * symbol of the timestamp element in the beacon is received". | ||
129 | * This correction depends on the rate. | ||
130 | * | ||
131 | * Based on similar code in ibss.c | ||
132 | */ | ||
133 | int rate; | ||
134 | |||
135 | if (rx_status->flag & RX_FLAG_HT) { | ||
136 | /* TODO: | ||
137 | * In principle there could be HT-beacons (Dual Beacon | ||
138 | * HT Operation options), but for now ignore them and | ||
139 | * just use the primary (i.e. non-HT) beacons for | ||
140 | * synchronization. | ||
141 | * */ | ||
142 | goto no_sync; | ||
143 | } else | ||
144 | rate = local->hw.wiphy->bands[rx_status->band]-> | ||
145 | bitrates[rx_status->rate_idx].bitrate; | ||
146 | |||
147 | /* 24 bytes of header * 8 bits/byte * | ||
148 | * 10*(100 Kbps)/Mbps / rate (100 Kbps)*/ | ||
149 | t_r = rx_status->mactime + (24 * 8 * 10 / rate); | ||
150 | } | ||
151 | |||
152 | /* Timing offset calculation (see 13.13.2.2.2) */ | ||
153 | t_t = le64_to_cpu(mgmt->u.beacon.timestamp); | ||
154 | sta->t_offset = t_t - t_r; | ||
155 | |||
156 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | ||
157 | s64 t_clockdrift = sta->t_offset_setpoint | ||
158 | - sta->t_offset; | ||
159 | |||
160 | msync_dbg("STA %pM : sta->t_offset=%lld," | ||
161 | " sta->t_offset_setpoint=%lld," | ||
162 | " t_clockdrift=%lld", | ||
163 | sta->sta.addr, | ||
164 | (long long) sta->t_offset, | ||
165 | (long long) | ||
166 | sta->t_offset_setpoint, | ||
167 | (long long) t_clockdrift); | ||
168 | rcu_read_unlock(); | ||
169 | |||
170 | spin_lock_bh(&ifmsh->sync_offset_lock); | ||
171 | if (t_clockdrift > | ||
172 | ifmsh->sync_offset_clockdrift_max) | ||
173 | ifmsh->sync_offset_clockdrift_max | ||
174 | = t_clockdrift; | ||
175 | spin_unlock_bh(&ifmsh->sync_offset_lock); | ||
176 | |||
177 | } else { | ||
178 | sta->t_offset_setpoint = sta->t_offset; | ||
179 | set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); | ||
180 | msync_dbg("STA %pM : offset was invalid, " | ||
181 | " sta->t_offset=%lld", | ||
182 | sta->sta.addr, | ||
183 | (long long) sta->t_offset); | ||
184 | rcu_read_unlock(); | ||
185 | } | ||
186 | return; | ||
187 | |||
188 | no_sync: | ||
189 | rcu_read_unlock(); | ||
190 | } | ||
191 | |||
192 | static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | ||
193 | { | ||
194 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
195 | |||
196 | WARN_ON(ifmsh->mesh_sp_id | ||
197 | != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); | ||
198 | BUG_ON(!rcu_read_lock_held()); | ||
199 | |||
200 | spin_lock_bh(&ifmsh->sync_offset_lock); | ||
201 | |||
202 | if (ifmsh->sync_offset_clockdrift_max > | ||
203 | TBTT_MINIMUM_ADJUSTMENT) { | ||
204 | /* Since ajusting the tsf here would | ||
205 | * require a possibly blocking call | ||
206 | * to the driver tsf setter, we punt | ||
207 | * the tsf adjustment to the mesh tasklet | ||
208 | */ | ||
209 | msync_dbg("TBTT : kicking off TBTT " | ||
210 | "adjustment with " | ||
211 | "clockdrift_max=%lld", | ||
212 | ifmsh->sync_offset_clockdrift_max); | ||
213 | set_bit(MESH_WORK_DRIFT_ADJUST, | ||
214 | &ifmsh->wrkq_flags); | ||
215 | } else { | ||
216 | msync_dbg("TBTT : max clockdrift=%lld; " | ||
217 | "too small to adjust", | ||
218 | (long long) | ||
219 | ifmsh->sync_offset_clockdrift_max); | ||
220 | ifmsh->sync_offset_clockdrift_max = 0; | ||
221 | } | ||
222 | spin_unlock_bh(&ifmsh->sync_offset_lock); | ||
223 | } | ||
224 | |||
225 | static const u8 *mesh_get_vendor_oui(struct ieee80211_sub_if_data *sdata) | ||
226 | { | ||
227 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
228 | u8 offset; | ||
229 | |||
230 | if (!ifmsh->ie || !ifmsh->ie_len) | ||
231 | return NULL; | ||
232 | |||
233 | offset = ieee80211_ie_split_vendor(ifmsh->ie, | ||
234 | ifmsh->ie_len, 0); | ||
235 | |||
236 | if (!offset) | ||
237 | return NULL; | ||
238 | |||
239 | return ifmsh->ie + offset + 2; | ||
240 | } | ||
241 | |||
242 | static void mesh_sync_vendor_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | ||
243 | u16 stype, | ||
244 | struct ieee80211_mgmt *mgmt, | ||
245 | struct ieee802_11_elems *elems, | ||
246 | struct ieee80211_rx_status *rx_status) | ||
247 | { | ||
248 | const u8 *oui; | ||
249 | |||
250 | WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR); | ||
251 | msync_dbg("called mesh_sync_vendor_rx_bcn_presp"); | ||
252 | oui = mesh_get_vendor_oui(sdata); | ||
253 | /* here you would implement the vendor offset tracking for this oui */ | ||
254 | } | ||
255 | |||
256 | static void mesh_sync_vendor_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | ||
257 | { | ||
258 | const u8 *oui; | ||
259 | |||
260 | WARN_ON(sdata->u.mesh.mesh_sp_id != IEEE80211_SYNC_METHOD_VENDOR); | ||
261 | msync_dbg("called mesh_sync_vendor_adjust_tbtt"); | ||
262 | oui = mesh_get_vendor_oui(sdata); | ||
263 | /* here you would implement the vendor tsf adjustment for this oui */ | ||
264 | } | ||
265 | |||
266 | /* global variable */ | ||
267 | static struct sync_method sync_methods[] = { | ||
268 | { | ||
269 | .method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, | ||
270 | .ops = { | ||
271 | .rx_bcn_presp = &mesh_sync_offset_rx_bcn_presp, | ||
272 | .adjust_tbtt = &mesh_sync_offset_adjust_tbtt, | ||
273 | } | ||
274 | }, | ||
275 | { | ||
276 | .method = IEEE80211_SYNC_METHOD_VENDOR, | ||
277 | .ops = { | ||
278 | .rx_bcn_presp = &mesh_sync_vendor_rx_bcn_presp, | ||
279 | .adjust_tbtt = &mesh_sync_vendor_adjust_tbtt, | ||
280 | } | ||
281 | }, | ||
282 | }; | ||
283 | |||
284 | struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method) | ||
285 | { | ||
286 | struct ieee80211_mesh_sync_ops *ops = NULL; | ||
287 | u8 i; | ||
288 | |||
289 | for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) { | ||
290 | if (sync_methods[i].method == method) { | ||
291 | ops = &sync_methods[i].ops; | ||
292 | break; | ||
293 | } | ||
294 | } | ||
295 | return ops; | ||
296 | } | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 576fb25456dd..bbf1100d90d6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -171,122 +171,64 @@ static int ecw2cw(int ecw) | |||
171 | return (1 << ecw) - 1; | 171 | return (1 << ecw) - 1; |
172 | } | 172 | } |
173 | 173 | ||
174 | /* | 174 | static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, |
175 | * ieee80211_enable_ht should be called only after the operating band | 175 | struct ieee80211_ht_operation *ht_oper, |
176 | * has been determined as ht configuration depends on the hw's | 176 | const u8 *bssid, bool reconfig) |
177 | * HT abilities for a specific band. | ||
178 | */ | ||
179 | static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | ||
180 | struct ieee80211_ht_info *hti, | ||
181 | const u8 *bssid, u16 ap_ht_cap_flags, | ||
182 | bool beacon_htcap_ie) | ||
183 | { | 177 | { |
184 | struct ieee80211_local *local = sdata->local; | 178 | struct ieee80211_local *local = sdata->local; |
185 | struct ieee80211_supported_band *sband; | 179 | struct ieee80211_supported_band *sband; |
186 | struct sta_info *sta; | 180 | struct sta_info *sta; |
187 | u32 changed = 0; | 181 | u32 changed = 0; |
188 | int hti_cfreq; | ||
189 | u16 ht_opmode; | 182 | u16 ht_opmode; |
190 | bool enable_ht = true; | 183 | bool disable_40 = false; |
191 | enum nl80211_channel_type prev_chantype; | ||
192 | enum nl80211_channel_type rx_channel_type = NL80211_CHAN_NO_HT; | ||
193 | enum nl80211_channel_type tx_channel_type; | ||
194 | 184 | ||
195 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 185 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
196 | prev_chantype = sdata->vif.bss_conf.channel_type; | ||
197 | |||
198 | 186 | ||
199 | hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan, | 187 | switch (sdata->vif.bss_conf.channel_type) { |
200 | sband->band); | 188 | case NL80211_CHAN_HT40PLUS: |
201 | /* check that channel matches the right operating channel */ | 189 | if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40PLUS) |
202 | if (local->hw.conf.channel->center_freq != hti_cfreq) { | 190 | disable_40 = true; |
203 | /* Some APs mess this up, evidently. | 191 | break; |
204 | * Netgear WNDR3700 sometimes reports 4 higher than | 192 | case NL80211_CHAN_HT40MINUS: |
205 | * the actual channel, for instance. | 193 | if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40MINUS) |
206 | */ | 194 | disable_40 = true; |
207 | printk(KERN_DEBUG | 195 | break; |
208 | "%s: Wrong control channel in association" | 196 | default: |
209 | " response: configured center-freq: %d" | 197 | break; |
210 | " hti-cfreq: %d hti->control_chan: %d" | ||
211 | " band: %d. Disabling HT.\n", | ||
212 | sdata->name, | ||
213 | local->hw.conf.channel->center_freq, | ||
214 | hti_cfreq, hti->control_chan, | ||
215 | sband->band); | ||
216 | enable_ht = false; | ||
217 | } | ||
218 | |||
219 | if (enable_ht) { | ||
220 | rx_channel_type = NL80211_CHAN_HT20; | ||
221 | |||
222 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | ||
223 | !ieee80111_cfg_override_disables_ht40(sdata) && | ||
224 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && | ||
225 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { | ||
226 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
227 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
228 | rx_channel_type = NL80211_CHAN_HT40PLUS; | ||
229 | break; | ||
230 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
231 | rx_channel_type = NL80211_CHAN_HT40MINUS; | ||
232 | break; | ||
233 | } | ||
234 | } | ||
235 | } | 198 | } |
236 | 199 | ||
237 | tx_channel_type = ieee80211_get_tx_channel_type(local, rx_channel_type); | 200 | /* This can change during the lifetime of the BSS */ |
238 | 201 | if (!(ht_oper->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) | |
239 | if (local->tmp_channel) | 202 | disable_40 = true; |
240 | local->tmp_channel_type = rx_channel_type; | ||
241 | 203 | ||
242 | if (!ieee80211_set_channel_type(local, sdata, rx_channel_type)) { | 204 | mutex_lock(&local->sta_mtx); |
243 | /* can only fail due to HT40+/- mismatch */ | 205 | sta = sta_info_get(sdata, bssid); |
244 | rx_channel_type = NL80211_CHAN_HT20; | ||
245 | WARN_ON(!ieee80211_set_channel_type(local, sdata, | ||
246 | rx_channel_type)); | ||
247 | } | ||
248 | |||
249 | if (beacon_htcap_ie && (prev_chantype != rx_channel_type)) { | ||
250 | /* | ||
251 | * Whenever the AP announces the HT mode change that can be | ||
252 | * 40MHz intolerant or etc., it would be safer to stop tx | ||
253 | * queues before doing hw config to avoid buffer overflow. | ||
254 | */ | ||
255 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
256 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
257 | 206 | ||
258 | /* flush out all packets */ | 207 | WARN_ON_ONCE(!sta); |
259 | synchronize_net(); | ||
260 | 208 | ||
261 | drv_flush(local, false); | 209 | if (sta && !sta->supports_40mhz) |
262 | } | 210 | disable_40 = true; |
263 | 211 | ||
264 | /* channel_type change automatically detected */ | 212 | if (sta && (!reconfig || |
265 | ieee80211_hw_config(local, 0); | 213 | (disable_40 != !!(sta->sta.ht_cap.cap & |
214 | IEEE80211_HT_CAP_SUP_WIDTH_20_40)))) { | ||
266 | 215 | ||
267 | if (prev_chantype != tx_channel_type) { | 216 | if (disable_40) |
268 | rcu_read_lock(); | 217 | sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
269 | sta = sta_info_get(sdata, bssid); | 218 | else |
270 | if (sta) | 219 | sta->sta.ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
271 | rate_control_rate_update(local, sband, sta, | ||
272 | IEEE80211_RC_HT_CHANGED, | ||
273 | tx_channel_type); | ||
274 | rcu_read_unlock(); | ||
275 | 220 | ||
276 | if (beacon_htcap_ie) | 221 | rate_control_rate_update(local, sband, sta, |
277 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 222 | IEEE80211_RC_BW_CHANGED); |
278 | IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); | ||
279 | } | 223 | } |
224 | mutex_unlock(&local->sta_mtx); | ||
280 | 225 | ||
281 | ht_opmode = le16_to_cpu(hti->operation_mode); | 226 | ht_opmode = le16_to_cpu(ht_oper->operation_mode); |
282 | 227 | ||
283 | /* if bss configuration changed store the new one */ | 228 | /* if bss configuration changed store the new one */ |
284 | if (sdata->ht_opmode_valid != enable_ht || | 229 | if (!reconfig || (sdata->vif.bss_conf.ht_operation_mode != ht_opmode)) { |
285 | sdata->vif.bss_conf.ht_operation_mode != ht_opmode || | ||
286 | prev_chantype != rx_channel_type) { | ||
287 | changed |= BSS_CHANGED_HT; | 230 | changed |= BSS_CHANGED_HT; |
288 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | 231 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; |
289 | sdata->ht_opmode_valid = enable_ht; | ||
290 | } | 232 | } |
291 | 233 | ||
292 | return changed; | 234 | return changed; |
@@ -316,12 +258,12 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | |||
316 | } | 258 | } |
317 | 259 | ||
318 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | 260 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, |
319 | struct sk_buff *skb, const u8 *ht_info_ie, | 261 | struct sk_buff *skb, const u8 *ht_oper_ie, |
320 | struct ieee80211_supported_band *sband, | 262 | struct ieee80211_supported_band *sband, |
321 | struct ieee80211_channel *channel, | 263 | struct ieee80211_channel *channel, |
322 | enum ieee80211_smps_mode smps) | 264 | enum ieee80211_smps_mode smps) |
323 | { | 265 | { |
324 | struct ieee80211_ht_info *ht_info; | 266 | struct ieee80211_ht_operation *ht_oper; |
325 | u8 *pos; | 267 | u8 *pos; |
326 | u32 flags = channel->flags; | 268 | u32 flags = channel->flags; |
327 | u16 cap; | 269 | u16 cap; |
@@ -329,21 +271,21 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | |||
329 | 271 | ||
330 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); | 272 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); |
331 | 273 | ||
332 | if (!ht_info_ie) | 274 | if (!ht_oper_ie) |
333 | return; | 275 | return; |
334 | 276 | ||
335 | if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) | 277 | if (ht_oper_ie[1] < sizeof(struct ieee80211_ht_operation)) |
336 | return; | 278 | return; |
337 | 279 | ||
338 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | 280 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); |
339 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | 281 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); |
340 | 282 | ||
341 | ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); | 283 | ht_oper = (struct ieee80211_ht_operation *)(ht_oper_ie + 2); |
342 | 284 | ||
343 | /* determine capability flags */ | 285 | /* determine capability flags */ |
344 | cap = ht_cap.cap; | 286 | cap = ht_cap.cap; |
345 | 287 | ||
346 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 288 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
347 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 289 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
348 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | 290 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { |
349 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 291 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
@@ -358,6 +300,16 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | |||
358 | break; | 300 | break; |
359 | } | 301 | } |
360 | 302 | ||
303 | /* | ||
304 | * If 40 MHz was disabled associate as though we weren't | ||
305 | * capable of 40 MHz -- some broken APs will never fall | ||
306 | * back to trying to transmit in 20 MHz. | ||
307 | */ | ||
308 | if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_40MHZ) { | ||
309 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
310 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
311 | } | ||
312 | |||
361 | /* set SM PS mode properly */ | 313 | /* set SM PS mode properly */ |
362 | cap &= ~IEEE80211_HT_CAP_SM_PS; | 314 | cap &= ~IEEE80211_HT_CAP_SM_PS; |
363 | switch (smps) { | 315 | switch (smps) { |
@@ -557,7 +509,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
557 | } | 509 | } |
558 | 510 | ||
559 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 511 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
560 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie, | 512 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_operation_ie, |
561 | sband, local->oper_channel, ifmgd->ap_smps); | 513 | sband, local->oper_channel, ifmgd->ap_smps); |
562 | 514 | ||
563 | /* if present, add any custom non-vendor IEs that go after HT */ | 515 | /* if present, add any custom non-vendor IEs that go after HT */ |
@@ -1182,7 +1134,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1182 | if (!local->ops->conf_tx) | 1134 | if (!local->ops->conf_tx) |
1183 | return; | 1135 | return; |
1184 | 1136 | ||
1185 | if (local->hw.queues < 4) | 1137 | if (local->hw.queues < IEEE80211_NUM_ACS) |
1186 | return; | 1138 | return; |
1187 | 1139 | ||
1188 | if (!wmm_param) | 1140 | if (!wmm_param) |
@@ -1435,7 +1387,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1435 | sdata->vif.bss_conf.assoc = false; | 1387 | sdata->vif.bss_conf.assoc = false; |
1436 | 1388 | ||
1437 | /* on the next assoc, re-program HT parameters */ | 1389 | /* on the next assoc, re-program HT parameters */ |
1438 | sdata->ht_opmode_valid = false; | ||
1439 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); | 1390 | memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa)); |
1440 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); | 1391 | memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask)); |
1441 | 1392 | ||
@@ -1567,14 +1518,23 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1567 | ifmgd->nullfunc_failed = false; | 1518 | ifmgd->nullfunc_failed = false; |
1568 | ieee80211_send_nullfunc(sdata->local, sdata, 0); | 1519 | ieee80211_send_nullfunc(sdata->local, sdata, 0); |
1569 | } else { | 1520 | } else { |
1521 | int ssid_len; | ||
1522 | |||
1570 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1523 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1571 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0, | 1524 | if (WARN_ON_ONCE(ssid == NULL)) |
1572 | (u32) -1, true, false); | 1525 | ssid_len = 0; |
1526 | else | ||
1527 | ssid_len = ssid[1]; | ||
1528 | |||
1529 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, | ||
1530 | 0, (u32) -1, true, false); | ||
1573 | } | 1531 | } |
1574 | 1532 | ||
1575 | ifmgd->probe_send_count++; | 1533 | ifmgd->probe_send_count++; |
1576 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); | 1534 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); |
1577 | run_again(ifmgd, ifmgd->probe_timeout); | 1535 | run_again(ifmgd, ifmgd->probe_timeout); |
1536 | if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | ||
1537 | drv_flush(sdata->local, false); | ||
1578 | } | 1538 | } |
1579 | 1539 | ||
1580 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | 1540 | static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, |
@@ -1643,6 +1603,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1643 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1603 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1644 | struct sk_buff *skb; | 1604 | struct sk_buff *skb; |
1645 | const u8 *ssid; | 1605 | const u8 *ssid; |
1606 | int ssid_len; | ||
1646 | 1607 | ||
1647 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) | 1608 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) |
1648 | return NULL; | 1609 | return NULL; |
@@ -1653,8 +1614,13 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1653 | return NULL; | 1614 | return NULL; |
1654 | 1615 | ||
1655 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1616 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1617 | if (WARN_ON_ONCE(ssid == NULL)) | ||
1618 | ssid_len = 0; | ||
1619 | else | ||
1620 | ssid_len = ssid[1]; | ||
1621 | |||
1656 | skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, | 1622 | skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, |
1657 | (u32) -1, ssid + 2, ssid[1], | 1623 | (u32) -1, ssid + 2, ssid_len, |
1658 | NULL, 0, true); | 1624 | NULL, 0, true); |
1659 | 1625 | ||
1660 | return skb; | 1626 | return skb; |
@@ -2000,7 +1966,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2000 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 1966 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
2001 | u32 changed = 0; | 1967 | u32 changed = 0; |
2002 | int err; | 1968 | int err; |
2003 | u16 ap_ht_cap_flags; | ||
2004 | 1969 | ||
2005 | /* AssocResp and ReassocResp have identical structure */ | 1970 | /* AssocResp and ReassocResp have identical structure */ |
2006 | 1971 | ||
@@ -2051,7 +2016,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2051 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 2016 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
2052 | elems.ht_cap_elem, &sta->sta.ht_cap); | 2017 | elems.ht_cap_elem, &sta->sta.ht_cap); |
2053 | 2018 | ||
2054 | ap_ht_cap_flags = sta->sta.ht_cap.cap; | 2019 | sta->supports_40mhz = |
2020 | sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
2055 | 2021 | ||
2056 | rate_control_rate_init(sta); | 2022 | rate_control_rate_init(sta); |
2057 | 2023 | ||
@@ -2092,11 +2058,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2092 | ieee80211_set_wmm_default(sdata, false); | 2058 | ieee80211_set_wmm_default(sdata, false); |
2093 | changed |= BSS_CHANGED_QOS; | 2059 | changed |= BSS_CHANGED_QOS; |
2094 | 2060 | ||
2095 | if (elems.ht_info_elem && elems.wmm_param && | 2061 | if (elems.ht_operation && elems.wmm_param && |
2096 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2062 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
2097 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 2063 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, |
2098 | cbss->bssid, ap_ht_cap_flags, | 2064 | cbss->bssid, false); |
2099 | false); | ||
2100 | 2065 | ||
2101 | /* set AID and assoc capability, | 2066 | /* set AID and assoc capability, |
2102 | * ieee80211_set_associated() will tell the driver */ | 2067 | * ieee80211_set_associated() will tell the driver */ |
@@ -2319,7 +2284,7 @@ static const u64 care_about_ies = | |||
2319 | (1ULL << WLAN_EID_CHANNEL_SWITCH) | | 2284 | (1ULL << WLAN_EID_CHANNEL_SWITCH) | |
2320 | (1ULL << WLAN_EID_PWR_CONSTRAINT) | | 2285 | (1ULL << WLAN_EID_PWR_CONSTRAINT) | |
2321 | (1ULL << WLAN_EID_HT_CAPABILITY) | | 2286 | (1ULL << WLAN_EID_HT_CAPABILITY) | |
2322 | (1ULL << WLAN_EID_HT_INFORMATION); | 2287 | (1ULL << WLAN_EID_HT_OPERATION); |
2323 | 2288 | ||
2324 | static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | 2289 | static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, |
2325 | struct ieee80211_mgmt *mgmt, | 2290 | struct ieee80211_mgmt *mgmt, |
@@ -2468,11 +2433,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2468 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { | 2433 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { |
2469 | if (directed_tim) { | 2434 | if (directed_tim) { |
2470 | if (local->hw.conf.dynamic_ps_timeout > 0) { | 2435 | if (local->hw.conf.dynamic_ps_timeout > 0) { |
2471 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | 2436 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
2472 | ieee80211_hw_config(local, | 2437 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; |
2473 | IEEE80211_CONF_CHANGE_PS); | 2438 | ieee80211_hw_config(local, |
2439 | IEEE80211_CONF_CHANGE_PS); | ||
2440 | } | ||
2474 | ieee80211_send_nullfunc(local, sdata, 0); | 2441 | ieee80211_send_nullfunc(local, sdata, 0); |
2475 | } else { | 2442 | } else if (!local->pspolling && sdata->u.mgd.powersave) { |
2476 | local->pspolling = true; | 2443 | local->pspolling = true; |
2477 | 2444 | ||
2478 | /* | 2445 | /* |
@@ -2504,31 +2471,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2504 | erp_valid, erp_value); | 2471 | erp_valid, erp_value); |
2505 | 2472 | ||
2506 | 2473 | ||
2507 | if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && | 2474 | if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && |
2508 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { | 2475 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { |
2509 | struct sta_info *sta; | ||
2510 | struct ieee80211_supported_band *sband; | 2476 | struct ieee80211_supported_band *sband; |
2511 | u16 ap_ht_cap_flags; | ||
2512 | |||
2513 | rcu_read_lock(); | ||
2514 | |||
2515 | sta = sta_info_get(sdata, bssid); | ||
2516 | if (WARN_ON(!sta)) { | ||
2517 | rcu_read_unlock(); | ||
2518 | return; | ||
2519 | } | ||
2520 | 2477 | ||
2521 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 2478 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
2522 | 2479 | ||
2523 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 2480 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, |
2524 | elems.ht_cap_elem, &sta->sta.ht_cap); | 2481 | bssid, true); |
2525 | |||
2526 | ap_ht_cap_flags = sta->sta.ht_cap.cap; | ||
2527 | |||
2528 | rcu_read_unlock(); | ||
2529 | |||
2530 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | ||
2531 | bssid, ap_ht_cap_flags, true); | ||
2532 | } | 2482 | } |
2533 | 2483 | ||
2534 | /* Note: country IE parsing is done for us by cfg80211 */ | 2484 | /* Note: country IE parsing is done for us by cfg80211 */ |
@@ -3060,6 +3010,11 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3060 | struct sta_info *sta; | 3010 | struct sta_info *sta; |
3061 | bool have_sta = false; | 3011 | bool have_sta = false; |
3062 | int err; | 3012 | int err; |
3013 | int ht_cfreq; | ||
3014 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
3015 | const u8 *ht_oper_ie; | ||
3016 | const struct ieee80211_ht_operation *ht_oper = NULL; | ||
3017 | struct ieee80211_supported_band *sband; | ||
3063 | 3018 | ||
3064 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) | 3019 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) |
3065 | return -EINVAL; | 3020 | return -EINVAL; |
@@ -3081,17 +3036,76 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3081 | mutex_unlock(&local->mtx); | 3036 | mutex_unlock(&local->mtx); |
3082 | 3037 | ||
3083 | /* switch to the right channel */ | 3038 | /* switch to the right channel */ |
3039 | sband = local->hw.wiphy->bands[cbss->channel->band]; | ||
3040 | |||
3041 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; | ||
3042 | |||
3043 | if (sband->ht_cap.ht_supported) { | ||
3044 | ht_oper_ie = cfg80211_find_ie(WLAN_EID_HT_OPERATION, | ||
3045 | cbss->information_elements, | ||
3046 | cbss->len_information_elements); | ||
3047 | if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper)) | ||
3048 | ht_oper = (void *)(ht_oper_ie + 2); | ||
3049 | } | ||
3050 | |||
3051 | if (ht_oper) { | ||
3052 | ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan, | ||
3053 | cbss->channel->band); | ||
3054 | /* check that channel matches the right operating channel */ | ||
3055 | if (cbss->channel->center_freq != ht_cfreq) { | ||
3056 | /* | ||
3057 | * It's possible that some APs are confused here; | ||
3058 | * Netgear WNDR3700 sometimes reports 4 higher than | ||
3059 | * the actual channel in association responses, but | ||
3060 | * since we look at probe response/beacon data here | ||
3061 | * it should be OK. | ||
3062 | */ | ||
3063 | printk(KERN_DEBUG | ||
3064 | "%s: Wrong control channel: center-freq: %d" | ||
3065 | " ht-cfreq: %d ht->primary_chan: %d" | ||
3066 | " band: %d. Disabling HT.\n", | ||
3067 | sdata->name, cbss->channel->center_freq, | ||
3068 | ht_cfreq, ht_oper->primary_chan, | ||
3069 | cbss->channel->band); | ||
3070 | ht_oper = NULL; | ||
3071 | } | ||
3072 | } | ||
3073 | |||
3074 | if (ht_oper) { | ||
3075 | channel_type = NL80211_CHAN_HT20; | ||
3076 | |||
3077 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | ||
3078 | switch (ht_oper->ht_param & | ||
3079 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
3080 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
3081 | channel_type = NL80211_CHAN_HT40PLUS; | ||
3082 | break; | ||
3083 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
3084 | channel_type = NL80211_CHAN_HT40MINUS; | ||
3085 | break; | ||
3086 | } | ||
3087 | } | ||
3088 | } | ||
3089 | |||
3090 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | ||
3091 | /* can only fail due to HT40+/- mismatch */ | ||
3092 | channel_type = NL80211_CHAN_HT20; | ||
3093 | printk(KERN_DEBUG | ||
3094 | "%s: disabling 40 MHz due to multi-vif mismatch\n", | ||
3095 | sdata->name); | ||
3096 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | ||
3097 | WARN_ON(!ieee80211_set_channel_type(local, sdata, | ||
3098 | channel_type)); | ||
3099 | } | ||
3100 | |||
3084 | local->oper_channel = cbss->channel; | 3101 | local->oper_channel = cbss->channel; |
3085 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 3102 | ieee80211_hw_config(local, 0); |
3086 | 3103 | ||
3087 | if (!have_sta) { | 3104 | if (!have_sta) { |
3088 | struct ieee80211_supported_band *sband; | ||
3089 | u32 rates = 0, basic_rates = 0; | 3105 | u32 rates = 0, basic_rates = 0; |
3090 | bool have_higher_than_11mbit; | 3106 | bool have_higher_than_11mbit; |
3091 | int min_rate = INT_MAX, min_rate_index = -1; | 3107 | int min_rate = INT_MAX, min_rate_index = -1; |
3092 | 3108 | ||
3093 | sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; | ||
3094 | |||
3095 | ieee80211_get_rates(sband, bss->supp_rates, | 3109 | ieee80211_get_rates(sband, bss->supp_rates, |
3096 | bss->supp_rates_len, | 3110 | bss->supp_rates_len, |
3097 | &rates, &basic_rates, | 3111 | &rates, &basic_rates, |
@@ -3311,7 +3325,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3311 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 3325 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
3312 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3326 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
3313 | if (!sband->ht_cap.ht_supported || | 3327 | if (!sband->ht_cap.ht_supported || |
3314 | local->hw.queues < 4 || !bss->wmm_used) | 3328 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) |
3315 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3329 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3316 | 3330 | ||
3317 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); | 3331 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); |
@@ -3334,11 +3348,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3334 | ifmgd->ap_smps = ifmgd->req_smps; | 3348 | ifmgd->ap_smps = ifmgd->req_smps; |
3335 | 3349 | ||
3336 | assoc_data->capability = req->bss->capability; | 3350 | assoc_data->capability = req->bss->capability; |
3337 | assoc_data->wmm = bss->wmm_used && (local->hw.queues >= 4); | 3351 | assoc_data->wmm = bss->wmm_used && |
3352 | (local->hw.queues >= IEEE80211_NUM_ACS); | ||
3338 | assoc_data->supp_rates = bss->supp_rates; | 3353 | assoc_data->supp_rates = bss->supp_rates; |
3339 | assoc_data->supp_rates_len = bss->supp_rates_len; | 3354 | assoc_data->supp_rates_len = bss->supp_rates_len; |
3340 | assoc_data->ht_information_ie = | 3355 | assoc_data->ht_operation_ie = |
3341 | ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); | 3356 | ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); |
3342 | 3357 | ||
3343 | if (bss->wmm_used && bss->uapsd_supported && | 3358 | if (bss->wmm_used && bss->uapsd_supported && |
3344 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 3359 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
@@ -3387,8 +3402,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3387 | */ | 3402 | */ |
3388 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", | 3403 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", |
3389 | sdata->name, ifmgd->bssid); | 3404 | sdata->name, ifmgd->bssid); |
3390 | assoc_data->timeout = jiffies + | 3405 | assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); |
3391 | TU_TO_EXP_TIME(req->bss->beacon_interval); | ||
3392 | } else { | 3406 | } else { |
3393 | assoc_data->have_beacon = true; | 3407 | assoc_data->have_beacon = true; |
3394 | assoc_data->sent_assoc = false; | 3408 | assoc_data->sent_assoc = false; |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index ef8eba1d736d..af1c4e26e965 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -127,6 +127,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
127 | drv_remove_interface(local, sdata); | 127 | drv_remove_interface(local, sdata); |
128 | } | 128 | } |
129 | 129 | ||
130 | sdata = rtnl_dereference(local->monitor_sdata); | ||
131 | if (sdata) | ||
132 | drv_remove_interface(local, sdata); | ||
133 | |||
130 | /* stop hardware - this must stop RX */ | 134 | /* stop hardware - this must stop RX */ |
131 | if (local->open_count) | 135 | if (local->open_count) |
132 | ieee80211_stop_device(local); | 136 | ieee80211_stop_device(local); |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index fbb1efdc4d04..6e4fd32c6617 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | #include "ieee80211_i.h" | 18 | #include "ieee80211_i.h" |
19 | #include "sta_info.h" | 19 | #include "sta_info.h" |
20 | #include "driver-ops.h" | ||
20 | 21 | ||
21 | struct rate_control_ref { | 22 | struct rate_control_ref { |
22 | struct ieee80211_local *local; | 23 | struct ieee80211_local *local; |
@@ -63,8 +64,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
63 | 64 | ||
64 | static inline void rate_control_rate_update(struct ieee80211_local *local, | 65 | static inline void rate_control_rate_update(struct ieee80211_local *local, |
65 | struct ieee80211_supported_band *sband, | 66 | struct ieee80211_supported_band *sband, |
66 | struct sta_info *sta, u32 changed, | 67 | struct sta_info *sta, u32 changed) |
67 | enum nl80211_channel_type oper_chan_type) | ||
68 | { | 68 | { |
69 | struct rate_control_ref *ref = local->rate_ctrl; | 69 | struct rate_control_ref *ref = local->rate_ctrl; |
70 | struct ieee80211_sta *ista = &sta->sta; | 70 | struct ieee80211_sta *ista = &sta->sta; |
@@ -72,7 +72,8 @@ static inline void rate_control_rate_update(struct ieee80211_local *local, | |||
72 | 72 | ||
73 | if (ref && ref->ops->rate_update) | 73 | if (ref && ref->ops->rate_update) |
74 | ref->ops->rate_update(ref->priv, sband, ista, | 74 | ref->ops->rate_update(ref->priv, sband, ista, |
75 | priv_sta, changed, oper_chan_type); | 75 | priv_sta, changed); |
76 | drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); | ||
76 | } | 77 | } |
77 | 78 | ||
78 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, | 79 | static inline void *rate_control_alloc_sta(struct rate_control_ref *ref, |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 16e0b277b9a8..3b3dcae13bbc 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -686,8 +686,7 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
686 | 686 | ||
687 | static void | 687 | static void |
688 | minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | 688 | minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, |
689 | struct ieee80211_sta *sta, void *priv_sta, | 689 | struct ieee80211_sta *sta, void *priv_sta) |
690 | enum nl80211_channel_type oper_chan_type) | ||
691 | { | 690 | { |
692 | struct minstrel_priv *mp = priv; | 691 | struct minstrel_priv *mp = priv; |
693 | struct minstrel_ht_sta_priv *msp = priv_sta; | 692 | struct minstrel_ht_sta_priv *msp = priv_sta; |
@@ -735,10 +734,6 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
735 | if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING) | 734 | if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING) |
736 | mi->tx_flags |= IEEE80211_TX_CTL_LDPC; | 735 | mi->tx_flags |= IEEE80211_TX_CTL_LDPC; |
737 | 736 | ||
738 | if (oper_chan_type != NL80211_CHAN_HT40MINUS && | ||
739 | oper_chan_type != NL80211_CHAN_HT40PLUS) | ||
740 | sta_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
741 | |||
742 | smps = (sta_cap & IEEE80211_HT_CAP_SM_PS) >> | 737 | smps = (sta_cap & IEEE80211_HT_CAP_SM_PS) >> |
743 | IEEE80211_HT_CAP_SM_PS_SHIFT; | 738 | IEEE80211_HT_CAP_SM_PS_SHIFT; |
744 | 739 | ||
@@ -788,17 +783,15 @@ static void | |||
788 | minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband, | 783 | minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband, |
789 | struct ieee80211_sta *sta, void *priv_sta) | 784 | struct ieee80211_sta *sta, void *priv_sta) |
790 | { | 785 | { |
791 | struct minstrel_priv *mp = priv; | 786 | minstrel_ht_update_caps(priv, sband, sta, priv_sta); |
792 | |||
793 | minstrel_ht_update_caps(priv, sband, sta, priv_sta, mp->hw->conf.channel_type); | ||
794 | } | 787 | } |
795 | 788 | ||
796 | static void | 789 | static void |
797 | minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband, | 790 | minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband, |
798 | struct ieee80211_sta *sta, void *priv_sta, | 791 | struct ieee80211_sta *sta, void *priv_sta, |
799 | u32 changed, enum nl80211_channel_type oper_chan_type) | 792 | u32 changed) |
800 | { | 793 | { |
801 | minstrel_ht_update_caps(priv, sband, sta, priv_sta, oper_chan_type); | 794 | minstrel_ht_update_caps(priv, sband, sta, priv_sta); |
802 | } | 795 | } |
803 | 796 | ||
804 | static void * | 797 | static void * |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bcfe8c77c839..54a049123a60 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -793,8 +793,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) | |||
793 | 793 | ||
794 | /* reset session timer */ | 794 | /* reset session timer */ |
795 | if (tid_agg_rx->timeout) | 795 | if (tid_agg_rx->timeout) |
796 | mod_timer(&tid_agg_rx->session_timer, | 796 | tid_agg_rx->last_rx = jiffies; |
797 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); | ||
798 | 797 | ||
799 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 798 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
800 | sc = le16_to_cpu(hdr->seq_ctrl); | 799 | sc = le16_to_cpu(hdr->seq_ctrl); |
@@ -2269,11 +2268,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2269 | 2268 | ||
2270 | sband = rx->local->hw.wiphy->bands[status->band]; | 2269 | sband = rx->local->hw.wiphy->bands[status->band]; |
2271 | 2270 | ||
2272 | rate_control_rate_update( | 2271 | rate_control_rate_update(local, sband, rx->sta, |
2273 | local, sband, rx->sta, | 2272 | IEEE80211_RC_SMPS_CHANGED); |
2274 | IEEE80211_RC_SMPS_CHANGED, | ||
2275 | ieee80211_get_tx_channel_type( | ||
2276 | local, local->_oper_channel_type)); | ||
2277 | goto handled; | 2273 | goto handled; |
2278 | } | 2274 | } |
2279 | default: | 2275 | default: |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 38137cb5f6f0..7fd7ac48f893 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1195,13 +1195,15 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta, | |||
1195 | ieee80211_is_qos_nullfunc(hdr->frame_control)) | 1195 | ieee80211_is_qos_nullfunc(hdr->frame_control)) |
1196 | qoshdr = ieee80211_get_qos_ctl(hdr); | 1196 | qoshdr = ieee80211_get_qos_ctl(hdr); |
1197 | 1197 | ||
1198 | /* set EOSP for the frame */ | 1198 | /* end service period after last frame */ |
1199 | if (reason == IEEE80211_FRAME_RELEASE_UAPSD && | 1199 | if (skb_queue_empty(&frames)) { |
1200 | qoshdr && skb_queue_empty(&frames)) | 1200 | if (reason == IEEE80211_FRAME_RELEASE_UAPSD && |
1201 | *qoshdr |= IEEE80211_QOS_CTL_EOSP; | 1201 | qoshdr) |
1202 | 1202 | *qoshdr |= IEEE80211_QOS_CTL_EOSP; | |
1203 | info->flags |= IEEE80211_TX_STATUS_EOSP | | 1203 | |
1204 | IEEE80211_TX_CTL_REQ_TX_STATUS; | 1204 | info->flags |= IEEE80211_TX_STATUS_EOSP | |
1205 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1206 | } | ||
1205 | 1207 | ||
1206 | if (qoshdr) | 1208 | if (qoshdr) |
1207 | tids |= BIT(*qoshdr & IEEE80211_QOS_CTL_TID_MASK); | 1209 | tids |= BIT(*qoshdr & IEEE80211_QOS_CTL_TID_MASK); |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index ab0576827baf..f75f5d9ac06d 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -55,6 +55,7 @@ | |||
55 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. | 55 | * @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame. |
56 | * @WLAN_STA_INSERTED: This station is inserted into the hash table. | 56 | * @WLAN_STA_INSERTED: This station is inserted into the hash table. |
57 | * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. | 57 | * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. |
58 | * @WLAN_STA_TOFFSET_KNOWN: toffset calculated for this station is valid. | ||
58 | */ | 59 | */ |
59 | enum ieee80211_sta_info_flags { | 60 | enum ieee80211_sta_info_flags { |
60 | WLAN_STA_AUTH, | 61 | WLAN_STA_AUTH, |
@@ -76,6 +77,7 @@ enum ieee80211_sta_info_flags { | |||
76 | WLAN_STA_4ADDR_EVENT, | 77 | WLAN_STA_4ADDR_EVENT, |
77 | WLAN_STA_INSERTED, | 78 | WLAN_STA_INSERTED, |
78 | WLAN_STA_RATE_CONTROL, | 79 | WLAN_STA_RATE_CONTROL, |
80 | WLAN_STA_TOFFSET_KNOWN, | ||
79 | }; | 81 | }; |
80 | 82 | ||
81 | #define STA_TID_NUM 16 | 83 | #define STA_TID_NUM 16 |
@@ -101,6 +103,7 @@ enum ieee80211_sta_info_flags { | |||
101 | * @dialog_token: dialog token for aggregation session | 103 | * @dialog_token: dialog token for aggregation session |
102 | * @timeout: session timeout value to be filled in ADDBA requests | 104 | * @timeout: session timeout value to be filled in ADDBA requests |
103 | * @state: session state (see above) | 105 | * @state: session state (see above) |
106 | * @last_tx: jiffies of last tx activity | ||
104 | * @stop_initiator: initiator of a session stop | 107 | * @stop_initiator: initiator of a session stop |
105 | * @tx_stop: TX DelBA frame when stopping | 108 | * @tx_stop: TX DelBA frame when stopping |
106 | * @buf_size: reorder buffer size at receiver | 109 | * @buf_size: reorder buffer size at receiver |
@@ -122,6 +125,7 @@ struct tid_ampdu_tx { | |||
122 | struct timer_list addba_resp_timer; | 125 | struct timer_list addba_resp_timer; |
123 | struct sk_buff_head pending; | 126 | struct sk_buff_head pending; |
124 | unsigned long state; | 127 | unsigned long state; |
128 | unsigned long last_tx; | ||
125 | u16 timeout; | 129 | u16 timeout; |
126 | u8 dialog_token; | 130 | u8 dialog_token; |
127 | u8 stop_initiator; | 131 | u8 stop_initiator; |
@@ -139,6 +143,7 @@ struct tid_ampdu_tx { | |||
139 | * @reorder_time: jiffies when skb was added | 143 | * @reorder_time: jiffies when skb was added |
140 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) | 144 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) |
141 | * @reorder_timer: releases expired frames from the reorder buffer. | 145 | * @reorder_timer: releases expired frames from the reorder buffer. |
146 | * @last_rx: jiffies of last rx activity | ||
142 | * @head_seq_num: head sequence number in reordering buffer. | 147 | * @head_seq_num: head sequence number in reordering buffer. |
143 | * @stored_mpdu_num: number of MPDUs in reordering buffer | 148 | * @stored_mpdu_num: number of MPDUs in reordering buffer |
144 | * @ssn: Starting Sequence Number expected to be aggregated. | 149 | * @ssn: Starting Sequence Number expected to be aggregated. |
@@ -163,6 +168,7 @@ struct tid_ampdu_rx { | |||
163 | unsigned long *reorder_time; | 168 | unsigned long *reorder_time; |
164 | struct timer_list session_timer; | 169 | struct timer_list session_timer; |
165 | struct timer_list reorder_timer; | 170 | struct timer_list reorder_timer; |
171 | unsigned long last_rx; | ||
166 | u16 head_seq_num; | 172 | u16 head_seq_num; |
167 | u16 stored_mpdu_num; | 173 | u16 stored_mpdu_num; |
168 | u16 ssn; | 174 | u16 ssn; |
@@ -264,6 +270,7 @@ struct sta_ampdu_mlme { | |||
264 | * @plink_timeout: timeout of peer link | 270 | * @plink_timeout: timeout of peer link |
265 | * @plink_timer: peer link watch timer | 271 | * @plink_timer: peer link watch timer |
266 | * @plink_timer_was_running: used by suspend/resume to restore timers | 272 | * @plink_timer_was_running: used by suspend/resume to restore timers |
273 | * @t_offset: timing offset relative to this host | ||
267 | * @debugfs: debug filesystem info | 274 | * @debugfs: debug filesystem info |
268 | * @dead: set to true when sta is unlinked | 275 | * @dead: set to true when sta is unlinked |
269 | * @uploaded: set to true when sta is uploaded to the driver | 276 | * @uploaded: set to true when sta is uploaded to the driver |
@@ -353,6 +360,8 @@ struct sta_info { | |||
353 | enum nl80211_plink_state plink_state; | 360 | enum nl80211_plink_state plink_state; |
354 | u32 plink_timeout; | 361 | u32 plink_timeout; |
355 | struct timer_list plink_timer; | 362 | struct timer_list plink_timer; |
363 | s64 t_offset; | ||
364 | s64 t_offset_setpoint; | ||
356 | #endif | 365 | #endif |
357 | 366 | ||
358 | #ifdef CONFIG_MAC80211_DEBUGFS | 367 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -365,6 +374,8 @@ struct sta_info { | |||
365 | unsigned int lost_packets; | 374 | unsigned int lost_packets; |
366 | unsigned int beacon_loss_count; | 375 | unsigned int beacon_loss_count; |
367 | 376 | ||
377 | bool supports_40mhz; | ||
378 | |||
368 | /* keep last! */ | 379 | /* keep last! */ |
369 | struct ieee80211_sta sta; | 380 | struct ieee80211_sta sta; |
370 | }; | 381 | }; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 782a60198df4..4f6aac16ac3a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -230,9 +230,9 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) | |||
230 | * changed via debugfs, user needs to reassociate manually to have | 230 | * changed via debugfs, user needs to reassociate manually to have |
231 | * everything in sync. | 231 | * everything in sync. |
232 | */ | 232 | */ |
233 | if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) | 233 | if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) && |
234 | && (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) | 234 | (ifmgd->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) && |
235 | && skb_get_queue_mapping(tx->skb) == 0) | 235 | skb_get_queue_mapping(tx->skb) == IEEE80211_AC_VO) |
236 | return TX_CONTINUE; | 236 | return TX_CONTINUE; |
237 | 237 | ||
238 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 238 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
@@ -400,6 +400,8 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
400 | return TX_CONTINUE; | 400 | return TX_CONTINUE; |
401 | 401 | ||
402 | info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; | 402 | info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; |
403 | if (tx->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | ||
404 | info->hw_queue = tx->sdata->vif.cab_queue; | ||
403 | 405 | ||
404 | /* device releases frame after DTIM beacon */ | 406 | /* device releases frame after DTIM beacon */ |
405 | if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) | 407 | if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) |
@@ -1118,8 +1120,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | |||
1118 | 1120 | ||
1119 | /* reset session timer */ | 1121 | /* reset session timer */ |
1120 | if (reset_agg_timer && tid_tx->timeout) | 1122 | if (reset_agg_timer && tid_tx->timeout) |
1121 | mod_timer(&tid_tx->session_timer, | 1123 | tid_tx->last_tx = jiffies; |
1122 | TU_TO_EXP_TIME(tid_tx->timeout)); | ||
1123 | 1124 | ||
1124 | return queued; | 1125 | return queued; |
1125 | } | 1126 | } |
@@ -1215,11 +1216,19 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1215 | bool txpending) | 1216 | bool txpending) |
1216 | { | 1217 | { |
1217 | struct sk_buff *skb, *tmp; | 1218 | struct sk_buff *skb, *tmp; |
1218 | struct ieee80211_tx_info *info; | ||
1219 | unsigned long flags; | 1219 | unsigned long flags; |
1220 | 1220 | ||
1221 | skb_queue_walk_safe(skbs, skb, tmp) { | 1221 | skb_queue_walk_safe(skbs, skb, tmp) { |
1222 | int q = skb_get_queue_mapping(skb); | 1222 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1223 | int q = info->hw_queue; | ||
1224 | |||
1225 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1226 | if (WARN_ON_ONCE(q >= local->hw.queues)) { | ||
1227 | __skb_unlink(skb, skbs); | ||
1228 | dev_kfree_skb(skb); | ||
1229 | continue; | ||
1230 | } | ||
1231 | #endif | ||
1223 | 1232 | ||
1224 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 1233 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
1225 | if (local->queue_stop_reasons[q] || | 1234 | if (local->queue_stop_reasons[q] || |
@@ -1241,7 +1250,6 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1241 | } | 1250 | } |
1242 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 1251 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
1243 | 1252 | ||
1244 | info = IEEE80211_SKB_CB(skb); | ||
1245 | info->control.vif = vif; | 1253 | info->control.vif = vif; |
1246 | info->control.sta = sta; | 1254 | info->control.sta = sta; |
1247 | 1255 | ||
@@ -1284,8 +1292,16 @@ static bool __ieee80211_tx(struct ieee80211_local *local, | |||
1284 | 1292 | ||
1285 | switch (sdata->vif.type) { | 1293 | switch (sdata->vif.type) { |
1286 | case NL80211_IFTYPE_MONITOR: | 1294 | case NL80211_IFTYPE_MONITOR: |
1287 | sdata = NULL; | 1295 | sdata = rcu_dereference(local->monitor_sdata); |
1288 | vif = NULL; | 1296 | if (sdata) { |
1297 | vif = &sdata->vif; | ||
1298 | info->hw_queue = | ||
1299 | vif->hw_queue[skb_get_queue_mapping(skb)]; | ||
1300 | } else if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) { | ||
1301 | dev_kfree_skb(skb); | ||
1302 | return true; | ||
1303 | } else | ||
1304 | vif = NULL; | ||
1289 | break; | 1305 | break; |
1290 | case NL80211_IFTYPE_AP_VLAN: | 1306 | case NL80211_IFTYPE_AP_VLAN: |
1291 | sdata = container_of(sdata->bss, | 1307 | sdata = container_of(sdata->bss, |
@@ -1400,6 +1416,12 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1400 | tx.channel = local->hw.conf.channel; | 1416 | tx.channel = local->hw.conf.channel; |
1401 | info->band = tx.channel->band; | 1417 | info->band = tx.channel->band; |
1402 | 1418 | ||
1419 | /* set up hw_queue value early */ | ||
1420 | if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || | ||
1421 | !(local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) | ||
1422 | info->hw_queue = | ||
1423 | sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; | ||
1424 | |||
1403 | if (!invoke_tx_handlers(&tx)) | 1425 | if (!invoke_tx_handlers(&tx)) |
1404 | result = __ieee80211_tx(local, &tx.skbs, led_len, | 1426 | result = __ieee80211_tx(local, &tx.skbs, led_len, |
1405 | tx.sta, txpending); | 1427 | tx.sta, txpending); |
@@ -1468,12 +1490,12 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
1468 | 1490 | ||
1469 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 1491 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
1470 | ieee80211_is_data(hdr->frame_control) && | 1492 | ieee80211_is_data(hdr->frame_control) && |
1471 | !is_multicast_ether_addr(hdr->addr1)) | 1493 | !is_multicast_ether_addr(hdr->addr1) && |
1472 | if (mesh_nexthop_resolve(skb, sdata)) { | 1494 | mesh_nexthop_resolve(skb, sdata)) { |
1473 | /* skb queued: don't free */ | 1495 | /* skb queued: don't free */ |
1474 | rcu_read_unlock(); | 1496 | rcu_read_unlock(); |
1475 | return; | 1497 | return; |
1476 | } | 1498 | } |
1477 | 1499 | ||
1478 | ieee80211_set_qos_hdr(sdata, skb); | 1500 | ieee80211_set_qos_hdr(sdata, skb); |
1479 | ieee80211_tx(sdata, skb, false); | 1501 | ieee80211_tx(sdata, skb, false); |
@@ -1929,7 +1951,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1929 | wme_sta = true; | 1951 | wme_sta = true; |
1930 | 1952 | ||
1931 | /* receiver and we are QoS enabled, use a QoS type frame */ | 1953 | /* receiver and we are QoS enabled, use a QoS type frame */ |
1932 | if (wme_sta && local->hw.queues >= 4) { | 1954 | if (wme_sta && local->hw.queues >= IEEE80211_NUM_ACS) { |
1933 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | 1955 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1934 | hdrlen += 2; | 1956 | hdrlen += 2; |
1935 | } | 1957 | } |
@@ -2170,7 +2192,6 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
2170 | void ieee80211_tx_pending(unsigned long data) | 2192 | void ieee80211_tx_pending(unsigned long data) |
2171 | { | 2193 | { |
2172 | struct ieee80211_local *local = (struct ieee80211_local *)data; | 2194 | struct ieee80211_local *local = (struct ieee80211_local *)data; |
2173 | struct ieee80211_sub_if_data *sdata; | ||
2174 | unsigned long flags; | 2195 | unsigned long flags; |
2175 | int i; | 2196 | int i; |
2176 | bool txok; | 2197 | bool txok; |
@@ -2207,8 +2228,7 @@ void ieee80211_tx_pending(unsigned long data) | |||
2207 | } | 2228 | } |
2208 | 2229 | ||
2209 | if (skb_queue_empty(&local->pending[i])) | 2230 | if (skb_queue_empty(&local->pending[i])) |
2210 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 2231 | ieee80211_propagate_queue_wake(local, i); |
2211 | netif_wake_subqueue(sdata->dev, i); | ||
2212 | } | 2232 | } |
2213 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 2233 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
2214 | 2234 | ||
@@ -2374,6 +2394,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2374 | IEEE80211_STYPE_BEACON); | 2394 | IEEE80211_STYPE_BEACON); |
2375 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 2395 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
2376 | struct ieee80211_mgmt *mgmt; | 2396 | struct ieee80211_mgmt *mgmt; |
2397 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
2377 | u8 *pos; | 2398 | u8 *pos; |
2378 | int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) + | 2399 | int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) + |
2379 | sizeof(mgmt->u.beacon); | 2400 | sizeof(mgmt->u.beacon); |
@@ -2383,6 +2404,10 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2383 | goto out; | 2404 | goto out; |
2384 | #endif | 2405 | #endif |
2385 | 2406 | ||
2407 | if (ifmsh->sync_ops) | ||
2408 | ifmsh->sync_ops->adjust_tbtt( | ||
2409 | sdata); | ||
2410 | |||
2386 | skb = dev_alloc_skb(local->tx_headroom + | 2411 | skb = dev_alloc_skb(local->tx_headroom + |
2387 | hdr_len + | 2412 | hdr_len + |
2388 | 2 + /* NULL SSID */ | 2413 | 2 + /* NULL SSID */ |
@@ -2390,7 +2415,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2390 | 2 + 3 + /* DS params */ | 2415 | 2 + 3 + /* DS params */ |
2391 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + | 2416 | 2 + (IEEE80211_MAX_SUPP_RATES - 8) + |
2392 | 2 + sizeof(struct ieee80211_ht_cap) + | 2417 | 2 + sizeof(struct ieee80211_ht_cap) + |
2393 | 2 + sizeof(struct ieee80211_ht_info) + | 2418 | 2 + sizeof(struct ieee80211_ht_operation) + |
2394 | 2 + sdata->u.mesh.mesh_id_len + | 2419 | 2 + sdata->u.mesh.mesh_id_len + |
2395 | 2 + sizeof(struct ieee80211_meshconf_ie) + | 2420 | 2 + sizeof(struct ieee80211_meshconf_ie) + |
2396 | sdata->u.mesh.ie_len); | 2421 | sdata->u.mesh.ie_len); |
@@ -2414,12 +2439,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2414 | *pos++ = WLAN_EID_SSID; | 2439 | *pos++ = WLAN_EID_SSID; |
2415 | *pos++ = 0x0; | 2440 | *pos++ = 0x0; |
2416 | 2441 | ||
2417 | if (ieee80211_add_srates_ie(&sdata->vif, skb) || | 2442 | if (ieee80211_add_srates_ie(&sdata->vif, skb, true) || |
2418 | mesh_add_ds_params_ie(skb, sdata) || | 2443 | mesh_add_ds_params_ie(skb, sdata) || |
2419 | ieee80211_add_ext_srates_ie(&sdata->vif, skb) || | 2444 | ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) || |
2420 | mesh_add_rsn_ie(skb, sdata) || | 2445 | mesh_add_rsn_ie(skb, sdata) || |
2421 | mesh_add_ht_cap_ie(skb, sdata) || | 2446 | mesh_add_ht_cap_ie(skb, sdata) || |
2422 | mesh_add_ht_info_ie(skb, sdata) || | 2447 | mesh_add_ht_oper_ie(skb, sdata) || |
2423 | mesh_add_meshid_ie(skb, sdata) || | 2448 | mesh_add_meshid_ie(skb, sdata) || |
2424 | mesh_add_meshconf_ie(skb, sdata) || | 2449 | mesh_add_meshconf_ie(skb, sdata) || |
2425 | mesh_add_vendor_ies(skb, sdata)) { | 2450 | mesh_add_vendor_ies(skb, sdata)) { |
@@ -2603,7 +2628,7 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | |||
2603 | pos = skb_put(skb, ie_ssid_len); | 2628 | pos = skb_put(skb, ie_ssid_len); |
2604 | *pos++ = WLAN_EID_SSID; | 2629 | *pos++ = WLAN_EID_SSID; |
2605 | *pos++ = ssid_len; | 2630 | *pos++ = ssid_len; |
2606 | if (ssid) | 2631 | if (ssid_len) |
2607 | memcpy(pos, ssid, ssid_len); | 2632 | memcpy(pos, ssid, ssid_len); |
2608 | pos += ssid_len; | 2633 | pos += ssid_len; |
2609 | 2634 | ||
@@ -2710,11 +2735,13 @@ EXPORT_SYMBOL(ieee80211_get_buffered_bc); | |||
2710 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | 2735 | void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, |
2711 | struct sk_buff *skb, int tid) | 2736 | struct sk_buff *skb, int tid) |
2712 | { | 2737 | { |
2738 | int ac = ieee802_1d_to_ac[tid]; | ||
2739 | |||
2713 | skb_set_mac_header(skb, 0); | 2740 | skb_set_mac_header(skb, 0); |
2714 | skb_set_network_header(skb, 0); | 2741 | skb_set_network_header(skb, 0); |
2715 | skb_set_transport_header(skb, 0); | 2742 | skb_set_transport_header(skb, 0); |
2716 | 2743 | ||
2717 | skb_set_queue_mapping(skb, ieee802_1d_to_ac[tid]); | 2744 | skb_set_queue_mapping(skb, ac); |
2718 | skb->priority = tid; | 2745 | skb->priority = tid; |
2719 | 2746 | ||
2720 | /* | 2747 | /* |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 32f7a3b3d43c..e67fe5c1def9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -265,17 +265,45 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
265 | } | 265 | } |
266 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); | 266 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); |
267 | 267 | ||
268 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) | ||
269 | { | ||
270 | struct ieee80211_sub_if_data *sdata; | ||
271 | |||
272 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
273 | int ac; | ||
274 | |||
275 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) | ||
276 | continue; | ||
277 | |||
278 | if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE && | ||
279 | local->queue_stop_reasons[sdata->vif.cab_queue] != 0) | ||
280 | continue; | ||
281 | |||
282 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
283 | int ac_queue = sdata->vif.hw_queue[ac]; | ||
284 | |||
285 | if (ac_queue == queue || | ||
286 | (sdata->vif.cab_queue == queue && | ||
287 | local->queue_stop_reasons[ac_queue] == 0 && | ||
288 | skb_queue_empty(&local->pending[ac_queue]))) | ||
289 | netif_wake_subqueue(sdata->dev, ac); | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | |||
268 | static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | 294 | static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, |
269 | enum queue_stop_reason reason) | 295 | enum queue_stop_reason reason) |
270 | { | 296 | { |
271 | struct ieee80211_local *local = hw_to_local(hw); | 297 | struct ieee80211_local *local = hw_to_local(hw); |
272 | struct ieee80211_sub_if_data *sdata; | ||
273 | 298 | ||
274 | trace_wake_queue(local, queue, reason); | 299 | trace_wake_queue(local, queue, reason); |
275 | 300 | ||
276 | if (WARN_ON(queue >= hw->queues)) | 301 | if (WARN_ON(queue >= hw->queues)) |
277 | return; | 302 | return; |
278 | 303 | ||
304 | if (!test_bit(reason, &local->queue_stop_reasons[queue])) | ||
305 | return; | ||
306 | |||
279 | __clear_bit(reason, &local->queue_stop_reasons[queue]); | 307 | __clear_bit(reason, &local->queue_stop_reasons[queue]); |
280 | 308 | ||
281 | if (local->queue_stop_reasons[queue] != 0) | 309 | if (local->queue_stop_reasons[queue] != 0) |
@@ -284,11 +312,7 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
284 | 312 | ||
285 | if (skb_queue_empty(&local->pending[queue])) { | 313 | if (skb_queue_empty(&local->pending[queue])) { |
286 | rcu_read_lock(); | 314 | rcu_read_lock(); |
287 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 315 | ieee80211_propagate_queue_wake(local, queue); |
288 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) | ||
289 | continue; | ||
290 | netif_wake_subqueue(sdata->dev, queue); | ||
291 | } | ||
292 | rcu_read_unlock(); | 316 | rcu_read_unlock(); |
293 | } else | 317 | } else |
294 | tasklet_schedule(&local->tx_pending_tasklet); | 318 | tasklet_schedule(&local->tx_pending_tasklet); |
@@ -323,11 +347,21 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
323 | if (WARN_ON(queue >= hw->queues)) | 347 | if (WARN_ON(queue >= hw->queues)) |
324 | return; | 348 | return; |
325 | 349 | ||
350 | if (test_bit(reason, &local->queue_stop_reasons[queue])) | ||
351 | return; | ||
352 | |||
326 | __set_bit(reason, &local->queue_stop_reasons[queue]); | 353 | __set_bit(reason, &local->queue_stop_reasons[queue]); |
327 | 354 | ||
328 | rcu_read_lock(); | 355 | rcu_read_lock(); |
329 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 356 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
330 | netif_stop_subqueue(sdata->dev, queue); | 357 | int ac; |
358 | |||
359 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
360 | if (sdata->vif.hw_queue[ac] == queue || | ||
361 | sdata->vif.cab_queue == queue) | ||
362 | netif_stop_subqueue(sdata->dev, ac); | ||
363 | } | ||
364 | } | ||
331 | rcu_read_unlock(); | 365 | rcu_read_unlock(); |
332 | } | 366 | } |
333 | 367 | ||
@@ -354,8 +388,8 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
354 | { | 388 | { |
355 | struct ieee80211_hw *hw = &local->hw; | 389 | struct ieee80211_hw *hw = &local->hw; |
356 | unsigned long flags; | 390 | unsigned long flags; |
357 | int queue = skb_get_queue_mapping(skb); | ||
358 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 391 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
392 | int queue = info->hw_queue; | ||
359 | 393 | ||
360 | if (WARN_ON(!info->control.vif)) { | 394 | if (WARN_ON(!info->control.vif)) { |
361 | kfree_skb(skb); | 395 | kfree_skb(skb); |
@@ -379,10 +413,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
379 | int queue, i; | 413 | int queue, i; |
380 | 414 | ||
381 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 415 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
382 | for (i = 0; i < hw->queues; i++) | ||
383 | __ieee80211_stop_queue(hw, i, | ||
384 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | ||
385 | |||
386 | while ((skb = skb_dequeue(skbs))) { | 416 | while ((skb = skb_dequeue(skbs))) { |
387 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 417 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
388 | 418 | ||
@@ -391,7 +421,11 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
391 | continue; | 421 | continue; |
392 | } | 422 | } |
393 | 423 | ||
394 | queue = skb_get_queue_mapping(skb); | 424 | queue = info->hw_queue; |
425 | |||
426 | __ieee80211_stop_queue(hw, queue, | ||
427 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | ||
428 | |||
395 | __skb_queue_tail(&local->pending[queue], skb); | 429 | __skb_queue_tail(&local->pending[queue], skb); |
396 | } | 430 | } |
397 | 431 | ||
@@ -404,12 +438,6 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
404 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 438 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
405 | } | 439 | } |
406 | 440 | ||
407 | void ieee80211_add_pending_skbs(struct ieee80211_local *local, | ||
408 | struct sk_buff_head *skbs) | ||
409 | { | ||
410 | ieee80211_add_pending_skbs_fn(local, skbs, NULL, NULL); | ||
411 | } | ||
412 | |||
413 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 441 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
414 | enum queue_stop_reason reason) | 442 | enum queue_stop_reason reason) |
415 | { | 443 | { |
@@ -684,9 +712,9 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
684 | else | 712 | else |
685 | elem_parse_failed = true; | 713 | elem_parse_failed = true; |
686 | break; | 714 | break; |
687 | case WLAN_EID_HT_INFORMATION: | 715 | case WLAN_EID_HT_OPERATION: |
688 | if (elen >= sizeof(struct ieee80211_ht_info)) | 716 | if (elen >= sizeof(struct ieee80211_ht_operation)) |
689 | elems->ht_info_elem = (void *)pos; | 717 | elems->ht_operation = (void *)pos; |
690 | else | 718 | else |
691 | elem_parse_failed = true; | 719 | elem_parse_failed = true; |
692 | break; | 720 | break; |
@@ -775,19 +803,22 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
775 | { | 803 | { |
776 | struct ieee80211_local *local = sdata->local; | 804 | struct ieee80211_local *local = sdata->local; |
777 | struct ieee80211_tx_queue_params qparam; | 805 | struct ieee80211_tx_queue_params qparam; |
778 | int queue; | 806 | int ac; |
779 | bool use_11b; | 807 | bool use_11b; |
780 | int aCWmin, aCWmax; | 808 | int aCWmin, aCWmax; |
781 | 809 | ||
782 | if (!local->ops->conf_tx) | 810 | if (!local->ops->conf_tx) |
783 | return; | 811 | return; |
784 | 812 | ||
813 | if (local->hw.queues < IEEE80211_NUM_ACS) | ||
814 | return; | ||
815 | |||
785 | memset(&qparam, 0, sizeof(qparam)); | 816 | memset(&qparam, 0, sizeof(qparam)); |
786 | 817 | ||
787 | use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && | 818 | use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && |
788 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); | 819 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); |
789 | 820 | ||
790 | for (queue = 0; queue < local->hw.queues; queue++) { | 821 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
791 | /* Set defaults according to 802.11-2007 Table 7-37 */ | 822 | /* Set defaults according to 802.11-2007 Table 7-37 */ |
792 | aCWmax = 1023; | 823 | aCWmax = 1023; |
793 | if (use_11b) | 824 | if (use_11b) |
@@ -795,21 +826,21 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
795 | else | 826 | else |
796 | aCWmin = 15; | 827 | aCWmin = 15; |
797 | 828 | ||
798 | switch (queue) { | 829 | switch (ac) { |
799 | case 3: /* AC_BK */ | 830 | case IEEE80211_AC_BK: |
800 | qparam.cw_max = aCWmax; | 831 | qparam.cw_max = aCWmax; |
801 | qparam.cw_min = aCWmin; | 832 | qparam.cw_min = aCWmin; |
802 | qparam.txop = 0; | 833 | qparam.txop = 0; |
803 | qparam.aifs = 7; | 834 | qparam.aifs = 7; |
804 | break; | 835 | break; |
805 | default: /* never happens but let's not leave undefined */ | 836 | default: /* never happens but let's not leave undefined */ |
806 | case 2: /* AC_BE */ | 837 | case IEEE80211_AC_BE: |
807 | qparam.cw_max = aCWmax; | 838 | qparam.cw_max = aCWmax; |
808 | qparam.cw_min = aCWmin; | 839 | qparam.cw_min = aCWmin; |
809 | qparam.txop = 0; | 840 | qparam.txop = 0; |
810 | qparam.aifs = 3; | 841 | qparam.aifs = 3; |
811 | break; | 842 | break; |
812 | case 1: /* AC_VI */ | 843 | case IEEE80211_AC_VI: |
813 | qparam.cw_max = aCWmin; | 844 | qparam.cw_max = aCWmin; |
814 | qparam.cw_min = (aCWmin + 1) / 2 - 1; | 845 | qparam.cw_min = (aCWmin + 1) / 2 - 1; |
815 | if (use_11b) | 846 | if (use_11b) |
@@ -818,7 +849,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
818 | qparam.txop = 3008/32; | 849 | qparam.txop = 3008/32; |
819 | qparam.aifs = 2; | 850 | qparam.aifs = 2; |
820 | break; | 851 | break; |
821 | case 0: /* AC_VO */ | 852 | case IEEE80211_AC_VO: |
822 | qparam.cw_max = (aCWmin + 1) / 2 - 1; | 853 | qparam.cw_max = (aCWmin + 1) / 2 - 1; |
823 | qparam.cw_min = (aCWmin + 1) / 4 - 1; | 854 | qparam.cw_min = (aCWmin + 1) / 4 - 1; |
824 | if (use_11b) | 855 | if (use_11b) |
@@ -831,8 +862,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
831 | 862 | ||
832 | qparam.uapsd = false; | 863 | qparam.uapsd = false; |
833 | 864 | ||
834 | sdata->tx_conf[queue] = qparam; | 865 | sdata->tx_conf[ac] = qparam; |
835 | drv_conf_tx(local, sdata, queue, &qparam); | 866 | drv_conf_tx(local, sdata, ac, &qparam); |
836 | } | 867 | } |
837 | 868 | ||
838 | /* after reinitialize QoS TX queues setting to default, | 869 | /* after reinitialize QoS TX queues setting to default, |
@@ -1106,7 +1137,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1106 | 1137 | ||
1107 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1138 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
1108 | struct ieee802_11_elems *elems, | 1139 | struct ieee802_11_elems *elems, |
1109 | enum ieee80211_band band) | 1140 | enum ieee80211_band band, u32 *basic_rates) |
1110 | { | 1141 | { |
1111 | struct ieee80211_supported_band *sband; | 1142 | struct ieee80211_supported_band *sband; |
1112 | struct ieee80211_rate *bitrates; | 1143 | struct ieee80211_rate *bitrates; |
@@ -1127,15 +1158,25 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
1127 | elems->ext_supp_rates_len; i++) { | 1158 | elems->ext_supp_rates_len; i++) { |
1128 | u8 rate = 0; | 1159 | u8 rate = 0; |
1129 | int own_rate; | 1160 | int own_rate; |
1161 | bool is_basic; | ||
1130 | if (i < elems->supp_rates_len) | 1162 | if (i < elems->supp_rates_len) |
1131 | rate = elems->supp_rates[i]; | 1163 | rate = elems->supp_rates[i]; |
1132 | else if (elems->ext_supp_rates) | 1164 | else if (elems->ext_supp_rates) |
1133 | rate = elems->ext_supp_rates | 1165 | rate = elems->ext_supp_rates |
1134 | [i - elems->supp_rates_len]; | 1166 | [i - elems->supp_rates_len]; |
1135 | own_rate = 5 * (rate & 0x7f); | 1167 | own_rate = 5 * (rate & 0x7f); |
1136 | for (j = 0; j < num_rates; j++) | 1168 | is_basic = !!(rate & 0x80); |
1137 | if (bitrates[j].bitrate == own_rate) | 1169 | |
1170 | if (is_basic && (rate & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY) | ||
1171 | continue; | ||
1172 | |||
1173 | for (j = 0; j < num_rates; j++) { | ||
1174 | if (bitrates[j].bitrate == own_rate) { | ||
1138 | supp_rates |= BIT(j); | 1175 | supp_rates |= BIT(j); |
1176 | if (basic_rates && is_basic) | ||
1177 | *basic_rates |= BIT(j); | ||
1178 | } | ||
1179 | } | ||
1139 | } | 1180 | } |
1140 | return supp_rates; | 1181 | return supp_rates; |
1141 | } | 1182 | } |
@@ -1210,6 +1251,16 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1210 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | 1251 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); |
1211 | 1252 | ||
1212 | /* add interfaces */ | 1253 | /* add interfaces */ |
1254 | sdata = rtnl_dereference(local->monitor_sdata); | ||
1255 | if (sdata) { | ||
1256 | res = drv_add_interface(local, sdata); | ||
1257 | if (WARN_ON(res)) { | ||
1258 | rcu_assign_pointer(local->monitor_sdata, NULL); | ||
1259 | synchronize_net(); | ||
1260 | kfree(sdata); | ||
1261 | } | ||
1262 | } | ||
1263 | |||
1213 | list_for_each_entry(sdata, &local->interfaces, list) { | 1264 | list_for_each_entry(sdata, &local->interfaces, list) { |
1214 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1265 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
1215 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | 1266 | sdata->vif.type != NL80211_IFTYPE_MONITOR && |
@@ -1232,14 +1283,17 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1232 | mutex_unlock(&local->sta_mtx); | 1283 | mutex_unlock(&local->sta_mtx); |
1233 | 1284 | ||
1234 | /* reconfigure tx conf */ | 1285 | /* reconfigure tx conf */ |
1235 | list_for_each_entry(sdata, &local->interfaces, list) { | 1286 | if (hw->queues >= IEEE80211_NUM_ACS) { |
1236 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 1287 | list_for_each_entry(sdata, &local->interfaces, list) { |
1237 | sdata->vif.type == NL80211_IFTYPE_MONITOR || | 1288 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
1238 | !ieee80211_sdata_running(sdata)) | 1289 | sdata->vif.type == NL80211_IFTYPE_MONITOR || |
1239 | continue; | 1290 | !ieee80211_sdata_running(sdata)) |
1291 | continue; | ||
1240 | 1292 | ||
1241 | for (i = 0; i < hw->queues; i++) | 1293 | for (i = 0; i < IEEE80211_NUM_ACS; i++) |
1242 | drv_conf_tx(local, sdata, i, &sdata->tx_conf[i]); | 1294 | drv_conf_tx(local, sdata, i, |
1295 | &sdata->tx_conf[i]); | ||
1296 | } | ||
1243 | } | 1297 | } |
1244 | 1298 | ||
1245 | /* reconfigure hardware */ | 1299 | /* reconfigure hardware */ |
@@ -1611,57 +1665,56 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1611 | return pos; | 1665 | return pos; |
1612 | } | 1666 | } |
1613 | 1667 | ||
1614 | u8 *ieee80211_ie_build_ht_info(u8 *pos, | 1668 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1615 | struct ieee80211_sta_ht_cap *ht_cap, | ||
1616 | struct ieee80211_channel *channel, | 1669 | struct ieee80211_channel *channel, |
1617 | enum nl80211_channel_type channel_type) | 1670 | enum nl80211_channel_type channel_type) |
1618 | { | 1671 | { |
1619 | struct ieee80211_ht_info *ht_info; | 1672 | struct ieee80211_ht_operation *ht_oper; |
1620 | /* Build HT Information */ | 1673 | /* Build HT Information */ |
1621 | *pos++ = WLAN_EID_HT_INFORMATION; | 1674 | *pos++ = WLAN_EID_HT_OPERATION; |
1622 | *pos++ = sizeof(struct ieee80211_ht_info); | 1675 | *pos++ = sizeof(struct ieee80211_ht_operation); |
1623 | ht_info = (struct ieee80211_ht_info *)pos; | 1676 | ht_oper = (struct ieee80211_ht_operation *)pos; |
1624 | ht_info->control_chan = | 1677 | ht_oper->primary_chan = |
1625 | ieee80211_frequency_to_channel(channel->center_freq); | 1678 | ieee80211_frequency_to_channel(channel->center_freq); |
1626 | switch (channel_type) { | 1679 | switch (channel_type) { |
1627 | case NL80211_CHAN_HT40MINUS: | 1680 | case NL80211_CHAN_HT40MINUS: |
1628 | ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | 1681 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; |
1629 | break; | 1682 | break; |
1630 | case NL80211_CHAN_HT40PLUS: | 1683 | case NL80211_CHAN_HT40PLUS: |
1631 | ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | 1684 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; |
1632 | break; | 1685 | break; |
1633 | case NL80211_CHAN_HT20: | 1686 | case NL80211_CHAN_HT20: |
1634 | default: | 1687 | default: |
1635 | ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; | 1688 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; |
1636 | break; | 1689 | break; |
1637 | } | 1690 | } |
1638 | if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | 1691 | if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) |
1639 | ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; | 1692 | ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; |
1640 | 1693 | ||
1641 | /* | 1694 | /* |
1642 | * Note: According to 802.11n-2009 9.13.3.1, HT Protection field and | 1695 | * Note: According to 802.11n-2009 9.13.3.1, HT Protection field and |
1643 | * RIFS Mode are reserved in IBSS mode, therefore keep them at 0 | 1696 | * RIFS Mode are reserved in IBSS mode, therefore keep them at 0 |
1644 | */ | 1697 | */ |
1645 | ht_info->operation_mode = 0x0000; | 1698 | ht_oper->operation_mode = 0x0000; |
1646 | ht_info->stbc_param = 0x0000; | 1699 | ht_oper->stbc_param = 0x0000; |
1647 | 1700 | ||
1648 | /* It seems that Basic MCS set and Supported MCS set | 1701 | /* It seems that Basic MCS set and Supported MCS set |
1649 | are identical for the first 10 bytes */ | 1702 | are identical for the first 10 bytes */ |
1650 | memset(&ht_info->basic_set, 0, 16); | 1703 | memset(&ht_oper->basic_set, 0, 16); |
1651 | memcpy(&ht_info->basic_set, &ht_cap->mcs, 10); | 1704 | memcpy(&ht_oper->basic_set, &ht_cap->mcs, 10); |
1652 | 1705 | ||
1653 | return pos + sizeof(struct ieee80211_ht_info); | 1706 | return pos + sizeof(struct ieee80211_ht_operation); |
1654 | } | 1707 | } |
1655 | 1708 | ||
1656 | enum nl80211_channel_type | 1709 | enum nl80211_channel_type |
1657 | ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info) | 1710 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) |
1658 | { | 1711 | { |
1659 | enum nl80211_channel_type channel_type; | 1712 | enum nl80211_channel_type channel_type; |
1660 | 1713 | ||
1661 | if (!ht_info) | 1714 | if (!ht_oper) |
1662 | return NL80211_CHAN_NO_HT; | 1715 | return NL80211_CHAN_NO_HT; |
1663 | 1716 | ||
1664 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 1717 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
1665 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | 1718 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: |
1666 | channel_type = NL80211_CHAN_HT20; | 1719 | channel_type = NL80211_CHAN_HT20; |
1667 | break; | 1720 | break; |
@@ -1678,13 +1731,15 @@ ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info) | |||
1678 | return channel_type; | 1731 | return channel_type; |
1679 | } | 1732 | } |
1680 | 1733 | ||
1681 | int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) | 1734 | int ieee80211_add_srates_ie(struct ieee80211_vif *vif, |
1735 | struct sk_buff *skb, bool need_basic) | ||
1682 | { | 1736 | { |
1683 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1737 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
1684 | struct ieee80211_local *local = sdata->local; | 1738 | struct ieee80211_local *local = sdata->local; |
1685 | struct ieee80211_supported_band *sband; | 1739 | struct ieee80211_supported_band *sband; |
1686 | int rate; | 1740 | int rate; |
1687 | u8 i, rates, *pos; | 1741 | u8 i, rates, *pos; |
1742 | u32 basic_rates = vif->bss_conf.basic_rates; | ||
1688 | 1743 | ||
1689 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1744 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1690 | rates = sband->n_bitrates; | 1745 | rates = sband->n_bitrates; |
@@ -1698,20 +1753,25 @@ int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) | |||
1698 | *pos++ = WLAN_EID_SUPP_RATES; | 1753 | *pos++ = WLAN_EID_SUPP_RATES; |
1699 | *pos++ = rates; | 1754 | *pos++ = rates; |
1700 | for (i = 0; i < rates; i++) { | 1755 | for (i = 0; i < rates; i++) { |
1756 | u8 basic = 0; | ||
1757 | if (need_basic && basic_rates & BIT(i)) | ||
1758 | basic = 0x80; | ||
1701 | rate = sband->bitrates[i].bitrate; | 1759 | rate = sband->bitrates[i].bitrate; |
1702 | *pos++ = (u8) (rate / 5); | 1760 | *pos++ = basic | (u8) (rate / 5); |
1703 | } | 1761 | } |
1704 | 1762 | ||
1705 | return 0; | 1763 | return 0; |
1706 | } | 1764 | } |
1707 | 1765 | ||
1708 | int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) | 1766 | int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, |
1767 | struct sk_buff *skb, bool need_basic) | ||
1709 | { | 1768 | { |
1710 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1769 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
1711 | struct ieee80211_local *local = sdata->local; | 1770 | struct ieee80211_local *local = sdata->local; |
1712 | struct ieee80211_supported_band *sband; | 1771 | struct ieee80211_supported_band *sband; |
1713 | int rate; | 1772 | int rate; |
1714 | u8 i, exrates, *pos; | 1773 | u8 i, exrates, *pos; |
1774 | u32 basic_rates = vif->bss_conf.basic_rates; | ||
1715 | 1775 | ||
1716 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1776 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1717 | exrates = sband->n_bitrates; | 1777 | exrates = sband->n_bitrates; |
@@ -1728,8 +1788,11 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb) | |||
1728 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 1788 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
1729 | *pos++ = exrates; | 1789 | *pos++ = exrates; |
1730 | for (i = 8; i < sband->n_bitrates; i++) { | 1790 | for (i = 8; i < sband->n_bitrates; i++) { |
1791 | u8 basic = 0; | ||
1792 | if (need_basic && basic_rates & BIT(i)) | ||
1793 | basic = 0x80; | ||
1731 | rate = sband->bitrates[i].bitrate; | 1794 | rate = sband->bitrates[i].bitrate; |
1732 | *pos++ = (u8) (rate / 5); | 1795 | *pos++ = basic | (u8) (rate / 5); |
1733 | } | 1796 | } |
1734 | } | 1797 | } |
1735 | return 0; | 1798 | return 0; |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 89511be3111e..c3d643a6536c 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -52,6 +52,26 @@ static int wme_downgrade_ac(struct sk_buff *skb) | |||
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | static u16 ieee80211_downgrade_queue(struct ieee80211_local *local, | ||
56 | struct sk_buff *skb) | ||
57 | { | ||
58 | /* in case we are a client verify acm is not set for this ac */ | ||
59 | while (unlikely(local->wmm_acm & BIT(skb->priority))) { | ||
60 | if (wme_downgrade_ac(skb)) { | ||
61 | /* | ||
62 | * This should not really happen. The AP has marked all | ||
63 | * lower ACs to require admission control which is not | ||
64 | * a reasonable configuration. Allow the frame to be | ||
65 | * transmitted using AC_BK as a workaround. | ||
66 | */ | ||
67 | break; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /* look up which queue to use for frames with this 1d tag */ | ||
72 | return ieee802_1d_to_ac[skb->priority]; | ||
73 | } | ||
74 | |||
55 | /* Indicate which queue to use for this fully formed 802.11 frame */ | 75 | /* Indicate which queue to use for this fully formed 802.11 frame */ |
56 | u16 ieee80211_select_queue_80211(struct ieee80211_local *local, | 76 | u16 ieee80211_select_queue_80211(struct ieee80211_local *local, |
57 | struct sk_buff *skb, | 77 | struct sk_buff *skb, |
@@ -59,7 +79,7 @@ u16 ieee80211_select_queue_80211(struct ieee80211_local *local, | |||
59 | { | 79 | { |
60 | u8 *p; | 80 | u8 *p; |
61 | 81 | ||
62 | if (local->hw.queues < 4) | 82 | if (local->hw.queues < IEEE80211_NUM_ACS) |
63 | return 0; | 83 | return 0; |
64 | 84 | ||
65 | if (!ieee80211_is_data(hdr->frame_control)) { | 85 | if (!ieee80211_is_data(hdr->frame_control)) { |
@@ -86,9 +106,9 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
86 | const u8 *ra = NULL; | 106 | const u8 *ra = NULL; |
87 | bool qos = false; | 107 | bool qos = false; |
88 | 108 | ||
89 | if (local->hw.queues < 4 || skb->len < 6) { | 109 | if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) { |
90 | skb->priority = 0; /* required for correct WPA/11i MIC */ | 110 | skb->priority = 0; /* required for correct WPA/11i MIC */ |
91 | return min_t(u16, local->hw.queues - 1, IEEE80211_AC_BE); | 111 | return 0; |
92 | } | 112 | } |
93 | 113 | ||
94 | rcu_read_lock(); | 114 | rcu_read_lock(); |
@@ -139,26 +159,6 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
139 | return ieee80211_downgrade_queue(local, skb); | 159 | return ieee80211_downgrade_queue(local, skb); |
140 | } | 160 | } |
141 | 161 | ||
142 | u16 ieee80211_downgrade_queue(struct ieee80211_local *local, | ||
143 | struct sk_buff *skb) | ||
144 | { | ||
145 | /* in case we are a client verify acm is not set for this ac */ | ||
146 | while (unlikely(local->wmm_acm & BIT(skb->priority))) { | ||
147 | if (wme_downgrade_ac(skb)) { | ||
148 | /* | ||
149 | * This should not really happen. The AP has marked all | ||
150 | * lower ACs to require admission control which is not | ||
151 | * a reasonable configuration. Allow the frame to be | ||
152 | * transmitted using AC_BK as a workaround. | ||
153 | */ | ||
154 | break; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /* look up which queue to use for frames with this 1d tag */ | ||
159 | return ieee802_1d_to_ac[skb->priority]; | ||
160 | } | ||
161 | |||
162 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, | 162 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, |
163 | struct sk_buff *skb) | 163 | struct sk_buff *skb) |
164 | { | 164 | { |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 94edceb617ff..ca80818b7b66 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -22,8 +22,5 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
22 | struct sk_buff *skb); | 22 | struct sk_buff *skb); |
23 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, | 23 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, |
24 | struct sk_buff *skb); | 24 | struct sk_buff *skb); |
25 | u16 ieee80211_downgrade_queue(struct ieee80211_local *local, | ||
26 | struct sk_buff *skb); | ||
27 | |||
28 | 25 | ||
29 | #endif /* _WME_H */ | 26 | #endif /* _WME_H */ |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index 7b76eb7192f3..ef10ffcb4b6f 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -474,7 +474,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
474 | 474 | ||
475 | while (remaining_len > 0) { | 475 | while (remaining_len > 0) { |
476 | 476 | ||
477 | frag_len = min_t(u16, local->remote_miu, remaining_len); | 477 | frag_len = min_t(size_t, local->remote_miu, remaining_len); |
478 | 478 | ||
479 | pr_debug("Fragment %zd bytes remaining %zd", | 479 | pr_debug("Fragment %zd bytes remaining %zd", |
480 | frag_len, remaining_len); | 480 | frag_len, remaining_len); |
@@ -497,7 +497,7 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
497 | release_sock(sk); | 497 | release_sock(sk); |
498 | 498 | ||
499 | remaining_len -= frag_len; | 499 | remaining_len -= frag_len; |
500 | msg_ptr += len; | 500 | msg_ptr += frag_len; |
501 | } | 501 | } |
502 | 502 | ||
503 | kfree(msg_data); | 503 | kfree(msg_data); |
diff --git a/net/wireless/core.c b/net/wireless/core.c index ccdfed897651..59f4a7e7c092 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -708,6 +708,10 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
708 | flush_work(&rdev->scan_done_wk); | 708 | flush_work(&rdev->scan_done_wk); |
709 | cancel_work_sync(&rdev->conn_work); | 709 | cancel_work_sync(&rdev->conn_work); |
710 | flush_work(&rdev->event_work); | 710 | flush_work(&rdev->event_work); |
711 | |||
712 | if (rdev->wowlan && rdev->ops->set_wakeup) | ||
713 | rdev->ops->set_wakeup(&rdev->wiphy, false); | ||
714 | cfg80211_rdev_free_wowlan(rdev); | ||
711 | } | 715 | } |
712 | EXPORT_SYMBOL(wiphy_unregister); | 716 | EXPORT_SYMBOL(wiphy_unregister); |
713 | 717 | ||
@@ -720,7 +724,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) | |||
720 | mutex_destroy(&rdev->sched_scan_mtx); | 724 | mutex_destroy(&rdev->sched_scan_mtx); |
721 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) | 725 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) |
722 | cfg80211_put_bss(&scan->pub); | 726 | cfg80211_put_bss(&scan->pub); |
723 | cfg80211_rdev_free_wowlan(rdev); | ||
724 | kfree(rdev); | 727 | kfree(rdev); |
725 | } | 728 | } |
726 | 729 | ||
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index ba21ab22187b..8c747fa9319b 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -38,6 +38,7 @@ | |||
38 | 38 | ||
39 | #define MESH_MAX_PREQ_RETRIES 4 | 39 | #define MESH_MAX_PREQ_RETRIES 4 |
40 | 40 | ||
41 | #define MESH_SYNC_NEIGHBOR_OFFSET_MAX 50 | ||
41 | 42 | ||
42 | const struct mesh_config default_mesh_config = { | 43 | const struct mesh_config default_mesh_config = { |
43 | .dot11MeshRetryTimeout = MESH_RET_T, | 44 | .dot11MeshRetryTimeout = MESH_RET_T, |
@@ -48,6 +49,7 @@ const struct mesh_config default_mesh_config = { | |||
48 | .element_ttl = MESH_DEFAULT_ELEMENT_TTL, | 49 | .element_ttl = MESH_DEFAULT_ELEMENT_TTL, |
49 | .auto_open_plinks = true, | 50 | .auto_open_plinks = true, |
50 | .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS, | 51 | .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS, |
52 | .dot11MeshNbrOffsetMaxNeighbor = MESH_SYNC_NEIGHBOR_OFFSET_MAX, | ||
51 | .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT, | 53 | .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT, |
52 | .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT, | 54 | .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT, |
53 | .dot11MeshHWMPperrMinInterval = MESH_PERR_MIN_INT, | 55 | .dot11MeshHWMPperrMinInterval = MESH_PERR_MIN_INT, |
@@ -62,6 +64,7 @@ const struct mesh_config default_mesh_config = { | |||
62 | }; | 64 | }; |
63 | 65 | ||
64 | const struct mesh_setup default_mesh_setup = { | 66 | const struct mesh_setup default_mesh_setup = { |
67 | .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, | ||
65 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, | 68 | .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, |
66 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, | 69 | .path_metric = IEEE80211_PATH_METRIC_AIRTIME, |
67 | .ie = NULL, | 70 | .ie = NULL, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index f5a7ac3a0939..6801d96bc224 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/etherdevice.h> | ||
9 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
10 | #include <linux/nl80211.h> | 11 | #include <linux/nl80211.h> |
11 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
@@ -100,7 +101,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
100 | ASSERT_WDEV_LOCK(wdev); | 101 | ASSERT_WDEV_LOCK(wdev); |
101 | 102 | ||
102 | if (wdev->current_bss && | 103 | if (wdev->current_bss && |
103 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { | 104 | compare_ether_addr(wdev->current_bss->pub.bssid, bssid) == 0) { |
104 | cfg80211_unhold_bss(wdev->current_bss); | 105 | cfg80211_unhold_bss(wdev->current_bss); |
105 | cfg80211_put_bss(&wdev->current_bss->pub); | 106 | cfg80211_put_bss(&wdev->current_bss->pub); |
106 | wdev->current_bss = NULL; | 107 | wdev->current_bss = NULL; |
@@ -115,7 +116,7 @@ void __cfg80211_send_deauth(struct net_device *dev, | |||
115 | 116 | ||
116 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 117 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
117 | 118 | ||
118 | from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0; | 119 | from_ap = compare_ether_addr(mgmt->sa, dev->dev_addr) != 0; |
119 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); | 120 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); |
120 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { | 121 | } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { |
121 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, | 122 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, |
@@ -154,7 +155,7 @@ void __cfg80211_send_disassoc(struct net_device *dev, | |||
154 | return; | 155 | return; |
155 | 156 | ||
156 | if (wdev->current_bss && | 157 | if (wdev->current_bss && |
157 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { | 158 | compare_ether_addr(wdev->current_bss->pub.bssid, bssid) == 0) { |
158 | cfg80211_sme_disassoc(dev, wdev->current_bss); | 159 | cfg80211_sme_disassoc(dev, wdev->current_bss); |
159 | cfg80211_unhold_bss(wdev->current_bss); | 160 | cfg80211_unhold_bss(wdev->current_bss); |
160 | cfg80211_put_bss(&wdev->current_bss->pub); | 161 | cfg80211_put_bss(&wdev->current_bss->pub); |
@@ -165,7 +166,7 @@ void __cfg80211_send_disassoc(struct net_device *dev, | |||
165 | 166 | ||
166 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 167 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
167 | 168 | ||
168 | from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0; | 169 | from_ap = compare_ether_addr(mgmt->sa, dev->dev_addr) != 0; |
169 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); | 170 | __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); |
170 | } | 171 | } |
171 | EXPORT_SYMBOL(__cfg80211_send_disassoc); | 172 | EXPORT_SYMBOL(__cfg80211_send_disassoc); |
@@ -285,7 +286,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
285 | return -EINVAL; | 286 | return -EINVAL; |
286 | 287 | ||
287 | if (wdev->current_bss && | 288 | if (wdev->current_bss && |
288 | memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) | 289 | compare_ether_addr(bssid, wdev->current_bss->pub.bssid) == 0) |
289 | return -EALREADY; | 290 | return -EALREADY; |
290 | 291 | ||
291 | memset(&req, 0, sizeof(req)); | 292 | memset(&req, 0, sizeof(req)); |
@@ -362,7 +363,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
362 | memset(&req, 0, sizeof(req)); | 363 | memset(&req, 0, sizeof(req)); |
363 | 364 | ||
364 | if (wdev->current_bss && prev_bssid && | 365 | if (wdev->current_bss && prev_bssid && |
365 | memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) { | 366 | compare_ether_addr(wdev->current_bss->pub.bssid, prev_bssid) == 0) { |
366 | /* | 367 | /* |
367 | * Trying to reassociate: Allow this to proceed and let the old | 368 | * Trying to reassociate: Allow this to proceed and let the old |
368 | * association to be dropped when the new one is completed. | 369 | * association to be dropped when the new one is completed. |
@@ -446,7 +447,8 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
446 | 447 | ||
447 | if (local_state_change) { | 448 | if (local_state_change) { |
448 | if (wdev->current_bss && | 449 | if (wdev->current_bss && |
449 | memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) { | 450 | compare_ether_addr(wdev->current_bss->pub.bssid, bssid) |
451 | == 0) { | ||
450 | cfg80211_unhold_bss(wdev->current_bss); | 452 | cfg80211_unhold_bss(wdev->current_bss); |
451 | cfg80211_put_bss(&wdev->current_bss->pub); | 453 | cfg80211_put_bss(&wdev->current_bss->pub); |
452 | wdev->current_bss = NULL; | 454 | wdev->current_bss = NULL; |
@@ -495,7 +497,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
495 | req.local_state_change = local_state_change; | 497 | req.local_state_change = local_state_change; |
496 | req.ie = ie; | 498 | req.ie = ie; |
497 | req.ie_len = ie_len; | 499 | req.ie_len = ie_len; |
498 | if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) | 500 | if (compare_ether_addr(wdev->current_bss->pub.bssid, bssid) == 0) |
499 | req.bss = &wdev->current_bss->pub; | 501 | req.bss = &wdev->current_bss->pub; |
500 | else | 502 | else |
501 | return -ENOTCONN; | 503 | return -ENOTCONN; |
@@ -758,8 +760,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
758 | break; | 760 | break; |
759 | } | 761 | } |
760 | 762 | ||
761 | if (memcmp(wdev->current_bss->pub.bssid, | 763 | if (compare_ether_addr(wdev->current_bss->pub.bssid, |
762 | mgmt->bssid, ETH_ALEN)) { | 764 | mgmt->bssid)) { |
763 | err = -ENOTCONN; | 765 | err = -ENOTCONN; |
764 | break; | 766 | break; |
765 | } | 767 | } |
@@ -772,8 +774,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
772 | break; | 774 | break; |
773 | 775 | ||
774 | /* for station, check that DA is the AP */ | 776 | /* for station, check that DA is the AP */ |
775 | if (memcmp(wdev->current_bss->pub.bssid, | 777 | if (compare_ether_addr(wdev->current_bss->pub.bssid, |
776 | mgmt->da, ETH_ALEN)) { | 778 | mgmt->da)) { |
777 | err = -ENOTCONN; | 779 | err = -ENOTCONN; |
778 | break; | 780 | break; |
779 | } | 781 | } |
@@ -781,11 +783,11 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
781 | case NL80211_IFTYPE_AP: | 783 | case NL80211_IFTYPE_AP: |
782 | case NL80211_IFTYPE_P2P_GO: | 784 | case NL80211_IFTYPE_P2P_GO: |
783 | case NL80211_IFTYPE_AP_VLAN: | 785 | case NL80211_IFTYPE_AP_VLAN: |
784 | if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN)) | 786 | if (compare_ether_addr(mgmt->bssid, dev->dev_addr)) |
785 | err = -EINVAL; | 787 | err = -EINVAL; |
786 | break; | 788 | break; |
787 | case NL80211_IFTYPE_MESH_POINT: | 789 | case NL80211_IFTYPE_MESH_POINT: |
788 | if (memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN)) { | 790 | if (compare_ether_addr(mgmt->sa, mgmt->bssid)) { |
789 | err = -EINVAL; | 791 | err = -EINVAL; |
790 | break; | 792 | break; |
791 | } | 793 | } |
@@ -804,7 +806,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
804 | return err; | 806 | return err; |
805 | } | 807 | } |
806 | 808 | ||
807 | if (memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0) | 809 | if (compare_ether_addr(mgmt->sa, dev->dev_addr) != 0) |
808 | return -EINVAL; | 810 | return -EINVAL; |
809 | 811 | ||
810 | /* Transmit the Action frame as requested by user space */ | 812 | /* Transmit the Action frame as requested by user space */ |
@@ -928,6 +930,33 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index, | |||
928 | } | 930 | } |
929 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); | 931 | EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify); |
930 | 932 | ||
933 | void cfg80211_ch_switch_notify(struct net_device *dev, int freq, | ||
934 | enum nl80211_channel_type type) | ||
935 | { | ||
936 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
937 | struct wiphy *wiphy = wdev->wiphy; | ||
938 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
939 | struct ieee80211_channel *chan; | ||
940 | |||
941 | wdev_lock(wdev); | ||
942 | |||
943 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP && | ||
944 | wdev->iftype != NL80211_IFTYPE_P2P_GO)) | ||
945 | goto out; | ||
946 | |||
947 | chan = rdev_freq_to_chan(rdev, freq, type); | ||
948 | if (WARN_ON(!chan)) | ||
949 | goto out; | ||
950 | |||
951 | wdev->channel = chan; | ||
952 | |||
953 | nl80211_ch_switch_notify(rdev, dev, freq, type, GFP_KERNEL); | ||
954 | out: | ||
955 | wdev_unlock(wdev); | ||
956 | return; | ||
957 | } | ||
958 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | ||
959 | |||
931 | bool cfg80211_rx_spurious_frame(struct net_device *dev, | 960 | bool cfg80211_rx_spurious_frame(struct net_device *dev, |
932 | const u8 *addr, gfp_t gfp) | 961 | const u8 *addr, gfp_t gfp) |
933 | { | 962 | { |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index a4aab1d36285..ff1a6c7fbe33 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1142,17 +1142,20 @@ static const struct nla_policy txq_params_policy[NL80211_TXQ_ATTR_MAX + 1] = { | |||
1142 | static int parse_txq_params(struct nlattr *tb[], | 1142 | static int parse_txq_params(struct nlattr *tb[], |
1143 | struct ieee80211_txq_params *txq_params) | 1143 | struct ieee80211_txq_params *txq_params) |
1144 | { | 1144 | { |
1145 | if (!tb[NL80211_TXQ_ATTR_QUEUE] || !tb[NL80211_TXQ_ATTR_TXOP] || | 1145 | if (!tb[NL80211_TXQ_ATTR_AC] || !tb[NL80211_TXQ_ATTR_TXOP] || |
1146 | !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || | 1146 | !tb[NL80211_TXQ_ATTR_CWMIN] || !tb[NL80211_TXQ_ATTR_CWMAX] || |
1147 | !tb[NL80211_TXQ_ATTR_AIFS]) | 1147 | !tb[NL80211_TXQ_ATTR_AIFS]) |
1148 | return -EINVAL; | 1148 | return -EINVAL; |
1149 | 1149 | ||
1150 | txq_params->queue = nla_get_u8(tb[NL80211_TXQ_ATTR_QUEUE]); | 1150 | txq_params->ac = nla_get_u8(tb[NL80211_TXQ_ATTR_AC]); |
1151 | txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); | 1151 | txq_params->txop = nla_get_u16(tb[NL80211_TXQ_ATTR_TXOP]); |
1152 | txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); | 1152 | txq_params->cwmin = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMIN]); |
1153 | txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); | 1153 | txq_params->cwmax = nla_get_u16(tb[NL80211_TXQ_ATTR_CWMAX]); |
1154 | txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); | 1154 | txq_params->aifs = nla_get_u8(tb[NL80211_TXQ_ATTR_AIFS]); |
1155 | 1155 | ||
1156 | if (txq_params->ac >= NL80211_NUM_ACS) | ||
1157 | return -EINVAL; | ||
1158 | |||
1156 | return 0; | 1159 | return 0; |
1157 | } | 1160 | } |
1158 | 1161 | ||
@@ -1332,6 +1335,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
1332 | goto bad_res; | 1335 | goto bad_res; |
1333 | } | 1336 | } |
1334 | 1337 | ||
1338 | if (!netif_running(netdev)) { | ||
1339 | result = -ENETDOWN; | ||
1340 | goto bad_res; | ||
1341 | } | ||
1342 | |||
1335 | nla_for_each_nested(nl_txq_params, | 1343 | nla_for_each_nested(nl_txq_params, |
1336 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], | 1344 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], |
1337 | rem_txq_params) { | 1345 | rem_txq_params) { |
@@ -2540,6 +2548,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
2540 | sizeof(struct nl80211_sta_flag_update), | 2548 | sizeof(struct nl80211_sta_flag_update), |
2541 | &sinfo->sta_flags)) | 2549 | &sinfo->sta_flags)) |
2542 | goto nla_put_failure; | 2550 | goto nla_put_failure; |
2551 | if ((sinfo->filled & STATION_INFO_T_OFFSET) && | ||
2552 | nla_put_u64(msg, NL80211_STA_INFO_T_OFFSET, | ||
2553 | sinfo->t_offset)) | ||
2554 | goto nla_put_failure; | ||
2543 | nla_nest_end(msg, sinfoattr); | 2555 | nla_nest_end(msg, sinfoattr); |
2544 | 2556 | ||
2545 | if ((sinfo->filled & STATION_INFO_ASSOC_REQ_IES) && | 2557 | if ((sinfo->filled & STATION_INFO_ASSOC_REQ_IES) && |
@@ -3340,6 +3352,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, | |||
3340 | cur_params.element_ttl) || | 3352 | cur_params.element_ttl) || |
3341 | nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, | 3353 | nla_put_u8(msg, NL80211_MESHCONF_AUTO_OPEN_PLINKS, |
3342 | cur_params.auto_open_plinks) || | 3354 | cur_params.auto_open_plinks) || |
3355 | nla_put_u32(msg, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, | ||
3356 | cur_params.dot11MeshNbrOffsetMaxNeighbor) || | ||
3343 | nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | 3357 | nla_put_u8(msg, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, |
3344 | cur_params.dot11MeshHWMPmaxPREQretries) || | 3358 | cur_params.dot11MeshHWMPmaxPREQretries) || |
3345 | nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME, | 3359 | nla_put_u32(msg, NL80211_MESHCONF_PATH_REFRESH_TIME, |
@@ -3385,6 +3399,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
3385 | [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, | 3399 | [NL80211_MESHCONF_TTL] = { .type = NLA_U8 }, |
3386 | [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 }, | 3400 | [NL80211_MESHCONF_ELEMENT_TTL] = { .type = NLA_U8 }, |
3387 | [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, | 3401 | [NL80211_MESHCONF_AUTO_OPEN_PLINKS] = { .type = NLA_U8 }, |
3402 | [NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR] = { .type = NLA_U32 }, | ||
3388 | 3403 | ||
3389 | [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, | 3404 | [NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES] = { .type = NLA_U8 }, |
3390 | [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 }, | 3405 | [NL80211_MESHCONF_PATH_REFRESH_TIME] = { .type = NLA_U32 }, |
@@ -3402,6 +3417,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A | |||
3402 | 3417 | ||
3403 | static const struct nla_policy | 3418 | static const struct nla_policy |
3404 | nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { | 3419 | nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = { |
3420 | [NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC] = { .type = NLA_U8 }, | ||
3405 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, | 3421 | [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 }, |
3406 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, | 3422 | [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 }, |
3407 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, | 3423 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, |
@@ -3454,6 +3470,9 @@ do {\ | |||
3454 | mask, NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8); | 3470 | mask, NL80211_MESHCONF_ELEMENT_TTL, nla_get_u8); |
3455 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, | 3471 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, auto_open_plinks, |
3456 | mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8); | 3472 | mask, NL80211_MESHCONF_AUTO_OPEN_PLINKS, nla_get_u8); |
3473 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshNbrOffsetMaxNeighbor, | ||
3474 | mask, NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, | ||
3475 | nla_get_u32); | ||
3457 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, | 3476 | FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshHWMPmaxPREQretries, |
3458 | mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, | 3477 | mask, NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, |
3459 | nla_get_u8); | 3478 | nla_get_u8); |
@@ -3511,6 +3530,12 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, | |||
3511 | nl80211_mesh_setup_params_policy)) | 3530 | nl80211_mesh_setup_params_policy)) |
3512 | return -EINVAL; | 3531 | return -EINVAL; |
3513 | 3532 | ||
3533 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC]) | ||
3534 | setup->sync_method = | ||
3535 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC])) ? | ||
3536 | IEEE80211_SYNC_METHOD_VENDOR : | ||
3537 | IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET; | ||
3538 | |||
3514 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL]) | 3539 | if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL]) |
3515 | setup->path_sel_proto = | 3540 | setup->path_sel_proto = |
3516 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ? | 3541 | (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ? |
@@ -6077,6 +6102,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
6077 | struct cfg80211_wowlan new_triggers = {}; | 6102 | struct cfg80211_wowlan new_triggers = {}; |
6078 | struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; | 6103 | struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; |
6079 | int err, i; | 6104 | int err, i; |
6105 | bool prev_enabled = rdev->wowlan; | ||
6080 | 6106 | ||
6081 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) | 6107 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) |
6082 | return -EOPNOTSUPP; | 6108 | return -EOPNOTSUPP; |
@@ -6209,6 +6235,9 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
6209 | rdev->wowlan = NULL; | 6235 | rdev->wowlan = NULL; |
6210 | } | 6236 | } |
6211 | 6237 | ||
6238 | if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan) | ||
6239 | rdev->ops->set_wakeup(&rdev->wiphy, rdev->wowlan); | ||
6240 | |||
6212 | return 0; | 6241 | return 0; |
6213 | error: | 6242 | error: |
6214 | for (i = 0; i < new_triggers.n_patterns; i++) | 6243 | for (i = 0; i < new_triggers.n_patterns; i++) |
@@ -6467,7 +6496,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6467 | .doit = nl80211_get_key, | 6496 | .doit = nl80211_get_key, |
6468 | .policy = nl80211_policy, | 6497 | .policy = nl80211_policy, |
6469 | .flags = GENL_ADMIN_PERM, | 6498 | .flags = GENL_ADMIN_PERM, |
6470 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6499 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6471 | NL80211_FLAG_NEED_RTNL, | 6500 | NL80211_FLAG_NEED_RTNL, |
6472 | }, | 6501 | }, |
6473 | { | 6502 | { |
@@ -6499,7 +6528,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6499 | .policy = nl80211_policy, | 6528 | .policy = nl80211_policy, |
6500 | .flags = GENL_ADMIN_PERM, | 6529 | .flags = GENL_ADMIN_PERM, |
6501 | .doit = nl80211_set_beacon, | 6530 | .doit = nl80211_set_beacon, |
6502 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6531 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6503 | NL80211_FLAG_NEED_RTNL, | 6532 | NL80211_FLAG_NEED_RTNL, |
6504 | }, | 6533 | }, |
6505 | { | 6534 | { |
@@ -6507,7 +6536,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6507 | .policy = nl80211_policy, | 6536 | .policy = nl80211_policy, |
6508 | .flags = GENL_ADMIN_PERM, | 6537 | .flags = GENL_ADMIN_PERM, |
6509 | .doit = nl80211_start_ap, | 6538 | .doit = nl80211_start_ap, |
6510 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6539 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6511 | NL80211_FLAG_NEED_RTNL, | 6540 | NL80211_FLAG_NEED_RTNL, |
6512 | }, | 6541 | }, |
6513 | { | 6542 | { |
@@ -6515,7 +6544,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6515 | .policy = nl80211_policy, | 6544 | .policy = nl80211_policy, |
6516 | .flags = GENL_ADMIN_PERM, | 6545 | .flags = GENL_ADMIN_PERM, |
6517 | .doit = nl80211_stop_ap, | 6546 | .doit = nl80211_stop_ap, |
6518 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6547 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6519 | NL80211_FLAG_NEED_RTNL, | 6548 | NL80211_FLAG_NEED_RTNL, |
6520 | }, | 6549 | }, |
6521 | { | 6550 | { |
@@ -6531,7 +6560,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6531 | .doit = nl80211_set_station, | 6560 | .doit = nl80211_set_station, |
6532 | .policy = nl80211_policy, | 6561 | .policy = nl80211_policy, |
6533 | .flags = GENL_ADMIN_PERM, | 6562 | .flags = GENL_ADMIN_PERM, |
6534 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6563 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6535 | NL80211_FLAG_NEED_RTNL, | 6564 | NL80211_FLAG_NEED_RTNL, |
6536 | }, | 6565 | }, |
6537 | { | 6566 | { |
@@ -6547,7 +6576,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6547 | .doit = nl80211_del_station, | 6576 | .doit = nl80211_del_station, |
6548 | .policy = nl80211_policy, | 6577 | .policy = nl80211_policy, |
6549 | .flags = GENL_ADMIN_PERM, | 6578 | .flags = GENL_ADMIN_PERM, |
6550 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6579 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6551 | NL80211_FLAG_NEED_RTNL, | 6580 | NL80211_FLAG_NEED_RTNL, |
6552 | }, | 6581 | }, |
6553 | { | 6582 | { |
@@ -6580,7 +6609,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6580 | .doit = nl80211_del_mpath, | 6609 | .doit = nl80211_del_mpath, |
6581 | .policy = nl80211_policy, | 6610 | .policy = nl80211_policy, |
6582 | .flags = GENL_ADMIN_PERM, | 6611 | .flags = GENL_ADMIN_PERM, |
6583 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6612 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6584 | NL80211_FLAG_NEED_RTNL, | 6613 | NL80211_FLAG_NEED_RTNL, |
6585 | }, | 6614 | }, |
6586 | { | 6615 | { |
@@ -6588,7 +6617,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6588 | .doit = nl80211_set_bss, | 6617 | .doit = nl80211_set_bss, |
6589 | .policy = nl80211_policy, | 6618 | .policy = nl80211_policy, |
6590 | .flags = GENL_ADMIN_PERM, | 6619 | .flags = GENL_ADMIN_PERM, |
6591 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6620 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6592 | NL80211_FLAG_NEED_RTNL, | 6621 | NL80211_FLAG_NEED_RTNL, |
6593 | }, | 6622 | }, |
6594 | { | 6623 | { |
@@ -6614,7 +6643,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6614 | .doit = nl80211_get_mesh_config, | 6643 | .doit = nl80211_get_mesh_config, |
6615 | .policy = nl80211_policy, | 6644 | .policy = nl80211_policy, |
6616 | /* can be retrieved by unprivileged users */ | 6645 | /* can be retrieved by unprivileged users */ |
6617 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6646 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6618 | NL80211_FLAG_NEED_RTNL, | 6647 | NL80211_FLAG_NEED_RTNL, |
6619 | }, | 6648 | }, |
6620 | { | 6649 | { |
@@ -6747,7 +6776,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6747 | .doit = nl80211_setdel_pmksa, | 6776 | .doit = nl80211_setdel_pmksa, |
6748 | .policy = nl80211_policy, | 6777 | .policy = nl80211_policy, |
6749 | .flags = GENL_ADMIN_PERM, | 6778 | .flags = GENL_ADMIN_PERM, |
6750 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6779 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6751 | NL80211_FLAG_NEED_RTNL, | 6780 | NL80211_FLAG_NEED_RTNL, |
6752 | }, | 6781 | }, |
6753 | { | 6782 | { |
@@ -6755,7 +6784,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6755 | .doit = nl80211_setdel_pmksa, | 6784 | .doit = nl80211_setdel_pmksa, |
6756 | .policy = nl80211_policy, | 6785 | .policy = nl80211_policy, |
6757 | .flags = GENL_ADMIN_PERM, | 6786 | .flags = GENL_ADMIN_PERM, |
6758 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6787 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6759 | NL80211_FLAG_NEED_RTNL, | 6788 | NL80211_FLAG_NEED_RTNL, |
6760 | }, | 6789 | }, |
6761 | { | 6790 | { |
@@ -6763,7 +6792,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6763 | .doit = nl80211_flush_pmksa, | 6792 | .doit = nl80211_flush_pmksa, |
6764 | .policy = nl80211_policy, | 6793 | .policy = nl80211_policy, |
6765 | .flags = GENL_ADMIN_PERM, | 6794 | .flags = GENL_ADMIN_PERM, |
6766 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6795 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6767 | NL80211_FLAG_NEED_RTNL, | 6796 | NL80211_FLAG_NEED_RTNL, |
6768 | }, | 6797 | }, |
6769 | { | 6798 | { |
@@ -6923,7 +6952,7 @@ static struct genl_ops nl80211_ops[] = { | |||
6923 | .doit = nl80211_probe_client, | 6952 | .doit = nl80211_probe_client, |
6924 | .policy = nl80211_policy, | 6953 | .policy = nl80211_policy, |
6925 | .flags = GENL_ADMIN_PERM, | 6954 | .flags = GENL_ADMIN_PERM, |
6926 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 6955 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
6927 | NL80211_FLAG_NEED_RTNL, | 6956 | NL80211_FLAG_NEED_RTNL, |
6928 | }, | 6957 | }, |
6929 | { | 6958 | { |
@@ -8012,6 +8041,39 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | |||
8012 | nlmsg_free(msg); | 8041 | nlmsg_free(msg); |
8013 | } | 8042 | } |
8014 | 8043 | ||
8044 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | ||
8045 | struct net_device *netdev, int freq, | ||
8046 | enum nl80211_channel_type type, gfp_t gfp) | ||
8047 | { | ||
8048 | struct sk_buff *msg; | ||
8049 | void *hdr; | ||
8050 | |||
8051 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
8052 | if (!msg) | ||
8053 | return; | ||
8054 | |||
8055 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CH_SWITCH_NOTIFY); | ||
8056 | if (!hdr) { | ||
8057 | nlmsg_free(msg); | ||
8058 | return; | ||
8059 | } | ||
8060 | |||
8061 | if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | ||
8062 | nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || | ||
8063 | nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, type)) | ||
8064 | goto nla_put_failure; | ||
8065 | |||
8066 | genlmsg_end(msg, hdr); | ||
8067 | |||
8068 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
8069 | nl80211_mlme_mcgrp.id, gfp); | ||
8070 | return; | ||
8071 | |||
8072 | nla_put_failure: | ||
8073 | genlmsg_cancel(msg, hdr); | ||
8074 | nlmsg_free(msg); | ||
8075 | } | ||
8076 | |||
8015 | void | 8077 | void |
8016 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, | 8078 | nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev, |
8017 | struct net_device *netdev, const u8 *peer, | 8079 | struct net_device *netdev, const u8 *peer, |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 4ffe50df9f31..01a1122c3b33 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -118,6 +118,10 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev, | |||
118 | struct net_device *netdev, int index, | 118 | struct net_device *netdev, int index, |
119 | const u8 *bssid, bool preauth, gfp_t gfp); | 119 | const u8 *bssid, bool preauth, gfp_t gfp); |
120 | 120 | ||
121 | void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev, | ||
122 | struct net_device *dev, int freq, | ||
123 | enum nl80211_channel_type type, gfp_t gfp); | ||
124 | |||
121 | bool nl80211_unexpected_frame(struct net_device *dev, | 125 | bool nl80211_unexpected_frame(struct net_device *dev, |
122 | const u8 *addr, gfp_t gfp); | 126 | const u8 *addr, gfp_t gfp); |
123 | bool nl80211_unexpected_4addr_frame(struct net_device *dev, | 127 | bool nl80211_unexpected_4addr_frame(struct net_device *dev, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index e9a0ac83b84c..15f347477a99 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -388,7 +388,15 @@ static void reg_regdb_query(const char *alpha2) | |||
388 | 388 | ||
389 | schedule_work(®_regdb_work); | 389 | schedule_work(®_regdb_work); |
390 | } | 390 | } |
391 | |||
392 | /* Feel free to add any other sanity checks here */ | ||
393 | static void reg_regdb_size_check(void) | ||
394 | { | ||
395 | /* We should ideally BUILD_BUG_ON() but then random builds would fail */ | ||
396 | WARN_ONCE(!reg_regdb_size, "db.txt is empty, you should update it..."); | ||
397 | } | ||
391 | #else | 398 | #else |
399 | static inline void reg_regdb_size_check(void) {} | ||
392 | static inline void reg_regdb_query(const char *alpha2) {} | 400 | static inline void reg_regdb_query(const char *alpha2) {} |
393 | #endif /* CONFIG_CFG80211_INTERNAL_REGDB */ | 401 | #endif /* CONFIG_CFG80211_INTERNAL_REGDB */ |
394 | 402 | ||
@@ -2322,6 +2330,8 @@ int __init regulatory_init(void) | |||
2322 | spin_lock_init(®_requests_lock); | 2330 | spin_lock_init(®_requests_lock); |
2323 | spin_lock_init(®_pending_beacons_lock); | 2331 | spin_lock_init(®_pending_beacons_lock); |
2324 | 2332 | ||
2333 | reg_regdb_size_check(); | ||
2334 | |||
2325 | cfg80211_regdomain = cfg80211_world_regdom; | 2335 | cfg80211_regdomain = cfg80211_world_regdom; |
2326 | 2336 | ||
2327 | user_alpha2[0] = '9'; | 2337 | user_alpha2[0] = '9'; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 70faadf16a32..fdbcfe692a36 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -378,7 +378,7 @@ 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 memcmp(a->bssid, b->bssid, ETH_ALEN); | 381 | return compare_ether_addr(a->bssid, b->bssid); |
382 | } | 382 | } |
383 | 383 | ||
384 | static int cmp_bss(struct cfg80211_bss *a, | 384 | static int cmp_bss(struct cfg80211_bss *a, |
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 9f544c95171c..22adfebaad27 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c | |||
@@ -781,8 +781,10 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, | |||
781 | if (cmd == SIOCSIWENCODEEXT) { | 781 | if (cmd == SIOCSIWENCODEEXT) { |
782 | struct iw_encode_ext *ee = (void *) extra; | 782 | struct iw_encode_ext *ee = (void *) extra; |
783 | 783 | ||
784 | if (iwp->length < sizeof(*ee) + ee->key_len) | 784 | if (iwp->length < sizeof(*ee) + ee->key_len) { |
785 | return -EFAULT; | 785 | err = -EFAULT; |
786 | goto out; | ||
787 | } | ||
786 | } | 788 | } |
787 | } | 789 | } |
788 | 790 | ||