diff options
Diffstat (limited to 'drivers/net/wireless')
121 files changed, 3876 insertions, 2420 deletions
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 2504ab005589..c8d123957188 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -241,6 +241,7 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) | |||
241 | 241 | ||
242 | sc->hw_busy_count = 0; | 242 | sc->hw_busy_count = 0; |
243 | del_timer_sync(&common->ani.timer); | 243 | del_timer_sync(&common->ani.timer); |
244 | del_timer_sync(&sc->rx_poll_timer); | ||
244 | 245 | ||
245 | ath9k_debug_samp_bb_mac(sc); | 246 | ath9k_debug_samp_bb_mac(sc); |
246 | ath9k_hw_disable_interrupts(ah); | 247 | ath9k_hw_disable_interrupts(ah); |
@@ -282,6 +283,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
282 | 283 | ||
283 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 284 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
284 | 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); | ||
285 | if (!common->disable_ani) | 287 | if (!common->disable_ani) |
286 | ath_start_ani(common); | 288 | ath_start_ani(common); |
287 | } | 289 | } |
@@ -912,10 +914,19 @@ void ath_hw_check(struct work_struct *work) | |||
912 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 914 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
913 | unsigned long flags; | 915 | unsigned long flags; |
914 | int busy; | 916 | int busy; |
917 | u8 is_alive, nbeacon = 1; | ||
915 | 918 | ||
916 | ath9k_ps_wakeup(sc); | 919 | ath9k_ps_wakeup(sc); |
917 | 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)) | ||
918 | 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 | } | ||
919 | 930 | ||
920 | spin_lock_irqsave(&common->cc_lock, flags); | 931 | spin_lock_irqsave(&common->cc_lock, flags); |
921 | busy = ath_update_survey_stats(sc); | 932 | busy = ath_update_survey_stats(sc); |
@@ -926,12 +937,18 @@ void ath_hw_check(struct work_struct *work) | |||
926 | if (busy >= 99) { | 937 | if (busy >= 99) { |
927 | if (++sc->hw_busy_count >= 3) { | 938 | if (++sc->hw_busy_count >= 3) { |
928 | RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); | 939 | RESET_STAT_INC(sc, RESET_TYPE_BB_HANG); |
929 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | 940 | goto sched_reset; |
930 | } | 941 | } |
931 | 942 | } else if (busy >= 0) { | |
932 | } else if (busy >= 0) | ||
933 | sc->hw_busy_count = 0; | 943 | sc->hw_busy_count = 0; |
944 | nbeacon = 3; | ||
945 | } | ||
934 | 946 | ||
947 | ath_start_rx_poll(sc, nbeacon); | ||
948 | goto out; | ||
949 | |||
950 | sched_reset: | ||
951 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); | ||
935 | out: | 952 | out: |
936 | ath9k_ps_restore(sc); | 953 | ath9k_ps_restore(sc); |
937 | } | 954 | } |
@@ -1133,6 +1150,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1133 | 1150 | ||
1134 | if (ath_tx_start(hw, skb, &txctl) != 0) { | 1151 | if (ath_tx_start(hw, skb, &txctl) != 0) { |
1135 | ath_dbg(common, XMIT, "TX failed\n"); | 1152 | ath_dbg(common, XMIT, "TX failed\n"); |
1153 | TX_STAT_INC(txctl.txq->axq_qnum, txfailed); | ||
1136 | goto exit; | 1154 | goto exit; |
1137 | } | 1155 | } |
1138 | 1156 | ||
@@ -1151,6 +1169,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1151 | mutex_lock(&sc->mutex); | 1169 | mutex_lock(&sc->mutex); |
1152 | 1170 | ||
1153 | ath_cancel_work(sc); | 1171 | ath_cancel_work(sc); |
1172 | del_timer_sync(&sc->rx_poll_timer); | ||
1154 | 1173 | ||
1155 | if (sc->sc_flags & SC_OP_INVALID) { | 1174 | if (sc->sc_flags & SC_OP_INVALID) { |
1156 | ath_dbg(common, ANY, "Device not present\n"); | 1175 | ath_dbg(common, ANY, "Device not present\n"); |
@@ -1383,6 +1402,24 @@ static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, | |||
1383 | } | 1402 | } |
1384 | } | 1403 | } |
1385 | 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 | } | ||
1386 | 1423 | ||
1387 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 1424 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
1388 | struct ieee80211_vif *vif) | 1425 | struct ieee80211_vif *vif) |
@@ -1904,6 +1941,8 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
1904 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; | 1941 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; |
1905 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | 1942 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; |
1906 | 1943 | ||
1944 | ath_start_rx_poll(sc, 3); | ||
1945 | |||
1907 | if (!common->disable_ani) { | 1946 | if (!common->disable_ani) { |
1908 | sc->sc_flags |= SC_OP_ANI_RUN; | 1947 | sc->sc_flags |= SC_OP_ANI_RUN; |
1909 | ath_start_ani(common); | 1948 | ath_start_ani(common); |
@@ -1943,6 +1982,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
1943 | /* Stop ANI */ | 1982 | /* Stop ANI */ |
1944 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 1983 | sc->sc_flags &= ~SC_OP_ANI_RUN; |
1945 | del_timer_sync(&common->ani.timer); | 1984 | del_timer_sync(&common->ani.timer); |
1985 | del_timer_sync(&sc->rx_poll_timer); | ||
1946 | memset(&sc->caldata, 0, sizeof(sc->caldata)); | 1986 | memset(&sc->caldata, 0, sizeof(sc->caldata)); |
1947 | } | 1987 | } |
1948 | } | 1988 | } |
@@ -1986,6 +2026,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1986 | } else { | 2026 | } else { |
1987 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 2027 | sc->sc_flags &= ~SC_OP_ANI_RUN; |
1988 | del_timer_sync(&common->ani.timer); | 2028 | del_timer_sync(&common->ani.timer); |
2029 | del_timer_sync(&sc->rx_poll_timer); | ||
1989 | } | 2030 | } |
1990 | } | 2031 | } |
1991 | 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 99cba968aa58..18741a409cf2 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 76f7f9251436..d65dac88e190 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c | |||
@@ -420,10 +420,13 @@ nla_put_failure: | |||
420 | static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) | 420 | static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) |
421 | { | 421 | { |
422 | struct iwl_notification_wait calib_wait; | 422 | struct iwl_notification_wait calib_wait; |
423 | static const u8 calib_complete[] = { | ||
424 | CALIBRATION_COMPLETE_NOTIFICATION | ||
425 | }; | ||
423 | int ret; | 426 | int ret; |
424 | 427 | ||
425 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, | 428 | iwl_init_notification_wait(&priv->notif_wait, &calib_wait, |
426 | CALIBRATION_COMPLETE_NOTIFICATION, | 429 | calib_complete, ARRAY_SIZE(calib_complete), |
427 | NULL, NULL); | 430 | NULL, NULL); |
428 | ret = iwl_init_alive_start(priv); | 431 | ret = iwl_init_alive_start(priv); |
429 | if (ret) { | 432 | if (ret) { |
@@ -598,11 +601,11 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | |||
598 | IWL_ERR(priv, "No uCode has not been loaded\n"); | 601 | IWL_ERR(priv, "No uCode has not been loaded\n"); |
599 | return -EINVAL; | 602 | return -EINVAL; |
600 | } else { | 603 | } else { |
601 | img = &priv->fw->img[priv->shrd->ucode_type]; | 604 | img = &priv->fw->img[priv->cur_ucode]; |
602 | inst_size = img->sec[IWL_UCODE_SECTION_INST].len; | 605 | inst_size = img->sec[IWL_UCODE_SECTION_INST].len; |
603 | data_size = img->sec[IWL_UCODE_SECTION_DATA].len; | 606 | data_size = img->sec[IWL_UCODE_SECTION_DATA].len; |
604 | } | 607 | } |
605 | NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type); | 608 | NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->cur_ucode); |
606 | NLA_PUT_U32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size); | 609 | NLA_PUT_U32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size); |
607 | NLA_PUT_U32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size); | 610 | NLA_PUT_U32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size); |
608 | status = cfg80211_testmode_reply(skb); | 611 | status = cfg80211_testmode_reply(skb); |
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 b7ce6a6e355f..2d2bfce24fc1 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -632,6 +632,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
632 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 632 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
633 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 633 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
634 | struct ieee80211_rx_status rx_status; | 634 | struct ieee80211_rx_status rx_status; |
635 | struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); | ||
635 | 636 | ||
636 | if (data->idle) { | 637 | if (data->idle) { |
637 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); | 638 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); |
@@ -666,6 +667,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
666 | spin_lock(&hwsim_radio_lock); | 667 | spin_lock(&hwsim_radio_lock); |
667 | list_for_each_entry(data2, &hwsim_radios, list) { | 668 | list_for_each_entry(data2, &hwsim_radios, list) { |
668 | struct sk_buff *nskb; | 669 | struct sk_buff *nskb; |
670 | struct ieee80211_mgmt *mgmt; | ||
669 | 671 | ||
670 | if (data == data2) | 672 | if (data == data2) |
671 | continue; | 673 | continue; |
@@ -683,8 +685,17 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
683 | 685 | ||
684 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) | 686 | if (mac80211_hwsim_addr_match(data2, hdr->addr1)) |
685 | ack = true; | 687 | ack = true; |
688 | |||
689 | /* set bcn timestamp relative to receiver mactime */ | ||
686 | rx_status.mactime = | 690 | rx_status.mactime = |
687 | le64_to_cpu(__mac80211_hwsim_get_tsf(data2)); | 691 | le64_to_cpu(__mac80211_hwsim_get_tsf(data2)); |
692 | mgmt = (struct ieee80211_mgmt *) nskb->data; | ||
693 | if (ieee80211_is_beacon(mgmt->frame_control) || | ||
694 | ieee80211_is_probe_resp(mgmt->frame_control)) | ||
695 | mgmt->u.beacon.timestamp = cpu_to_le64( | ||
696 | rx_status.mactime + | ||
697 | 24 * 8 * 10 / txrate->bitrate); | ||
698 | |||
688 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 699 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
689 | ieee80211_rx_irqsafe(data2->hw, nskb); | 700 | ieee80211_rx_irqsafe(data2->hw, nskb); |
690 | } | 701 | } |
@@ -698,12 +709,6 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
698 | bool ack; | 709 | bool ack; |
699 | struct ieee80211_tx_info *txi; | 710 | struct ieee80211_tx_info *txi; |
700 | u32 _pid; | 711 | u32 _pid; |
701 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data; | ||
702 | struct mac80211_hwsim_data *data = hw->priv; | ||
703 | |||
704 | if (ieee80211_is_beacon(mgmt->frame_control) || | ||
705 | ieee80211_is_probe_resp(mgmt->frame_control)) | ||
706 | mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data); | ||
707 | 712 | ||
708 | mac80211_hwsim_monitor_rx(hw, skb); | 713 | mac80211_hwsim_monitor_rx(hw, skb); |
709 | 714 | ||
@@ -800,11 +805,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
800 | struct ieee80211_vif *vif) | 805 | struct ieee80211_vif *vif) |
801 | { | 806 | { |
802 | struct ieee80211_hw *hw = arg; | 807 | struct ieee80211_hw *hw = arg; |
803 | struct mac80211_hwsim_data *data = hw->priv; | ||
804 | struct sk_buff *skb; | 808 | struct sk_buff *skb; |
805 | struct ieee80211_tx_info *info; | 809 | struct ieee80211_tx_info *info; |
806 | u32 _pid; | 810 | u32 _pid; |
807 | struct ieee80211_mgmt *mgmt; | ||
808 | 811 | ||
809 | hwsim_check_magic(vif); | 812 | hwsim_check_magic(vif); |
810 | 813 | ||
@@ -818,9 +821,6 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
818 | return; | 821 | return; |
819 | info = IEEE80211_SKB_CB(skb); | 822 | info = IEEE80211_SKB_CB(skb); |
820 | 823 | ||
821 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
822 | mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data); | ||
823 | |||
824 | mac80211_hwsim_monitor_rx(hw, skb); | 824 | mac80211_hwsim_monitor_rx(hw, skb); |
825 | 825 | ||
826 | /* wmediumd mode check */ | 826 | /* wmediumd mode check */ |
@@ -1444,7 +1444,7 @@ DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group, | |||
1444 | hwsim_fops_group_read, hwsim_fops_group_write, | 1444 | hwsim_fops_group_read, hwsim_fops_group_write, |
1445 | "%llx\n"); | 1445 | "%llx\n"); |
1446 | 1446 | ||
1447 | struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr( | 1447 | static struct mac80211_hwsim_data *get_hwsim_data_ref_from_addr( |
1448 | struct mac_address *addr) | 1448 | struct mac_address *addr) |
1449 | { | 1449 | { |
1450 | struct mac80211_hwsim_data *data; | 1450 | struct mac80211_hwsim_data *data; |
@@ -1789,9 +1789,11 @@ static int __init init_mac80211_hwsim(void) | |||
1789 | IEEE80211_HW_SIGNAL_DBM | | 1789 | IEEE80211_HW_SIGNAL_DBM | |
1790 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | 1790 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | |
1791 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | | 1791 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
1792 | IEEE80211_HW_AMPDU_AGGREGATION; | 1792 | IEEE80211_HW_AMPDU_AGGREGATION | |
1793 | IEEE80211_HW_WANT_MONITOR_VIF; | ||
1793 | 1794 | ||
1794 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; | 1795 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
1796 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | ||
1795 | 1797 | ||
1796 | /* ask mac80211 to reserve space for magic */ | 1798 | /* ask mac80211 to reserve space for magic */ |
1797 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 1799 | 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/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/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/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/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/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 28ebc69218a3..521398803099 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -1958,37 +1958,35 @@ static inline void rtl_write_dword(struct rtl_priv *rtlpriv, | |||
1958 | static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, | 1958 | static inline u32 rtl_get_bbreg(struct ieee80211_hw *hw, |
1959 | u32 regaddr, u32 bitmask) | 1959 | u32 regaddr, u32 bitmask) |
1960 | { | 1960 | { |
1961 | return ((struct rtl_priv *)(hw)->priv)->cfg->ops->get_bbreg(hw, | 1961 | struct rtl_priv *rtlpriv = hw->priv; |
1962 | regaddr, | 1962 | |
1963 | bitmask); | 1963 | return rtlpriv->cfg->ops->get_bbreg(hw, regaddr, bitmask); |
1964 | } | 1964 | } |
1965 | 1965 | ||
1966 | 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, |
1967 | u32 bitmask, u32 data) | 1967 | u32 bitmask, u32 data) |
1968 | { | 1968 | { |
1969 | ((struct rtl_priv *)(hw)->priv)->cfg->ops->set_bbreg(hw, | 1969 | struct rtl_priv *rtlpriv = hw->priv; |
1970 | regaddr, bitmask, | ||
1971 | data); | ||
1972 | 1970 | ||
1971 | rtlpriv->cfg->ops->set_bbreg(hw, regaddr, bitmask, data); | ||
1973 | } | 1972 | } |
1974 | 1973 | ||
1975 | static inline u32 rtl_get_rfreg(struct ieee80211_hw *hw, | 1974 | static inline u32 rtl_get_rfreg(struct ieee80211_hw *hw, |
1976 | enum radio_path rfpath, u32 regaddr, | 1975 | enum radio_path rfpath, u32 regaddr, |
1977 | u32 bitmask) | 1976 | u32 bitmask) |
1978 | { | 1977 | { |
1979 | return ((struct rtl_priv *)(hw)->priv)->cfg->ops->get_rfreg(hw, | 1978 | struct rtl_priv *rtlpriv = hw->priv; |
1980 | rfpath, | 1979 | |
1981 | regaddr, | 1980 | return rtlpriv->cfg->ops->get_rfreg(hw, rfpath, regaddr, bitmask); |
1982 | bitmask); | ||
1983 | } | 1981 | } |
1984 | 1982 | ||
1985 | static inline void rtl_set_rfreg(struct ieee80211_hw *hw, | 1983 | static inline void rtl_set_rfreg(struct ieee80211_hw *hw, |
1986 | enum radio_path rfpath, u32 regaddr, | 1984 | enum radio_path rfpath, u32 regaddr, |
1987 | u32 bitmask, u32 data) | 1985 | u32 bitmask, u32 data) |
1988 | { | 1986 | { |
1989 | ((struct rtl_priv *)(hw)->priv)->cfg->ops->set_rfreg(hw, | 1987 | struct rtl_priv *rtlpriv = hw->priv; |
1990 | rfpath, regaddr, | 1988 | |
1991 | bitmask, data); | 1989 | rtlpriv->cfg->ops->set_rfreg(hw, rfpath, regaddr, bitmask, data); |
1992 | } | 1990 | } |
1993 | 1991 | ||
1994 | 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) + |