diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-04-15 16:21:34 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-15 16:21:34 -0400 |
commit | 5c01d5669356e13f0fb468944c1dd4c6a7e978ad (patch) | |
tree | fa43345288d7b25fac92b3b35360a177c4947313 | |
parent | fea069152614cdeefba4b2bf80afcddb9c217fc8 (diff) | |
parent | a5e944f1d955f3819503348426763e21e0413ba6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts:
Documentation/feature-removal-schedule.txt
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/wl12xx/wl1271_main.c
174 files changed, 8597 insertions, 5613 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 267e90582d20..116a13c4f13f 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -520,7 +520,6 @@ Who: Hans de Goede <hdegoede@redhat.com> | |||
520 | 520 | ||
521 | ---------------------------- | 521 | ---------------------------- |
522 | 522 | ||
523 | |||
524 | What: corgikbd, spitzkbd, tosakbd driver | 523 | What: corgikbd, spitzkbd, tosakbd driver |
525 | When: 2.6.35 | 524 | When: 2.6.35 |
526 | Files: drivers/input/keyboard/{corgi,spitz,tosa}kbd.c | 525 | Files: drivers/input/keyboard/{corgi,spitz,tosa}kbd.c |
@@ -608,3 +607,24 @@ Why: Useful in 2003, implementation is a hack. | |||
608 | Generally invoked by accident today. | 607 | Generally invoked by accident today. |
609 | Seen as doing more harm than good. | 608 | Seen as doing more harm than good. |
610 | Who: Len Brown <len.brown@intel.com> | 609 | Who: Len Brown <len.brown@intel.com> |
610 | |||
611 | ---------------------------- | ||
612 | |||
613 | What: iwlwifi 50XX module parameters | ||
614 | When: 2.6.40 | ||
615 | Why: The "..50" modules parameters were used to configure 5000 series and | ||
616 | up devices; different set of module parameters also available for 4965 | ||
617 | with same functionalities. Consolidate both set into single place | ||
618 | in drivers/net/wireless/iwlwifi/iwl-agn.c | ||
619 | |||
620 | Who: Wey-Yi Guy <wey-yi.w.guy@intel.com> | ||
621 | |||
622 | ---------------------------- | ||
623 | |||
624 | What: iwl4965 alias support | ||
625 | When: 2.6.40 | ||
626 | Why: Internal alias support has been present in module-init-tools for some | ||
627 | time, the MODULE_ALIAS("iwl4965") boilerplate aliases can be removed | ||
628 | with no impact. | ||
629 | |||
630 | Who: Wey-Yi Guy <wey-yi.w.guy@intel.com> | ||
diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h index 826c45e6b274..ec8134b4b949 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.h +++ b/drivers/net/wireless/ath/ar9170/cmd.h | |||
@@ -79,7 +79,7 @@ __regwrite_out : \ | |||
79 | if (__nreg) { \ | 79 | if (__nreg) { \ |
80 | if (IS_ACCEPTING_CMD(__ar)) \ | 80 | if (IS_ACCEPTING_CMD(__ar)) \ |
81 | __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ | 81 | __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ |
82 | 8 * __nreg, \ | 82 | 8 * __nreg, \ |
83 | (u8 *) &__ar->cmdbuf[1], \ | 83 | (u8 *) &__ar->cmdbuf[1], \ |
84 | 0, NULL); \ | 84 | 0, NULL); \ |
85 | __nreg = 0; \ | 85 | __nreg = 0; \ |
diff --git a/drivers/net/wireless/ath/ar9170/eeprom.h b/drivers/net/wireless/ath/ar9170/eeprom.h index d2c8cc83f1dd..6c4663883423 100644 --- a/drivers/net/wireless/ath/ar9170/eeprom.h +++ b/drivers/net/wireless/ath/ar9170/eeprom.h | |||
@@ -127,8 +127,8 @@ struct ar9170_eeprom { | |||
127 | __le16 checksum; | 127 | __le16 checksum; |
128 | __le16 version; | 128 | __le16 version; |
129 | u8 operating_flags; | 129 | u8 operating_flags; |
130 | #define AR9170_OPFLAG_5GHZ 1 | 130 | #define AR9170_OPFLAG_5GHZ 1 |
131 | #define AR9170_OPFLAG_2GHZ 2 | 131 | #define AR9170_OPFLAG_2GHZ 2 |
132 | u8 misc; | 132 | u8 misc; |
133 | __le16 reg_domain[2]; | 133 | __le16 reg_domain[2]; |
134 | u8 mac_address[6]; | 134 | u8 mac_address[6]; |
diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 0a1d4c28e68a..06f1f3c951a4 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h | |||
@@ -425,5 +425,6 @@ enum ar9170_txq { | |||
425 | 425 | ||
426 | #define AR9170_TXQ_DEPTH 32 | 426 | #define AR9170_TXQ_DEPTH 32 |
427 | #define AR9170_TX_MAX_PENDING 128 | 427 | #define AR9170_TX_MAX_PENDING 128 |
428 | #define AR9170_RX_STREAM_MAX_SIZE 65535 | ||
428 | 429 | ||
429 | #endif /* __AR9170_HW_H */ | 430 | #endif /* __AR9170_HW_H */ |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 7c4a7d84535c..0312cee39570 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -236,7 +236,7 @@ static void __ar9170_dump_txqueue(struct ar9170 *ar, | |||
236 | wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); | 236 | wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); |
237 | 237 | ||
238 | skb_queue_walk(queue, skb) { | 238 | skb_queue_walk(queue, skb) { |
239 | printk(KERN_DEBUG "index:%d => \n", i++); | 239 | printk(KERN_DEBUG "index:%d =>\n", i++); |
240 | ar9170_print_txheader(ar, skb); | 240 | ar9170_print_txheader(ar, skb); |
241 | } | 241 | } |
242 | if (i != skb_queue_len(queue)) | 242 | if (i != skb_queue_len(queue)) |
@@ -281,7 +281,7 @@ static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) | |||
281 | unsigned long flags; | 281 | unsigned long flags; |
282 | 282 | ||
283 | spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); | 283 | spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); |
284 | printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n", | 284 | printk(KERN_DEBUG "%s: A-MPDU tx_status queue =>\n", |
285 | wiphy_name(ar->hw->wiphy)); | 285 | wiphy_name(ar->hw->wiphy)); |
286 | __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); | 286 | __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); |
287 | spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); | 287 | spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); |
@@ -308,7 +308,7 @@ static void ar9170_recycle_expired(struct ar9170 *ar, | |||
308 | if (time_is_before_jiffies(arinfo->timeout)) { | 308 | if (time_is_before_jiffies(arinfo->timeout)) { |
309 | #ifdef AR9170_QUEUE_DEBUG | 309 | #ifdef AR9170_QUEUE_DEBUG |
310 | printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => " | 310 | printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => " |
311 | "recycle \n", wiphy_name(ar->hw->wiphy), | 311 | "recycle\n", wiphy_name(ar->hw->wiphy), |
312 | jiffies, arinfo->timeout); | 312 | jiffies, arinfo->timeout); |
313 | ar9170_print_txheader(ar, skb); | 313 | ar9170_print_txheader(ar, skb); |
314 | #endif /* AR9170_QUEUE_DEBUG */ | 314 | #endif /* AR9170_QUEUE_DEBUG */ |
@@ -689,7 +689,8 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | |||
689 | 689 | ||
690 | /* firmware debug */ | 690 | /* firmware debug */ |
691 | case 0xca: | 691 | case 0xca: |
692 | printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4); | 692 | printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, |
693 | (char *)buf + 4); | ||
693 | break; | 694 | break; |
694 | case 0xcb: | 695 | case 0xcb: |
695 | len -= 4; | 696 | len -= 4; |
@@ -1728,7 +1729,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1728 | printk(KERN_DEBUG "%s: queue %d full\n", | 1729 | printk(KERN_DEBUG "%s: queue %d full\n", |
1729 | wiphy_name(ar->hw->wiphy), i); | 1730 | wiphy_name(ar->hw->wiphy), i); |
1730 | 1731 | ||
1731 | printk(KERN_DEBUG "%s: stuck frames: ===> \n", | 1732 | printk(KERN_DEBUG "%s: stuck frames: ===>\n", |
1732 | wiphy_name(ar->hw->wiphy)); | 1733 | wiphy_name(ar->hw->wiphy)); |
1733 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); | 1734 | ar9170_dump_txqueue(ar, &ar->tx_pending[i]); |
1734 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); | 1735 | ar9170_dump_txqueue(ar, &ar->tx_status[i]); |
@@ -2512,7 +2513,7 @@ void *ar9170_alloc(size_t priv_size) | |||
2512 | * tends to split the streams into separate rx descriptors. | 2513 | * tends to split the streams into separate rx descriptors. |
2513 | */ | 2514 | */ |
2514 | 2515 | ||
2515 | skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL); | 2516 | skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); |
2516 | if (!skb) | 2517 | if (!skb) |
2517 | goto err_nomem; | 2518 | goto err_nomem; |
2518 | 2519 | ||
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 99a6da464bd3..c1c7c427501c 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
@@ -67,18 +67,28 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
67 | { USB_DEVICE(0x0cf3, 0x1001) }, | 67 | { USB_DEVICE(0x0cf3, 0x1001) }, |
68 | /* TP-Link TL-WN821N v2 */ | 68 | /* TP-Link TL-WN821N v2 */ |
69 | { USB_DEVICE(0x0cf3, 0x1002) }, | 69 | { USB_DEVICE(0x0cf3, 0x1002) }, |
70 | /* 3Com Dual Band 802.11n USB Adapter */ | ||
71 | { USB_DEVICE(0x0cf3, 0x1010) }, | ||
72 | /* H3C Dual Band 802.11n USB Adapter */ | ||
73 | { USB_DEVICE(0x0cf3, 0x1011) }, | ||
70 | /* Cace Airpcap NX */ | 74 | /* Cace Airpcap NX */ |
71 | { USB_DEVICE(0xcace, 0x0300) }, | 75 | { USB_DEVICE(0xcace, 0x0300) }, |
72 | /* D-Link DWA 160 A1 */ | 76 | /* D-Link DWA 160 A1 */ |
73 | { USB_DEVICE(0x07d1, 0x3c10) }, | 77 | { USB_DEVICE(0x07d1, 0x3c10) }, |
74 | /* D-Link DWA 160 A2 */ | 78 | /* D-Link DWA 160 A2 */ |
75 | { USB_DEVICE(0x07d1, 0x3a09) }, | 79 | { USB_DEVICE(0x07d1, 0x3a09) }, |
80 | /* Netgear WNA1000 */ | ||
81 | { USB_DEVICE(0x0846, 0x9040) }, | ||
76 | /* Netgear WNDA3100 */ | 82 | /* Netgear WNDA3100 */ |
77 | { USB_DEVICE(0x0846, 0x9010) }, | 83 | { USB_DEVICE(0x0846, 0x9010) }, |
78 | /* Netgear WN111 v2 */ | 84 | /* Netgear WN111 v2 */ |
79 | { USB_DEVICE(0x0846, 0x9001) }, | 85 | { USB_DEVICE(0x0846, 0x9001) }, |
80 | /* Zydas ZD1221 */ | 86 | /* Zydas ZD1221 */ |
81 | { USB_DEVICE(0x0ace, 0x1221) }, | 87 | { USB_DEVICE(0x0ace, 0x1221) }, |
88 | /* Proxim ORiNOCO 802.11n USB */ | ||
89 | { USB_DEVICE(0x1435, 0x0804) }, | ||
90 | /* WNC Generic 11n USB Dongle */ | ||
91 | { USB_DEVICE(0x1435, 0x0326) }, | ||
82 | /* ZyXEL NWD271N */ | 92 | /* ZyXEL NWD271N */ |
83 | { USB_DEVICE(0x0586, 0x3417) }, | 93 | { USB_DEVICE(0x0586, 0x3417) }, |
84 | /* Z-Com UB81 BG */ | 94 | /* Z-Com UB81 BG */ |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 71fc960814f0..1fbf6b1f9a7e 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -48,6 +48,12 @@ enum ath_device_state { | |||
48 | ATH_HW_INITIALIZED, | 48 | ATH_HW_INITIALIZED, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | enum ath_bus_type { | ||
52 | ATH_PCI, | ||
53 | ATH_AHB, | ||
54 | ATH_USB, | ||
55 | }; | ||
56 | |||
51 | struct reg_dmn_pair_mapping { | 57 | struct reg_dmn_pair_mapping { |
52 | u16 regDmnEnum; | 58 | u16 regDmnEnum; |
53 | u16 reg_5ghz_ctl; | 59 | u16 reg_5ghz_ctl; |
@@ -73,9 +79,10 @@ struct ath_ops { | |||
73 | struct ath_common; | 79 | struct ath_common; |
74 | 80 | ||
75 | struct ath_bus_ops { | 81 | struct ath_bus_ops { |
76 | void (*read_cachesize)(struct ath_common *common, int *csz); | 82 | enum ath_bus_type ath_bus_type; |
77 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); | 83 | void (*read_cachesize)(struct ath_common *common, int *csz); |
78 | void (*bt_coex_prep)(struct ath_common *common); | 84 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); |
85 | void (*bt_coex_prep)(struct ath_common *common); | ||
79 | }; | 86 | }; |
80 | 87 | ||
81 | struct ath_common { | 88 | struct ath_common { |
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index 090dc6d268a3..cc09595b781a 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile | |||
@@ -12,5 +12,6 @@ ath5k-y += attach.o | |||
12 | ath5k-y += base.o | 12 | ath5k-y += base.o |
13 | ath5k-y += led.o | 13 | ath5k-y += led.o |
14 | ath5k-y += rfkill.o | 14 | ath5k-y += rfkill.o |
15 | ath5k-y += ani.o | ||
15 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o | 16 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o |
16 | obj-$(CONFIG_ATH5K) += ath5k.o | 17 | obj-$(CONFIG_ATH5K) += ath5k.o |
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c new file mode 100644 index 000000000000..584a32859bdb --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -0,0 +1,744 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Bruno Randolf <br1@einfach.org> | ||
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 "ath5k.h" | ||
18 | #include "base.h" | ||
19 | #include "reg.h" | ||
20 | #include "debug.h" | ||
21 | #include "ani.h" | ||
22 | |||
23 | /** | ||
24 | * DOC: Basic ANI Operation | ||
25 | * | ||
26 | * Adaptive Noise Immunity (ANI) controls five noise immunity parameters | ||
27 | * depending on the amount of interference in the environment, increasing | ||
28 | * or reducing sensitivity as necessary. | ||
29 | * | ||
30 | * The parameters are: | ||
31 | * - "noise immunity" | ||
32 | * - "spur immunity" | ||
33 | * - "firstep level" | ||
34 | * - "OFDM weak signal detection" | ||
35 | * - "CCK weak signal detection" | ||
36 | * | ||
37 | * Basically we look at the amount of ODFM and CCK timing errors we get and then | ||
38 | * raise or lower immunity accordingly by setting one or more of these | ||
39 | * parameters. | ||
40 | * Newer chipsets have PHY error counters in hardware which will generate a MIB | ||
41 | * interrupt when they overflow. Older hardware has too enable PHY error frames | ||
42 | * by setting a RX flag and then count every single PHY error. When a specified | ||
43 | * threshold of errors has been reached we will raise immunity. | ||
44 | * Also we regularly check the amount of errors and lower or raise immunity as | ||
45 | * necessary. | ||
46 | */ | ||
47 | |||
48 | |||
49 | /*** ANI parameter control ***/ | ||
50 | |||
51 | /** | ||
52 | * ath5k_ani_set_noise_immunity_level() - Set noise immunity level | ||
53 | * | ||
54 | * @level: level between 0 and @ATH5K_ANI_MAX_NOISE_IMM_LVL | ||
55 | */ | ||
56 | void | ||
57 | ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) | ||
58 | { | ||
59 | /* TODO: | ||
60 | * ANI documents suggest the following five levels to use, but the HAL | ||
61 | * and ath9k use only use the last two levels, making this | ||
62 | * essentially an on/off option. There *may* be a reason for this (???), | ||
63 | * so i stick with the HAL version for now... | ||
64 | */ | ||
65 | #if 0 | ||
66 | const s8 hi[] = { -18, -18, -16, -14, -12 }; | ||
67 | const s8 lo[] = { -52, -56, -60, -64, -70 }; | ||
68 | const s8 sz[] = { -34, -41, -48, -55, -62 }; | ||
69 | const s8 fr[] = { -70, -72, -75, -78, -80 }; | ||
70 | #else | ||
71 | const s8 sz[] = { -55, -62 }; | ||
72 | const s8 lo[] = { -64, -70 }; | ||
73 | const s8 hi[] = { -14, -12 }; | ||
74 | const s8 fr[] = { -78, -80 }; | ||
75 | #endif | ||
76 | if (level < 0 || level > ARRAY_SIZE(sz)) { | ||
77 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
78 | "level out of range %d", level); | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, | ||
83 | AR5K_PHY_DESIRED_SIZE_TOT, sz[level]); | ||
84 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_AGCCOARSE, | ||
85 | AR5K_PHY_AGCCOARSE_LO, lo[level]); | ||
86 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_AGCCOARSE, | ||
87 | AR5K_PHY_AGCCOARSE_HI, hi[level]); | ||
88 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, | ||
89 | AR5K_PHY_SIG_FIRPWR, fr[level]); | ||
90 | |||
91 | ah->ah_sc->ani_state.noise_imm_level = level; | ||
92 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); | ||
93 | } | ||
94 | |||
95 | |||
96 | /** | ||
97 | * ath5k_ani_set_spur_immunity_level() - Set spur immunity level | ||
98 | * | ||
99 | * @level: level between 0 and @max_spur_level (the maximum level is dependent | ||
100 | * on the chip revision). | ||
101 | */ | ||
102 | void | ||
103 | ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) | ||
104 | { | ||
105 | const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; | ||
106 | |||
107 | if (level < 0 || level > ARRAY_SIZE(val) || | ||
108 | level > ah->ah_sc->ani_state.max_spur_level) { | ||
109 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
110 | "level out of range %d", level); | ||
111 | return; | ||
112 | } | ||
113 | |||
114 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, | ||
115 | AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, val[level]); | ||
116 | |||
117 | ah->ah_sc->ani_state.spur_level = level; | ||
118 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); | ||
119 | } | ||
120 | |||
121 | |||
122 | /** | ||
123 | * ath5k_ani_set_firstep_level() - Set "firstep" level | ||
124 | * | ||
125 | * @level: level between 0 and @ATH5K_ANI_MAX_FIRSTEP_LVL | ||
126 | */ | ||
127 | void | ||
128 | ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) | ||
129 | { | ||
130 | const int val[] = { 0, 4, 8 }; | ||
131 | |||
132 | if (level < 0 || level > ARRAY_SIZE(val)) { | ||
133 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
134 | "level out of range %d", level); | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SIG, | ||
139 | AR5K_PHY_SIG_FIRSTEP, val[level]); | ||
140 | |||
141 | ah->ah_sc->ani_state.firstep_level = level; | ||
142 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "new level %d", level); | ||
143 | } | ||
144 | |||
145 | |||
146 | /** | ||
147 | * ath5k_ani_set_ofdm_weak_signal_detection() - Control OFDM weak signal | ||
148 | * detection | ||
149 | * | ||
150 | * @on: turn on or off | ||
151 | */ | ||
152 | void | ||
153 | ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) | ||
154 | { | ||
155 | const int m1l[] = { 127, 50 }; | ||
156 | const int m2l[] = { 127, 40 }; | ||
157 | const int m1[] = { 127, 0x4d }; | ||
158 | const int m2[] = { 127, 0x40 }; | ||
159 | const int m2cnt[] = { 31, 16 }; | ||
160 | const int m2lcnt[] = { 63, 48 }; | ||
161 | |||
162 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
163 | AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]); | ||
164 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
165 | AR5K_PHY_WEAK_OFDM_LOW_THR_M2, m2l[on]); | ||
166 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, | ||
167 | AR5K_PHY_WEAK_OFDM_HIGH_THR_M1, m1[on]); | ||
168 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, | ||
169 | AR5K_PHY_WEAK_OFDM_HIGH_THR_M2, m2[on]); | ||
170 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_HIGH_THR, | ||
171 | AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT, m2cnt[on]); | ||
172 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
173 | AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT, m2lcnt[on]); | ||
174 | |||
175 | if (on) | ||
176 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
177 | AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN); | ||
178 | else | ||
179 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | ||
180 | AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN); | ||
181 | |||
182 | ah->ah_sc->ani_state.ofdm_weak_sig = on; | ||
183 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", | ||
184 | on ? "on" : "off"); | ||
185 | } | ||
186 | |||
187 | |||
188 | /** | ||
189 | * ath5k_ani_set_cck_weak_signal_detection() - control CCK weak signal detection | ||
190 | * | ||
191 | * @on: turn on or off | ||
192 | */ | ||
193 | void | ||
194 | ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) | ||
195 | { | ||
196 | const int val[] = { 8, 6 }; | ||
197 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR, | ||
198 | AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]); | ||
199 | ah->ah_sc->ani_state.cck_weak_sig = on; | ||
200 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "turned %s", | ||
201 | on ? "on" : "off"); | ||
202 | } | ||
203 | |||
204 | |||
205 | /*** ANI algorithm ***/ | ||
206 | |||
207 | /** | ||
208 | * ath5k_ani_raise_immunity() - Increase noise immunity | ||
209 | * | ||
210 | * @ofdm_trigger: If this is true we are called because of too many OFDM errors, | ||
211 | * the algorithm will tune more parameters then. | ||
212 | * | ||
213 | * Try to raise noise immunity (=decrease sensitivity) in several steps | ||
214 | * depending on the average RSSI of the beacons we received. | ||
215 | */ | ||
216 | static void | ||
217 | ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, | ||
218 | bool ofdm_trigger) | ||
219 | { | ||
220 | int rssi = ah->ah_beacon_rssi_avg.avg; | ||
221 | |||
222 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)", | ||
223 | ofdm_trigger ? "ODFM" : "CCK"); | ||
224 | |||
225 | /* first: raise noise immunity */ | ||
226 | if (as->noise_imm_level < ATH5K_ANI_MAX_NOISE_IMM_LVL) { | ||
227 | ath5k_ani_set_noise_immunity_level(ah, as->noise_imm_level + 1); | ||
228 | return; | ||
229 | } | ||
230 | |||
231 | /* only OFDM: raise spur immunity level */ | ||
232 | if (ofdm_trigger && | ||
233 | as->spur_level < ah->ah_sc->ani_state.max_spur_level) { | ||
234 | ath5k_ani_set_spur_immunity_level(ah, as->spur_level + 1); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | /* AP mode */ | ||
239 | if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { | ||
240 | if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) | ||
241 | ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); | ||
242 | return; | ||
243 | } | ||
244 | |||
245 | /* STA and IBSS mode */ | ||
246 | |||
247 | /* TODO: for IBSS mode it would be better to keep a beacon RSSI average | ||
248 | * per each neighbour node and use the minimum of these, to make sure we | ||
249 | * don't shut out a remote node by raising immunity too high. */ | ||
250 | |||
251 | if (rssi > ATH5K_ANI_RSSI_THR_HIGH) { | ||
252 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
253 | "beacon RSSI high"); | ||
254 | /* only OFDM: beacon RSSI is high, we can disable ODFM weak | ||
255 | * signal detection */ | ||
256 | if (ofdm_trigger && as->ofdm_weak_sig == true) { | ||
257 | ath5k_ani_set_ofdm_weak_signal_detection(ah, false); | ||
258 | ath5k_ani_set_spur_immunity_level(ah, 0); | ||
259 | return; | ||
260 | } | ||
261 | /* as a last resort or CCK: raise firstep level */ | ||
262 | if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) { | ||
263 | ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); | ||
264 | return; | ||
265 | } | ||
266 | } else if (rssi > ATH5K_ANI_RSSI_THR_LOW) { | ||
267 | /* beacon RSSI in mid range, we need OFDM weak signal detect, | ||
268 | * but can raise firstep level */ | ||
269 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
270 | "beacon RSSI mid"); | ||
271 | if (ofdm_trigger && as->ofdm_weak_sig == false) | ||
272 | ath5k_ani_set_ofdm_weak_signal_detection(ah, true); | ||
273 | if (as->firstep_level < ATH5K_ANI_MAX_FIRSTEP_LVL) | ||
274 | ath5k_ani_set_firstep_level(ah, as->firstep_level + 1); | ||
275 | return; | ||
276 | } else if (ah->ah_current_channel->band == IEEE80211_BAND_2GHZ) { | ||
277 | /* beacon RSSI is low. in B/G mode turn of OFDM weak signal | ||
278 | * detect and zero firstep level to maximize CCK sensitivity */ | ||
279 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
280 | "beacon RSSI low, 2GHz"); | ||
281 | if (ofdm_trigger && as->ofdm_weak_sig == true) | ||
282 | ath5k_ani_set_ofdm_weak_signal_detection(ah, false); | ||
283 | if (as->firstep_level > 0) | ||
284 | ath5k_ani_set_firstep_level(ah, 0); | ||
285 | return; | ||
286 | } | ||
287 | |||
288 | /* TODO: why not?: | ||
289 | if (as->cck_weak_sig == true) { | ||
290 | ath5k_ani_set_cck_weak_signal_detection(ah, false); | ||
291 | } | ||
292 | */ | ||
293 | } | ||
294 | |||
295 | |||
296 | /** | ||
297 | * ath5k_ani_lower_immunity() - Decrease noise immunity | ||
298 | * | ||
299 | * Try to lower noise immunity (=increase sensitivity) in several steps | ||
300 | * depending on the average RSSI of the beacons we received. | ||
301 | */ | ||
302 | static void | ||
303 | ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) | ||
304 | { | ||
305 | int rssi = ah->ah_beacon_rssi_avg.avg; | ||
306 | |||
307 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity"); | ||
308 | |||
309 | if (ah->ah_sc->opmode == NL80211_IFTYPE_AP) { | ||
310 | /* AP mode */ | ||
311 | if (as->firstep_level > 0) { | ||
312 | ath5k_ani_set_firstep_level(ah, as->firstep_level - 1); | ||
313 | return; | ||
314 | } | ||
315 | } else { | ||
316 | /* STA and IBSS mode (see TODO above) */ | ||
317 | if (rssi > ATH5K_ANI_RSSI_THR_HIGH) { | ||
318 | /* beacon signal is high, leave OFDM weak signal | ||
319 | * detection off or it may oscillate | ||
320 | * TODO: who said it's off??? */ | ||
321 | } else if (rssi > ATH5K_ANI_RSSI_THR_LOW) { | ||
322 | /* beacon RSSI is mid-range: turn on ODFM weak signal | ||
323 | * detection and next, lower firstep level */ | ||
324 | if (as->ofdm_weak_sig == false) { | ||
325 | ath5k_ani_set_ofdm_weak_signal_detection(ah, | ||
326 | true); | ||
327 | return; | ||
328 | } | ||
329 | if (as->firstep_level > 0) { | ||
330 | ath5k_ani_set_firstep_level(ah, | ||
331 | as->firstep_level - 1); | ||
332 | return; | ||
333 | } | ||
334 | } else { | ||
335 | /* beacon signal is low: only reduce firstep level */ | ||
336 | if (as->firstep_level > 0) { | ||
337 | ath5k_ani_set_firstep_level(ah, | ||
338 | as->firstep_level - 1); | ||
339 | return; | ||
340 | } | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /* all modes */ | ||
345 | if (as->spur_level > 0) { | ||
346 | ath5k_ani_set_spur_immunity_level(ah, as->spur_level - 1); | ||
347 | return; | ||
348 | } | ||
349 | |||
350 | /* finally, reduce noise immunity */ | ||
351 | if (as->noise_imm_level > 0) { | ||
352 | ath5k_ani_set_noise_immunity_level(ah, as->noise_imm_level - 1); | ||
353 | return; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | |||
358 | /** | ||
359 | * ath5k_hw_ani_get_listen_time() - Calculate time spent listening | ||
360 | * | ||
361 | * Return an approximation of the time spent "listening" in milliseconds (ms) | ||
362 | * since the last call of this function by deducting the cycles spent | ||
363 | * transmitting and receiving from the total cycle count. | ||
364 | * Save profile count values for debugging/statistics and because we might want | ||
365 | * to use them later. | ||
366 | * | ||
367 | * We assume no one else clears these registers! | ||
368 | */ | ||
369 | static int | ||
370 | ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as) | ||
371 | { | ||
372 | int listen; | ||
373 | |||
374 | /* freeze */ | ||
375 | ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC); | ||
376 | /* read */ | ||
377 | as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE); | ||
378 | as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR); | ||
379 | as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX); | ||
380 | as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX); | ||
381 | /* clear */ | ||
382 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
383 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
384 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
385 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
386 | /* un-freeze */ | ||
387 | ath5k_hw_reg_write(ah, 0, AR5K_MIBC); | ||
388 | |||
389 | /* TODO: where does 44000 come from? (11g clock rate?) */ | ||
390 | listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000; | ||
391 | |||
392 | if (as->pfc_cycles == 0 || listen < 0) | ||
393 | return 0; | ||
394 | return listen; | ||
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * ath5k_ani_save_and_clear_phy_errors() - Clear and save PHY error counters | ||
400 | * | ||
401 | * Clear the PHY error counters as soon as possible, since this might be called | ||
402 | * from a MIB interrupt and we want to make sure we don't get interrupted again. | ||
403 | * Add the count of CCK and OFDM errors to our internal state, so it can be used | ||
404 | * by the algorithm later. | ||
405 | * | ||
406 | * Will be called from interrupt and tasklet context. | ||
407 | * Returns 0 if both counters are zero. | ||
408 | */ | ||
409 | static int | ||
410 | ath5k_ani_save_and_clear_phy_errors(struct ath5k_hw *ah, | ||
411 | struct ath5k_ani_state *as) | ||
412 | { | ||
413 | unsigned int ofdm_err, cck_err; | ||
414 | |||
415 | if (!ah->ah_capabilities.cap_has_phyerr_counters) | ||
416 | return 0; | ||
417 | |||
418 | ofdm_err = ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1); | ||
419 | cck_err = ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2); | ||
420 | |||
421 | /* reset counters first, we might be in a hurry (interrupt) */ | ||
422 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_OFDM_TRIG_HIGH, | ||
423 | AR5K_PHYERR_CNT1); | ||
424 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_CCK_TRIG_HIGH, | ||
425 | AR5K_PHYERR_CNT2); | ||
426 | |||
427 | ofdm_err = ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - ofdm_err); | ||
428 | cck_err = ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - cck_err); | ||
429 | |||
430 | /* sometimes both can be zero, especially when there is a superfluous | ||
431 | * second interrupt. detect that here and return an error. */ | ||
432 | if (ofdm_err <= 0 && cck_err <= 0) | ||
433 | return 0; | ||
434 | |||
435 | /* avoid negative values should one of the registers overflow */ | ||
436 | if (ofdm_err > 0) { | ||
437 | as->ofdm_errors += ofdm_err; | ||
438 | as->sum_ofdm_errors += ofdm_err; | ||
439 | } | ||
440 | if (cck_err > 0) { | ||
441 | as->cck_errors += cck_err; | ||
442 | as->sum_cck_errors += cck_err; | ||
443 | } | ||
444 | return 1; | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * ath5k_ani_period_restart() - Restart ANI period | ||
450 | * | ||
451 | * Just reset counters, so they are clear for the next "ani period". | ||
452 | */ | ||
453 | static void | ||
454 | ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as) | ||
455 | { | ||
456 | /* keep last values for debugging */ | ||
457 | as->last_ofdm_errors = as->ofdm_errors; | ||
458 | as->last_cck_errors = as->cck_errors; | ||
459 | as->last_listen = as->listen_time; | ||
460 | |||
461 | as->ofdm_errors = 0; | ||
462 | as->cck_errors = 0; | ||
463 | as->listen_time = 0; | ||
464 | } | ||
465 | |||
466 | |||
467 | /** | ||
468 | * ath5k_ani_calibration() - The main ANI calibration function | ||
469 | * | ||
470 | * We count OFDM and CCK errors relative to the time where we did not send or | ||
471 | * receive ("listen" time) and raise or lower immunity accordingly. | ||
472 | * This is called regularly (every second) from the calibration timer, but also | ||
473 | * when an error threshold has been reached. | ||
474 | * | ||
475 | * In order to synchronize access from different contexts, this should be | ||
476 | * called only indirectly by scheduling the ANI tasklet! | ||
477 | */ | ||
478 | void | ||
479 | ath5k_ani_calibration(struct ath5k_hw *ah) | ||
480 | { | ||
481 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | ||
482 | int listen, ofdm_high, ofdm_low, cck_high, cck_low; | ||
483 | |||
484 | if (as->ani_mode != ATH5K_ANI_MODE_AUTO) | ||
485 | return; | ||
486 | |||
487 | /* get listen time since last call and add it to the counter because we | ||
488 | * might not have restarted the "ani period" last time */ | ||
489 | listen = ath5k_hw_ani_get_listen_time(ah, as); | ||
490 | as->listen_time += listen; | ||
491 | |||
492 | ath5k_ani_save_and_clear_phy_errors(ah, as); | ||
493 | |||
494 | ofdm_high = as->listen_time * ATH5K_ANI_OFDM_TRIG_HIGH / 1000; | ||
495 | cck_high = as->listen_time * ATH5K_ANI_CCK_TRIG_HIGH / 1000; | ||
496 | ofdm_low = as->listen_time * ATH5K_ANI_OFDM_TRIG_LOW / 1000; | ||
497 | cck_low = as->listen_time * ATH5K_ANI_CCK_TRIG_LOW / 1000; | ||
498 | |||
499 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
500 | "listen %d (now %d)", as->listen_time, listen); | ||
501 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
502 | "check high ofdm %d/%d cck %d/%d", | ||
503 | as->ofdm_errors, ofdm_high, as->cck_errors, cck_high); | ||
504 | |||
505 | if (as->ofdm_errors > ofdm_high || as->cck_errors > cck_high) { | ||
506 | /* too many PHY errors - we have to raise immunity */ | ||
507 | bool ofdm_flag = as->ofdm_errors > ofdm_high ? true : false; | ||
508 | ath5k_ani_raise_immunity(ah, as, ofdm_flag); | ||
509 | ath5k_ani_period_restart(ah, as); | ||
510 | |||
511 | } else if (as->listen_time > 5 * ATH5K_ANI_LISTEN_PERIOD) { | ||
512 | /* If more than 5 (TODO: why 5?) periods have passed and we got | ||
513 | * relatively little errors we can try to lower immunity */ | ||
514 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
515 | "check low ofdm %d/%d cck %d/%d", | ||
516 | as->ofdm_errors, ofdm_low, as->cck_errors, cck_low); | ||
517 | |||
518 | if (as->ofdm_errors <= ofdm_low && as->cck_errors <= cck_low) | ||
519 | ath5k_ani_lower_immunity(ah, as); | ||
520 | |||
521 | ath5k_ani_period_restart(ah, as); | ||
522 | } | ||
523 | } | ||
524 | |||
525 | |||
526 | /*** INTERRUPT HANDLER ***/ | ||
527 | |||
528 | /** | ||
529 | * ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters | ||
530 | * | ||
531 | * Just read & reset the registers quickly, so they don't generate more | ||
532 | * interrupts, save the counters and schedule the tasklet to decide whether | ||
533 | * to raise immunity or not. | ||
534 | * | ||
535 | * We just need to handle PHY error counters, ath5k_hw_update_mib_counters() | ||
536 | * should take care of all "normal" MIB interrupts. | ||
537 | */ | ||
538 | void | ||
539 | ath5k_ani_mib_intr(struct ath5k_hw *ah) | ||
540 | { | ||
541 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | ||
542 | |||
543 | /* nothing to do here if HW does not have PHY error counters - they | ||
544 | * can't be the reason for the MIB interrupt then */ | ||
545 | if (!ah->ah_capabilities.cap_has_phyerr_counters) | ||
546 | return; | ||
547 | |||
548 | /* not in use but clear anyways */ | ||
549 | ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); | ||
550 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | ||
551 | |||
552 | if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) | ||
553 | return; | ||
554 | |||
555 | /* if one of the errors triggered, we can get a superfluous second | ||
556 | * interrupt, even though we have already reset the register. the | ||
557 | * function detects that so we can return early */ | ||
558 | if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) | ||
559 | return; | ||
560 | |||
561 | if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH || | ||
562 | as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) | ||
563 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
564 | } | ||
565 | |||
566 | |||
567 | /** | ||
568 | * ath5k_ani_phy_error_report() - Used by older HW to report PHY errors | ||
569 | * | ||
570 | * This is used by hardware without PHY error counters to report PHY errors | ||
571 | * on a frame-by-frame basis, instead of the interrupt. | ||
572 | */ | ||
573 | void | ||
574 | ath5k_ani_phy_error_report(struct ath5k_hw *ah, | ||
575 | enum ath5k_phy_error_code phyerr) | ||
576 | { | ||
577 | struct ath5k_ani_state *as = &ah->ah_sc->ani_state; | ||
578 | |||
579 | if (phyerr == AR5K_RX_PHY_ERROR_OFDM_TIMING) { | ||
580 | as->ofdm_errors++; | ||
581 | if (as->ofdm_errors > ATH5K_ANI_OFDM_TRIG_HIGH) | ||
582 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
583 | } else if (phyerr == AR5K_RX_PHY_ERROR_CCK_TIMING) { | ||
584 | as->cck_errors++; | ||
585 | if (as->cck_errors > ATH5K_ANI_CCK_TRIG_HIGH) | ||
586 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | |||
591 | /*** INIT ***/ | ||
592 | |||
593 | /** | ||
594 | * ath5k_enable_phy_err_counters() - Enable PHY error counters | ||
595 | * | ||
596 | * Enable PHY error counters for OFDM and CCK timing errors. | ||
597 | */ | ||
598 | static void | ||
599 | ath5k_enable_phy_err_counters(struct ath5k_hw *ah) | ||
600 | { | ||
601 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_OFDM_TRIG_HIGH, | ||
602 | AR5K_PHYERR_CNT1); | ||
603 | ath5k_hw_reg_write(ah, ATH5K_PHYERR_CNT_MAX - ATH5K_ANI_CCK_TRIG_HIGH, | ||
604 | AR5K_PHYERR_CNT2); | ||
605 | ath5k_hw_reg_write(ah, AR5K_PHY_ERR_FIL_OFDM, AR5K_PHYERR_CNT1_MASK); | ||
606 | ath5k_hw_reg_write(ah, AR5K_PHY_ERR_FIL_CCK, AR5K_PHYERR_CNT2_MASK); | ||
607 | |||
608 | /* not in use */ | ||
609 | ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); | ||
610 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | ||
611 | } | ||
612 | |||
613 | |||
614 | /** | ||
615 | * ath5k_disable_phy_err_counters() - Disable PHY error counters | ||
616 | * | ||
617 | * Disable PHY error counters for OFDM and CCK timing errors. | ||
618 | */ | ||
619 | static void | ||
620 | ath5k_disable_phy_err_counters(struct ath5k_hw *ah) | ||
621 | { | ||
622 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT1); | ||
623 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT2); | ||
624 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT1_MASK); | ||
625 | ath5k_hw_reg_write(ah, 0, AR5K_PHYERR_CNT2_MASK); | ||
626 | |||
627 | /* not in use */ | ||
628 | ath5k_hw_reg_write(ah, 0, AR5K_OFDM_FIL_CNT); | ||
629 | ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); | ||
630 | } | ||
631 | |||
632 | |||
633 | /** | ||
634 | * ath5k_ani_init() - Initialize ANI | ||
635 | * @mode: Which mode to use (auto, manual high, manual low, off) | ||
636 | * | ||
637 | * Initialize ANI according to mode. | ||
638 | */ | ||
639 | void | ||
640 | ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode) | ||
641 | { | ||
642 | /* ANI is only possible on 5212 and newer */ | ||
643 | if (ah->ah_version < AR5K_AR5212) | ||
644 | return; | ||
645 | |||
646 | /* clear old state information */ | ||
647 | memset(&ah->ah_sc->ani_state, 0, sizeof(ah->ah_sc->ani_state)); | ||
648 | |||
649 | /* older hardware has more spur levels than newer */ | ||
650 | if (ah->ah_mac_srev < AR5K_SREV_AR2414) | ||
651 | ah->ah_sc->ani_state.max_spur_level = 7; | ||
652 | else | ||
653 | ah->ah_sc->ani_state.max_spur_level = 2; | ||
654 | |||
655 | /* initial values for our ani parameters */ | ||
656 | if (mode == ATH5K_ANI_MODE_OFF) { | ||
657 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI off\n"); | ||
658 | } else if (mode == ATH5K_ANI_MODE_MANUAL_LOW) { | ||
659 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
660 | "ANI manual low -> high sensitivity\n"); | ||
661 | ath5k_ani_set_noise_immunity_level(ah, 0); | ||
662 | ath5k_ani_set_spur_immunity_level(ah, 0); | ||
663 | ath5k_ani_set_firstep_level(ah, 0); | ||
664 | ath5k_ani_set_ofdm_weak_signal_detection(ah, true); | ||
665 | ath5k_ani_set_cck_weak_signal_detection(ah, true); | ||
666 | } else if (mode == ATH5K_ANI_MODE_MANUAL_HIGH) { | ||
667 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, | ||
668 | "ANI manual high -> low sensitivity\n"); | ||
669 | ath5k_ani_set_noise_immunity_level(ah, | ||
670 | ATH5K_ANI_MAX_NOISE_IMM_LVL); | ||
671 | ath5k_ani_set_spur_immunity_level(ah, | ||
672 | ah->ah_sc->ani_state.max_spur_level); | ||
673 | ath5k_ani_set_firstep_level(ah, ATH5K_ANI_MAX_FIRSTEP_LVL); | ||
674 | ath5k_ani_set_ofdm_weak_signal_detection(ah, false); | ||
675 | ath5k_ani_set_cck_weak_signal_detection(ah, false); | ||
676 | } else if (mode == ATH5K_ANI_MODE_AUTO) { | ||
677 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "ANI auto\n"); | ||
678 | ath5k_ani_set_noise_immunity_level(ah, 0); | ||
679 | ath5k_ani_set_spur_immunity_level(ah, 0); | ||
680 | ath5k_ani_set_firstep_level(ah, 0); | ||
681 | ath5k_ani_set_ofdm_weak_signal_detection(ah, true); | ||
682 | ath5k_ani_set_cck_weak_signal_detection(ah, false); | ||
683 | } | ||
684 | |||
685 | /* newer hardware has PHY error counter registers which we can use to | ||
686 | * get OFDM and CCK error counts. older hardware has to set rxfilter and | ||
687 | * report every single PHY error by calling ath5k_ani_phy_error_report() | ||
688 | */ | ||
689 | if (mode == ATH5K_ANI_MODE_AUTO) { | ||
690 | if (ah->ah_capabilities.cap_has_phyerr_counters) | ||
691 | ath5k_enable_phy_err_counters(ah); | ||
692 | else | ||
693 | ath5k_hw_set_rx_filter(ah, ath5k_hw_get_rx_filter(ah) | | ||
694 | AR5K_RX_FILTER_PHYERR); | ||
695 | } else { | ||
696 | if (ah->ah_capabilities.cap_has_phyerr_counters) | ||
697 | ath5k_disable_phy_err_counters(ah); | ||
698 | else | ||
699 | ath5k_hw_set_rx_filter(ah, ath5k_hw_get_rx_filter(ah) & | ||
700 | ~AR5K_RX_FILTER_PHYERR); | ||
701 | } | ||
702 | |||
703 | ah->ah_sc->ani_state.ani_mode = mode; | ||
704 | } | ||
705 | |||
706 | |||
707 | /*** DEBUG ***/ | ||
708 | |||
709 | #ifdef CONFIG_ATH5K_DEBUG | ||
710 | |||
711 | void | ||
712 | ath5k_ani_print_counters(struct ath5k_hw *ah) | ||
713 | { | ||
714 | /* clears too */ | ||
715 | printk(KERN_NOTICE "ACK fail\t%d\n", | ||
716 | ath5k_hw_reg_read(ah, AR5K_ACK_FAIL)); | ||
717 | printk(KERN_NOTICE "RTS fail\t%d\n", | ||
718 | ath5k_hw_reg_read(ah, AR5K_RTS_FAIL)); | ||
719 | printk(KERN_NOTICE "RTS success\t%d\n", | ||
720 | ath5k_hw_reg_read(ah, AR5K_RTS_OK)); | ||
721 | printk(KERN_NOTICE "FCS error\t%d\n", | ||
722 | ath5k_hw_reg_read(ah, AR5K_FCS_FAIL)); | ||
723 | |||
724 | /* no clear */ | ||
725 | printk(KERN_NOTICE "tx\t%d\n", | ||
726 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX)); | ||
727 | printk(KERN_NOTICE "rx\t%d\n", | ||
728 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX)); | ||
729 | printk(KERN_NOTICE "busy\t%d\n", | ||
730 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR)); | ||
731 | printk(KERN_NOTICE "cycles\t%d\n", | ||
732 | ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE)); | ||
733 | |||
734 | printk(KERN_NOTICE "AR5K_PHYERR_CNT1\t%d\n", | ||
735 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT1)); | ||
736 | printk(KERN_NOTICE "AR5K_PHYERR_CNT2\t%d\n", | ||
737 | ath5k_hw_reg_read(ah, AR5K_PHYERR_CNT2)); | ||
738 | printk(KERN_NOTICE "AR5K_OFDM_FIL_CNT\t%d\n", | ||
739 | ath5k_hw_reg_read(ah, AR5K_OFDM_FIL_CNT)); | ||
740 | printk(KERN_NOTICE "AR5K_CCK_FIL_CNT\t%d\n", | ||
741 | ath5k_hw_reg_read(ah, AR5K_CCK_FIL_CNT)); | ||
742 | } | ||
743 | |||
744 | #endif | ||
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h new file mode 100644 index 000000000000..55cf26d8522c --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ani.h | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 Bruno Randolf <br1@einfach.org> | ||
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 | #ifndef ANI_H | ||
17 | #define ANI_H | ||
18 | |||
19 | /* these thresholds are relative to the ATH5K_ANI_LISTEN_PERIOD */ | ||
20 | #define ATH5K_ANI_LISTEN_PERIOD 100 | ||
21 | #define ATH5K_ANI_OFDM_TRIG_HIGH 500 | ||
22 | #define ATH5K_ANI_OFDM_TRIG_LOW 200 | ||
23 | #define ATH5K_ANI_CCK_TRIG_HIGH 200 | ||
24 | #define ATH5K_ANI_CCK_TRIG_LOW 100 | ||
25 | |||
26 | /* average beacon RSSI thresholds */ | ||
27 | #define ATH5K_ANI_RSSI_THR_HIGH 40 | ||
28 | #define ATH5K_ANI_RSSI_THR_LOW 7 | ||
29 | |||
30 | /* maximum availabe levels */ | ||
31 | #define ATH5K_ANI_MAX_FIRSTEP_LVL 2 | ||
32 | #define ATH5K_ANI_MAX_NOISE_IMM_LVL 1 | ||
33 | |||
34 | |||
35 | /** | ||
36 | * enum ath5k_ani_mode - mode for ANI / noise sensitivity | ||
37 | * | ||
38 | * @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI | ||
39 | * algorithm after it has been on auto mode. | ||
40 | * ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low, | ||
41 | * maximizing sensitivity. ANI will not run. | ||
42 | * ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high, | ||
43 | * minimizing sensitivity. ANI will not run. | ||
44 | * ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the | ||
45 | * amount of OFDM and CCK frame errors (default). | ||
46 | */ | ||
47 | enum ath5k_ani_mode { | ||
48 | ATH5K_ANI_MODE_OFF = 0, | ||
49 | ATH5K_ANI_MODE_MANUAL_LOW = 1, | ||
50 | ATH5K_ANI_MODE_MANUAL_HIGH = 2, | ||
51 | ATH5K_ANI_MODE_AUTO = 3 | ||
52 | }; | ||
53 | |||
54 | |||
55 | /** | ||
56 | * struct ath5k_ani_state - ANI state and associated counters | ||
57 | * | ||
58 | * @max_spur_level: the maximum spur level is chip dependent | ||
59 | */ | ||
60 | struct ath5k_ani_state { | ||
61 | enum ath5k_ani_mode ani_mode; | ||
62 | |||
63 | /* state */ | ||
64 | int noise_imm_level; | ||
65 | int spur_level; | ||
66 | int firstep_level; | ||
67 | bool ofdm_weak_sig; | ||
68 | bool cck_weak_sig; | ||
69 | |||
70 | int max_spur_level; | ||
71 | |||
72 | /* used by the algorithm */ | ||
73 | unsigned int listen_time; | ||
74 | unsigned int ofdm_errors; | ||
75 | unsigned int cck_errors; | ||
76 | |||
77 | /* debug/statistics only: numbers from last ANI calibration */ | ||
78 | unsigned int pfc_tx; | ||
79 | unsigned int pfc_rx; | ||
80 | unsigned int pfc_busy; | ||
81 | unsigned int pfc_cycles; | ||
82 | unsigned int last_listen; | ||
83 | unsigned int last_ofdm_errors; | ||
84 | unsigned int last_cck_errors; | ||
85 | unsigned int sum_ofdm_errors; | ||
86 | unsigned int sum_cck_errors; | ||
87 | }; | ||
88 | |||
89 | void ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode); | ||
90 | void ath5k_ani_mib_intr(struct ath5k_hw *ah); | ||
91 | void ath5k_ani_calibration(struct ath5k_hw *ah); | ||
92 | void ath5k_ani_phy_error_report(struct ath5k_hw *ah, | ||
93 | enum ath5k_phy_error_code phyerr); | ||
94 | |||
95 | /* for manual control */ | ||
96 | void ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level); | ||
97 | void ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level); | ||
98 | void ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level); | ||
99 | void ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on); | ||
100 | void ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on); | ||
101 | |||
102 | void ath5k_ani_print_counters(struct ath5k_hw *ah); | ||
103 | |||
104 | #endif /* ANI_H */ | ||
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 1d7491c85460..2785946f659a 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -202,6 +202,8 @@ | |||
202 | #define AR5K_TUNE_MAX_TXPOWER 63 | 202 | #define AR5K_TUNE_MAX_TXPOWER 63 |
203 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 | 203 | #define AR5K_TUNE_DEFAULT_TXPOWER 25 |
204 | #define AR5K_TUNE_TPC_TXPOWER false | 204 | #define AR5K_TUNE_TPC_TXPOWER false |
205 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_FULL 10000 /* 10 sec */ | ||
206 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ | ||
205 | 207 | ||
206 | #define AR5K_INIT_CARR_SENSE_EN 1 | 208 | #define AR5K_INIT_CARR_SENSE_EN 1 |
207 | 209 | ||
@@ -799,9 +801,9 @@ struct ath5k_athchan_2ghz { | |||
799 | * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold | 801 | * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold |
800 | * We currently do increments on interrupt by | 802 | * We currently do increments on interrupt by |
801 | * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 | 803 | * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 |
802 | * @AR5K_INT_MIB: Indicates the Management Information Base counters should be | 804 | * @AR5K_INT_MIB: Indicates the either Management Information Base counters or |
803 | * checked. We should do this with ath5k_hw_update_mib_counters() but | 805 | * one of the PHY error counters reached the maximum value and should be |
804 | * it seems we should also then do some noise immunity work. | 806 | * read and cleared. |
805 | * @AR5K_INT_RXPHY: RX PHY Error | 807 | * @AR5K_INT_RXPHY: RX PHY Error |
806 | * @AR5K_INT_RXKCM: RX Key cache miss | 808 | * @AR5K_INT_RXKCM: RX Key cache miss |
807 | * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a | 809 | * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a |
@@ -889,10 +891,11 @@ enum ath5k_int { | |||
889 | AR5K_INT_NOCARD = 0xffffffff | 891 | AR5K_INT_NOCARD = 0xffffffff |
890 | }; | 892 | }; |
891 | 893 | ||
892 | /* Software interrupts used for calibration */ | 894 | /* mask which calibration is active at the moment */ |
893 | enum ath5k_software_interrupt { | 895 | enum ath5k_calibration_mask { |
894 | AR5K_SWI_FULL_CALIBRATION = 0x01, | 896 | AR5K_CALIBRATION_FULL = 0x01, |
895 | AR5K_SWI_SHORT_CALIBRATION = 0x02, | 897 | AR5K_CALIBRATION_SHORT = 0x02, |
898 | AR5K_CALIBRATION_ANI = 0x04, | ||
896 | }; | 899 | }; |
897 | 900 | ||
898 | /* | 901 | /* |
@@ -981,6 +984,8 @@ struct ath5k_capabilities { | |||
981 | struct { | 984 | struct { |
982 | u8 q_tx_num; | 985 | u8 q_tx_num; |
983 | } cap_queues; | 986 | } cap_queues; |
987 | |||
988 | bool cap_has_phyerr_counters; | ||
984 | }; | 989 | }; |
985 | 990 | ||
986 | /* size of noise floor history (keep it a power of two) */ | 991 | /* size of noise floor history (keep it a power of two) */ |
@@ -991,6 +996,15 @@ struct ath5k_nfcal_hist | |||
991 | s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ | 996 | s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ |
992 | }; | 997 | }; |
993 | 998 | ||
999 | /** | ||
1000 | * struct avg_val - Helper structure for average calculation | ||
1001 | * @avg: contains the actual average value | ||
1002 | * @avg_weight: is used internally during calculation to prevent rounding errors | ||
1003 | */ | ||
1004 | struct ath5k_avg_val { | ||
1005 | int avg; | ||
1006 | int avg_weight; | ||
1007 | }; | ||
994 | 1008 | ||
995 | /***************************************\ | 1009 | /***************************************\ |
996 | HARDWARE ABSTRACTION LAYER STRUCTURE | 1010 | HARDWARE ABSTRACTION LAYER STRUCTURE |
@@ -1095,17 +1109,18 @@ struct ath5k_hw { | |||
1095 | 1109 | ||
1096 | struct ath5k_nfcal_hist ah_nfcal_hist; | 1110 | struct ath5k_nfcal_hist ah_nfcal_hist; |
1097 | 1111 | ||
1112 | /* average beacon RSSI in our BSS (used by ANI) */ | ||
1113 | struct ath5k_avg_val ah_beacon_rssi_avg; | ||
1114 | |||
1098 | /* noise floor from last periodic calibration */ | 1115 | /* noise floor from last periodic calibration */ |
1099 | s32 ah_noise_floor; | 1116 | s32 ah_noise_floor; |
1100 | 1117 | ||
1101 | /* Calibration timestamp */ | 1118 | /* Calibration timestamp */ |
1102 | unsigned long ah_cal_tstamp; | 1119 | unsigned long ah_cal_next_full; |
1103 | 1120 | unsigned long ah_cal_next_ani; | |
1104 | /* Calibration interval (secs) */ | ||
1105 | u8 ah_cal_intval; | ||
1106 | 1121 | ||
1107 | /* Software interrupt mask */ | 1122 | /* Calibration mask */ |
1108 | u8 ah_swi_mask; | 1123 | u8 ah_cal_mask; |
1109 | 1124 | ||
1110 | /* | 1125 | /* |
1111 | * Function pointers | 1126 | * Function pointers |
@@ -1163,8 +1178,7 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); | |||
1163 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); | 1178 | bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); |
1164 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); | 1179 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); |
1165 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); | 1180 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); |
1166 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | 1181 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); |
1167 | struct ieee80211_low_level_stats *stats); | ||
1168 | 1182 | ||
1169 | /* EEPROM access functions */ | 1183 | /* EEPROM access functions */ |
1170 | int ath5k_eeprom_init(struct ath5k_hw *ah); | 1184 | int ath5k_eeprom_init(struct ath5k_hw *ah); |
@@ -1256,7 +1270,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | |||
1256 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); | 1270 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); |
1257 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | 1271 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, |
1258 | struct ieee80211_channel *channel); | 1272 | struct ieee80211_channel *channel); |
1259 | void ath5k_hw_calibration_poll(struct ath5k_hw *ah); | ||
1260 | /* Spur mitigation */ | 1273 | /* Spur mitigation */ |
1261 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1274 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, |
1262 | struct ieee80211_channel *channel); | 1275 | struct ieee80211_channel *channel); |
@@ -1308,4 +1321,27 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | |||
1308 | return retval; | 1321 | return retval; |
1309 | } | 1322 | } |
1310 | 1323 | ||
1324 | #define AVG_SAMPLES 8 | ||
1325 | #define AVG_FACTOR 1000 | ||
1326 | |||
1327 | /** | ||
1328 | * ath5k_moving_average - Exponentially weighted moving average | ||
1329 | * @avg: average structure | ||
1330 | * @val: current value | ||
1331 | * | ||
1332 | * This implementation make use of a struct ath5k_avg_val to prevent rounding | ||
1333 | * errors. | ||
1334 | */ | ||
1335 | static inline struct ath5k_avg_val | ||
1336 | ath5k_moving_average(const struct ath5k_avg_val avg, const int val) | ||
1337 | { | ||
1338 | struct ath5k_avg_val new; | ||
1339 | new.avg_weight = avg.avg_weight ? | ||
1340 | (((avg.avg_weight * ((AVG_SAMPLES) - 1)) + | ||
1341 | (val * (AVG_FACTOR))) / (AVG_SAMPLES)) : | ||
1342 | (val * (AVG_FACTOR)); | ||
1343 | new.avg = new.avg_weight / (AVG_FACTOR); | ||
1344 | return new; | ||
1345 | } | ||
1346 | |||
1311 | #endif | 1347 | #endif |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index f571ad1a225e..e0c244b02f05 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -124,6 +124,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
124 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | 124 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; |
125 | ah->ah_software_retry = false; | 125 | ah->ah_software_retry = false; |
126 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; | 126 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; |
127 | ah->ah_noise_floor = -95; /* until first NF calibration is run */ | ||
128 | sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; | ||
127 | 129 | ||
128 | /* | 130 | /* |
129 | * Find the mac version | 131 | * Find the mac version |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 7ac3a720e52c..93005f1d326d 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -59,8 +59,8 @@ | |||
59 | #include "base.h" | 59 | #include "base.h" |
60 | #include "reg.h" | 60 | #include "reg.h" |
61 | #include "debug.h" | 61 | #include "debug.h" |
62 | #include "ani.h" | ||
62 | 63 | ||
63 | static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ | ||
64 | static int modparam_nohwcrypt; | 64 | static int modparam_nohwcrypt; |
65 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 65 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); |
66 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 66 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
@@ -365,6 +365,7 @@ static void ath5k_beacon_send(struct ath5k_softc *sc); | |||
365 | static void ath5k_beacon_config(struct ath5k_softc *sc); | 365 | static void ath5k_beacon_config(struct ath5k_softc *sc); |
366 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | 366 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); |
367 | static void ath5k_tasklet_beacon(unsigned long data); | 367 | static void ath5k_tasklet_beacon(unsigned long data); |
368 | static void ath5k_tasklet_ani(unsigned long data); | ||
368 | 369 | ||
369 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | 370 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) |
370 | { | 371 | { |
@@ -830,6 +831,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
830 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); | 831 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); |
831 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); | 832 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); |
832 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); | 833 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); |
834 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); | ||
833 | 835 | ||
834 | ret = ath5k_eeprom_read_mac(ah, mac); | 836 | ret = ath5k_eeprom_read_mac(ah, mac); |
835 | if (ret) { | 837 | if (ret) { |
@@ -1635,7 +1637,6 @@ ath5k_txq_cleanup(struct ath5k_softc *sc) | |||
1635 | sc->txqs[i].link); | 1637 | sc->txqs[i].link); |
1636 | } | 1638 | } |
1637 | } | 1639 | } |
1638 | ieee80211_wake_queues(sc->hw); /* XXX move to callers */ | ||
1639 | 1640 | ||
1640 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) | 1641 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) |
1641 | if (sc->txqs[i].setup) | 1642 | if (sc->txqs[i].setup) |
@@ -1805,6 +1806,25 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1805 | } | 1806 | } |
1806 | } | 1807 | } |
1807 | 1808 | ||
1809 | static void | ||
1810 | ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) | ||
1811 | { | ||
1812 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | ||
1813 | struct ath5k_hw *ah = sc->ah; | ||
1814 | struct ath_common *common = ath5k_hw_common(ah); | ||
1815 | |||
1816 | /* only beacons from our BSSID */ | ||
1817 | if (!ieee80211_is_beacon(mgmt->frame_control) || | ||
1818 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) | ||
1819 | return; | ||
1820 | |||
1821 | ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg, | ||
1822 | rssi); | ||
1823 | |||
1824 | /* in IBSS mode we should keep RSSI statistics per neighbour */ | ||
1825 | /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ | ||
1826 | } | ||
1827 | |||
1808 | /* | 1828 | /* |
1809 | * Compute padding position. skb must contains an IEEE 802.11 frame | 1829 | * Compute padding position. skb must contains an IEEE 802.11 frame |
1810 | */ | 1830 | */ |
@@ -1923,6 +1943,8 @@ ath5k_tasklet_rx(unsigned long data) | |||
1923 | sc->stats.rxerr_fifo++; | 1943 | sc->stats.rxerr_fifo++; |
1924 | if (rs.rs_status & AR5K_RXERR_PHY) { | 1944 | if (rs.rs_status & AR5K_RXERR_PHY) { |
1925 | sc->stats.rxerr_phy++; | 1945 | sc->stats.rxerr_phy++; |
1946 | if (rs.rs_phyerr > 0 && rs.rs_phyerr < 32) | ||
1947 | sc->stats.rxerr_phy_code[rs.rs_phyerr]++; | ||
1926 | goto next; | 1948 | goto next; |
1927 | } | 1949 | } |
1928 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { | 1950 | if (rs.rs_status & AR5K_RXERR_DECRYPT) { |
@@ -2024,6 +2046,8 @@ accept: | |||
2024 | 2046 | ||
2025 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 2047 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); |
2026 | 2048 | ||
2049 | ath5k_update_beacon_rssi(sc, skb, rs.rs_rssi); | ||
2050 | |||
2027 | /* check beacons in IBSS mode */ | 2051 | /* check beacons in IBSS mode */ |
2028 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | 2052 | if (sc->opmode == NL80211_IFTYPE_ADHOC) |
2029 | ath5k_check_ibss_tsf(sc, skb, rxs); | 2053 | ath5k_check_ibss_tsf(sc, skb, rxs); |
@@ -2060,6 +2084,17 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
2060 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | 2084 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { |
2061 | ds = bf->desc; | 2085 | ds = bf->desc; |
2062 | 2086 | ||
2087 | /* | ||
2088 | * It's possible that the hardware can say the buffer is | ||
2089 | * completed when it hasn't yet loaded the ds_link from | ||
2090 | * host memory and moved on. If there are more TX | ||
2091 | * descriptors in the queue, wait for TXDP to change | ||
2092 | * before processing this one. | ||
2093 | */ | ||
2094 | if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr && | ||
2095 | !list_is_last(&bf->list, &txq->q)) | ||
2096 | break; | ||
2097 | |||
2063 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); | 2098 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); |
2064 | if (unlikely(ret == -EINPROGRESS)) | 2099 | if (unlikely(ret == -EINPROGRESS)) |
2065 | break; | 2100 | break; |
@@ -2095,7 +2130,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
2095 | info->status.rates[ts.ts_final_idx].count++; | 2130 | info->status.rates[ts.ts_final_idx].count++; |
2096 | 2131 | ||
2097 | if (unlikely(ts.ts_status)) { | 2132 | if (unlikely(ts.ts_status)) { |
2098 | sc->ll_stats.dot11ACKFailureCount++; | 2133 | sc->stats.ack_fail++; |
2099 | if (ts.ts_status & AR5K_TXERR_FILT) { | 2134 | if (ts.ts_status & AR5K_TXERR_FILT) { |
2100 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 2135 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
2101 | sc->stats.txerr_filt++; | 2136 | sc->stats.txerr_filt++; |
@@ -2498,9 +2533,6 @@ ath5k_init(struct ath5k_softc *sc) | |||
2498 | */ | 2533 | */ |
2499 | ath5k_stop_locked(sc); | 2534 | ath5k_stop_locked(sc); |
2500 | 2535 | ||
2501 | /* Set PHY calibration interval */ | ||
2502 | ah->ah_cal_intval = ath5k_calinterval; | ||
2503 | |||
2504 | /* | 2536 | /* |
2505 | * The basic interface to setting the hardware in a good | 2537 | * The basic interface to setting the hardware in a good |
2506 | * state is ``reset''. On return the hardware is known to | 2538 | * state is ``reset''. On return the hardware is known to |
@@ -2512,7 +2544,8 @@ ath5k_init(struct ath5k_softc *sc) | |||
2512 | sc->curband = &sc->sbands[sc->curchan->band]; | 2544 | sc->curband = &sc->sbands[sc->curchan->band]; |
2513 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | 2545 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | |
2514 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | 2546 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | |
2515 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI; | 2547 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; |
2548 | |||
2516 | ret = ath5k_reset(sc, NULL); | 2549 | ret = ath5k_reset(sc, NULL); |
2517 | if (ret) | 2550 | if (ret) |
2518 | goto done; | 2551 | goto done; |
@@ -2526,8 +2559,7 @@ ath5k_init(struct ath5k_softc *sc) | |||
2526 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) | 2559 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) |
2527 | ath5k_hw_reset_key(ah, i); | 2560 | ath5k_hw_reset_key(ah, i); |
2528 | 2561 | ||
2529 | /* Set ack to be sent at low bit-rates */ | 2562 | ath5k_hw_set_ack_bitrate_high(ah, true); |
2530 | ath5k_hw_set_ack_bitrate_high(ah, false); | ||
2531 | ret = 0; | 2563 | ret = 0; |
2532 | done: | 2564 | done: |
2533 | mmiowb(); | 2565 | mmiowb(); |
@@ -2624,12 +2656,33 @@ ath5k_stop_hw(struct ath5k_softc *sc) | |||
2624 | tasklet_kill(&sc->restq); | 2656 | tasklet_kill(&sc->restq); |
2625 | tasklet_kill(&sc->calib); | 2657 | tasklet_kill(&sc->calib); |
2626 | tasklet_kill(&sc->beacontq); | 2658 | tasklet_kill(&sc->beacontq); |
2659 | tasklet_kill(&sc->ani_tasklet); | ||
2627 | 2660 | ||
2628 | ath5k_rfkill_hw_stop(sc->ah); | 2661 | ath5k_rfkill_hw_stop(sc->ah); |
2629 | 2662 | ||
2630 | return ret; | 2663 | return ret; |
2631 | } | 2664 | } |
2632 | 2665 | ||
2666 | static void | ||
2667 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) | ||
2668 | { | ||
2669 | if (time_is_before_eq_jiffies(ah->ah_cal_next_ani) && | ||
2670 | !(ah->ah_cal_mask & AR5K_CALIBRATION_FULL)) { | ||
2671 | /* run ANI only when full calibration is not active */ | ||
2672 | ah->ah_cal_next_ani = jiffies + | ||
2673 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_ANI); | ||
2674 | tasklet_schedule(&ah->ah_sc->ani_tasklet); | ||
2675 | |||
2676 | } else if (time_is_before_eq_jiffies(ah->ah_cal_next_full)) { | ||
2677 | ah->ah_cal_next_full = jiffies + | ||
2678 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_FULL); | ||
2679 | tasklet_schedule(&ah->ah_sc->calib); | ||
2680 | } | ||
2681 | /* we could use SWI to generate enough interrupts to meet our | ||
2682 | * calibration interval requirements, if necessary: | ||
2683 | * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ | ||
2684 | } | ||
2685 | |||
2633 | static irqreturn_t | 2686 | static irqreturn_t |
2634 | ath5k_intr(int irq, void *dev_id) | 2687 | ath5k_intr(int irq, void *dev_id) |
2635 | { | 2688 | { |
@@ -2653,7 +2706,20 @@ ath5k_intr(int irq, void *dev_id) | |||
2653 | */ | 2706 | */ |
2654 | tasklet_schedule(&sc->restq); | 2707 | tasklet_schedule(&sc->restq); |
2655 | } else if (unlikely(status & AR5K_INT_RXORN)) { | 2708 | } else if (unlikely(status & AR5K_INT_RXORN)) { |
2656 | tasklet_schedule(&sc->restq); | 2709 | /* |
2710 | * Receive buffers are full. Either the bus is busy or | ||
2711 | * the CPU is not fast enough to process all received | ||
2712 | * frames. | ||
2713 | * Older chipsets need a reset to come out of this | ||
2714 | * condition, but we treat it as RX for newer chips. | ||
2715 | * We don't know exactly which versions need a reset - | ||
2716 | * this guess is copied from the HAL. | ||
2717 | */ | ||
2718 | sc->stats.rxorn_intr++; | ||
2719 | if (ah->ah_mac_srev < AR5K_SREV_AR5212) | ||
2720 | tasklet_schedule(&sc->restq); | ||
2721 | else | ||
2722 | tasklet_schedule(&sc->rxtq); | ||
2657 | } else { | 2723 | } else { |
2658 | if (status & AR5K_INT_SWBA) { | 2724 | if (status & AR5K_INT_SWBA) { |
2659 | tasklet_hi_schedule(&sc->beacontq); | 2725 | tasklet_hi_schedule(&sc->beacontq); |
@@ -2678,15 +2744,10 @@ ath5k_intr(int irq, void *dev_id) | |||
2678 | if (status & AR5K_INT_BMISS) { | 2744 | if (status & AR5K_INT_BMISS) { |
2679 | /* TODO */ | 2745 | /* TODO */ |
2680 | } | 2746 | } |
2681 | if (status & AR5K_INT_SWI) { | ||
2682 | tasklet_schedule(&sc->calib); | ||
2683 | } | ||
2684 | if (status & AR5K_INT_MIB) { | 2747 | if (status & AR5K_INT_MIB) { |
2685 | /* | 2748 | sc->stats.mib_intr++; |
2686 | * These stats are also used for ANI i think | 2749 | ath5k_hw_update_mib_counters(ah); |
2687 | * so how about updating them more often ? | 2750 | ath5k_ani_mib_intr(ah); |
2688 | */ | ||
2689 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | ||
2690 | } | 2751 | } |
2691 | if (status & AR5K_INT_GPIO) | 2752 | if (status & AR5K_INT_GPIO) |
2692 | tasklet_schedule(&sc->rf_kill.toggleq); | 2753 | tasklet_schedule(&sc->rf_kill.toggleq); |
@@ -2697,7 +2758,7 @@ ath5k_intr(int irq, void *dev_id) | |||
2697 | if (unlikely(!counter)) | 2758 | if (unlikely(!counter)) |
2698 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); | 2759 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); |
2699 | 2760 | ||
2700 | ath5k_hw_calibration_poll(ah); | 2761 | ath5k_intr_calibration_poll(ah); |
2701 | 2762 | ||
2702 | return IRQ_HANDLED; | 2763 | return IRQ_HANDLED; |
2703 | } | 2764 | } |
@@ -2721,8 +2782,7 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2721 | struct ath5k_hw *ah = sc->ah; | 2782 | struct ath5k_hw *ah = sc->ah; |
2722 | 2783 | ||
2723 | /* Only full calibration for now */ | 2784 | /* Only full calibration for now */ |
2724 | if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION) | 2785 | ah->ah_cal_mask |= AR5K_CALIBRATION_FULL; |
2725 | return; | ||
2726 | 2786 | ||
2727 | /* Stop queues so that calibration | 2787 | /* Stop queues so that calibration |
2728 | * doesn't interfere with tx */ | 2788 | * doesn't interfere with tx */ |
@@ -2738,18 +2798,29 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2738 | * to load new gain values. | 2798 | * to load new gain values. |
2739 | */ | 2799 | */ |
2740 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); | 2800 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); |
2741 | ath5k_reset_wake(sc); | 2801 | ath5k_reset(sc, sc->curchan); |
2742 | } | 2802 | } |
2743 | if (ath5k_hw_phy_calibrate(ah, sc->curchan)) | 2803 | if (ath5k_hw_phy_calibrate(ah, sc->curchan)) |
2744 | ATH5K_ERR(sc, "calibration of channel %u failed\n", | 2804 | ATH5K_ERR(sc, "calibration of channel %u failed\n", |
2745 | ieee80211_frequency_to_channel( | 2805 | ieee80211_frequency_to_channel( |
2746 | sc->curchan->center_freq)); | 2806 | sc->curchan->center_freq)); |
2747 | 2807 | ||
2748 | ah->ah_swi_mask = 0; | ||
2749 | |||
2750 | /* Wake queues */ | 2808 | /* Wake queues */ |
2751 | ieee80211_wake_queues(sc->hw); | 2809 | ieee80211_wake_queues(sc->hw); |
2752 | 2810 | ||
2811 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; | ||
2812 | } | ||
2813 | |||
2814 | |||
2815 | static void | ||
2816 | ath5k_tasklet_ani(unsigned long data) | ||
2817 | { | ||
2818 | struct ath5k_softc *sc = (void *)data; | ||
2819 | struct ath5k_hw *ah = sc->ah; | ||
2820 | |||
2821 | ah->ah_cal_mask |= AR5K_CALIBRATION_ANI; | ||
2822 | ath5k_ani_calibration(ah); | ||
2823 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_ANI; | ||
2753 | } | 2824 | } |
2754 | 2825 | ||
2755 | 2826 | ||
@@ -2852,6 +2923,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
2852 | goto err; | 2923 | goto err; |
2853 | } | 2924 | } |
2854 | 2925 | ||
2926 | ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); | ||
2927 | |||
2855 | /* | 2928 | /* |
2856 | * Change channels and update the h/w rate map if we're switching; | 2929 | * Change channels and update the h/w rate map if we're switching; |
2857 | * e.g. 11a to 11b/g. | 2930 | * e.g. 11a to 11b/g. |
@@ -3207,12 +3280,14 @@ ath5k_get_stats(struct ieee80211_hw *hw, | |||
3207 | struct ieee80211_low_level_stats *stats) | 3280 | struct ieee80211_low_level_stats *stats) |
3208 | { | 3281 | { |
3209 | struct ath5k_softc *sc = hw->priv; | 3282 | struct ath5k_softc *sc = hw->priv; |
3210 | struct ath5k_hw *ah = sc->ah; | ||
3211 | 3283 | ||
3212 | /* Force update */ | 3284 | /* Force update */ |
3213 | ath5k_hw_update_mib_counters(ah, &sc->ll_stats); | 3285 | ath5k_hw_update_mib_counters(sc->ah); |
3214 | 3286 | ||
3215 | memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); | 3287 | stats->dot11ACKFailureCount = sc->stats.ack_fail; |
3288 | stats->dot11RTSFailureCount = sc->stats.rts_fail; | ||
3289 | stats->dot11RTSSuccessCount = sc->stats.rts_ok; | ||
3290 | stats->dot11FCSErrorCount = sc->stats.fcs_error; | ||
3216 | 3291 | ||
3217 | return 0; | 3292 | return 0; |
3218 | } | 3293 | } |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 33f1d8b87ee1..56221bc7c8cd 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -50,6 +50,7 @@ | |||
50 | 50 | ||
51 | #include "ath5k.h" | 51 | #include "ath5k.h" |
52 | #include "debug.h" | 52 | #include "debug.h" |
53 | #include "ani.h" | ||
53 | 54 | ||
54 | #include "../regd.h" | 55 | #include "../regd.h" |
55 | #include "../ath.h" | 56 | #include "../ath.h" |
@@ -105,14 +106,18 @@ struct ath5k_rfkill { | |||
105 | struct tasklet_struct toggleq; | 106 | struct tasklet_struct toggleq; |
106 | }; | 107 | }; |
107 | 108 | ||
108 | /* statistics (only used for debugging now) */ | 109 | /* statistics */ |
109 | struct ath5k_statistics { | 110 | struct ath5k_statistics { |
111 | /* antenna use */ | ||
110 | unsigned int antenna_rx[5]; /* frames count per antenna RX */ | 112 | unsigned int antenna_rx[5]; /* frames count per antenna RX */ |
111 | unsigned int antenna_tx[5]; /* frames count per antenna TX */ | 113 | unsigned int antenna_tx[5]; /* frames count per antenna TX */ |
114 | |||
115 | /* frame errors */ | ||
112 | unsigned int rx_all_count; /* all RX frames, including errors */ | 116 | unsigned int rx_all_count; /* all RX frames, including errors */ |
113 | unsigned int tx_all_count; /* all TX frames, including errors */ | 117 | unsigned int tx_all_count; /* all TX frames, including errors */ |
114 | unsigned int rxerr_crc; | 118 | unsigned int rxerr_crc; |
115 | unsigned int rxerr_phy; | 119 | unsigned int rxerr_phy; |
120 | unsigned int rxerr_phy_code[32]; | ||
116 | unsigned int rxerr_fifo; | 121 | unsigned int rxerr_fifo; |
117 | unsigned int rxerr_decrypt; | 122 | unsigned int rxerr_decrypt; |
118 | unsigned int rxerr_mic; | 123 | unsigned int rxerr_mic; |
@@ -121,6 +126,16 @@ struct ath5k_statistics { | |||
121 | unsigned int txerr_retry; | 126 | unsigned int txerr_retry; |
122 | unsigned int txerr_fifo; | 127 | unsigned int txerr_fifo; |
123 | unsigned int txerr_filt; | 128 | unsigned int txerr_filt; |
129 | |||
130 | /* MIB counters */ | ||
131 | unsigned int ack_fail; | ||
132 | unsigned int rts_fail; | ||
133 | unsigned int rts_ok; | ||
134 | unsigned int fcs_error; | ||
135 | unsigned int beacons; | ||
136 | |||
137 | unsigned int mib_intr; | ||
138 | unsigned int rxorn_intr; | ||
124 | }; | 139 | }; |
125 | 140 | ||
126 | #if CHAN_DEBUG | 141 | #if CHAN_DEBUG |
@@ -135,7 +150,6 @@ struct ath5k_softc { | |||
135 | struct pci_dev *pdev; /* for dma mapping */ | 150 | struct pci_dev *pdev; /* for dma mapping */ |
136 | void __iomem *iobase; /* address of the device */ | 151 | void __iomem *iobase; /* address of the device */ |
137 | struct mutex lock; /* dev-level lock */ | 152 | struct mutex lock; /* dev-level lock */ |
138 | struct ieee80211_low_level_stats ll_stats; | ||
139 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ | 153 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ |
140 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 154 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
141 | struct ieee80211_channel channels[ATH_CHAN_MAX]; | 155 | struct ieee80211_channel channels[ATH_CHAN_MAX]; |
@@ -211,6 +225,9 @@ struct ath5k_softc { | |||
211 | bool enable_beacon; /* true if beacons are on */ | 225 | bool enable_beacon; /* true if beacons are on */ |
212 | 226 | ||
213 | struct ath5k_statistics stats; | 227 | struct ath5k_statistics stats; |
228 | |||
229 | struct ath5k_ani_state ani_state; | ||
230 | struct tasklet_struct ani_tasklet; /* ANI calibration */ | ||
214 | }; | 231 | }; |
215 | 232 | ||
216 | #define ath5k_hw_hasbssidmask(_ah) \ | 233 | #define ath5k_hw_hasbssidmask(_ah) \ |
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index e618e71b1ce6..74f007126f41 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c | |||
@@ -109,6 +109,12 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
109 | else | 109 | else |
110 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; | 110 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; |
111 | 111 | ||
112 | /* newer hardware has PHY error counters */ | ||
113 | if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) | ||
114 | ah->ah_capabilities.cap_has_phyerr_counters = true; | ||
115 | else | ||
116 | ah->ah_capabilities.cap_has_phyerr_counters = false; | ||
117 | |||
112 | return 0; | 118 | return 0; |
113 | } | 119 | } |
114 | 120 | ||
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index bccd4a78027e..6fb5c5ffa5b1 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -69,6 +69,7 @@ module_param_named(debug, ath5k_debug, uint, 0); | |||
69 | 69 | ||
70 | #include <linux/seq_file.h> | 70 | #include <linux/seq_file.h> |
71 | #include "reg.h" | 71 | #include "reg.h" |
72 | #include "ani.h" | ||
72 | 73 | ||
73 | static struct dentry *ath5k_global_debugfs; | 74 | static struct dentry *ath5k_global_debugfs; |
74 | 75 | ||
@@ -307,6 +308,7 @@ static const struct { | |||
307 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, | 308 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, |
308 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, | 309 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, |
309 | { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, | 310 | { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, |
311 | { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, | ||
310 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, | 312 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, |
311 | }; | 313 | }; |
312 | 314 | ||
@@ -474,6 +476,7 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, | |||
474 | struct ath5k_statistics *st = &sc->stats; | 476 | struct ath5k_statistics *st = &sc->stats; |
475 | char buf[700]; | 477 | char buf[700]; |
476 | unsigned int len = 0; | 478 | unsigned int len = 0; |
479 | int i; | ||
477 | 480 | ||
478 | len += snprintf(buf+len, sizeof(buf)-len, | 481 | len += snprintf(buf+len, sizeof(buf)-len, |
479 | "RX\n---------------------\n"); | 482 | "RX\n---------------------\n"); |
@@ -485,6 +488,13 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, | |||
485 | st->rxerr_phy, | 488 | st->rxerr_phy, |
486 | st->rx_all_count > 0 ? | 489 | st->rx_all_count > 0 ? |
487 | st->rxerr_phy*100/st->rx_all_count : 0); | 490 | st->rxerr_phy*100/st->rx_all_count : 0); |
491 | for (i = 0; i < 32; i++) { | ||
492 | if (st->rxerr_phy_code[i]) | ||
493 | len += snprintf(buf+len, sizeof(buf)-len, | ||
494 | " phy_err[%d]\t%d\n", | ||
495 | i, st->rxerr_phy_code[i]); | ||
496 | } | ||
497 | |||
488 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", | 498 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", |
489 | st->rxerr_fifo, | 499 | st->rxerr_fifo, |
490 | st->rx_all_count > 0 ? | 500 | st->rx_all_count > 0 ? |
@@ -565,6 +575,160 @@ static const struct file_operations fops_frameerrors = { | |||
565 | }; | 575 | }; |
566 | 576 | ||
567 | 577 | ||
578 | /* debugfs: ani */ | ||
579 | |||
580 | static ssize_t read_file_ani(struct file *file, char __user *user_buf, | ||
581 | size_t count, loff_t *ppos) | ||
582 | { | ||
583 | struct ath5k_softc *sc = file->private_data; | ||
584 | struct ath5k_statistics *st = &sc->stats; | ||
585 | struct ath5k_ani_state *as = &sc->ani_state; | ||
586 | |||
587 | char buf[700]; | ||
588 | unsigned int len = 0; | ||
589 | |||
590 | len += snprintf(buf+len, sizeof(buf)-len, | ||
591 | "HW has PHY error counters:\t%s\n", | ||
592 | sc->ah->ah_capabilities.cap_has_phyerr_counters ? | ||
593 | "yes" : "no"); | ||
594 | len += snprintf(buf+len, sizeof(buf)-len, | ||
595 | "HW max spur immunity level:\t%d\n", | ||
596 | as->max_spur_level); | ||
597 | len += snprintf(buf+len, sizeof(buf)-len, | ||
598 | "\nANI state\n--------------------------------------------\n"); | ||
599 | len += snprintf(buf+len, sizeof(buf)-len, "operating mode:\t\t\t"); | ||
600 | switch (as->ani_mode) { | ||
601 | case ATH5K_ANI_MODE_OFF: | ||
602 | len += snprintf(buf+len, sizeof(buf)-len, "OFF\n"); | ||
603 | break; | ||
604 | case ATH5K_ANI_MODE_MANUAL_LOW: | ||
605 | len += snprintf(buf+len, sizeof(buf)-len, | ||
606 | "MANUAL LOW\n"); | ||
607 | break; | ||
608 | case ATH5K_ANI_MODE_MANUAL_HIGH: | ||
609 | len += snprintf(buf+len, sizeof(buf)-len, | ||
610 | "MANUAL HIGH\n"); | ||
611 | break; | ||
612 | case ATH5K_ANI_MODE_AUTO: | ||
613 | len += snprintf(buf+len, sizeof(buf)-len, "AUTO\n"); | ||
614 | break; | ||
615 | default: | ||
616 | len += snprintf(buf+len, sizeof(buf)-len, | ||
617 | "??? (not good)\n"); | ||
618 | break; | ||
619 | } | ||
620 | len += snprintf(buf+len, sizeof(buf)-len, | ||
621 | "noise immunity level:\t\t%d\n", | ||
622 | as->noise_imm_level); | ||
623 | len += snprintf(buf+len, sizeof(buf)-len, | ||
624 | "spur immunity level:\t\t%d\n", | ||
625 | as->spur_level); | ||
626 | len += snprintf(buf+len, sizeof(buf)-len, "firstep level:\t\t\t%d\n", | ||
627 | as->firstep_level); | ||
628 | len += snprintf(buf+len, sizeof(buf)-len, | ||
629 | "OFDM weak signal detection:\t%s\n", | ||
630 | as->ofdm_weak_sig ? "on" : "off"); | ||
631 | len += snprintf(buf+len, sizeof(buf)-len, | ||
632 | "CCK weak signal detection:\t%s\n", | ||
633 | as->cck_weak_sig ? "on" : "off"); | ||
634 | |||
635 | len += snprintf(buf+len, sizeof(buf)-len, | ||
636 | "\nMIB INTERRUPTS:\t\t%u\n", | ||
637 | st->mib_intr); | ||
638 | len += snprintf(buf+len, sizeof(buf)-len, | ||
639 | "beacon RSSI average:\t%d\n", | ||
640 | sc->ah->ah_beacon_rssi_avg.avg); | ||
641 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n", | ||
642 | as->pfc_tx, | ||
643 | as->pfc_cycles > 0 ? | ||
644 | as->pfc_tx*100/as->pfc_cycles : 0); | ||
645 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n", | ||
646 | as->pfc_rx, | ||
647 | as->pfc_cycles > 0 ? | ||
648 | as->pfc_rx*100/as->pfc_cycles : 0); | ||
649 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n", | ||
650 | as->pfc_busy, | ||
651 | as->pfc_cycles > 0 ? | ||
652 | as->pfc_busy*100/as->pfc_cycles : 0); | ||
653 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n", | ||
654 | as->pfc_cycles); | ||
655 | len += snprintf(buf+len, sizeof(buf)-len, | ||
656 | "listen time\t\t%d\tlast: %d\n", | ||
657 | as->listen_time, as->last_listen); | ||
658 | len += snprintf(buf+len, sizeof(buf)-len, | ||
659 | "OFDM errors\t\t%u\tlast: %u\tsum: %u\n", | ||
660 | as->ofdm_errors, as->last_ofdm_errors, | ||
661 | as->sum_ofdm_errors); | ||
662 | len += snprintf(buf+len, sizeof(buf)-len, | ||
663 | "CCK errors\t\t%u\tlast: %u\tsum: %u\n", | ||
664 | as->cck_errors, as->last_cck_errors, | ||
665 | as->sum_cck_errors); | ||
666 | len += snprintf(buf+len, sizeof(buf)-len, | ||
667 | "AR5K_PHYERR_CNT1\t%x\t(=%d)\n", | ||
668 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1), | ||
669 | ATH5K_ANI_OFDM_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - | ||
670 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT1))); | ||
671 | len += snprintf(buf+len, sizeof(buf)-len, | ||
672 | "AR5K_PHYERR_CNT2\t%x\t(=%d)\n", | ||
673 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2), | ||
674 | ATH5K_ANI_CCK_TRIG_HIGH - (ATH5K_PHYERR_CNT_MAX - | ||
675 | ath5k_hw_reg_read(sc->ah, AR5K_PHYERR_CNT2))); | ||
676 | |||
677 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
678 | } | ||
679 | |||
680 | static ssize_t write_file_ani(struct file *file, | ||
681 | const char __user *userbuf, | ||
682 | size_t count, loff_t *ppos) | ||
683 | { | ||
684 | struct ath5k_softc *sc = file->private_data; | ||
685 | char buf[20]; | ||
686 | |||
687 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
688 | return -EFAULT; | ||
689 | |||
690 | if (strncmp(buf, "sens-low", 8) == 0) { | ||
691 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_HIGH); | ||
692 | } else if (strncmp(buf, "sens-high", 9) == 0) { | ||
693 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_MANUAL_LOW); | ||
694 | } else if (strncmp(buf, "ani-off", 7) == 0) { | ||
695 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_OFF); | ||
696 | } else if (strncmp(buf, "ani-on", 6) == 0) { | ||
697 | ath5k_ani_init(sc->ah, ATH5K_ANI_MODE_AUTO); | ||
698 | } else if (strncmp(buf, "noise-low", 9) == 0) { | ||
699 | ath5k_ani_set_noise_immunity_level(sc->ah, 0); | ||
700 | } else if (strncmp(buf, "noise-high", 10) == 0) { | ||
701 | ath5k_ani_set_noise_immunity_level(sc->ah, | ||
702 | ATH5K_ANI_MAX_NOISE_IMM_LVL); | ||
703 | } else if (strncmp(buf, "spur-low", 8) == 0) { | ||
704 | ath5k_ani_set_spur_immunity_level(sc->ah, 0); | ||
705 | } else if (strncmp(buf, "spur-high", 9) == 0) { | ||
706 | ath5k_ani_set_spur_immunity_level(sc->ah, | ||
707 | sc->ani_state.max_spur_level); | ||
708 | } else if (strncmp(buf, "fir-low", 7) == 0) { | ||
709 | ath5k_ani_set_firstep_level(sc->ah, 0); | ||
710 | } else if (strncmp(buf, "fir-high", 8) == 0) { | ||
711 | ath5k_ani_set_firstep_level(sc->ah, ATH5K_ANI_MAX_FIRSTEP_LVL); | ||
712 | } else if (strncmp(buf, "ofdm-off", 8) == 0) { | ||
713 | ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, false); | ||
714 | } else if (strncmp(buf, "ofdm-on", 7) == 0) { | ||
715 | ath5k_ani_set_ofdm_weak_signal_detection(sc->ah, true); | ||
716 | } else if (strncmp(buf, "cck-off", 7) == 0) { | ||
717 | ath5k_ani_set_cck_weak_signal_detection(sc->ah, false); | ||
718 | } else if (strncmp(buf, "cck-on", 6) == 0) { | ||
719 | ath5k_ani_set_cck_weak_signal_detection(sc->ah, true); | ||
720 | } | ||
721 | return count; | ||
722 | } | ||
723 | |||
724 | static const struct file_operations fops_ani = { | ||
725 | .read = read_file_ani, | ||
726 | .write = write_file_ani, | ||
727 | .open = ath5k_debugfs_open, | ||
728 | .owner = THIS_MODULE, | ||
729 | }; | ||
730 | |||
731 | |||
568 | /* init */ | 732 | /* init */ |
569 | 733 | ||
570 | void | 734 | void |
@@ -603,6 +767,11 @@ ath5k_debug_init_device(struct ath5k_softc *sc) | |||
603 | S_IWUSR | S_IRUSR, | 767 | S_IWUSR | S_IRUSR, |
604 | sc->debug.debugfs_phydir, sc, | 768 | sc->debug.debugfs_phydir, sc, |
605 | &fops_frameerrors); | 769 | &fops_frameerrors); |
770 | |||
771 | sc->debug.debugfs_ani = debugfs_create_file("ani", | ||
772 | S_IWUSR | S_IRUSR, | ||
773 | sc->debug.debugfs_phydir, sc, | ||
774 | &fops_ani); | ||
606 | } | 775 | } |
607 | 776 | ||
608 | void | 777 | void |
@@ -620,6 +789,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) | |||
620 | debugfs_remove(sc->debug.debugfs_reset); | 789 | debugfs_remove(sc->debug.debugfs_reset); |
621 | debugfs_remove(sc->debug.debugfs_antenna); | 790 | debugfs_remove(sc->debug.debugfs_antenna); |
622 | debugfs_remove(sc->debug.debugfs_frameerrors); | 791 | debugfs_remove(sc->debug.debugfs_frameerrors); |
792 | debugfs_remove(sc->debug.debugfs_ani); | ||
623 | debugfs_remove(sc->debug.debugfs_phydir); | 793 | debugfs_remove(sc->debug.debugfs_phydir); |
624 | } | 794 | } |
625 | 795 | ||
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index da24ff52e274..ddd5b3a99e8d 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h | |||
@@ -76,6 +76,7 @@ struct ath5k_dbg_info { | |||
76 | struct dentry *debugfs_reset; | 76 | struct dentry *debugfs_reset; |
77 | struct dentry *debugfs_antenna; | 77 | struct dentry *debugfs_antenna; |
78 | struct dentry *debugfs_frameerrors; | 78 | struct dentry *debugfs_frameerrors; |
79 | struct dentry *debugfs_ani; | ||
79 | }; | 80 | }; |
80 | 81 | ||
81 | /** | 82 | /** |
@@ -115,6 +116,7 @@ enum ath5k_debug_level { | |||
115 | ATH5K_DEBUG_DUMP_TX = 0x00000200, | 116 | ATH5K_DEBUG_DUMP_TX = 0x00000200, |
116 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, | 117 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, |
117 | ATH5K_DEBUG_TRACE = 0x00001000, | 118 | ATH5K_DEBUG_TRACE = 0x00001000, |
119 | ATH5K_DEBUG_ANI = 0x00002000, | ||
118 | ATH5K_DEBUG_ANY = 0xffffffff | 120 | ATH5K_DEBUG_ANY = 0xffffffff |
119 | }; | 121 | }; |
120 | 122 | ||
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 9d920fb14d5d..7d7b646ab65a 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -645,6 +645,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
645 | rs->rs_status |= AR5K_RXERR_PHY; | 645 | rs->rs_status |= AR5K_RXERR_PHY; |
646 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, | 646 | rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, |
647 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); | 647 | AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); |
648 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); | ||
648 | } | 649 | } |
649 | 650 | ||
650 | if (rx_status->rx_status_1 & | 651 | if (rx_status->rx_status_1 & |
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index 56158c804e3e..64538fbe4167 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h | |||
@@ -112,15 +112,32 @@ struct ath5k_hw_rx_error { | |||
112 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 | 112 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 |
113 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 | 113 | #define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 |
114 | 114 | ||
115 | /* PHY Error codes */ | 115 | /** |
116 | #define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 | 116 | * enum ath5k_phy_error_code - PHY Error codes |
117 | #define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 | 117 | */ |
118 | #define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 | 118 | enum ath5k_phy_error_code { |
119 | #define AR5K_DESC_RX_PHY_ERROR_RATE 0x60 | 119 | AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun */ |
120 | #define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80 | 120 | AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ |
121 | #define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0 | 121 | AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ |
122 | #define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 | 122 | AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ |
123 | #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 | 123 | AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ |
124 | AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect */ | ||
125 | AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ | ||
126 | AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ | ||
127 | /* these are specific to the 5212 */ | ||
128 | AR5K_RX_PHY_ERROR_OFDM_TIMING = 17, | ||
129 | AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18, | ||
130 | AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19, | ||
131 | AR5K_RX_PHY_ERROR_OFDM_LENGTH_ILLEGAL = 20, | ||
132 | AR5K_RX_PHY_ERROR_OFDM_POWER_DROP = 21, | ||
133 | AR5K_RX_PHY_ERROR_OFDM_SERVICE = 22, | ||
134 | AR5K_RX_PHY_ERROR_OFDM_RESTART = 23, | ||
135 | AR5K_RX_PHY_ERROR_CCK_TIMING = 25, | ||
136 | AR5K_RX_PHY_ERROR_CCK_HEADER_CRC = 26, | ||
137 | AR5K_RX_PHY_ERROR_CCK_RATE_ILLEGAL = 27, | ||
138 | AR5K_RX_PHY_ERROR_CCK_SERVICE = 30, | ||
139 | AR5K_RX_PHY_ERROR_CCK_RESTART = 31, | ||
140 | }; | ||
124 | 141 | ||
125 | /* | 142 | /* |
126 | * 5210/5211 hardware 2-word TX control descriptor | 143 | * 5210/5211 hardware 2-word TX control descriptor |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 1b9fcb842167..174412fc81f8 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -113,39 +113,26 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | |||
113 | } | 113 | } |
114 | 114 | ||
115 | /** | 115 | /** |
116 | * ath5k_hw_update - Update mib counters (mac layer statistics) | 116 | * ath5k_hw_update - Update MIB counters (mac layer statistics) |
117 | * | 117 | * |
118 | * @ah: The &struct ath5k_hw | 118 | * @ah: The &struct ath5k_hw |
119 | * @stats: The &struct ieee80211_low_level_stats we use to track | ||
120 | * statistics on the driver | ||
121 | * | 119 | * |
122 | * Reads MIB counters from PCU and updates sw statistics. Must be | 120 | * Reads MIB counters from PCU and updates sw statistics. Is called after a |
123 | * called after a MIB interrupt. | 121 | * MIB interrupt, because one of these counters might have reached their maximum |
122 | * and triggered the MIB interrupt, to let us read and clear the counter. | ||
123 | * | ||
124 | * Is called in interrupt context! | ||
124 | */ | 125 | */ |
125 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, | 126 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) |
126 | struct ieee80211_low_level_stats *stats) | ||
127 | { | 127 | { |
128 | ATH5K_TRACE(ah->ah_sc); | 128 | struct ath5k_statistics *stats = &ah->ah_sc->stats; |
129 | 129 | ||
130 | /* Read-And-Clear */ | 130 | /* Read-And-Clear */ |
131 | stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); | 131 | stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); |
132 | stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); | 132 | stats->rts_fail += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); |
133 | stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); | 133 | stats->rts_ok += ath5k_hw_reg_read(ah, AR5K_RTS_OK); |
134 | stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); | 134 | stats->fcs_error += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); |
135 | 135 | stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | |
136 | /* XXX: Should we use this to track beacon count ? | ||
137 | * -we read it anyway to clear the register */ | ||
138 | ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | ||
139 | |||
140 | /* Reset profile count registers on 5212*/ | ||
141 | if (ah->ah_version == AR5K_AR5212) { | ||
142 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | ||
143 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | ||
144 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
145 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
146 | } | ||
147 | |||
148 | /* TODO: Handle ANI stats */ | ||
149 | } | 136 | } |
150 | 137 | ||
151 | /** | 138 | /** |
@@ -167,9 +154,9 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | |||
167 | else { | 154 | else { |
168 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; | 155 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; |
169 | if (high) | 156 | if (high) |
170 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | ||
171 | else | ||
172 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); | 157 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); |
158 | else | ||
159 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | ||
173 | } | 160 | } |
174 | } | 161 | } |
175 | 162 | ||
@@ -392,7 +379,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | |||
392 | * (ACK etc). | 379 | * (ACK etc). |
393 | * | 380 | * |
394 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | 381 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma |
395 | * TODO: Init ANI here | ||
396 | */ | 382 | */ |
397 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | 383 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) |
398 | { | 384 | { |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 3ee74c839768..3ce9afba1d88 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -980,7 +980,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | |||
980 | return -EINVAL; | 980 | return -EINVAL; |
981 | 981 | ||
982 | data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); | 982 | data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); |
983 | } else if ((c - (c % 5)) != 2 || c > 5435) { | 983 | } else if ((c % 5) != 2 || c > 5435) { |
984 | if (!(c % 20) && c >= 5120) { | 984 | if (!(c % 20) && c >= 5120) { |
985 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); | 985 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); |
986 | data2 = ath5k_hw_bitswap(3, 2); | 986 | data2 = ath5k_hw_bitswap(3, 2); |
@@ -993,7 +993,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, | |||
993 | } else | 993 | } else |
994 | return -EINVAL; | 994 | return -EINVAL; |
995 | } else { | 995 | } else { |
996 | data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); | 996 | data0 = ath5k_hw_bitswap((10 * (c - 2 - 4800)) / 25 + 1, 8); |
997 | data2 = ath5k_hw_bitswap(0, 2); | 997 | data2 = ath5k_hw_bitswap(0, 2); |
998 | } | 998 | } |
999 | 999 | ||
@@ -1021,7 +1021,7 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | |||
1021 | data0 = ath5k_hw_bitswap((c - 2272), 8); | 1021 | data0 = ath5k_hw_bitswap((c - 2272), 8); |
1022 | data2 = 0; | 1022 | data2 = 0; |
1023 | /* ? 5GHz ? */ | 1023 | /* ? 5GHz ? */ |
1024 | } else if ((c - (c % 5)) != 2 || c > 5435) { | 1024 | } else if ((c % 5) != 2 || c > 5435) { |
1025 | if (!(c % 20) && c < 5120) | 1025 | if (!(c % 20) && c < 5120) |
1026 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); | 1026 | data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); |
1027 | else if (!(c % 10)) | 1027 | else if (!(c % 10)) |
@@ -1032,7 +1032,7 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | |||
1032 | return -EINVAL; | 1032 | return -EINVAL; |
1033 | data2 = ath5k_hw_bitswap(1, 2); | 1033 | data2 = ath5k_hw_bitswap(1, 2); |
1034 | } else { | 1034 | } else { |
1035 | data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); | 1035 | data0 = ath5k_hw_bitswap((10 * (c - 2 - 4800)) / 25 + 1, 8); |
1036 | data2 = ath5k_hw_bitswap(0, 2); | 1036 | data2 = ath5k_hw_bitswap(0, 2); |
1037 | } | 1037 | } |
1038 | 1038 | ||
@@ -1103,28 +1103,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1103 | PHY calibration | 1103 | PHY calibration |
1104 | \*****************/ | 1104 | \*****************/ |
1105 | 1105 | ||
1106 | void | ||
1107 | ath5k_hw_calibration_poll(struct ath5k_hw *ah) | ||
1108 | { | ||
1109 | /* Calibration interval in jiffies */ | ||
1110 | unsigned long cal_intval; | ||
1111 | |||
1112 | cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000); | ||
1113 | |||
1114 | /* Initialize timestamp if needed */ | ||
1115 | if (!ah->ah_cal_tstamp) | ||
1116 | ah->ah_cal_tstamp = jiffies; | ||
1117 | |||
1118 | /* For now we always do full calibration | ||
1119 | * Mark software interrupt mask and fire software | ||
1120 | * interrupt (bit gets auto-cleared) */ | ||
1121 | if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) { | ||
1122 | ah->ah_cal_tstamp = jiffies; | ||
1123 | ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; | ||
1124 | AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); | ||
1125 | } | ||
1126 | } | ||
1127 | |||
1128 | static int sign_extend(int val, const int nbits) | 1106 | static int sign_extend(int val, const int nbits) |
1129 | { | 1107 | { |
1130 | int order = BIT(nbits-1); | 1108 | int order = BIT(nbits-1); |
@@ -1411,7 +1389,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | |||
1411 | i_coff = (-iq_corr) / i_coffd; | 1389 | i_coff = (-iq_corr) / i_coffd; |
1412 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ | 1390 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ |
1413 | 1391 | ||
1414 | q_coff = (i_pwr / q_coffd) - 128; | 1392 | if (ah->ah_version == AR5K_AR5211) |
1393 | q_coff = (i_pwr / q_coffd) - 64; | ||
1394 | else | ||
1395 | q_coff = (i_pwr / q_coffd) - 128; | ||
1415 | q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */ | 1396 | q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */ |
1416 | 1397 | ||
1417 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, | 1398 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, |
@@ -2580,7 +2561,7 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, | |||
2580 | max_idx = (pdadc_n < table_size) ? pdadc_n : table_size; | 2561 | max_idx = (pdadc_n < table_size) ? pdadc_n : table_size; |
2581 | 2562 | ||
2582 | /* Fill pdadc_out table */ | 2563 | /* Fill pdadc_out table */ |
2583 | while (pdadc_0 < max_idx) | 2564 | while (pdadc_0 < max_idx && pdadc_i < 128) |
2584 | pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++]; | 2565 | pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++]; |
2585 | 2566 | ||
2586 | /* Need to extrapolate above this pdgain? */ | 2567 | /* Need to extrapolate above this pdgain? */ |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 47f04932ab8b..55b4ac6d236f 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -212,10 +212,10 @@ | |||
212 | * MIB control register | 212 | * MIB control register |
213 | */ | 213 | */ |
214 | #define AR5K_MIBC 0x0040 /* Register Address */ | 214 | #define AR5K_MIBC 0x0040 /* Register Address */ |
215 | #define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */ | 215 | #define AR5K_MIBC_COW 0x00000001 /* Counter Overflow Warning */ |
216 | #define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ | 216 | #define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ |
217 | #define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */ | 217 | #define AR5K_MIBC_CMC 0x00000004 /* Clear MIB Counters */ |
218 | #define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */ | 218 | #define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe, increment all */ |
219 | 219 | ||
220 | /* | 220 | /* |
221 | * Timeout prescale register | 221 | * Timeout prescale register |
@@ -1139,8 +1139,8 @@ | |||
1139 | #define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ | 1139 | #define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ |
1140 | #define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */ | 1140 | #define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */ |
1141 | #define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */ | 1141 | #define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */ |
1142 | #define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */ | 1142 | #define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Rate to use for ACK/CTS. 0: highest mandatory rate <= RX rate; 1: 1Mbps in B mode */ |
1143 | #define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */ | 1143 | #define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* 802.11b base rate. 0: 1, 2, 5.5 and 11Mbps; 1: 1 and 2Mbps. [5211+] */ |
1144 | #define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */ | 1144 | #define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */ |
1145 | #define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */ | 1145 | #define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */ |
1146 | #define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */ | 1146 | #define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */ |
@@ -1516,7 +1516,14 @@ | |||
1516 | AR5K_NAV_5210 : AR5K_NAV_5211) | 1516 | AR5K_NAV_5210 : AR5K_NAV_5211) |
1517 | 1517 | ||
1518 | /* | 1518 | /* |
1519 | * RTS success register | 1519 | * MIB counters: |
1520 | * | ||
1521 | * max value is 0xc000, if this is reached we get a MIB interrupt. | ||
1522 | * they can be controlled via AR5K_MIBC and are cleared on read. | ||
1523 | */ | ||
1524 | |||
1525 | /* | ||
1526 | * RTS success (MIB counter) | ||
1520 | */ | 1527 | */ |
1521 | #define AR5K_RTS_OK_5210 0x8090 | 1528 | #define AR5K_RTS_OK_5210 0x8090 |
1522 | #define AR5K_RTS_OK_5211 0x8088 | 1529 | #define AR5K_RTS_OK_5211 0x8088 |
@@ -1524,7 +1531,7 @@ | |||
1524 | AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) | 1531 | AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) |
1525 | 1532 | ||
1526 | /* | 1533 | /* |
1527 | * RTS failure register | 1534 | * RTS failure (MIB counter) |
1528 | */ | 1535 | */ |
1529 | #define AR5K_RTS_FAIL_5210 0x8094 | 1536 | #define AR5K_RTS_FAIL_5210 0x8094 |
1530 | #define AR5K_RTS_FAIL_5211 0x808c | 1537 | #define AR5K_RTS_FAIL_5211 0x808c |
@@ -1532,7 +1539,7 @@ | |||
1532 | AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) | 1539 | AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) |
1533 | 1540 | ||
1534 | /* | 1541 | /* |
1535 | * ACK failure register | 1542 | * ACK failure (MIB counter) |
1536 | */ | 1543 | */ |
1537 | #define AR5K_ACK_FAIL_5210 0x8098 | 1544 | #define AR5K_ACK_FAIL_5210 0x8098 |
1538 | #define AR5K_ACK_FAIL_5211 0x8090 | 1545 | #define AR5K_ACK_FAIL_5211 0x8090 |
@@ -1540,7 +1547,7 @@ | |||
1540 | AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) | 1547 | AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) |
1541 | 1548 | ||
1542 | /* | 1549 | /* |
1543 | * FCS failure register | 1550 | * FCS failure (MIB counter) |
1544 | */ | 1551 | */ |
1545 | #define AR5K_FCS_FAIL_5210 0x809c | 1552 | #define AR5K_FCS_FAIL_5210 0x809c |
1546 | #define AR5K_FCS_FAIL_5211 0x8094 | 1553 | #define AR5K_FCS_FAIL_5211 0x8094 |
@@ -1667,11 +1674,17 @@ | |||
1667 | 1674 | ||
1668 | /* | 1675 | /* |
1669 | * Profile count registers | 1676 | * Profile count registers |
1677 | * | ||
1678 | * These registers can be cleared and freezed with ATH5K_MIBC, but they do not | ||
1679 | * generate a MIB interrupt. | ||
1680 | * Instead of overflowing, they shift by one bit to the right. All registers | ||
1681 | * shift together, i.e. when one reaches the max, all shift at the same time by | ||
1682 | * one bit to the right. This way we should always get consistent values. | ||
1670 | */ | 1683 | */ |
1671 | #define AR5K_PROFCNT_TX 0x80ec /* Tx count */ | 1684 | #define AR5K_PROFCNT_TX 0x80ec /* Tx count */ |
1672 | #define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ | 1685 | #define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ |
1673 | #define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */ | 1686 | #define AR5K_PROFCNT_RXCLR 0x80f4 /* Busy count */ |
1674 | #define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */ | 1687 | #define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle counter */ |
1675 | 1688 | ||
1676 | /* | 1689 | /* |
1677 | * Quiet period control registers | 1690 | * Quiet period control registers |
@@ -1758,7 +1771,7 @@ | |||
1758 | #define AR5K_CCK_FIL_CNT 0x8128 | 1771 | #define AR5K_CCK_FIL_CNT 0x8128 |
1759 | 1772 | ||
1760 | /* | 1773 | /* |
1761 | * PHY Error Counters (?) | 1774 | * PHY Error Counters (same masks as AR5K_PHY_ERR_FIL) |
1762 | */ | 1775 | */ |
1763 | #define AR5K_PHYERR_CNT1 0x812c | 1776 | #define AR5K_PHYERR_CNT1 0x812c |
1764 | #define AR5K_PHYERR_CNT1_MASK 0x8130 | 1777 | #define AR5K_PHYERR_CNT1_MASK 0x8130 |
@@ -1766,6 +1779,9 @@ | |||
1766 | #define AR5K_PHYERR_CNT2 0x8134 | 1779 | #define AR5K_PHYERR_CNT2 0x8134 |
1767 | #define AR5K_PHYERR_CNT2_MASK 0x8138 | 1780 | #define AR5K_PHYERR_CNT2_MASK 0x8138 |
1768 | 1781 | ||
1782 | /* if the PHY Error Counters reach this maximum, we get MIB interrupts */ | ||
1783 | #define ATH5K_PHYERR_CNT_MAX 0x00c00000 | ||
1784 | |||
1769 | /* | 1785 | /* |
1770 | * TSF Threshold register (?) | 1786 | * TSF Threshold register (?) |
1771 | */ | 1787 | */ |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index ca4994f13151..85fdd26039c8 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -47,6 +47,7 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
47 | } | 47 | } |
48 | 48 | ||
49 | static struct ath_bus_ops ath_ahb_bus_ops = { | 49 | static struct ath_bus_ops ath_ahb_bus_ops = { |
50 | .ath_bus_type = ATH_AHB, | ||
50 | .read_cachesize = ath_ahb_read_cachesize, | 51 | .read_cachesize = ath_ahb_read_cachesize, |
51 | .eeprom_read = ath_ahb_eeprom_read, | 52 | .eeprom_read = ath_ahb_eeprom_read, |
52 | }; | 53 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 83c7ea4c007f..bdcd257ca7a4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -178,9 +178,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
178 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ | 178 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ |
179 | ((((_seqno) - (_start)) & 4095) < (_bawsz)) | 179 | ((((_seqno) - (_start)) & 4095) < (_bawsz)) |
180 | 180 | ||
181 | #define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum) | ||
182 | #define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low) | ||
183 | #define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) | ||
184 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) | 181 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) |
185 | 182 | ||
186 | #define ATH_TX_COMPLETE_POLL_INT 1000 | 183 | #define ATH_TX_COMPLETE_POLL_INT 1000 |
@@ -483,7 +480,6 @@ struct ath_softc { | |||
483 | bool ps_enabled; | 480 | bool ps_enabled; |
484 | bool ps_idle; | 481 | bool ps_idle; |
485 | unsigned long ps_usecount; | 482 | unsigned long ps_usecount; |
486 | enum ath9k_int imask; | ||
487 | 483 | ||
488 | struct ath_config config; | 484 | struct ath_config config; |
489 | struct ath_rx rx; | 485 | struct ath_rx rx; |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index b4a31a43a62c..22375a754718 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -524,6 +524,7 @@ static void ath9k_beacon_init(struct ath_softc *sc, | |||
524 | static void ath_beacon_config_ap(struct ath_softc *sc, | 524 | static void ath_beacon_config_ap(struct ath_softc *sc, |
525 | struct ath_beacon_config *conf) | 525 | struct ath_beacon_config *conf) |
526 | { | 526 | { |
527 | struct ath_hw *ah = sc->sc_ah; | ||
527 | u32 nexttbtt, intval; | 528 | u32 nexttbtt, intval; |
528 | 529 | ||
529 | /* NB: the beacon interval is kept internally in TU's */ | 530 | /* NB: the beacon interval is kept internally in TU's */ |
@@ -539,15 +540,15 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
539 | * prepare beacon frames. | 540 | * prepare beacon frames. |
540 | */ | 541 | */ |
541 | intval |= ATH9K_BEACON_ENA; | 542 | intval |= ATH9K_BEACON_ENA; |
542 | sc->imask |= ATH9K_INT_SWBA; | 543 | ah->imask |= ATH9K_INT_SWBA; |
543 | ath_beaconq_config(sc); | 544 | ath_beaconq_config(sc); |
544 | 545 | ||
545 | /* Set the computed AP beacon timers */ | 546 | /* Set the computed AP beacon timers */ |
546 | 547 | ||
547 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 548 | ath9k_hw_set_interrupts(ah, 0); |
548 | ath9k_beacon_init(sc, nexttbtt, intval); | 549 | ath9k_beacon_init(sc, nexttbtt, intval); |
549 | sc->beacon.bmisscnt = 0; | 550 | sc->beacon.bmisscnt = 0; |
550 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 551 | ath9k_hw_set_interrupts(ah, ah->imask); |
551 | 552 | ||
552 | /* Clear the reset TSF flag, so that subsequent beacon updation | 553 | /* Clear the reset TSF flag, so that subsequent beacon updation |
553 | will not reset the HW TSF. */ | 554 | will not reset the HW TSF. */ |
@@ -566,7 +567,8 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
566 | static void ath_beacon_config_sta(struct ath_softc *sc, | 567 | static void ath_beacon_config_sta(struct ath_softc *sc, |
567 | struct ath_beacon_config *conf) | 568 | struct ath_beacon_config *conf) |
568 | { | 569 | { |
569 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 570 | struct ath_hw *ah = sc->sc_ah; |
571 | struct ath_common *common = ath9k_hw_common(ah); | ||
570 | struct ath9k_beacon_state bs; | 572 | struct ath9k_beacon_state bs; |
571 | int dtimperiod, dtimcount, sleepduration; | 573 | int dtimperiod, dtimcount, sleepduration; |
572 | int cfpperiod, cfpcount; | 574 | int cfpperiod, cfpcount; |
@@ -605,7 +607,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
605 | * Pull nexttbtt forward to reflect the current | 607 | * Pull nexttbtt forward to reflect the current |
606 | * TSF and calculate dtim+cfp state for the result. | 608 | * TSF and calculate dtim+cfp state for the result. |
607 | */ | 609 | */ |
608 | tsf = ath9k_hw_gettsf64(sc->sc_ah); | 610 | tsf = ath9k_hw_gettsf64(ah); |
609 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; | 611 | tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; |
610 | 612 | ||
611 | num_beacons = tsftu / intval + 1; | 613 | num_beacons = tsftu / intval + 1; |
@@ -678,17 +680,18 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
678 | 680 | ||
679 | /* Set the computed STA beacon timers */ | 681 | /* Set the computed STA beacon timers */ |
680 | 682 | ||
681 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 683 | ath9k_hw_set_interrupts(ah, 0); |
682 | ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs); | 684 | ath9k_hw_set_sta_beacon_timers(ah, &bs); |
683 | sc->imask |= ATH9K_INT_BMISS; | 685 | ah->imask |= ATH9K_INT_BMISS; |
684 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 686 | ath9k_hw_set_interrupts(ah, ah->imask); |
685 | } | 687 | } |
686 | 688 | ||
687 | static void ath_beacon_config_adhoc(struct ath_softc *sc, | 689 | static void ath_beacon_config_adhoc(struct ath_softc *sc, |
688 | struct ath_beacon_config *conf, | 690 | struct ath_beacon_config *conf, |
689 | struct ieee80211_vif *vif) | 691 | struct ieee80211_vif *vif) |
690 | { | 692 | { |
691 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 693 | struct ath_hw *ah = sc->sc_ah; |
694 | struct ath_common *common = ath9k_hw_common(ah); | ||
692 | u64 tsf; | 695 | u64 tsf; |
693 | u32 tsftu, intval, nexttbtt; | 696 | u32 tsftu, intval, nexttbtt; |
694 | 697 | ||
@@ -703,7 +706,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
703 | else if (intval) | 706 | else if (intval) |
704 | nexttbtt = roundup(nexttbtt, intval); | 707 | nexttbtt = roundup(nexttbtt, intval); |
705 | 708 | ||
706 | tsf = ath9k_hw_gettsf64(sc->sc_ah); | 709 | tsf = ath9k_hw_gettsf64(ah); |
707 | tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; | 710 | tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; |
708 | do { | 711 | do { |
709 | nexttbtt += intval; | 712 | nexttbtt += intval; |
@@ -719,20 +722,20 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
719 | * self-linked tx descriptor and let the hardware deal with things. | 722 | * self-linked tx descriptor and let the hardware deal with things. |
720 | */ | 723 | */ |
721 | intval |= ATH9K_BEACON_ENA; | 724 | intval |= ATH9K_BEACON_ENA; |
722 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) | 725 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) |
723 | sc->imask |= ATH9K_INT_SWBA; | 726 | ah->imask |= ATH9K_INT_SWBA; |
724 | 727 | ||
725 | ath_beaconq_config(sc); | 728 | ath_beaconq_config(sc); |
726 | 729 | ||
727 | /* Set the computed ADHOC beacon timers */ | 730 | /* Set the computed ADHOC beacon timers */ |
728 | 731 | ||
729 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 732 | ath9k_hw_set_interrupts(ah, 0); |
730 | ath9k_beacon_init(sc, nexttbtt, intval); | 733 | ath9k_beacon_init(sc, nexttbtt, intval); |
731 | sc->beacon.bmisscnt = 0; | 734 | sc->beacon.bmisscnt = 0; |
732 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 735 | ath9k_hw_set_interrupts(ah, ah->imask); |
733 | 736 | ||
734 | /* FIXME: Handle properly when vif is NULL */ | 737 | /* FIXME: Handle properly when vif is NULL */ |
735 | if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) | 738 | if (vif && ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) |
736 | ath_beacon_start_adhoc(sc, vif); | 739 | ath_beacon_start_adhoc(sc, vif); |
737 | } | 740 | } |
738 | 741 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index d5026e4f484b..064f5b51dfcd 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | /* We can tune this as we go by monitoring really low values */ | 19 | /* We can tune this as we go by monitoring really low values */ |
20 | #define ATH9K_NF_TOO_LOW -60 | 20 | #define ATH9K_NF_TOO_LOW -60 |
21 | #define AR9285_CLCAL_REDO_THRESH 1 | ||
21 | 22 | ||
22 | /* AR5416 may return very high value (like -31 dBm), in those cases the nf | 23 | /* AR5416 may return very high value (like -31 dBm), in those cases the nf |
23 | * is incorrect and we should use the static NF value. Later we can try to | 24 | * is incorrect and we should use the static NF value. Later we can try to |
@@ -1091,7 +1092,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1091 | EXPORT_SYMBOL(ath9k_hw_calibrate); | 1092 | EXPORT_SYMBOL(ath9k_hw_calibrate); |
1092 | 1093 | ||
1093 | /* Carrier leakage Calibration fix */ | 1094 | /* Carrier leakage Calibration fix */ |
1094 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | 1095 | static bool ar9285_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) |
1095 | { | 1096 | { |
1096 | struct ath_common *common = ath9k_hw_common(ah); | 1097 | struct ath_common *common = ath9k_hw_common(ah); |
1097 | 1098 | ||
@@ -1132,6 +1133,62 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1132 | return true; | 1133 | return true; |
1133 | } | 1134 | } |
1134 | 1135 | ||
1136 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | ||
1137 | { | ||
1138 | int i; | ||
1139 | u_int32_t txgain_max; | ||
1140 | u_int32_t clc_gain, gain_mask = 0, clc_num = 0; | ||
1141 | u_int32_t reg_clc_I0, reg_clc_Q0; | ||
1142 | u_int32_t i0_num = 0; | ||
1143 | u_int32_t q0_num = 0; | ||
1144 | u_int32_t total_num = 0; | ||
1145 | u_int32_t reg_rf2g5_org; | ||
1146 | bool retv = true; | ||
1147 | |||
1148 | if (!(ar9285_cl_cal(ah, chan))) | ||
1149 | return false; | ||
1150 | |||
1151 | txgain_max = MS(REG_READ(ah, AR_PHY_TX_PWRCTRL7), | ||
1152 | AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX); | ||
1153 | |||
1154 | for (i = 0; i < (txgain_max+1); i++) { | ||
1155 | clc_gain = (REG_READ(ah, (AR_PHY_TX_GAIN_TBL1+(i<<2))) & | ||
1156 | AR_PHY_TX_GAIN_CLC) >> AR_PHY_TX_GAIN_CLC_S; | ||
1157 | if (!(gain_mask & (1 << clc_gain))) { | ||
1158 | gain_mask |= (1 << clc_gain); | ||
1159 | clc_num++; | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1163 | for (i = 0; i < clc_num; i++) { | ||
1164 | reg_clc_I0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) | ||
1165 | & AR_PHY_CLC_I0) >> AR_PHY_CLC_I0_S; | ||
1166 | reg_clc_Q0 = (REG_READ(ah, (AR_PHY_CLC_TBL1 + (i << 2))) | ||
1167 | & AR_PHY_CLC_Q0) >> AR_PHY_CLC_Q0_S; | ||
1168 | if (reg_clc_I0 == 0) | ||
1169 | i0_num++; | ||
1170 | |||
1171 | if (reg_clc_Q0 == 0) | ||
1172 | q0_num++; | ||
1173 | } | ||
1174 | total_num = i0_num + q0_num; | ||
1175 | if (total_num > AR9285_CLCAL_REDO_THRESH) { | ||
1176 | reg_rf2g5_org = REG_READ(ah, AR9285_RF2G5); | ||
1177 | if (AR_SREV_9285E_20(ah)) { | ||
1178 | REG_WRITE(ah, AR9285_RF2G5, | ||
1179 | (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | | ||
1180 | AR9285_RF2G5_IC50TX_XE_SET); | ||
1181 | } else { | ||
1182 | REG_WRITE(ah, AR9285_RF2G5, | ||
1183 | (reg_rf2g5_org & AR9285_RF2G5_IC50TX) | | ||
1184 | AR9285_RF2G5_IC50TX_SET); | ||
1185 | } | ||
1186 | retv = ar9285_cl_cal(ah, chan); | ||
1187 | REG_WRITE(ah, AR9285_RF2G5, reg_rf2g5_org); | ||
1188 | } | ||
1189 | return retv; | ||
1190 | } | ||
1191 | |||
1135 | bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | 1192 | bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) |
1136 | { | 1193 | { |
1137 | struct ath_common *common = ath9k_hw_common(ah); | 1194 | struct ath_common *common = ath9k_hw_common(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 7902d287f671..09effdedc8c0 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -255,7 +255,8 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, | |||
255 | 255 | ||
256 | keyix = rx_stats->rs_keyix; | 256 | keyix = rx_stats->rs_keyix; |
257 | 257 | ||
258 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { | 258 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && |
259 | ieee80211_has_protected(fc)) { | ||
259 | rxs->flag |= RX_FLAG_DECRYPTED; | 260 | rxs->flag |= RX_FLAG_DECRYPTED; |
260 | } else if (ieee80211_has_protected(fc) | 261 | } else if (ieee80211_has_protected(fc) |
261 | && !decrypt_error && skb->len >= hdrlen + 4) { | 262 | && !decrypt_error && skb->len >= hdrlen + 4) { |
@@ -303,88 +304,6 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) | |||
303 | } | 304 | } |
304 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); | 305 | EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); |
305 | 306 | ||
306 | /* | ||
307 | * Calculate the RX filter to be set in the HW. | ||
308 | */ | ||
309 | u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah, | ||
310 | unsigned int rxfilter) | ||
311 | { | ||
312 | #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) | ||
313 | |||
314 | u32 rfilt; | ||
315 | |||
316 | rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE) | ||
317 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | ||
318 | | ATH9K_RX_FILTER_MCAST; | ||
319 | |||
320 | /* If not a STA, enable processing of Probe Requests */ | ||
321 | if (ah->opmode != NL80211_IFTYPE_STATION) | ||
322 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | ||
323 | |||
324 | /* | ||
325 | * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station | ||
326 | * mode interface or when in monitor mode. AP mode does not need this | ||
327 | * since it receives all in-BSS frames anyway. | ||
328 | */ | ||
329 | if (((ah->opmode != NL80211_IFTYPE_AP) && | ||
330 | (rxfilter & FIF_PROMISC_IN_BSS)) || | ||
331 | (ah->opmode == NL80211_IFTYPE_MONITOR)) | ||
332 | rfilt |= ATH9K_RX_FILTER_PROM; | ||
333 | |||
334 | if (rxfilter & FIF_CONTROL) | ||
335 | rfilt |= ATH9K_RX_FILTER_CONTROL; | ||
336 | |||
337 | if ((ah->opmode == NL80211_IFTYPE_STATION) && | ||
338 | !(rxfilter & FIF_BCN_PRBRESP_PROMISC)) | ||
339 | rfilt |= ATH9K_RX_FILTER_MYBEACON; | ||
340 | else | ||
341 | rfilt |= ATH9K_RX_FILTER_BEACON; | ||
342 | |||
343 | if ((AR_SREV_9280_10_OR_LATER(ah) || | ||
344 | AR_SREV_9285_10_OR_LATER(ah)) && | ||
345 | (ah->opmode == NL80211_IFTYPE_AP) && | ||
346 | (rxfilter & FIF_PSPOLL)) | ||
347 | rfilt |= ATH9K_RX_FILTER_PSPOLL; | ||
348 | |||
349 | if (conf_is_ht(&hw->conf)) | ||
350 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | ||
351 | |||
352 | return rfilt; | ||
353 | |||
354 | #undef RX_FILTER_PRESERVE | ||
355 | } | ||
356 | EXPORT_SYMBOL(ath9k_cmn_calcrxfilter); | ||
357 | |||
358 | /* | ||
359 | * Recv initialization for opmode change. | ||
360 | */ | ||
361 | void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah, | ||
362 | unsigned int rxfilter) | ||
363 | { | ||
364 | struct ath_common *common = ath9k_hw_common(ah); | ||
365 | |||
366 | u32 rfilt, mfilt[2]; | ||
367 | |||
368 | /* configure rx filter */ | ||
369 | rfilt = ath9k_cmn_calcrxfilter(hw, ah, rxfilter); | ||
370 | ath9k_hw_setrxfilter(ah, rfilt); | ||
371 | |||
372 | /* configure bssid mask */ | ||
373 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | ||
374 | ath_hw_setbssidmask(common); | ||
375 | |||
376 | /* configure operational mode */ | ||
377 | ath9k_hw_setopmode(ah); | ||
378 | |||
379 | /* Handle any link-level address change. */ | ||
380 | ath9k_hw_setmac(ah, common->macaddr); | ||
381 | |||
382 | /* calculate and install multicast filter */ | ||
383 | mfilt[0] = mfilt[1] = ~0; | ||
384 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | ||
385 | } | ||
386 | EXPORT_SYMBOL(ath9k_cmn_opmode_init); | ||
387 | |||
388 | static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, | 307 | static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, |
389 | enum nl80211_channel_type channel_type) | 308 | enum nl80211_channel_type channel_type) |
390 | { | 309 | { |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index bbcc57f6eba3..72a835d9e97f 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -128,10 +128,6 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, | |||
128 | 128 | ||
129 | int ath9k_cmn_padpos(__le16 frame_control); | 129 | int ath9k_cmn_padpos(__le16 frame_control); |
130 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 130 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
131 | u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah, | ||
132 | unsigned int rxfilter); | ||
133 | void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah, | ||
134 | unsigned int rxfilter); | ||
135 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | 131 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, |
136 | struct ath9k_channel *ichan); | 132 | struct ath9k_channel *ichan); |
137 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | 133 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 081e0085ed4c..9a8e419398f9 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -157,10 +157,10 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
157 | "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", | 157 | "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", |
158 | (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); | 158 | (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); |
159 | 159 | ||
160 | len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x \n", | 160 | len += snprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n", |
161 | REG_READ_D(ah, AR_OBS_BUS_1)); | 161 | REG_READ_D(ah, AR_OBS_BUS_1)); |
162 | len += snprintf(buf + len, DMA_BUF_LEN - len, | 162 | len += snprintf(buf + len, DMA_BUF_LEN - len, |
163 | "AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR)); | 163 | "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR)); |
164 | 164 | ||
165 | ath9k_ps_restore(sc); | 165 | ath9k_ps_restore(sc); |
166 | 166 | ||
@@ -557,10 +557,8 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
557 | } | 557 | } |
558 | 558 | ||
559 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | 559 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, |
560 | struct ath_buf *bf) | 560 | struct ath_buf *bf, struct ath_tx_status *ts) |
561 | { | 561 | { |
562 | struct ath_desc *ds = bf->bf_desc; | ||
563 | |||
564 | if (bf_isampdu(bf)) { | 562 | if (bf_isampdu(bf)) { |
565 | if (bf_isxretried(bf)) | 563 | if (bf_isxretried(bf)) |
566 | TX_STAT_INC(txq->axq_qnum, a_xretries); | 564 | TX_STAT_INC(txq->axq_qnum, a_xretries); |
@@ -570,17 +568,17 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | |||
570 | TX_STAT_INC(txq->axq_qnum, completed); | 568 | TX_STAT_INC(txq->axq_qnum, completed); |
571 | } | 569 | } |
572 | 570 | ||
573 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO) | 571 | if (ts->ts_status & ATH9K_TXERR_FIFO) |
574 | TX_STAT_INC(txq->axq_qnum, fifo_underrun); | 572 | TX_STAT_INC(txq->axq_qnum, fifo_underrun); |
575 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP) | 573 | if (ts->ts_status & ATH9K_TXERR_XTXOP) |
576 | TX_STAT_INC(txq->axq_qnum, xtxop); | 574 | TX_STAT_INC(txq->axq_qnum, xtxop); |
577 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED) | 575 | if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) |
578 | TX_STAT_INC(txq->axq_qnum, timer_exp); | 576 | TX_STAT_INC(txq->axq_qnum, timer_exp); |
579 | if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR) | 577 | if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) |
580 | TX_STAT_INC(txq->axq_qnum, desc_cfg_err); | 578 | TX_STAT_INC(txq->axq_qnum, desc_cfg_err); |
581 | if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN) | 579 | if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) |
582 | TX_STAT_INC(txq->axq_qnum, data_underrun); | 580 | TX_STAT_INC(txq->axq_qnum, data_underrun); |
583 | if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN) | 581 | if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) |
584 | TX_STAT_INC(txq->axq_qnum, delim_underrun); | 582 | TX_STAT_INC(txq->axq_qnum, delim_underrun); |
585 | } | 583 | } |
586 | 584 | ||
@@ -663,30 +661,29 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
663 | #undef PHY_ERR | 661 | #undef PHY_ERR |
664 | } | 662 | } |
665 | 663 | ||
666 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf) | 664 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) |
667 | { | 665 | { |
668 | #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ | 666 | #define RX_STAT_INC(c) sc->debug.stats.rxstats.c++ |
669 | #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ | 667 | #define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++ |
670 | 668 | ||
671 | struct ath_desc *ds = bf->bf_desc; | ||
672 | u32 phyerr; | 669 | u32 phyerr; |
673 | 670 | ||
674 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) | 671 | if (rs->rs_status & ATH9K_RXERR_CRC) |
675 | RX_STAT_INC(crc_err); | 672 | RX_STAT_INC(crc_err); |
676 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) | 673 | if (rs->rs_status & ATH9K_RXERR_DECRYPT) |
677 | RX_STAT_INC(decrypt_crc_err); | 674 | RX_STAT_INC(decrypt_crc_err); |
678 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) | 675 | if (rs->rs_status & ATH9K_RXERR_MIC) |
679 | RX_STAT_INC(mic_err); | 676 | RX_STAT_INC(mic_err); |
680 | if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_PRE) | 677 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE) |
681 | RX_STAT_INC(pre_delim_crc_err); | 678 | RX_STAT_INC(pre_delim_crc_err); |
682 | if (ds->ds_rxstat.rs_status & ATH9K_RX_DELIM_CRC_POST) | 679 | if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST) |
683 | RX_STAT_INC(post_delim_crc_err); | 680 | RX_STAT_INC(post_delim_crc_err); |
684 | if (ds->ds_rxstat.rs_status & ATH9K_RX_DECRYPT_BUSY) | 681 | if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY) |
685 | RX_STAT_INC(decrypt_busy_err); | 682 | RX_STAT_INC(decrypt_busy_err); |
686 | 683 | ||
687 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) { | 684 | if (rs->rs_status & ATH9K_RXERR_PHY) { |
688 | RX_STAT_INC(phy_err); | 685 | RX_STAT_INC(phy_err); |
689 | phyerr = ds->ds_rxstat.rs_phyerr & 0x24; | 686 | phyerr = rs->rs_phyerr & 0x24; |
690 | RX_PHY_ERR_INC(phyerr); | 687 | RX_PHY_ERR_INC(phyerr); |
691 | } | 688 | } |
692 | 689 | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 86780e68b31e..b2af9de755e6 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -167,8 +167,8 @@ void ath9k_debug_remove_root(void); | |||
167 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | 167 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); |
168 | void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); | 168 | void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); |
169 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | 169 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, |
170 | struct ath_buf *bf); | 170 | struct ath_buf *bf, struct ath_tx_status *ts); |
171 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_buf *bf); | 171 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); |
172 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, | 172 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, |
173 | int xretries, int retries, u8 per); | 173 | int xretries, int retries, u8 per); |
174 | 174 | ||
@@ -204,12 +204,13 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc, | |||
204 | 204 | ||
205 | static inline void ath_debug_stat_tx(struct ath_softc *sc, | 205 | static inline void ath_debug_stat_tx(struct ath_softc *sc, |
206 | struct ath_txq *txq, | 206 | struct ath_txq *txq, |
207 | struct ath_buf *bf) | 207 | struct ath_buf *bf, |
208 | struct ath_tx_status *ts) | ||
208 | { | 209 | { |
209 | } | 210 | } |
210 | 211 | ||
211 | static inline void ath_debug_stat_rx(struct ath_softc *sc, | 212 | static inline void ath_debug_stat_rx(struct ath_softc *sc, |
212 | struct ath_buf *bf) | 213 | struct ath_rx_status *rs) |
213 | { | 214 | { |
214 | } | 215 | } |
215 | 216 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 68db16690abf..0354fe50f8e0 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -43,7 +43,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | |||
43 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { | 43 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { |
44 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { | 44 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { |
45 | ath_print(common, ATH_DBG_EEPROM, | 45 | ath_print(common, ATH_DBG_EEPROM, |
46 | "Unable to read eeprom region \n"); | 46 | "Unable to read eeprom region\n"); |
47 | return false; | 47 | return false; |
48 | } | 48 | } |
49 | eep_data++; | 49 | eep_data++; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 839d05a1df29..d8ca94c3fa0c 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -44,7 +44,7 @@ static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | |||
44 | if (!ath9k_hw_nvram_read(common, | 44 | if (!ath9k_hw_nvram_read(common, |
45 | addr + eep_start_loc, eep_data)) { | 45 | addr + eep_start_loc, eep_data)) { |
46 | ath_print(common, ATH_DBG_EEPROM, | 46 | ath_print(common, ATH_DBG_EEPROM, |
47 | "Unable to read eeprom region \n"); | 47 | "Unable to read eeprom region\n"); |
48 | return false; | 48 | return false; |
49 | } | 49 | } |
50 | eep_data++; | 50 | eep_data++; |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index deab8beb0680..0ee75e79fe35 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -283,22 +283,17 @@ static void ath9k_gen_timer_start(struct ath_hw *ah, | |||
283 | u32 timer_next, | 283 | u32 timer_next, |
284 | u32 timer_period) | 284 | u32 timer_period) |
285 | { | 285 | { |
286 | struct ath_common *common = ath9k_hw_common(ah); | ||
287 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
288 | |||
289 | ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); | 286 | ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); |
290 | 287 | ||
291 | if ((sc->imask & ATH9K_INT_GENTIMER) == 0) { | 288 | if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { |
292 | ath9k_hw_set_interrupts(ah, 0); | 289 | ath9k_hw_set_interrupts(ah, 0); |
293 | sc->imask |= ATH9K_INT_GENTIMER; | 290 | ah->imask |= ATH9K_INT_GENTIMER; |
294 | ath9k_hw_set_interrupts(ah, sc->imask); | 291 | ath9k_hw_set_interrupts(ah, ah->imask); |
295 | } | 292 | } |
296 | } | 293 | } |
297 | 294 | ||
298 | static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | 295 | static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) |
299 | { | 296 | { |
300 | struct ath_common *common = ath9k_hw_common(ah); | ||
301 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
302 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 297 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
303 | 298 | ||
304 | ath9k_hw_gen_timer_stop(ah, timer); | 299 | ath9k_hw_gen_timer_stop(ah, timer); |
@@ -306,8 +301,8 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | |||
306 | /* if no timer is enabled, turn off interrupt mask */ | 301 | /* if no timer is enabled, turn off interrupt mask */ |
307 | if (timer_table->timer_mask.val == 0) { | 302 | if (timer_table->timer_mask.val == 0) { |
308 | ath9k_hw_set_interrupts(ah, 0); | 303 | ath9k_hw_set_interrupts(ah, 0); |
309 | sc->imask &= ~ATH9K_INT_GENTIMER; | 304 | ah->imask &= ~ATH9K_INT_GENTIMER; |
310 | ath9k_hw_set_interrupts(ah, sc->imask); | 305 | ath9k_hw_set_interrupts(ah, ah->imask); |
311 | } | 306 | } |
312 | } | 307 | } |
313 | 308 | ||
@@ -364,7 +359,7 @@ static void ath_btcoex_no_stomp_timer(void *arg) | |||
364 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; | 359 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; |
365 | 360 | ||
366 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | 361 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, |
367 | "no stomp timer running \n"); | 362 | "no stomp timer running\n"); |
368 | 363 | ||
369 | spin_lock_bh(&btcoex->btcoex_lock); | 364 | spin_lock_bh(&btcoex->btcoex_lock); |
370 | 365 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index fc4f6e8c9ef3..fe994e229898 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -21,6 +21,7 @@ | |||
21 | 21 | ||
22 | static struct usb_device_id ath9k_hif_usb_ids[] = { | 22 | static struct usb_device_id ath9k_hif_usb_ids[] = { |
23 | ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"), | 23 | ATH9K_FW_USB_DEV(0x9271, "ar9271.fw"), |
24 | ATH9K_FW_USB_DEV(0x1006, "ar9271.fw"), | ||
24 | { }, | 25 | { }, |
25 | }; | 26 | }; |
26 | 27 | ||
@@ -31,27 +32,15 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev); | |||
31 | static void hif_usb_regout_cb(struct urb *urb) | 32 | static void hif_usb_regout_cb(struct urb *urb) |
32 | { | 33 | { |
33 | struct cmd_buf *cmd = (struct cmd_buf *)urb->context; | 34 | struct cmd_buf *cmd = (struct cmd_buf *)urb->context; |
34 | struct hif_device_usb *hif_dev = cmd->hif_dev; | ||
35 | |||
36 | if (!hif_dev) { | ||
37 | usb_free_urb(urb); | ||
38 | if (cmd) { | ||
39 | if (cmd->skb) | ||
40 | dev_kfree_skb_any(cmd->skb); | ||
41 | kfree(cmd); | ||
42 | } | ||
43 | return; | ||
44 | } | ||
45 | 35 | ||
46 | switch (urb->status) { | 36 | switch (urb->status) { |
47 | case 0: | 37 | case 0: |
48 | break; | 38 | break; |
49 | case -ENOENT: | 39 | case -ENOENT: |
50 | case -ECONNRESET: | 40 | case -ECONNRESET: |
51 | break; | ||
52 | case -ENODEV: | 41 | case -ENODEV: |
53 | case -ESHUTDOWN: | 42 | case -ESHUTDOWN: |
54 | return; | 43 | goto free; |
55 | default: | 44 | default: |
56 | break; | 45 | break; |
57 | } | 46 | } |
@@ -60,8 +49,12 @@ static void hif_usb_regout_cb(struct urb *urb) | |||
60 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, | 49 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, |
61 | cmd->skb, 1); | 50 | cmd->skb, 1); |
62 | kfree(cmd); | 51 | kfree(cmd); |
63 | usb_free_urb(urb); | ||
64 | } | 52 | } |
53 | |||
54 | return; | ||
55 | free: | ||
56 | kfree_skb(cmd->skb); | ||
57 | kfree(cmd); | ||
65 | } | 58 | } |
66 | 59 | ||
67 | static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | 60 | static int hif_usb_send_regout(struct hif_device_usb *hif_dev, |
@@ -89,11 +82,13 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | |||
89 | skb->data, skb->len, | 82 | skb->data, skb->len, |
90 | hif_usb_regout_cb, cmd, 1); | 83 | hif_usb_regout_cb, cmd, 1); |
91 | 84 | ||
85 | usb_anchor_urb(urb, &hif_dev->regout_submitted); | ||
92 | ret = usb_submit_urb(urb, GFP_KERNEL); | 86 | ret = usb_submit_urb(urb, GFP_KERNEL); |
93 | if (ret) { | 87 | if (ret) { |
94 | usb_free_urb(urb); | 88 | usb_unanchor_urb(urb); |
95 | kfree(cmd); | 89 | kfree(cmd); |
96 | } | 90 | } |
91 | usb_free_urb(urb); | ||
97 | 92 | ||
98 | return ret; | 93 | return ret; |
99 | } | 94 | } |
@@ -154,6 +149,13 @@ static void hif_usb_tx_cb(struct urb *urb) | |||
154 | } | 149 | } |
155 | } | 150 | } |
156 | 151 | ||
152 | static inline void ath9k_skb_queue_purge(struct sk_buff_head *list) | ||
153 | { | ||
154 | struct sk_buff *skb; | ||
155 | while ((skb = __skb_dequeue(list)) != NULL) | ||
156 | dev_kfree_skb_any(skb); | ||
157 | } | ||
158 | |||
157 | /* TX lock has to be taken */ | 159 | /* TX lock has to be taken */ |
158 | static int __hif_usb_tx(struct hif_device_usb *hif_dev) | 160 | static int __hif_usb_tx(struct hif_device_usb *hif_dev) |
159 | { | 161 | { |
@@ -212,7 +214,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) | |||
212 | ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); | 214 | ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); |
213 | if (ret) { | 215 | if (ret) { |
214 | tx_buf->len = tx_buf->offset = 0; | 216 | tx_buf->len = tx_buf->offset = 0; |
215 | __skb_queue_purge(&tx_buf->skb_queue); | 217 | ath9k_skb_queue_purge(&tx_buf->skb_queue); |
216 | __skb_queue_head_init(&tx_buf->skb_queue); | 218 | __skb_queue_head_init(&tx_buf->skb_queue); |
217 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); | 219 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); |
218 | hif_dev->tx.tx_buf_cnt++; | 220 | hif_dev->tx.tx_buf_cnt++; |
@@ -279,7 +281,7 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id) | |||
279 | unsigned long flags; | 281 | unsigned long flags; |
280 | 282 | ||
281 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | 283 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); |
282 | __skb_queue_purge(&hif_dev->tx.tx_skb_queue); | 284 | ath9k_skb_queue_purge(&hif_dev->tx.tx_skb_queue); |
283 | hif_dev->tx.tx_skb_cnt = 0; | 285 | hif_dev->tx.tx_skb_cnt = 0; |
284 | hif_dev->tx.flags |= HIF_USB_TX_STOP; | 286 | hif_dev->tx.flags |= HIF_USB_TX_STOP; |
285 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | 287 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
@@ -299,6 +301,8 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, | |||
299 | ret = hif_usb_send_regout(hif_dev, skb); | 301 | ret = hif_usb_send_regout(hif_dev, skb); |
300 | break; | 302 | break; |
301 | default: | 303 | default: |
304 | dev_err(&hif_dev->udev->dev, | ||
305 | "ath9k_htc: Invalid TX pipe: %d\n", pipe_id); | ||
302 | ret = -EINVAL; | 306 | ret = -EINVAL; |
303 | break; | 307 | break; |
304 | } | 308 | } |
@@ -321,12 +325,14 @@ static struct ath9k_htc_hif hif_usb = { | |||
321 | static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | 325 | static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, |
322 | struct sk_buff *skb) | 326 | struct sk_buff *skb) |
323 | { | 327 | { |
324 | struct sk_buff *nskb, *skb_pool[8]; | 328 | struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; |
325 | int index = 0, i = 0, chk_idx, len = skb->len; | 329 | int index = 0, i = 0, chk_idx, len = skb->len; |
326 | int rx_remain_len = 0, rx_pkt_len = 0; | 330 | int rx_remain_len = 0, rx_pkt_len = 0; |
327 | u16 pkt_len, pkt_tag, pool_index = 0; | 331 | u16 pkt_len, pkt_tag, pool_index = 0; |
328 | u8 *ptr; | 332 | u8 *ptr; |
329 | 333 | ||
334 | spin_lock(&hif_dev->rx_lock); | ||
335 | |||
330 | rx_remain_len = hif_dev->rx_remain_len; | 336 | rx_remain_len = hif_dev->rx_remain_len; |
331 | rx_pkt_len = hif_dev->rx_transfer_len; | 337 | rx_pkt_len = hif_dev->rx_transfer_len; |
332 | 338 | ||
@@ -353,6 +359,8 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |||
353 | } | 359 | } |
354 | } | 360 | } |
355 | 361 | ||
362 | spin_unlock(&hif_dev->rx_lock); | ||
363 | |||
356 | while (index < len) { | 364 | while (index < len) { |
357 | ptr = (u8 *) skb->data; | 365 | ptr = (u8 *) skb->data; |
358 | 366 | ||
@@ -370,6 +378,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |||
370 | index = index + 4 + pkt_len + pad_len; | 378 | index = index + 4 + pkt_len + pad_len; |
371 | 379 | ||
372 | if (index > MAX_RX_BUF_SIZE) { | 380 | if (index > MAX_RX_BUF_SIZE) { |
381 | spin_lock(&hif_dev->rx_lock); | ||
373 | hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; | 382 | hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; |
374 | hif_dev->rx_transfer_len = | 383 | hif_dev->rx_transfer_len = |
375 | MAX_RX_BUF_SIZE - chk_idx - 4; | 384 | MAX_RX_BUF_SIZE - chk_idx - 4; |
@@ -381,6 +390,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |||
381 | dev_err(&hif_dev->udev->dev, | 390 | dev_err(&hif_dev->udev->dev, |
382 | "ath9k_htc: RX memory allocation" | 391 | "ath9k_htc: RX memory allocation" |
383 | " error\n"); | 392 | " error\n"); |
393 | spin_unlock(&hif_dev->rx_lock); | ||
384 | goto err; | 394 | goto err; |
385 | } | 395 | } |
386 | skb_reserve(nskb, 32); | 396 | skb_reserve(nskb, 32); |
@@ -391,6 +401,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |||
391 | 401 | ||
392 | /* Record the buffer pointer */ | 402 | /* Record the buffer pointer */ |
393 | hif_dev->remain_skb = nskb; | 403 | hif_dev->remain_skb = nskb; |
404 | spin_unlock(&hif_dev->rx_lock); | ||
394 | } else { | 405 | } else { |
395 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); | 406 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); |
396 | if (!nskb) { | 407 | if (!nskb) { |
@@ -408,14 +419,11 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |||
408 | } | 419 | } |
409 | } else { | 420 | } else { |
410 | RX_STAT_INC(skb_dropped); | 421 | RX_STAT_INC(skb_dropped); |
411 | dev_kfree_skb_any(skb); | ||
412 | return; | 422 | return; |
413 | } | 423 | } |
414 | } | 424 | } |
415 | 425 | ||
416 | err: | 426 | err: |
417 | dev_kfree_skb_any(skb); | ||
418 | |||
419 | for (i = 0; i < pool_index; i++) { | 427 | for (i = 0; i < pool_index; i++) { |
420 | ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], | 428 | ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i], |
421 | skb_pool[i]->len, USB_WLAN_RX_PIPE); | 429 | skb_pool[i]->len, USB_WLAN_RX_PIPE); |
@@ -426,11 +434,13 @@ err: | |||
426 | static void ath9k_hif_usb_rx_cb(struct urb *urb) | 434 | static void ath9k_hif_usb_rx_cb(struct urb *urb) |
427 | { | 435 | { |
428 | struct sk_buff *skb = (struct sk_buff *) urb->context; | 436 | struct sk_buff *skb = (struct sk_buff *) urb->context; |
429 | struct sk_buff *nskb; | ||
430 | struct hif_device_usb *hif_dev = (struct hif_device_usb *) | 437 | struct hif_device_usb *hif_dev = (struct hif_device_usb *) |
431 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | 438 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); |
432 | int ret; | 439 | int ret; |
433 | 440 | ||
441 | if (!skb) | ||
442 | return; | ||
443 | |||
434 | if (!hif_dev) | 444 | if (!hif_dev) |
435 | goto free; | 445 | goto free; |
436 | 446 | ||
@@ -448,38 +458,23 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb) | |||
448 | 458 | ||
449 | if (likely(urb->actual_length != 0)) { | 459 | if (likely(urb->actual_length != 0)) { |
450 | skb_put(skb, urb->actual_length); | 460 | skb_put(skb, urb->actual_length); |
451 | |||
452 | nskb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_ATOMIC); | ||
453 | if (!nskb) | ||
454 | goto resubmit; | ||
455 | |||
456 | usb_fill_bulk_urb(urb, hif_dev->udev, | ||
457 | usb_rcvbulkpipe(hif_dev->udev, | ||
458 | USB_WLAN_RX_PIPE), | ||
459 | nskb->data, MAX_RX_BUF_SIZE, | ||
460 | ath9k_hif_usb_rx_cb, nskb); | ||
461 | |||
462 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
463 | if (ret) { | ||
464 | dev_kfree_skb_any(nskb); | ||
465 | goto free; | ||
466 | } | ||
467 | |||
468 | ath9k_hif_usb_rx_stream(hif_dev, skb); | 461 | ath9k_hif_usb_rx_stream(hif_dev, skb); |
469 | return; | ||
470 | } | 462 | } |
471 | 463 | ||
472 | resubmit: | 464 | resubmit: |
473 | skb_reset_tail_pointer(skb); | 465 | skb_reset_tail_pointer(skb); |
474 | skb_trim(skb, 0); | 466 | skb_trim(skb, 0); |
475 | 467 | ||
468 | usb_anchor_urb(urb, &hif_dev->rx_submitted); | ||
476 | ret = usb_submit_urb(urb, GFP_ATOMIC); | 469 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
477 | if (ret) | 470 | if (ret) { |
471 | usb_unanchor_urb(urb); | ||
478 | goto free; | 472 | goto free; |
473 | } | ||
479 | 474 | ||
480 | return; | 475 | return; |
481 | free: | 476 | free: |
482 | dev_kfree_skb_any(skb); | 477 | kfree_skb(skb); |
483 | } | 478 | } |
484 | 479 | ||
485 | static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | 480 | static void ath9k_hif_usb_reg_in_cb(struct urb *urb) |
@@ -490,6 +485,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
490 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | 485 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); |
491 | int ret; | 486 | int ret; |
492 | 487 | ||
488 | if (!skb) | ||
489 | return; | ||
490 | |||
493 | if (!hif_dev) | 491 | if (!hif_dev) |
494 | goto free; | 492 | goto free; |
495 | 493 | ||
@@ -508,7 +506,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
508 | if (likely(urb->actual_length != 0)) { | 506 | if (likely(urb->actual_length != 0)) { |
509 | skb_put(skb, urb->actual_length); | 507 | skb_put(skb, urb->actual_length); |
510 | 508 | ||
511 | nskb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); | 509 | nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC); |
512 | if (!nskb) | 510 | if (!nskb) |
513 | goto resubmit; | 511 | goto resubmit; |
514 | 512 | ||
@@ -519,7 +517,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
519 | 517 | ||
520 | ret = usb_submit_urb(urb, GFP_ATOMIC); | 518 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
521 | if (ret) { | 519 | if (ret) { |
522 | dev_kfree_skb_any(nskb); | 520 | kfree_skb(nskb); |
523 | goto free; | 521 | goto free; |
524 | } | 522 | } |
525 | 523 | ||
@@ -539,7 +537,8 @@ resubmit: | |||
539 | 537 | ||
540 | return; | 538 | return; |
541 | free: | 539 | free: |
542 | dev_kfree_skb_any(skb); | 540 | kfree_skb(skb); |
541 | urb->context = NULL; | ||
543 | } | 542 | } |
544 | 543 | ||
545 | static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) | 544 | static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) |
@@ -609,78 +608,66 @@ err: | |||
609 | return -ENOMEM; | 608 | return -ENOMEM; |
610 | } | 609 | } |
611 | 610 | ||
612 | static void ath9k_hif_usb_dealloc_rx_skbs(struct hif_device_usb *hif_dev) | ||
613 | { | ||
614 | int i; | ||
615 | |||
616 | for (i = 0; i < MAX_RX_URB_NUM; i++) { | ||
617 | if (hif_dev->wlan_rx_data_urb[i]) { | ||
618 | if (hif_dev->wlan_rx_data_urb[i]->transfer_buffer) | ||
619 | dev_kfree_skb_any((void *) | ||
620 | hif_dev->wlan_rx_data_urb[i]->context); | ||
621 | } | ||
622 | } | ||
623 | } | ||
624 | |||
625 | static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) | 611 | static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev) |
626 | { | 612 | { |
627 | int i; | 613 | usb_kill_anchored_urbs(&hif_dev->rx_submitted); |
628 | |||
629 | for (i = 0; i < MAX_RX_URB_NUM; i++) { | ||
630 | if (hif_dev->wlan_rx_data_urb[i]) { | ||
631 | usb_kill_urb(hif_dev->wlan_rx_data_urb[i]); | ||
632 | usb_free_urb(hif_dev->wlan_rx_data_urb[i]); | ||
633 | hif_dev->wlan_rx_data_urb[i] = NULL; | ||
634 | } | ||
635 | } | ||
636 | } | ||
637 | |||
638 | static int ath9k_hif_usb_prep_rx_urb(struct hif_device_usb *hif_dev, | ||
639 | struct urb *urb) | ||
640 | { | ||
641 | struct sk_buff *skb; | ||
642 | |||
643 | skb = __dev_alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); | ||
644 | if (!skb) | ||
645 | return -ENOMEM; | ||
646 | |||
647 | usb_fill_bulk_urb(urb, hif_dev->udev, | ||
648 | usb_rcvbulkpipe(hif_dev->udev, USB_WLAN_RX_PIPE), | ||
649 | skb->data, MAX_RX_BUF_SIZE, | ||
650 | ath9k_hif_usb_rx_cb, skb); | ||
651 | return 0; | ||
652 | } | 614 | } |
653 | 615 | ||
654 | static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) | 616 | static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev) |
655 | { | 617 | { |
618 | struct urb *urb = NULL; | ||
619 | struct sk_buff *skb = NULL; | ||
656 | int i, ret; | 620 | int i, ret; |
657 | 621 | ||
622 | init_usb_anchor(&hif_dev->rx_submitted); | ||
623 | spin_lock_init(&hif_dev->rx_lock); | ||
624 | |||
658 | for (i = 0; i < MAX_RX_URB_NUM; i++) { | 625 | for (i = 0; i < MAX_RX_URB_NUM; i++) { |
659 | 626 | ||
660 | /* Allocate URB */ | 627 | /* Allocate URB */ |
661 | hif_dev->wlan_rx_data_urb[i] = usb_alloc_urb(0, GFP_KERNEL); | 628 | urb = usb_alloc_urb(0, GFP_KERNEL); |
662 | if (hif_dev->wlan_rx_data_urb[i] == NULL) { | 629 | if (urb == NULL) { |
663 | ret = -ENOMEM; | 630 | ret = -ENOMEM; |
664 | goto err_rx_urb; | 631 | goto err_urb; |
665 | } | 632 | } |
666 | 633 | ||
667 | /* Allocate buffer */ | 634 | /* Allocate buffer */ |
668 | ret = ath9k_hif_usb_prep_rx_urb(hif_dev, | 635 | skb = alloc_skb(MAX_RX_BUF_SIZE, GFP_KERNEL); |
669 | hif_dev->wlan_rx_data_urb[i]); | 636 | if (!skb) { |
670 | if (ret) | 637 | ret = -ENOMEM; |
671 | goto err_rx_urb; | 638 | goto err_skb; |
639 | } | ||
640 | |||
641 | usb_fill_bulk_urb(urb, hif_dev->udev, | ||
642 | usb_rcvbulkpipe(hif_dev->udev, | ||
643 | USB_WLAN_RX_PIPE), | ||
644 | skb->data, MAX_RX_BUF_SIZE, | ||
645 | ath9k_hif_usb_rx_cb, skb); | ||
646 | |||
647 | /* Anchor URB */ | ||
648 | usb_anchor_urb(urb, &hif_dev->rx_submitted); | ||
672 | 649 | ||
673 | /* Submit URB */ | 650 | /* Submit URB */ |
674 | ret = usb_submit_urb(hif_dev->wlan_rx_data_urb[i], GFP_KERNEL); | 651 | ret = usb_submit_urb(urb, GFP_KERNEL); |
675 | if (ret) | 652 | if (ret) { |
676 | goto err_rx_urb; | 653 | usb_unanchor_urb(urb); |
654 | goto err_submit; | ||
655 | } | ||
677 | 656 | ||
657 | /* | ||
658 | * Drop reference count. | ||
659 | * This ensures that the URB is freed when killing them. | ||
660 | */ | ||
661 | usb_free_urb(urb); | ||
678 | } | 662 | } |
679 | 663 | ||
680 | return 0; | 664 | return 0; |
681 | 665 | ||
682 | err_rx_urb: | 666 | err_submit: |
683 | ath9k_hif_usb_dealloc_rx_skbs(hif_dev); | 667 | kfree_skb(skb); |
668 | err_skb: | ||
669 | usb_free_urb(urb); | ||
670 | err_urb: | ||
684 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); | 671 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); |
685 | return ret; | 672 | return ret; |
686 | } | 673 | } |
@@ -689,6 +676,8 @@ static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) | |||
689 | { | 676 | { |
690 | if (hif_dev->reg_in_urb) { | 677 | if (hif_dev->reg_in_urb) { |
691 | usb_kill_urb(hif_dev->reg_in_urb); | 678 | usb_kill_urb(hif_dev->reg_in_urb); |
679 | if (hif_dev->reg_in_urb->context) | ||
680 | kfree_skb((void *)hif_dev->reg_in_urb->context); | ||
692 | usb_free_urb(hif_dev->reg_in_urb); | 681 | usb_free_urb(hif_dev->reg_in_urb); |
693 | hif_dev->reg_in_urb = NULL; | 682 | hif_dev->reg_in_urb = NULL; |
694 | } | 683 | } |
@@ -702,7 +691,7 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) | |||
702 | if (hif_dev->reg_in_urb == NULL) | 691 | if (hif_dev->reg_in_urb == NULL) |
703 | return -ENOMEM; | 692 | return -ENOMEM; |
704 | 693 | ||
705 | skb = __dev_alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); | 694 | skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); |
706 | if (!skb) | 695 | if (!skb) |
707 | goto err; | 696 | goto err; |
708 | 697 | ||
@@ -712,12 +701,10 @@ static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) | |||
712 | ath9k_hif_usb_reg_in_cb, skb, 1); | 701 | ath9k_hif_usb_reg_in_cb, skb, 1); |
713 | 702 | ||
714 | if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) | 703 | if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) |
715 | goto err_skb; | 704 | goto err; |
716 | 705 | ||
717 | return 0; | 706 | return 0; |
718 | 707 | ||
719 | err_skb: | ||
720 | dev_kfree_skb_any(skb); | ||
721 | err: | 708 | err: |
722 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); | 709 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); |
723 | return -ENOMEM; | 710 | return -ENOMEM; |
@@ -725,6 +712,9 @@ err: | |||
725 | 712 | ||
726 | static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) | 713 | static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) |
727 | { | 714 | { |
715 | /* Register Write */ | ||
716 | init_usb_anchor(&hif_dev->regout_submitted); | ||
717 | |||
728 | /* TX */ | 718 | /* TX */ |
729 | if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0) | 719 | if (ath9k_hif_usb_alloc_tx_urbs(hif_dev) < 0) |
730 | goto err; | 720 | goto err; |
@@ -733,7 +723,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) | |||
733 | if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0) | 723 | if (ath9k_hif_usb_alloc_rx_urbs(hif_dev) < 0) |
734 | goto err; | 724 | goto err; |
735 | 725 | ||
736 | /* Register Read/Write */ | 726 | /* Register Read */ |
737 | if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) | 727 | if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) |
738 | goto err; | 728 | goto err; |
739 | 729 | ||
@@ -830,6 +820,7 @@ err_fw_req: | |||
830 | 820 | ||
831 | static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) | 821 | static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) |
832 | { | 822 | { |
823 | usb_kill_anchored_urbs(&hif_dev->regout_submitted); | ||
833 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); | 824 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); |
834 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); | 825 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); |
835 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); | 826 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 7cc3762a6789..7d49a8af420e 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h | |||
@@ -34,6 +34,7 @@ | |||
34 | 34 | ||
35 | #define MAX_RX_URB_NUM 8 | 35 | #define MAX_RX_URB_NUM 8 |
36 | #define MAX_RX_BUF_SIZE 16384 | 36 | #define MAX_RX_BUF_SIZE 16384 |
37 | #define MAX_PKT_NUM_IN_TRANSFER 10 | ||
37 | 38 | ||
38 | #define MAX_REG_OUT_URB_NUM 1 | 39 | #define MAX_REG_OUT_URB_NUM 1 |
39 | #define MAX_REG_OUT_BUF_NUM 8 | 40 | #define MAX_REG_OUT_BUF_NUM 8 |
@@ -85,18 +86,17 @@ struct hif_device_usb { | |||
85 | struct usb_interface *interface; | 86 | struct usb_interface *interface; |
86 | const struct firmware *firmware; | 87 | const struct firmware *firmware; |
87 | struct htc_target *htc_handle; | 88 | struct htc_target *htc_handle; |
88 | u8 flags; | ||
89 | |||
90 | struct hif_usb_tx tx; | 89 | struct hif_usb_tx tx; |
91 | |||
92 | struct urb *wlan_rx_data_urb[MAX_RX_URB_NUM]; | ||
93 | struct urb *reg_in_urb; | 90 | struct urb *reg_in_urb; |
94 | 91 | struct usb_anchor regout_submitted; | |
92 | struct usb_anchor rx_submitted; | ||
95 | struct sk_buff *remain_skb; | 93 | struct sk_buff *remain_skb; |
96 | int rx_remain_len; | 94 | int rx_remain_len; |
97 | int rx_pkt_len; | 95 | int rx_pkt_len; |
98 | int rx_transfer_len; | 96 | int rx_transfer_len; |
99 | int rx_pad_len; | 97 | int rx_pad_len; |
98 | spinlock_t rx_lock; | ||
99 | u8 flags; /* HIF_USB_* */ | ||
100 | }; | 100 | }; |
101 | 101 | ||
102 | int ath9k_hif_usb_init(void); | 102 | int ath9k_hif_usb_init(void); |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 777064945fca..78213fc71b09 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -309,6 +309,14 @@ struct ath_led { | |||
309 | int brightness; | 309 | int brightness; |
310 | }; | 310 | }; |
311 | 311 | ||
312 | struct htc_beacon_config { | ||
313 | u16 beacon_interval; | ||
314 | u16 listen_interval; | ||
315 | u16 dtim_period; | ||
316 | u16 bmiss_timeout; | ||
317 | u8 dtim_count; | ||
318 | }; | ||
319 | |||
312 | #define OP_INVALID BIT(0) | 320 | #define OP_INVALID BIT(0) |
313 | #define OP_SCANNING BIT(1) | 321 | #define OP_SCANNING BIT(1) |
314 | #define OP_FULL_RESET BIT(2) | 322 | #define OP_FULL_RESET BIT(2) |
@@ -349,7 +357,11 @@ struct ath9k_htc_priv { | |||
349 | struct sk_buff *beacon; | 357 | struct sk_buff *beacon; |
350 | spinlock_t beacon_lock; | 358 | spinlock_t beacon_lock; |
351 | 359 | ||
360 | bool tx_queues_stop; | ||
361 | spinlock_t tx_lock; | ||
362 | |||
352 | struct ieee80211_vif *vif; | 363 | struct ieee80211_vif *vif; |
364 | struct htc_beacon_config cur_beacon_conf; | ||
353 | unsigned int rxfilter; | 365 | unsigned int rxfilter; |
354 | struct tasklet_struct wmi_tasklet; | 366 | struct tasklet_struct wmi_tasklet; |
355 | struct tasklet_struct rx_tasklet; | 367 | struct tasklet_struct rx_tasklet; |
@@ -360,6 +372,11 @@ struct ath9k_htc_priv { | |||
360 | struct ath9k_htc_aggr_work aggr_work; | 372 | struct ath9k_htc_aggr_work aggr_work; |
361 | struct delayed_work ath9k_aggr_work; | 373 | struct delayed_work ath9k_aggr_work; |
362 | struct delayed_work ath9k_ani_work; | 374 | struct delayed_work ath9k_ani_work; |
375 | struct work_struct ps_work; | ||
376 | |||
377 | struct mutex htc_pm_lock; | ||
378 | unsigned long ps_usecount; | ||
379 | bool ps_enabled; | ||
363 | 380 | ||
364 | struct ath_led radio_led; | 381 | struct ath_led radio_led; |
365 | struct ath_led assoc_led; | 382 | struct ath_led assoc_led; |
@@ -386,8 +403,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) | |||
386 | } | 403 | } |
387 | 404 | ||
388 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 405 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
389 | struct ieee80211_vif *vif, | 406 | struct ieee80211_vif *vif); |
390 | struct ieee80211_bss_conf *bss_conf); | ||
391 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); | 407 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); |
392 | void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, | 408 | void ath9k_htc_beacon_update(struct ath9k_htc_priv *priv, |
393 | struct ieee80211_vif *vif); | 409 | struct ieee80211_vif *vif); |
@@ -415,6 +431,11 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv); | |||
415 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); | 431 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); |
416 | void ath9k_host_rx_init(struct ath9k_htc_priv *priv); | 432 | void ath9k_host_rx_init(struct ath9k_htc_priv *priv); |
417 | void ath9k_rx_tasklet(unsigned long data); | 433 | void ath9k_rx_tasklet(unsigned long data); |
434 | u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv); | ||
435 | |||
436 | void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv); | ||
437 | void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv); | ||
438 | void ath9k_ps_work(struct work_struct *work); | ||
418 | 439 | ||
419 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); | 440 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); |
420 | void ath9k_init_leds(struct ath9k_htc_priv *priv); | 441 | void ath9k_init_leds(struct ath9k_htc_priv *priv); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 25f5b5377bac..5e21f4d92ff5 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #define FUDGE 2 | 19 | #define FUDGE 2 |
20 | 20 | ||
21 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | 21 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, |
22 | struct ieee80211_bss_conf *bss_conf) | 22 | struct htc_beacon_config *bss_conf) |
23 | { | 23 | { |
24 | struct ath_common *common = ath9k_hw_common(priv->ah); | 24 | struct ath_common *common = ath9k_hw_common(priv->ah); |
25 | struct ath9k_beacon_state bs; | 25 | struct ath9k_beacon_state bs; |
@@ -34,8 +34,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
34 | 34 | ||
35 | memset(&bs, 0, sizeof(bs)); | 35 | memset(&bs, 0, sizeof(bs)); |
36 | 36 | ||
37 | intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD; | 37 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; |
38 | bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_int); | 38 | bmiss_timeout = (ATH_DEFAULT_BMISS_LIMIT * bss_conf->beacon_interval); |
39 | 39 | ||
40 | /* | 40 | /* |
41 | * Setup dtim and cfp parameters according to | 41 | * Setup dtim and cfp parameters according to |
@@ -138,7 +138,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
138 | } | 138 | } |
139 | 139 | ||
140 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | 140 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, |
141 | struct ieee80211_bss_conf *bss_conf) | 141 | struct htc_beacon_config *bss_conf) |
142 | { | 142 | { |
143 | struct ath_common *common = ath9k_hw_common(priv->ah); | 143 | struct ath_common *common = ath9k_hw_common(priv->ah); |
144 | enum ath9k_int imask = 0; | 144 | enum ath9k_int imask = 0; |
@@ -146,7 +146,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | |||
146 | int ret; | 146 | int ret; |
147 | u8 cmd_rsp; | 147 | u8 cmd_rsp; |
148 | 148 | ||
149 | intval = bss_conf->beacon_int & ATH9K_BEACON_PERIOD; | 149 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; |
150 | nexttbtt = intval; | 150 | nexttbtt = intval; |
151 | intval |= ATH9K_BEACON_ENA; | 151 | intval |= ATH9K_BEACON_ENA; |
152 | if (priv->op_flags & OP_ENABLE_BEACON) | 152 | if (priv->op_flags & OP_ENABLE_BEACON) |
@@ -154,7 +154,7 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | |||
154 | 154 | ||
155 | ath_print(common, ATH_DBG_BEACON, | 155 | ath_print(common, ATH_DBG_BEACON, |
156 | "IBSS Beacon config, intval: %d, imask: 0x%x\n", | 156 | "IBSS Beacon config, intval: %d, imask: 0x%x\n", |
157 | bss_conf->beacon_int, imask); | 157 | bss_conf->beacon_interval, imask); |
158 | 158 | ||
159 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 159 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
160 | ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); | 160 | ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); |
@@ -239,18 +239,35 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) | |||
239 | spin_unlock_bh(&priv->beacon_lock); | 239 | spin_unlock_bh(&priv->beacon_lock); |
240 | } | 240 | } |
241 | 241 | ||
242 | |||
242 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 243 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
243 | struct ieee80211_vif *vif, | 244 | struct ieee80211_vif *vif) |
244 | struct ieee80211_bss_conf *bss_conf) | ||
245 | { | 245 | { |
246 | struct ath_common *common = ath9k_hw_common(priv->ah); | 246 | struct ath_common *common = ath9k_hw_common(priv->ah); |
247 | 247 | enum nl80211_iftype iftype; | |
248 | switch (vif->type) { | 248 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; |
249 | |||
250 | if (vif) { | ||
251 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
252 | iftype = vif->type; | ||
253 | cur_conf->beacon_interval = bss_conf->beacon_int; | ||
254 | cur_conf->dtim_period = bss_conf->dtim_period; | ||
255 | cur_conf->listen_interval = 1; | ||
256 | cur_conf->dtim_count = 1; | ||
257 | cur_conf->bmiss_timeout = | ||
258 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; | ||
259 | } else | ||
260 | iftype = priv->ah->opmode; | ||
261 | |||
262 | if (cur_conf->beacon_interval == 0) | ||
263 | cur_conf->beacon_interval = 100; | ||
264 | |||
265 | switch (iftype) { | ||
249 | case NL80211_IFTYPE_STATION: | 266 | case NL80211_IFTYPE_STATION: |
250 | ath9k_htc_beacon_config_sta(priv, bss_conf); | 267 | ath9k_htc_beacon_config_sta(priv, cur_conf); |
251 | break; | 268 | break; |
252 | case NL80211_IFTYPE_ADHOC: | 269 | case NL80211_IFTYPE_ADHOC: |
253 | ath9k_htc_beacon_config_adhoc(priv, bss_conf); | 270 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); |
254 | break; | 271 | break; |
255 | default: | 272 | default: |
256 | ath_print(common, ATH_DBG_CONFIG, | 273 | ath_print(common, ATH_DBG_CONFIG, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 10c87605d2c4..aed53573c547 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -287,6 +287,7 @@ static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
287 | } | 287 | } |
288 | 288 | ||
289 | static const struct ath_bus_ops ath9k_usb_bus_ops = { | 289 | static const struct ath_bus_ops ath9k_usb_bus_ops = { |
290 | .ath_bus_type = ATH_USB, | ||
290 | .read_cachesize = ath_usb_read_cachesize, | 291 | .read_cachesize = ath_usb_read_cachesize, |
291 | .eeprom_read = ath_usb_eeprom_read, | 292 | .eeprom_read = ath_usb_eeprom_read, |
292 | }; | 293 | }; |
@@ -421,6 +422,7 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) | |||
421 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | 422 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
422 | 423 | ||
423 | priv->op_flags |= OP_TXAGGR; | 424 | priv->op_flags |= OP_TXAGGR; |
425 | priv->ah->opmode = NL80211_IFTYPE_STATION; | ||
424 | } | 426 | } |
425 | 427 | ||
426 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | 428 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) |
@@ -449,8 +451,10 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | |||
449 | 451 | ||
450 | spin_lock_init(&priv->wmi->wmi_lock); | 452 | spin_lock_init(&priv->wmi->wmi_lock); |
451 | spin_lock_init(&priv->beacon_lock); | 453 | spin_lock_init(&priv->beacon_lock); |
454 | spin_lock_init(&priv->tx_lock); | ||
452 | mutex_init(&priv->mutex); | 455 | mutex_init(&priv->mutex); |
453 | mutex_init(&priv->aggr_work.mutex); | 456 | mutex_init(&priv->aggr_work.mutex); |
457 | mutex_init(&priv->htc_pm_lock); | ||
454 | tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, | 458 | tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, |
455 | (unsigned long)priv); | 459 | (unsigned long)priv); |
456 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, | 460 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, |
@@ -458,6 +462,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | |||
458 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); | 462 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); |
459 | INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); | 463 | INIT_DELAYED_WORK(&priv->ath9k_aggr_work, ath9k_htc_aggr_work); |
460 | INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); | 464 | INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); |
465 | INIT_WORK(&priv->ps_work, ath9k_ps_work); | ||
461 | 466 | ||
462 | /* | 467 | /* |
463 | * Cache line size is used to size and align various | 468 | * Cache line size is used to size and align various |
@@ -511,12 +516,17 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
511 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 516 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
512 | IEEE80211_HW_AMPDU_AGGREGATION | | 517 | IEEE80211_HW_AMPDU_AGGREGATION | |
513 | IEEE80211_HW_SPECTRUM_MGMT | | 518 | IEEE80211_HW_SPECTRUM_MGMT | |
514 | IEEE80211_HW_HAS_RATE_CONTROL; | 519 | IEEE80211_HW_HAS_RATE_CONTROL | |
520 | IEEE80211_HW_RX_INCLUDES_FCS | | ||
521 | IEEE80211_HW_SUPPORTS_PS | | ||
522 | IEEE80211_HW_PS_NULLFUNC_STACK; | ||
515 | 523 | ||
516 | hw->wiphy->interface_modes = | 524 | hw->wiphy->interface_modes = |
517 | BIT(NL80211_IFTYPE_STATION) | | 525 | BIT(NL80211_IFTYPE_STATION) | |
518 | BIT(NL80211_IFTYPE_ADHOC); | 526 | BIT(NL80211_IFTYPE_ADHOC); |
519 | 527 | ||
528 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
529 | |||
520 | hw->queues = 4; | 530 | hw->queues = 4; |
521 | hw->channel_change_time = 5000; | 531 | hw->channel_change_time = 5000; |
522 | hw->max_listen_interval = 10; | 532 | hw->max_listen_interval = 10; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 20a2c1341e20..eb7722b2cfcc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -65,6 +65,56 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, | |||
65 | return mode; | 65 | return mode; |
66 | } | 66 | } |
67 | 67 | ||
68 | static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, | ||
69 | enum ath9k_power_mode mode) | ||
70 | { | ||
71 | bool ret; | ||
72 | |||
73 | mutex_lock(&priv->htc_pm_lock); | ||
74 | ret = ath9k_hw_setpower(priv->ah, mode); | ||
75 | mutex_unlock(&priv->htc_pm_lock); | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv) | ||
81 | { | ||
82 | mutex_lock(&priv->htc_pm_lock); | ||
83 | if (++priv->ps_usecount != 1) | ||
84 | goto unlock; | ||
85 | ath9k_hw_setpower(priv->ah, ATH9K_PM_AWAKE); | ||
86 | |||
87 | unlock: | ||
88 | mutex_unlock(&priv->htc_pm_lock); | ||
89 | } | ||
90 | |||
91 | void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv) | ||
92 | { | ||
93 | mutex_lock(&priv->htc_pm_lock); | ||
94 | if (--priv->ps_usecount != 0) | ||
95 | goto unlock; | ||
96 | |||
97 | if (priv->ps_enabled) | ||
98 | ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP); | ||
99 | unlock: | ||
100 | mutex_unlock(&priv->htc_pm_lock); | ||
101 | } | ||
102 | |||
103 | void ath9k_ps_work(struct work_struct *work) | ||
104 | { | ||
105 | struct ath9k_htc_priv *priv = | ||
106 | container_of(work, struct ath9k_htc_priv, | ||
107 | ps_work); | ||
108 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | ||
109 | |||
110 | /* The chip wakes up after receiving the first beacon | ||
111 | while network sleep is enabled. For the driver to | ||
112 | be in sync with the hw, set the chip to awake and | ||
113 | only then set it to sleep. | ||
114 | */ | ||
115 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); | ||
116 | } | ||
117 | |||
68 | static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | 118 | static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, |
69 | struct ieee80211_hw *hw, | 119 | struct ieee80211_hw *hw, |
70 | struct ath9k_channel *hchan) | 120 | struct ath9k_channel *hchan) |
@@ -87,7 +137,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
87 | 137 | ||
88 | /* Fiddle around with fastcc later on, for now just use full reset */ | 138 | /* Fiddle around with fastcc later on, for now just use full reset */ |
89 | fastcc = false; | 139 | fastcc = false; |
90 | 140 | ath9k_htc_ps_wakeup(priv); | |
91 | htc_stop(priv->htc); | 141 | htc_stop(priv->htc); |
92 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 142 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
93 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 143 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
@@ -103,6 +153,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
103 | ath_print(common, ATH_DBG_FATAL, | 153 | ath_print(common, ATH_DBG_FATAL, |
104 | "Unable to reset channel (%u Mhz) " | 154 | "Unable to reset channel (%u Mhz) " |
105 | "reset status %d\n", channel->center_freq, ret); | 155 | "reset status %d\n", channel->center_freq, ret); |
156 | ath9k_htc_ps_restore(priv); | ||
106 | goto err; | 157 | goto err; |
107 | } | 158 | } |
108 | 159 | ||
@@ -128,6 +179,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
128 | 179 | ||
129 | priv->op_flags &= ~OP_FULL_RESET; | 180 | priv->op_flags &= ~OP_FULL_RESET; |
130 | err: | 181 | err: |
182 | ath9k_htc_ps_restore(priv); | ||
131 | return ret; | 183 | return ret; |
132 | } | 184 | } |
133 | 185 | ||
@@ -412,32 +464,31 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv, | |||
412 | if (tid > ATH9K_HTC_MAX_TID) | 464 | if (tid > ATH9K_HTC_MAX_TID) |
413 | return -EINVAL; | 465 | return -EINVAL; |
414 | 466 | ||
467 | memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); | ||
468 | |||
415 | rcu_read_lock(); | 469 | rcu_read_lock(); |
470 | |||
471 | /* Check if we are able to retrieve the station */ | ||
416 | sta = ieee80211_find_sta(vif, sta_addr); | 472 | sta = ieee80211_find_sta(vif, sta_addr); |
417 | if (sta) { | 473 | if (!sta) { |
418 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
419 | } else { | ||
420 | rcu_read_unlock(); | 474 | rcu_read_unlock(); |
421 | return -EINVAL; | 475 | return -EINVAL; |
422 | } | 476 | } |
423 | 477 | ||
424 | if (!ista) { | 478 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
425 | rcu_read_unlock(); | ||
426 | return -EINVAL; | ||
427 | } | ||
428 | 479 | ||
429 | memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); | 480 | if (oper) |
481 | ista->tid_state[tid] = AGGR_START; | ||
482 | else | ||
483 | ista->tid_state[tid] = AGGR_STOP; | ||
430 | 484 | ||
431 | aggr.sta_index = ista->index; | 485 | aggr.sta_index = ista->index; |
486 | |||
432 | rcu_read_unlock(); | 487 | rcu_read_unlock(); |
488 | |||
433 | aggr.tidno = tid; | 489 | aggr.tidno = tid; |
434 | aggr.aggr_enable = oper; | 490 | aggr.aggr_enable = oper; |
435 | 491 | ||
436 | if (oper) | ||
437 | ista->tid_state[tid] = AGGR_START; | ||
438 | else | ||
439 | ista->tid_state[tid] = AGGR_STOP; | ||
440 | |||
441 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); | 492 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); |
442 | if (ret) | 493 | if (ret) |
443 | ath_print(common, ATH_DBG_CONFIG, | 494 | ath_print(common, ATH_DBG_CONFIG, |
@@ -694,6 +745,10 @@ void ath9k_ani_work(struct work_struct *work) | |||
694 | 745 | ||
695 | short_cal_interval = ATH_STA_SHORT_CALINTERVAL; | 746 | short_cal_interval = ATH_STA_SHORT_CALINTERVAL; |
696 | 747 | ||
748 | /* Only calibrate if awake */ | ||
749 | if (ah->power_mode != ATH9K_PM_AWAKE) | ||
750 | goto set_timer; | ||
751 | |||
697 | /* Long calibration runs independently of short calibration. */ | 752 | /* Long calibration runs independently of short calibration. */ |
698 | if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { | 753 | if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { |
699 | longcal = true; | 754 | longcal = true; |
@@ -728,6 +783,9 @@ void ath9k_ani_work(struct work_struct *work) | |||
728 | 783 | ||
729 | /* Skip all processing if there's nothing to do. */ | 784 | /* Skip all processing if there's nothing to do. */ |
730 | if (longcal || shortcal || aniflag) { | 785 | if (longcal || shortcal || aniflag) { |
786 | |||
787 | ath9k_htc_ps_wakeup(priv); | ||
788 | |||
731 | /* Call ANI routine if necessary */ | 789 | /* Call ANI routine if necessary */ |
732 | if (aniflag) | 790 | if (aniflag) |
733 | ath9k_hw_ani_monitor(ah, ah->curchan); | 791 | ath9k_hw_ani_monitor(ah, ah->curchan); |
@@ -749,8 +807,11 @@ void ath9k_ani_work(struct work_struct *work) | |||
749 | ah->curchan->channelFlags, | 807 | ah->curchan->channelFlags, |
750 | common->ani.noise_floor); | 808 | common->ani.noise_floor); |
751 | } | 809 | } |
810 | |||
811 | ath9k_htc_ps_restore(priv); | ||
752 | } | 812 | } |
753 | 813 | ||
814 | set_timer: | ||
754 | /* | 815 | /* |
755 | * Set timer interval based on previous results. | 816 | * Set timer interval based on previous results. |
756 | * The interval must be the shortest necessary to satisfy ANI, | 817 | * The interval must be the shortest necessary to satisfy ANI, |
@@ -995,7 +1056,7 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
995 | { | 1056 | { |
996 | struct ieee80211_hdr *hdr; | 1057 | struct ieee80211_hdr *hdr; |
997 | struct ath9k_htc_priv *priv = hw->priv; | 1058 | struct ath9k_htc_priv *priv = hw->priv; |
998 | int padpos, padsize; | 1059 | int padpos, padsize, ret; |
999 | 1060 | ||
1000 | hdr = (struct ieee80211_hdr *) skb->data; | 1061 | hdr = (struct ieee80211_hdr *) skb->data; |
1001 | 1062 | ||
@@ -1009,8 +1070,19 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1009 | memmove(skb->data, skb->data + padsize, padpos); | 1070 | memmove(skb->data, skb->data + padsize, padpos); |
1010 | } | 1071 | } |
1011 | 1072 | ||
1012 | if (ath9k_htc_tx_start(priv, skb) != 0) { | 1073 | ret = ath9k_htc_tx_start(priv, skb); |
1013 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed"); | 1074 | if (ret != 0) { |
1075 | if (ret == -ENOMEM) { | ||
1076 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1077 | "Stopping TX queues\n"); | ||
1078 | ieee80211_stop_queues(hw); | ||
1079 | spin_lock_bh(&priv->tx_lock); | ||
1080 | priv->tx_queues_stop = true; | ||
1081 | spin_unlock_bh(&priv->tx_lock); | ||
1082 | } else { | ||
1083 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1084 | "Tx failed"); | ||
1085 | } | ||
1014 | goto fail_tx; | 1086 | goto fail_tx; |
1015 | } | 1087 | } |
1016 | 1088 | ||
@@ -1075,6 +1147,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1075 | priv->op_flags &= ~OP_INVALID; | 1147 | priv->op_flags &= ~OP_INVALID; |
1076 | htc_start(priv->htc); | 1148 | htc_start(priv->htc); |
1077 | 1149 | ||
1150 | spin_lock_bh(&priv->tx_lock); | ||
1151 | priv->tx_queues_stop = false; | ||
1152 | spin_unlock_bh(&priv->tx_lock); | ||
1153 | |||
1154 | ieee80211_wake_queues(hw); | ||
1155 | |||
1078 | mutex_unlock: | 1156 | mutex_unlock: |
1079 | mutex_unlock(&priv->mutex); | 1157 | mutex_unlock(&priv->mutex); |
1080 | return ret; | 1158 | return ret; |
@@ -1096,6 +1174,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1096 | return; | 1174 | return; |
1097 | } | 1175 | } |
1098 | 1176 | ||
1177 | ath9k_htc_ps_wakeup(priv); | ||
1099 | htc_stop(priv->htc); | 1178 | htc_stop(priv->htc); |
1100 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 1179 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
1101 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 1180 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
@@ -1103,8 +1182,10 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1103 | ath9k_hw_phy_disable(ah); | 1182 | ath9k_hw_phy_disable(ah); |
1104 | ath9k_hw_disable(ah); | 1183 | ath9k_hw_disable(ah); |
1105 | ath9k_hw_configpcipowersave(ah, 1, 1); | 1184 | ath9k_hw_configpcipowersave(ah, 1, 1); |
1106 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | 1185 | ath9k_htc_ps_restore(priv); |
1186 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | ||
1107 | 1187 | ||
1188 | cancel_work_sync(&priv->ps_work); | ||
1108 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1189 | cancel_delayed_work_sync(&priv->ath9k_ani_work); |
1109 | cancel_delayed_work_sync(&priv->ath9k_aggr_work); | 1190 | cancel_delayed_work_sync(&priv->ath9k_aggr_work); |
1110 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | 1191 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); |
@@ -1145,6 +1226,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1145 | goto out; | 1226 | goto out; |
1146 | } | 1227 | } |
1147 | 1228 | ||
1229 | ath9k_htc_ps_wakeup(priv); | ||
1148 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | 1230 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
1149 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); | 1231 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); |
1150 | 1232 | ||
@@ -1191,6 +1273,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1191 | 1273 | ||
1192 | priv->vif = vif; | 1274 | priv->vif = vif; |
1193 | out: | 1275 | out: |
1276 | ath9k_htc_ps_restore(priv); | ||
1194 | mutex_unlock(&priv->mutex); | 1277 | mutex_unlock(&priv->mutex); |
1195 | return ret; | 1278 | return ret; |
1196 | } | 1279 | } |
@@ -1259,6 +1342,16 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1259 | } | 1342 | } |
1260 | 1343 | ||
1261 | } | 1344 | } |
1345 | if (changed & IEEE80211_CONF_CHANGE_PS) { | ||
1346 | if (conf->flags & IEEE80211_CONF_PS) { | ||
1347 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); | ||
1348 | priv->ps_enabled = true; | ||
1349 | } else { | ||
1350 | priv->ps_enabled = false; | ||
1351 | cancel_work_sync(&priv->ps_work); | ||
1352 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | ||
1353 | } | ||
1354 | } | ||
1262 | 1355 | ||
1263 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | 1356 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { |
1264 | if (conf->flags & IEEE80211_CONF_MONITOR) { | 1357 | if (conf->flags & IEEE80211_CONF_MONITOR) { |
@@ -1295,16 +1388,18 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, | |||
1295 | 1388 | ||
1296 | mutex_lock(&priv->mutex); | 1389 | mutex_lock(&priv->mutex); |
1297 | 1390 | ||
1391 | ath9k_htc_ps_wakeup(priv); | ||
1298 | changed_flags &= SUPPORTED_FILTERS; | 1392 | changed_flags &= SUPPORTED_FILTERS; |
1299 | *total_flags &= SUPPORTED_FILTERS; | 1393 | *total_flags &= SUPPORTED_FILTERS; |
1300 | 1394 | ||
1301 | priv->rxfilter = *total_flags; | 1395 | priv->rxfilter = *total_flags; |
1302 | rfilt = ath9k_cmn_calcrxfilter(hw, priv->ah, priv->rxfilter); | 1396 | rfilt = ath9k_htc_calcrxfilter(priv); |
1303 | ath9k_hw_setrxfilter(priv->ah, rfilt); | 1397 | ath9k_hw_setrxfilter(priv->ah, rfilt); |
1304 | 1398 | ||
1305 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, | 1399 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, |
1306 | "Set HW RX filter: 0x%x\n", rfilt); | 1400 | "Set HW RX filter: 0x%x\n", rfilt); |
1307 | 1401 | ||
1402 | ath9k_htc_ps_restore(priv); | ||
1308 | mutex_unlock(&priv->mutex); | 1403 | mutex_unlock(&priv->mutex); |
1309 | } | 1404 | } |
1310 | 1405 | ||
@@ -1382,6 +1477,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1382 | 1477 | ||
1383 | mutex_lock(&priv->mutex); | 1478 | mutex_lock(&priv->mutex); |
1384 | ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); | 1479 | ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); |
1480 | ath9k_htc_ps_wakeup(priv); | ||
1385 | 1481 | ||
1386 | switch (cmd) { | 1482 | switch (cmd) { |
1387 | case SET_KEY: | 1483 | case SET_KEY: |
@@ -1404,6 +1500,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1404 | ret = -EINVAL; | 1500 | ret = -EINVAL; |
1405 | } | 1501 | } |
1406 | 1502 | ||
1503 | ath9k_htc_ps_restore(priv); | ||
1407 | mutex_unlock(&priv->mutex); | 1504 | mutex_unlock(&priv->mutex); |
1408 | 1505 | ||
1409 | return ret; | 1506 | return ret; |
@@ -1419,6 +1516,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1419 | struct ath_common *common = ath9k_hw_common(ah); | 1516 | struct ath_common *common = ath9k_hw_common(ah); |
1420 | 1517 | ||
1421 | mutex_lock(&priv->mutex); | 1518 | mutex_lock(&priv->mutex); |
1519 | ath9k_htc_ps_wakeup(priv); | ||
1422 | 1520 | ||
1423 | if (changed & BSS_CHANGED_ASSOC) { | 1521 | if (changed & BSS_CHANGED_ASSOC) { |
1424 | common->curaid = bss_conf->assoc ? | 1522 | common->curaid = bss_conf->assoc ? |
@@ -1431,6 +1529,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1431 | ath_start_ani(priv); | 1529 | ath_start_ani(priv); |
1432 | } else { | 1530 | } else { |
1433 | priv->op_flags &= ~OP_ASSOCIATED; | 1531 | priv->op_flags &= ~OP_ASSOCIATED; |
1532 | cancel_work_sync(&priv->ps_work); | ||
1434 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1533 | cancel_delayed_work_sync(&priv->ath9k_ani_work); |
1435 | } | 1534 | } |
1436 | } | 1535 | } |
@@ -1450,7 +1549,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1450 | ((changed & BSS_CHANGED_BEACON_ENABLED) && | 1549 | ((changed & BSS_CHANGED_BEACON_ENABLED) && |
1451 | bss_conf->enable_beacon)) { | 1550 | bss_conf->enable_beacon)) { |
1452 | priv->op_flags |= OP_ENABLE_BEACON; | 1551 | priv->op_flags |= OP_ENABLE_BEACON; |
1453 | ath9k_htc_beacon_config(priv, vif, bss_conf); | 1552 | ath9k_htc_beacon_config(priv, vif); |
1454 | } | 1553 | } |
1455 | 1554 | ||
1456 | if (changed & BSS_CHANGED_BEACON) | 1555 | if (changed & BSS_CHANGED_BEACON) |
@@ -1459,7 +1558,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1459 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | 1558 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && |
1460 | !bss_conf->enable_beacon) { | 1559 | !bss_conf->enable_beacon) { |
1461 | priv->op_flags &= ~OP_ENABLE_BEACON; | 1560 | priv->op_flags &= ~OP_ENABLE_BEACON; |
1462 | ath9k_htc_beacon_config(priv, vif, bss_conf); | 1561 | ath9k_htc_beacon_config(priv, vif); |
1463 | } | 1562 | } |
1464 | 1563 | ||
1465 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 1564 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
@@ -1490,6 +1589,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1490 | ath9k_hw_init_global_settings(ah); | 1589 | ath9k_hw_init_global_settings(ah); |
1491 | } | 1590 | } |
1492 | 1591 | ||
1592 | ath9k_htc_ps_restore(priv); | ||
1493 | mutex_unlock(&priv->mutex); | 1593 | mutex_unlock(&priv->mutex); |
1494 | } | 1594 | } |
1495 | 1595 | ||
@@ -1518,9 +1618,11 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw) | |||
1518 | { | 1618 | { |
1519 | struct ath9k_htc_priv *priv = hw->priv; | 1619 | struct ath9k_htc_priv *priv = hw->priv; |
1520 | 1620 | ||
1621 | ath9k_htc_ps_wakeup(priv); | ||
1521 | mutex_lock(&priv->mutex); | 1622 | mutex_lock(&priv->mutex); |
1522 | ath9k_hw_reset_tsf(priv->ah); | 1623 | ath9k_hw_reset_tsf(priv->ah); |
1523 | mutex_unlock(&priv->mutex); | 1624 | mutex_unlock(&priv->mutex); |
1625 | ath9k_htc_ps_restore(priv); | ||
1524 | } | 1626 | } |
1525 | 1627 | ||
1526 | static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | 1628 | static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, |
@@ -1569,6 +1671,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | |||
1569 | spin_lock_bh(&priv->beacon_lock); | 1671 | spin_lock_bh(&priv->beacon_lock); |
1570 | priv->op_flags |= OP_SCANNING; | 1672 | priv->op_flags |= OP_SCANNING; |
1571 | spin_unlock_bh(&priv->beacon_lock); | 1673 | spin_unlock_bh(&priv->beacon_lock); |
1674 | cancel_work_sync(&priv->ps_work); | ||
1572 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1675 | cancel_delayed_work_sync(&priv->ath9k_ani_work); |
1573 | mutex_unlock(&priv->mutex); | 1676 | mutex_unlock(&priv->mutex); |
1574 | } | 1677 | } |
@@ -1577,13 +1680,17 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) | |||
1577 | { | 1680 | { |
1578 | struct ath9k_htc_priv *priv = hw->priv; | 1681 | struct ath9k_htc_priv *priv = hw->priv; |
1579 | 1682 | ||
1683 | ath9k_htc_ps_wakeup(priv); | ||
1580 | mutex_lock(&priv->mutex); | 1684 | mutex_lock(&priv->mutex); |
1581 | spin_lock_bh(&priv->beacon_lock); | 1685 | spin_lock_bh(&priv->beacon_lock); |
1582 | priv->op_flags &= ~OP_SCANNING; | 1686 | priv->op_flags &= ~OP_SCANNING; |
1583 | spin_unlock_bh(&priv->beacon_lock); | 1687 | spin_unlock_bh(&priv->beacon_lock); |
1584 | priv->op_flags |= OP_FULL_RESET; | 1688 | priv->op_flags |= OP_FULL_RESET; |
1689 | if (priv->op_flags & OP_ASSOCIATED) | ||
1690 | ath9k_htc_beacon_config(priv, NULL); | ||
1585 | ath_start_ani(priv); | 1691 | ath_start_ani(priv); |
1586 | mutex_unlock(&priv->mutex); | 1692 | mutex_unlock(&priv->mutex); |
1693 | ath9k_htc_ps_restore(priv); | ||
1587 | } | 1694 | } |
1588 | 1695 | ||
1589 | static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 1696 | static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index ac66cf0b2d53..0a7cb30af5b4 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -188,10 +188,20 @@ void ath9k_tx_tasklet(unsigned long data) | |||
188 | hdr = (struct ieee80211_hdr *) skb->data; | 188 | hdr = (struct ieee80211_hdr *) skb->data; |
189 | fc = hdr->frame_control; | 189 | fc = hdr->frame_control; |
190 | tx_info = IEEE80211_SKB_CB(skb); | 190 | tx_info = IEEE80211_SKB_CB(skb); |
191 | sta = tx_info->control.sta; | 191 | |
192 | memset(&tx_info->status, 0, sizeof(tx_info->status)); | ||
192 | 193 | ||
193 | rcu_read_lock(); | 194 | rcu_read_lock(); |
194 | 195 | ||
196 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | ||
197 | if (!sta) { | ||
198 | rcu_read_unlock(); | ||
199 | ieee80211_tx_status(priv->hw, skb); | ||
200 | continue; | ||
201 | } | ||
202 | |||
203 | /* Check if we need to start aggregation */ | ||
204 | |||
195 | if (sta && conf_is_ht(&priv->hw->conf) && | 205 | if (sta && conf_is_ht(&priv->hw->conf) && |
196 | (priv->op_flags & OP_TXAGGR) | 206 | (priv->op_flags & OP_TXAGGR) |
197 | && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | 207 | && !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { |
@@ -213,9 +223,21 @@ void ath9k_tx_tasklet(unsigned long data) | |||
213 | 223 | ||
214 | rcu_read_unlock(); | 224 | rcu_read_unlock(); |
215 | 225 | ||
216 | memset(&tx_info->status, 0, sizeof(tx_info->status)); | 226 | /* Send status to mac80211 */ |
217 | ieee80211_tx_status(priv->hw, skb); | 227 | ieee80211_tx_status(priv->hw, skb); |
218 | } | 228 | } |
229 | |||
230 | /* Wake TX queues if needed */ | ||
231 | spin_lock_bh(&priv->tx_lock); | ||
232 | if (priv->tx_queues_stop) { | ||
233 | priv->tx_queues_stop = false; | ||
234 | spin_unlock_bh(&priv->tx_lock); | ||
235 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
236 | "Waking up TX queues\n"); | ||
237 | ieee80211_wake_queues(priv->hw); | ||
238 | return; | ||
239 | } | ||
240 | spin_unlock_bh(&priv->tx_lock); | ||
219 | } | 241 | } |
220 | 242 | ||
221 | void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, | 243 | void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, |
@@ -290,10 +312,84 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, | |||
290 | /* RX */ | 312 | /* RX */ |
291 | /******/ | 313 | /******/ |
292 | 314 | ||
315 | /* | ||
316 | * Calculate the RX filter to be set in the HW. | ||
317 | */ | ||
318 | u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) | ||
319 | { | ||
320 | #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) | ||
321 | |||
322 | struct ath_hw *ah = priv->ah; | ||
323 | u32 rfilt; | ||
324 | |||
325 | rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE) | ||
326 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | ||
327 | | ATH9K_RX_FILTER_MCAST; | ||
328 | |||
329 | /* If not a STA, enable processing of Probe Requests */ | ||
330 | if (ah->opmode != NL80211_IFTYPE_STATION) | ||
331 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | ||
332 | |||
333 | /* | ||
334 | * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station | ||
335 | * mode interface or when in monitor mode. AP mode does not need this | ||
336 | * since it receives all in-BSS frames anyway. | ||
337 | */ | ||
338 | if (((ah->opmode != NL80211_IFTYPE_AP) && | ||
339 | (priv->rxfilter & FIF_PROMISC_IN_BSS)) || | ||
340 | (ah->opmode == NL80211_IFTYPE_MONITOR)) | ||
341 | rfilt |= ATH9K_RX_FILTER_PROM; | ||
342 | |||
343 | if (priv->rxfilter & FIF_CONTROL) | ||
344 | rfilt |= ATH9K_RX_FILTER_CONTROL; | ||
345 | |||
346 | if ((ah->opmode == NL80211_IFTYPE_STATION) && | ||
347 | !(priv->rxfilter & FIF_BCN_PRBRESP_PROMISC)) | ||
348 | rfilt |= ATH9K_RX_FILTER_MYBEACON; | ||
349 | else | ||
350 | rfilt |= ATH9K_RX_FILTER_BEACON; | ||
351 | |||
352 | if (conf_is_ht(&priv->hw->conf)) | ||
353 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | ||
354 | |||
355 | return rfilt; | ||
356 | |||
357 | #undef RX_FILTER_PRESERVE | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * Recv initialization for opmode change. | ||
362 | */ | ||
363 | static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) | ||
364 | { | ||
365 | struct ath_hw *ah = priv->ah; | ||
366 | struct ath_common *common = ath9k_hw_common(ah); | ||
367 | |||
368 | u32 rfilt, mfilt[2]; | ||
369 | |||
370 | /* configure rx filter */ | ||
371 | rfilt = ath9k_htc_calcrxfilter(priv); | ||
372 | ath9k_hw_setrxfilter(ah, rfilt); | ||
373 | |||
374 | /* configure bssid mask */ | ||
375 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | ||
376 | ath_hw_setbssidmask(common); | ||
377 | |||
378 | /* configure operational mode */ | ||
379 | ath9k_hw_setopmode(ah); | ||
380 | |||
381 | /* Handle any link-level address change. */ | ||
382 | ath9k_hw_setmac(ah, common->macaddr); | ||
383 | |||
384 | /* calculate and install multicast filter */ | ||
385 | mfilt[0] = mfilt[1] = ~0; | ||
386 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | ||
387 | } | ||
388 | |||
293 | void ath9k_host_rx_init(struct ath9k_htc_priv *priv) | 389 | void ath9k_host_rx_init(struct ath9k_htc_priv *priv) |
294 | { | 390 | { |
295 | ath9k_hw_rxena(priv->ah); | 391 | ath9k_hw_rxena(priv->ah); |
296 | ath9k_cmn_opmode_init(priv->hw, priv->ah, priv->rxfilter); | 392 | ath9k_htc_opmode_init(priv); |
297 | ath9k_hw_startpcureceive(priv->ah); | 393 | ath9k_hw_startpcureceive(priv->ah); |
298 | priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; | 394 | priv->rx.last_rssi = ATH_RSSI_DUMMY_MARKER; |
299 | } | 395 | } |
@@ -354,7 +450,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
354 | padpos = ath9k_cmn_padpos(fc); | 450 | padpos = ath9k_cmn_padpos(fc); |
355 | 451 | ||
356 | padsize = padpos & 3; | 452 | padsize = padpos & 3; |
357 | if (padsize && skb->len >= padpos+padsize) { | 453 | if (padsize && skb->len >= padpos+padsize+FCS_LEN) { |
358 | memmove(skb->data + padsize, skb->data, padpos); | 454 | memmove(skb->data + padsize, skb->data, padpos); |
359 | skb_pull(skb, padsize); | 455 | skb_pull(skb, padsize); |
360 | } | 456 | } |
@@ -457,7 +553,7 @@ void ath9k_rx_tasklet(unsigned long data) | |||
457 | struct ieee80211_rx_status rx_status; | 553 | struct ieee80211_rx_status rx_status; |
458 | struct sk_buff *skb; | 554 | struct sk_buff *skb; |
459 | unsigned long flags; | 555 | unsigned long flags; |
460 | 556 | struct ieee80211_hdr *hdr; | |
461 | 557 | ||
462 | do { | 558 | do { |
463 | spin_lock_irqsave(&priv->rx.rxbuflock, flags); | 559 | spin_lock_irqsave(&priv->rx.rxbuflock, flags); |
@@ -484,6 +580,11 @@ void ath9k_rx_tasklet(unsigned long data) | |||
484 | memcpy(IEEE80211_SKB_RXCB(rxbuf->skb), &rx_status, | 580 | memcpy(IEEE80211_SKB_RXCB(rxbuf->skb), &rx_status, |
485 | sizeof(struct ieee80211_rx_status)); | 581 | sizeof(struct ieee80211_rx_status)); |
486 | skb = rxbuf->skb; | 582 | skb = rxbuf->skb; |
583 | hdr = (struct ieee80211_hdr *) skb->data; | ||
584 | |||
585 | if (ieee80211_is_beacon(hdr->frame_control) && priv->ps_enabled) | ||
586 | ieee80211_queue_work(priv->hw, &priv->ps_work); | ||
587 | |||
487 | spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); | 588 | spin_unlock_irqrestore(&priv->rx.rxbuflock, flags); |
488 | 589 | ||
489 | ieee80211_rx(priv->hw, skb); | 590 | ieee80211_rx(priv->hw, skb); |
@@ -550,7 +651,6 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, | |||
550 | spin_lock(&priv->rx.rxbuflock); | 651 | spin_lock(&priv->rx.rxbuflock); |
551 | memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); | 652 | memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); |
552 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); | 653 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); |
553 | skb->len = rxstatus->rs_datalen; | ||
554 | rxbuf->skb = skb; | 654 | rxbuf->skb = skb; |
555 | rxbuf->in_process = true; | 655 | rxbuf->in_process = true; |
556 | spin_unlock(&priv->rx.rxbuflock); | 656 | spin_unlock(&priv->rx.rxbuflock); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 9a48999d0979..587d98ed0989 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -146,7 +146,7 @@ static int htc_config_pipe_credits(struct htc_target *target) | |||
146 | struct htc_config_pipe_msg *cp_msg; | 146 | struct htc_config_pipe_msg *cp_msg; |
147 | int ret, time_left; | 147 | int ret, time_left; |
148 | 148 | ||
149 | skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); | 149 | skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC); |
150 | if (!skb) { | 150 | if (!skb) { |
151 | dev_err(target->dev, "failed to allocate send buffer\n"); | 151 | dev_err(target->dev, "failed to allocate send buffer\n"); |
152 | return -ENOMEM; | 152 | return -ENOMEM; |
@@ -174,7 +174,7 @@ static int htc_config_pipe_credits(struct htc_target *target) | |||
174 | 174 | ||
175 | return 0; | 175 | return 0; |
176 | err: | 176 | err: |
177 | dev_kfree_skb(skb); | 177 | kfree_skb(skb); |
178 | return -EINVAL; | 178 | return -EINVAL; |
179 | } | 179 | } |
180 | 180 | ||
@@ -184,7 +184,7 @@ static int htc_setup_complete(struct htc_target *target) | |||
184 | struct htc_comp_msg *comp_msg; | 184 | struct htc_comp_msg *comp_msg; |
185 | int ret = 0, time_left; | 185 | int ret = 0, time_left; |
186 | 186 | ||
187 | skb = dev_alloc_skb(50 + sizeof(struct htc_frame_hdr)); | 187 | skb = alloc_skb(50 + sizeof(struct htc_frame_hdr), GFP_ATOMIC); |
188 | if (!skb) { | 188 | if (!skb) { |
189 | dev_err(target->dev, "failed to allocate send buffer\n"); | 189 | dev_err(target->dev, "failed to allocate send buffer\n"); |
190 | return -ENOMEM; | 190 | return -ENOMEM; |
@@ -210,7 +210,7 @@ static int htc_setup_complete(struct htc_target *target) | |||
210 | return 0; | 210 | return 0; |
211 | 211 | ||
212 | err: | 212 | err: |
213 | dev_kfree_skb(skb); | 213 | kfree_skb(skb); |
214 | return -EINVAL; | 214 | return -EINVAL; |
215 | } | 215 | } |
216 | 216 | ||
@@ -250,8 +250,8 @@ int htc_connect_service(struct htc_target *target, | |||
250 | endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id); | 250 | endpoint->dl_pipeid = service_to_dlpipe(service_connreq->service_id); |
251 | endpoint->ep_callbacks = service_connreq->ep_callbacks; | 251 | endpoint->ep_callbacks = service_connreq->ep_callbacks; |
252 | 252 | ||
253 | skb = dev_alloc_skb(sizeof(struct htc_conn_svc_msg) + | 253 | skb = alloc_skb(sizeof(struct htc_conn_svc_msg) + |
254 | sizeof(struct htc_frame_hdr)); | 254 | sizeof(struct htc_frame_hdr), GFP_ATOMIC); |
255 | if (!skb) { | 255 | if (!skb) { |
256 | dev_err(target->dev, "Failed to allocate buf to send" | 256 | dev_err(target->dev, "Failed to allocate buf to send" |
257 | "service connect req\n"); | 257 | "service connect req\n"); |
@@ -282,7 +282,7 @@ int htc_connect_service(struct htc_target *target, | |||
282 | *conn_rsp_epid = target->conn_rsp_epid; | 282 | *conn_rsp_epid = target->conn_rsp_epid; |
283 | return 0; | 283 | return 0; |
284 | err: | 284 | err: |
285 | dev_kfree_skb(skb); | 285 | kfree_skb(skb); |
286 | return ret; | 286 | return ret; |
287 | } | 287 | } |
288 | 288 | ||
@@ -321,16 +321,18 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, | |||
321 | struct sk_buff *skb, bool txok) | 321 | struct sk_buff *skb, bool txok) |
322 | { | 322 | { |
323 | struct htc_endpoint *endpoint; | 323 | struct htc_endpoint *endpoint; |
324 | struct htc_frame_hdr *htc_hdr; | 324 | struct htc_frame_hdr *htc_hdr = NULL; |
325 | 325 | ||
326 | if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) { | 326 | if (htc_handle->htc_flags & HTC_OP_CONFIG_PIPE_CREDITS) { |
327 | complete(&htc_handle->cmd_wait); | 327 | complete(&htc_handle->cmd_wait); |
328 | htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS; | 328 | htc_handle->htc_flags &= ~HTC_OP_CONFIG_PIPE_CREDITS; |
329 | goto ret; | ||
329 | } | 330 | } |
330 | 331 | ||
331 | if (htc_handle->htc_flags & HTC_OP_START_WAIT) { | 332 | if (htc_handle->htc_flags & HTC_OP_START_WAIT) { |
332 | complete(&htc_handle->cmd_wait); | 333 | complete(&htc_handle->cmd_wait); |
333 | htc_handle->htc_flags &= ~HTC_OP_START_WAIT; | 334 | htc_handle->htc_flags &= ~HTC_OP_START_WAIT; |
335 | goto ret; | ||
334 | } | 336 | } |
335 | 337 | ||
336 | if (skb) { | 338 | if (skb) { |
@@ -343,6 +345,14 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, | |||
343 | htc_hdr->endpoint_id, txok); | 345 | htc_hdr->endpoint_id, txok); |
344 | } | 346 | } |
345 | } | 347 | } |
348 | |||
349 | return; | ||
350 | ret: | ||
351 | /* HTC-generated packets are freed here. */ | ||
352 | if (htc_hdr && htc_hdr->endpoint_id != ENDPOINT0) | ||
353 | dev_kfree_skb_any(skb); | ||
354 | else | ||
355 | kfree_skb(skb); | ||
346 | } | 356 | } |
347 | 357 | ||
348 | /* | 358 | /* |
@@ -367,7 +377,10 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, | |||
367 | epid = htc_hdr->endpoint_id; | 377 | epid = htc_hdr->endpoint_id; |
368 | 378 | ||
369 | if (epid >= ENDPOINT_MAX) { | 379 | if (epid >= ENDPOINT_MAX) { |
370 | dev_kfree_skb_any(skb); | 380 | if (pipe_id != USB_REG_IN_PIPE) |
381 | dev_kfree_skb_any(skb); | ||
382 | else | ||
383 | kfree_skb(skb); | ||
371 | return; | 384 | return; |
372 | } | 385 | } |
373 | 386 | ||
@@ -377,7 +390,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, | |||
377 | if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { | 390 | if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) { |
378 | if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000) | 391 | if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000) |
379 | /* Move past the Watchdog pattern */ | 392 | /* Move past the Watchdog pattern */ |
380 | htc_hdr = (struct htc_frame_hdr *) skb->data + 4; | 393 | htc_hdr = (struct htc_frame_hdr *)(skb->data + 4); |
381 | } | 394 | } |
382 | 395 | ||
383 | /* Get the message ID */ | 396 | /* Get the message ID */ |
@@ -396,7 +409,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle, | |||
396 | break; | 409 | break; |
397 | } | 410 | } |
398 | 411 | ||
399 | dev_kfree_skb_any(skb); | 412 | kfree_skb(skb); |
400 | 413 | ||
401 | } else { | 414 | } else { |
402 | if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) | 415 | if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7fdaea3a1629..af730c7d50e6 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -28,9 +28,6 @@ | |||
28 | 28 | ||
29 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); | 29 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); |
30 | static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan); | 30 | static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan); |
31 | static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, | ||
32 | struct ar5416_eeprom_def *pEepData, | ||
33 | u32 reg, u32 value); | ||
34 | 31 | ||
35 | MODULE_AUTHOR("Atheros Communications"); | 32 | MODULE_AUTHOR("Atheros Communications"); |
36 | MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); | 33 | MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); |
@@ -548,7 +545,6 @@ static bool ath9k_hw_devid_supported(u16 devid) | |||
548 | case AR9285_DEVID_PCIE: | 545 | case AR9285_DEVID_PCIE: |
549 | case AR5416_DEVID_AR9287_PCI: | 546 | case AR5416_DEVID_AR9287_PCI: |
550 | case AR5416_DEVID_AR9287_PCIE: | 547 | case AR5416_DEVID_AR9287_PCIE: |
551 | case AR9271_USB: | ||
552 | case AR2427_DEVID_PCIE: | 548 | case AR2427_DEVID_PCIE: |
553 | return true; | 549 | return true; |
554 | default: | 550 | default: |
@@ -817,38 +813,46 @@ static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) | |||
817 | 813 | ||
818 | /* txgain table */ | 814 | /* txgain table */ |
819 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { | 815 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { |
820 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 816 | if (AR_SREV_9285E_20(ah)) { |
821 | ar9285Modes_high_power_tx_gain_9285_1_2, | 817 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
822 | ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6); | 818 | ar9285Modes_XE2_0_high_power, |
819 | ARRAY_SIZE( | ||
820 | ar9285Modes_XE2_0_high_power), 6); | ||
821 | } else { | ||
822 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
823 | ar9285Modes_high_power_tx_gain_9285_1_2, | ||
824 | ARRAY_SIZE( | ||
825 | ar9285Modes_high_power_tx_gain_9285_1_2), 6); | ||
826 | } | ||
823 | } else { | 827 | } else { |
824 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 828 | if (AR_SREV_9285E_20(ah)) { |
825 | ar9285Modes_original_tx_gain_9285_1_2, | 829 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
826 | ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6); | 830 | ar9285Modes_XE2_0_normal_power, |
831 | ARRAY_SIZE( | ||
832 | ar9285Modes_XE2_0_normal_power), 6); | ||
833 | } else { | ||
834 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
835 | ar9285Modes_original_tx_gain_9285_1_2, | ||
836 | ARRAY_SIZE( | ||
837 | ar9285Modes_original_tx_gain_9285_1_2), 6); | ||
838 | } | ||
827 | } | 839 | } |
828 | |||
829 | } | 840 | } |
830 | } | 841 | } |
831 | 842 | ||
832 | static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) | 843 | static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) |
833 | { | 844 | { |
834 | u32 i, j; | 845 | struct base_eep_header *pBase = &(ah->eeprom.def.baseEepHeader); |
835 | 846 | struct ath_common *common = ath9k_hw_common(ah); | |
836 | if (ah->hw_version.devid == AR9280_DEVID_PCI) { | ||
837 | |||
838 | /* EEPROM Fixup */ | ||
839 | for (i = 0; i < ah->iniModes.ia_rows; i++) { | ||
840 | u32 reg = INI_RA(&ah->iniModes, i, 0); | ||
841 | 847 | ||
842 | for (j = 1; j < ah->iniModes.ia_columns; j++) { | 848 | ah->need_an_top2_fixup = (ah->hw_version.devid == AR9280_DEVID_PCI) && |
843 | u32 val = INI_RA(&ah->iniModes, i, j); | 849 | (ah->eep_map != EEP_MAP_4KBITS) && |
850 | ((pBase->version & 0xff) > 0x0a) && | ||
851 | (pBase->pwdclkind == 0); | ||
844 | 852 | ||
845 | INI_RA(&ah->iniModes, i, j) = | 853 | if (ah->need_an_top2_fixup) |
846 | ath9k_hw_ini_fixup(ah, | 854 | ath_print(common, ATH_DBG_EEPROM, |
847 | &ah->eeprom.def, | 855 | "needs fixup for AR_AN_TOP2 register\n"); |
848 | reg, val); | ||
849 | } | ||
850 | } | ||
851 | } | ||
852 | } | 856 | } |
853 | 857 | ||
854 | int ath9k_hw_init(struct ath_hw *ah) | 858 | int ath9k_hw_init(struct ath_hw *ah) |
@@ -856,11 +860,13 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
856 | struct ath_common *common = ath9k_hw_common(ah); | 860 | struct ath_common *common = ath9k_hw_common(ah); |
857 | int r = 0; | 861 | int r = 0; |
858 | 862 | ||
859 | if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { | 863 | if (common->bus_ops->ath_bus_type != ATH_USB) { |
860 | ath_print(common, ATH_DBG_FATAL, | 864 | if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { |
861 | "Unsupported device ID: 0x%0x\n", | 865 | ath_print(common, ATH_DBG_FATAL, |
862 | ah->hw_version.devid); | 866 | "Unsupported device ID: 0x%0x\n", |
863 | return -EOPNOTSUPP; | 867 | ah->hw_version.devid); |
868 | return -EOPNOTSUPP; | ||
869 | } | ||
864 | } | 870 | } |
865 | 871 | ||
866 | ath9k_hw_init_defaults(ah); | 872 | ath9k_hw_init_defaults(ah); |
@@ -1121,23 +1127,23 @@ static void ath9k_hw_init_chain_masks(struct ath_hw *ah) | |||
1121 | static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | 1127 | static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, |
1122 | enum nl80211_iftype opmode) | 1128 | enum nl80211_iftype opmode) |
1123 | { | 1129 | { |
1124 | ah->mask_reg = AR_IMR_TXERR | | 1130 | u32 imr_reg = AR_IMR_TXERR | |
1125 | AR_IMR_TXURN | | 1131 | AR_IMR_TXURN | |
1126 | AR_IMR_RXERR | | 1132 | AR_IMR_RXERR | |
1127 | AR_IMR_RXORN | | 1133 | AR_IMR_RXORN | |
1128 | AR_IMR_BCNMISC; | 1134 | AR_IMR_BCNMISC; |
1129 | 1135 | ||
1130 | if (ah->config.rx_intr_mitigation) | 1136 | if (ah->config.rx_intr_mitigation) |
1131 | ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; | 1137 | imr_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; |
1132 | else | 1138 | else |
1133 | ah->mask_reg |= AR_IMR_RXOK; | 1139 | imr_reg |= AR_IMR_RXOK; |
1134 | 1140 | ||
1135 | ah->mask_reg |= AR_IMR_TXOK; | 1141 | imr_reg |= AR_IMR_TXOK; |
1136 | 1142 | ||
1137 | if (opmode == NL80211_IFTYPE_AP) | 1143 | if (opmode == NL80211_IFTYPE_AP) |
1138 | ah->mask_reg |= AR_IMR_MIB; | 1144 | imr_reg |= AR_IMR_MIB; |
1139 | 1145 | ||
1140 | REG_WRITE(ah, AR_IMR, ah->mask_reg); | 1146 | REG_WRITE(ah, AR_IMR, imr_reg); |
1141 | ah->imrs2_reg |= AR_IMR_S2_GTT; | 1147 | ah->imrs2_reg |= AR_IMR_S2_GTT; |
1142 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | 1148 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); |
1143 | 1149 | ||
@@ -1290,51 +1296,6 @@ static void ath9k_hw_override_ini(struct ath_hw *ah, | |||
1290 | } | 1296 | } |
1291 | } | 1297 | } |
1292 | 1298 | ||
1293 | static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, | ||
1294 | struct ar5416_eeprom_def *pEepData, | ||
1295 | u32 reg, u32 value) | ||
1296 | { | ||
1297 | struct base_eep_header *pBase = &(pEepData->baseEepHeader); | ||
1298 | struct ath_common *common = ath9k_hw_common(ah); | ||
1299 | |||
1300 | switch (ah->hw_version.devid) { | ||
1301 | case AR9280_DEVID_PCI: | ||
1302 | if (reg == 0x7894) { | ||
1303 | ath_print(common, ATH_DBG_EEPROM, | ||
1304 | "ini VAL: %x EEPROM: %x\n", value, | ||
1305 | (pBase->version & 0xff)); | ||
1306 | |||
1307 | if ((pBase->version & 0xff) > 0x0a) { | ||
1308 | ath_print(common, ATH_DBG_EEPROM, | ||
1309 | "PWDCLKIND: %d\n", | ||
1310 | pBase->pwdclkind); | ||
1311 | value &= ~AR_AN_TOP2_PWDCLKIND; | ||
1312 | value |= AR_AN_TOP2_PWDCLKIND & | ||
1313 | (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); | ||
1314 | } else { | ||
1315 | ath_print(common, ATH_DBG_EEPROM, | ||
1316 | "PWDCLKIND Earlier Rev\n"); | ||
1317 | } | ||
1318 | |||
1319 | ath_print(common, ATH_DBG_EEPROM, | ||
1320 | "final ini VAL: %x\n", value); | ||
1321 | } | ||
1322 | break; | ||
1323 | } | ||
1324 | |||
1325 | return value; | ||
1326 | } | ||
1327 | |||
1328 | static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, | ||
1329 | struct ar5416_eeprom_def *pEepData, | ||
1330 | u32 reg, u32 value) | ||
1331 | { | ||
1332 | if (ah->eep_map == EEP_MAP_4KBITS) | ||
1333 | return value; | ||
1334 | else | ||
1335 | return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value); | ||
1336 | } | ||
1337 | |||
1338 | static void ath9k_olc_init(struct ath_hw *ah) | 1299 | static void ath9k_olc_init(struct ath_hw *ah) |
1339 | { | 1300 | { |
1340 | u32 i; | 1301 | u32 i; |
@@ -1440,6 +1401,9 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1440 | u32 reg = INI_RA(&ah->iniModes, i, 0); | 1401 | u32 reg = INI_RA(&ah->iniModes, i, 0); |
1441 | u32 val = INI_RA(&ah->iniModes, i, modesIndex); | 1402 | u32 val = INI_RA(&ah->iniModes, i, modesIndex); |
1442 | 1403 | ||
1404 | if (reg == AR_AN_TOP2 && ah->need_an_top2_fixup) | ||
1405 | val &= ~AR_AN_TOP2_PWDCLKIND; | ||
1406 | |||
1443 | REG_WRITE(ah, reg, val); | 1407 | REG_WRITE(ah, reg, val); |
1444 | 1408 | ||
1445 | if (reg >= 0x7800 && reg < 0x78a0 | 1409 | if (reg >= 0x7800 && reg < 0x78a0 |
@@ -2840,7 +2804,7 @@ EXPORT_SYMBOL(ath9k_hw_getisr); | |||
2840 | 2804 | ||
2841 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | 2805 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) |
2842 | { | 2806 | { |
2843 | u32 omask = ah->mask_reg; | 2807 | enum ath9k_int omask = ah->imask; |
2844 | u32 mask, mask2; | 2808 | u32 mask, mask2; |
2845 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 2809 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
2846 | struct ath_common *common = ath9k_hw_common(ah); | 2810 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -2912,7 +2876,6 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | |||
2912 | AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); | 2876 | AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST); |
2913 | ah->imrs2_reg |= mask2; | 2877 | ah->imrs2_reg |= mask2; |
2914 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | 2878 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); |
2915 | ah->mask_reg = ints; | ||
2916 | 2879 | ||
2917 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | 2880 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { |
2918 | if (ints & ATH9K_INT_TIM_TIMER) | 2881 | if (ints & ATH9K_INT_TIM_TIMER) |
@@ -3231,8 +3194,10 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3231 | pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; | 3194 | pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; |
3232 | } | 3195 | } |
3233 | #endif | 3196 | #endif |
3234 | 3197 | if (AR_SREV_9271(ah)) | |
3235 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; | 3198 | pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP; |
3199 | else | ||
3200 | pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; | ||
3236 | 3201 | ||
3237 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) | 3202 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) |
3238 | pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; | 3203 | pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 6b03e1688b22..f4821cf33b87 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -44,8 +44,6 @@ | |||
44 | 44 | ||
45 | #define AR5416_AR9100_DEVID 0x000b | 45 | #define AR5416_AR9100_DEVID 0x000b |
46 | 46 | ||
47 | #define AR9271_USB 0x9271 | ||
48 | |||
49 | #define AR_SUBVENDOR_ID_NOG 0x0e11 | 47 | #define AR_SUBVENDOR_ID_NOG 0x0e11 |
50 | #define AR_SUBVENDOR_ID_NEW_A 0x7065 | 48 | #define AR_SUBVENDOR_ID_NEW_A 0x7065 |
51 | #define AR5416_MAGIC 0x19641014 | 49 | #define AR5416_MAGIC 0x19641014 |
@@ -461,6 +459,7 @@ struct ath_hw { | |||
461 | 459 | ||
462 | bool sw_mgmt_crypto; | 460 | bool sw_mgmt_crypto; |
463 | bool is_pciexpress; | 461 | bool is_pciexpress; |
462 | bool need_an_top2_fixup; | ||
464 | u16 tx_trig_level; | 463 | u16 tx_trig_level; |
465 | u16 rfsilent; | 464 | u16 rfsilent; |
466 | u32 rfkill_gpio; | 465 | u32 rfkill_gpio; |
@@ -478,7 +477,7 @@ struct ath_hw { | |||
478 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; | 477 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; |
479 | 478 | ||
480 | int16_t curchan_rad_index; | 479 | int16_t curchan_rad_index; |
481 | u32 mask_reg; | 480 | enum ath9k_int imask; |
482 | u32 imrs2_reg; | 481 | u32 imrs2_reg; |
483 | u32 txok_interrupt_mask; | 482 | u32 txok_interrupt_mask; |
484 | u32 txerr_interrupt_mask; | 483 | u32 txerr_interrupt_mask; |
diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h index 177bdeb84ad7..455e9d3b3f13 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/initvals.h | |||
@@ -4184,7 +4184,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4184 | { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, | 4184 | { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, |
4185 | { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, | 4185 | { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, |
4186 | { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, | 4186 | { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, |
4187 | { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, | 4187 | { 0x00009a50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, |
4188 | { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, | 4188 | { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, |
4189 | { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, | 4189 | { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, |
4190 | { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, | 4190 | { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, |
@@ -4198,8 +4198,8 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4198 | { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, | 4198 | { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, |
4199 | { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, | 4199 | { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, |
4200 | { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, | 4200 | { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, |
4201 | { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, | 4201 | { 0x00009a88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, |
4202 | { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 4202 | { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, |
4203 | { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 4203 | { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, |
4204 | { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, | 4204 | { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, |
4205 | { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, | 4205 | { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, |
@@ -4312,7 +4312,7 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4312 | { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, | 4312 | { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, |
4313 | { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, | 4313 | { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, |
4314 | { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, | 4314 | { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, |
4315 | { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, | 4315 | { 0x0000aa50, 0x00000000, 0x00000000, 0x00058224, 0x00058224, 0x00000000 }, |
4316 | { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, | 4316 | { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, |
4317 | { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, | 4317 | { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, |
4318 | { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, | 4318 | { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, |
@@ -4326,8 +4326,8 @@ static const u_int32_t ar9285Modes_9285_1_2[][6] = { | |||
4326 | { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, | 4326 | { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, |
4327 | { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, | 4327 | { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, |
4328 | { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, | 4328 | { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, |
4329 | { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, | 4329 | { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b00, 0x00078b00, 0x00000000 }, |
4330 | { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 4330 | { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, |
4331 | { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, | 4331 | { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, |
4332 | { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, | 4332 | { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, |
4333 | { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, | 4333 | { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, |
@@ -4731,17 +4731,12 @@ static const u_int32_t ar9285Common_9285_1_2[][2] = { | |||
4731 | { 0x00007808, 0x54214514 }, | 4731 | { 0x00007808, 0x54214514 }, |
4732 | { 0x0000780c, 0x02025830 }, | 4732 | { 0x0000780c, 0x02025830 }, |
4733 | { 0x00007810, 0x71c0d388 }, | 4733 | { 0x00007810, 0x71c0d388 }, |
4734 | { 0x00007814, 0x924934a8 }, | ||
4735 | { 0x0000781c, 0x00000000 }, | 4734 | { 0x0000781c, 0x00000000 }, |
4736 | { 0x00007824, 0x00d86fff }, | 4735 | { 0x00007824, 0x00d86fff }, |
4737 | { 0x00007828, 0x26d2491b }, | ||
4738 | { 0x0000782c, 0x6e36d97b }, | 4736 | { 0x0000782c, 0x6e36d97b }, |
4739 | { 0x00007830, 0xedb6d96e }, | ||
4740 | { 0x00007834, 0x71400087 }, | 4737 | { 0x00007834, 0x71400087 }, |
4741 | { 0x0000783c, 0x0001fffe }, | ||
4742 | { 0x00007840, 0xffeb1a20 }, | ||
4743 | { 0x00007844, 0x000c0db6 }, | 4738 | { 0x00007844, 0x000c0db6 }, |
4744 | { 0x00007848, 0x6db61b6f }, | 4739 | { 0x00007848, 0x6db6246f }, |
4745 | { 0x0000784c, 0x6d9b66db }, | 4740 | { 0x0000784c, 0x6d9b66db }, |
4746 | { 0x00007850, 0x6d8c6dba }, | 4741 | { 0x00007850, 0x6d8c6dba }, |
4747 | { 0x00007854, 0x00040000 }, | 4742 | { 0x00007854, 0x00040000 }, |
@@ -4777,7 +4772,12 @@ static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { | |||
4777 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4772 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4778 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4773 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4779 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4774 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4775 | { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, | ||
4776 | { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, | ||
4777 | { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, | ||
4780 | { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, | 4778 | { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, |
4779 | { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, | ||
4780 | { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, | ||
4781 | { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, | 4781 | { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, |
4782 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, | 4782 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, |
4783 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, | 4783 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, |
@@ -4813,7 +4813,12 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { | |||
4813 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4813 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4814 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4814 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4815 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | 4815 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, |
4816 | { 0x00007814, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8, 0x924934a8 }, | ||
4817 | { 0x00007828, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b, 0x26d2491b }, | ||
4818 | { 0x00007830, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e, 0xedb6d96e }, | ||
4816 | { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, | 4819 | { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, |
4820 | { 0x0000783c, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe, 0x0001fffe }, | ||
4821 | { 0x00007840, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20, 0xffeb1a20 }, | ||
4817 | { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, | 4822 | { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, |
4818 | { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, | 4823 | { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, |
4819 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, | 4824 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, |
@@ -4825,6 +4830,86 @@ static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { | |||
4825 | { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, | 4830 | { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, |
4826 | }; | 4831 | }; |
4827 | 4832 | ||
4833 | static const u_int32_t ar9285Modes_XE2_0_normal_power[][6] = { | ||
4834 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
4835 | { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, | ||
4836 | { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, | ||
4837 | { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, | ||
4838 | { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, | ||
4839 | { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, | ||
4840 | { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, | ||
4841 | { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, | ||
4842 | { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, | ||
4843 | { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, | ||
4844 | { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, | ||
4845 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, | ||
4846 | { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, | ||
4847 | { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, | ||
4848 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
4849 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
4850 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4851 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4852 | { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4853 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4854 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4855 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4856 | { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, | ||
4857 | { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, | ||
4858 | { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6dbae }, | ||
4859 | { 0x00007838, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441, 0xdac71441 }, | ||
4860 | { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, | ||
4861 | { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, | ||
4862 | { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, | ||
4863 | { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, | ||
4864 | { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, | ||
4865 | { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, | ||
4866 | { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, | ||
4867 | { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, | ||
4868 | { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, | ||
4869 | { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, | ||
4870 | { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, | ||
4871 | }; | ||
4872 | |||
4873 | static const u_int32_t ar9285Modes_XE2_0_high_power[][6] = { | ||
4874 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
4875 | { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, | ||
4876 | { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, | ||
4877 | { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, | ||
4878 | { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, | ||
4879 | { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, | ||
4880 | { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, | ||
4881 | { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, | ||
4882 | { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, | ||
4883 | { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, | ||
4884 | { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, | ||
4885 | { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, | ||
4886 | { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, | ||
4887 | { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, | ||
4888 | { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, | ||
4889 | { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, | ||
4890 | { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4891 | { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4892 | { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4893 | { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4894 | { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4895 | { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, | ||
4896 | { 0x00007814, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8, 0x92497ca8 }, | ||
4897 | { 0x00007828, 0x4ad2491b, 0x4ad2491b, 0x2ad2491b, 0x4ad2491b, 0x4ad2491b }, | ||
4898 | { 0x00007830, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e, 0xedb6da6e }, | ||
4899 | { 0x00007838, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443, 0xdac71443 }, | ||
4900 | { 0x0000783c, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe, 0x2481f6fe }, | ||
4901 | { 0x00007840, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c, 0xba5f638c }, | ||
4902 | { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, | ||
4903 | { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, | ||
4904 | { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, | ||
4905 | { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, | ||
4906 | { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, | ||
4907 | { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, | ||
4908 | { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, | ||
4909 | { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, | ||
4910 | { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, | ||
4911 | }; | ||
4912 | |||
4828 | static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { | 4913 | static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { |
4829 | {0x00004040, 0x9248fd00 }, | 4914 | {0x00004040, 0x9248fd00 }, |
4830 | {0x00004040, 0x24924924 }, | 4915 | {0x00004040, 0x24924924 }, |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 7af823a1527d..4a2060e5a777 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -105,7 +105,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | |||
105 | if (ah->tx_trig_level >= ah->config.max_txtrig_level) | 105 | if (ah->tx_trig_level >= ah->config.max_txtrig_level) |
106 | return false; | 106 | return false; |
107 | 107 | ||
108 | omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); | 108 | omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); |
109 | 109 | ||
110 | txcfg = REG_READ(ah, AR_TXCFG); | 110 | txcfg = REG_READ(ah, AR_TXCFG); |
111 | curLevel = MS(txcfg, AR_FTRIG); | 111 | curLevel = MS(txcfg, AR_FTRIG); |
@@ -246,79 +246,80 @@ void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) | |||
246 | } | 246 | } |
247 | EXPORT_SYMBOL(ath9k_hw_cleartxdesc); | 247 | EXPORT_SYMBOL(ath9k_hw_cleartxdesc); |
248 | 248 | ||
249 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) | 249 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
250 | struct ath_tx_status *ts) | ||
250 | { | 251 | { |
251 | struct ar5416_desc *ads = AR5416DESC(ds); | 252 | struct ar5416_desc *ads = AR5416DESC(ds); |
252 | 253 | ||
253 | if ((ads->ds_txstatus9 & AR_TxDone) == 0) | 254 | if ((ads->ds_txstatus9 & AR_TxDone) == 0) |
254 | return -EINPROGRESS; | 255 | return -EINPROGRESS; |
255 | 256 | ||
256 | ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); | 257 | ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); |
257 | ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp; | 258 | ts->ts_tstamp = ads->AR_SendTimestamp; |
258 | ds->ds_txstat.ts_status = 0; | 259 | ts->ts_status = 0; |
259 | ds->ds_txstat.ts_flags = 0; | 260 | ts->ts_flags = 0; |
260 | 261 | ||
261 | if (ads->ds_txstatus1 & AR_FrmXmitOK) | 262 | if (ads->ds_txstatus1 & AR_FrmXmitOK) |
262 | ds->ds_txstat.ts_status |= ATH9K_TX_ACKED; | 263 | ts->ts_status |= ATH9K_TX_ACKED; |
263 | if (ads->ds_txstatus1 & AR_ExcessiveRetries) | 264 | if (ads->ds_txstatus1 & AR_ExcessiveRetries) |
264 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; | 265 | ts->ts_status |= ATH9K_TXERR_XRETRY; |
265 | if (ads->ds_txstatus1 & AR_Filtered) | 266 | if (ads->ds_txstatus1 & AR_Filtered) |
266 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; | 267 | ts->ts_status |= ATH9K_TXERR_FILT; |
267 | if (ads->ds_txstatus1 & AR_FIFOUnderrun) { | 268 | if (ads->ds_txstatus1 & AR_FIFOUnderrun) { |
268 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; | 269 | ts->ts_status |= ATH9K_TXERR_FIFO; |
269 | ath9k_hw_updatetxtriglevel(ah, true); | 270 | ath9k_hw_updatetxtriglevel(ah, true); |
270 | } | 271 | } |
271 | if (ads->ds_txstatus9 & AR_TxOpExceeded) | 272 | if (ads->ds_txstatus9 & AR_TxOpExceeded) |
272 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; | 273 | ts->ts_status |= ATH9K_TXERR_XTXOP; |
273 | if (ads->ds_txstatus1 & AR_TxTimerExpired) | 274 | if (ads->ds_txstatus1 & AR_TxTimerExpired) |
274 | ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED; | 275 | ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; |
275 | 276 | ||
276 | if (ads->ds_txstatus1 & AR_DescCfgErr) | 277 | if (ads->ds_txstatus1 & AR_DescCfgErr) |
277 | ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR; | 278 | ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; |
278 | if (ads->ds_txstatus1 & AR_TxDataUnderrun) { | 279 | if (ads->ds_txstatus1 & AR_TxDataUnderrun) { |
279 | ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN; | 280 | ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; |
280 | ath9k_hw_updatetxtriglevel(ah, true); | 281 | ath9k_hw_updatetxtriglevel(ah, true); |
281 | } | 282 | } |
282 | if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { | 283 | if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { |
283 | ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN; | 284 | ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; |
284 | ath9k_hw_updatetxtriglevel(ah, true); | 285 | ath9k_hw_updatetxtriglevel(ah, true); |
285 | } | 286 | } |
286 | if (ads->ds_txstatus0 & AR_TxBaStatus) { | 287 | if (ads->ds_txstatus0 & AR_TxBaStatus) { |
287 | ds->ds_txstat.ts_flags |= ATH9K_TX_BA; | 288 | ts->ts_flags |= ATH9K_TX_BA; |
288 | ds->ds_txstat.ba_low = ads->AR_BaBitmapLow; | 289 | ts->ba_low = ads->AR_BaBitmapLow; |
289 | ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh; | 290 | ts->ba_high = ads->AR_BaBitmapHigh; |
290 | } | 291 | } |
291 | 292 | ||
292 | ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); | 293 | ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); |
293 | switch (ds->ds_txstat.ts_rateindex) { | 294 | switch (ts->ts_rateindex) { |
294 | case 0: | 295 | case 0: |
295 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); | 296 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); |
296 | break; | 297 | break; |
297 | case 1: | 298 | case 1: |
298 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); | 299 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); |
299 | break; | 300 | break; |
300 | case 2: | 301 | case 2: |
301 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); | 302 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); |
302 | break; | 303 | break; |
303 | case 3: | 304 | case 3: |
304 | ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); | 305 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); |
305 | break; | 306 | break; |
306 | } | 307 | } |
307 | 308 | ||
308 | ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); | 309 | ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); |
309 | ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); | 310 | ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); |
310 | ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); | 311 | ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); |
311 | ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); | 312 | ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); |
312 | ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); | 313 | ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); |
313 | ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); | 314 | ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); |
314 | ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); | 315 | ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); |
315 | ds->ds_txstat.evm0 = ads->AR_TxEVM0; | 316 | ts->evm0 = ads->AR_TxEVM0; |
316 | ds->ds_txstat.evm1 = ads->AR_TxEVM1; | 317 | ts->evm1 = ads->AR_TxEVM1; |
317 | ds->ds_txstat.evm2 = ads->AR_TxEVM2; | 318 | ts->evm2 = ads->AR_TxEVM2; |
318 | ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); | 319 | ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); |
319 | ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); | 320 | ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); |
320 | ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); | 321 | ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); |
321 | ds->ds_txstat.ts_antenna = 0; | 322 | ts->ts_antenna = 0; |
322 | 323 | ||
323 | return 0; | 324 | return 0; |
324 | } | 325 | } |
@@ -858,7 +859,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
858 | EXPORT_SYMBOL(ath9k_hw_resettxqueue); | 859 | EXPORT_SYMBOL(ath9k_hw_resettxqueue); |
859 | 860 | ||
860 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | 861 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
861 | u32 pa, struct ath_desc *nds, u64 tsf) | 862 | struct ath_rx_status *rs, u64 tsf) |
862 | { | 863 | { |
863 | struct ar5416_desc ads; | 864 | struct ar5416_desc ads; |
864 | struct ar5416_desc *adsp = AR5416DESC(ds); | 865 | struct ar5416_desc *adsp = AR5416DESC(ds); |
@@ -869,70 +870,70 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
869 | 870 | ||
870 | ads.u.rx = adsp->u.rx; | 871 | ads.u.rx = adsp->u.rx; |
871 | 872 | ||
872 | ds->ds_rxstat.rs_status = 0; | 873 | rs->rs_status = 0; |
873 | ds->ds_rxstat.rs_flags = 0; | 874 | rs->rs_flags = 0; |
874 | 875 | ||
875 | ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; | 876 | rs->rs_datalen = ads.ds_rxstatus1 & AR_DataLen; |
876 | ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; | 877 | rs->rs_tstamp = ads.AR_RcvTimestamp; |
877 | 878 | ||
878 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { | 879 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { |
879 | ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD; | 880 | rs->rs_rssi = ATH9K_RSSI_BAD; |
880 | ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD; | 881 | rs->rs_rssi_ctl0 = ATH9K_RSSI_BAD; |
881 | ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD; | 882 | rs->rs_rssi_ctl1 = ATH9K_RSSI_BAD; |
882 | ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD; | 883 | rs->rs_rssi_ctl2 = ATH9K_RSSI_BAD; |
883 | ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD; | 884 | rs->rs_rssi_ext0 = ATH9K_RSSI_BAD; |
884 | ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD; | 885 | rs->rs_rssi_ext1 = ATH9K_RSSI_BAD; |
885 | ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD; | 886 | rs->rs_rssi_ext2 = ATH9K_RSSI_BAD; |
886 | } else { | 887 | } else { |
887 | ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); | 888 | rs->rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); |
888 | ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, | 889 | rs->rs_rssi_ctl0 = MS(ads.ds_rxstatus0, |
889 | AR_RxRSSIAnt00); | 890 | AR_RxRSSIAnt00); |
890 | ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, | 891 | rs->rs_rssi_ctl1 = MS(ads.ds_rxstatus0, |
891 | AR_RxRSSIAnt01); | 892 | AR_RxRSSIAnt01); |
892 | ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, | 893 | rs->rs_rssi_ctl2 = MS(ads.ds_rxstatus0, |
893 | AR_RxRSSIAnt02); | 894 | AR_RxRSSIAnt02); |
894 | ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, | 895 | rs->rs_rssi_ext0 = MS(ads.ds_rxstatus4, |
895 | AR_RxRSSIAnt10); | 896 | AR_RxRSSIAnt10); |
896 | ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, | 897 | rs->rs_rssi_ext1 = MS(ads.ds_rxstatus4, |
897 | AR_RxRSSIAnt11); | 898 | AR_RxRSSIAnt11); |
898 | ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, | 899 | rs->rs_rssi_ext2 = MS(ads.ds_rxstatus4, |
899 | AR_RxRSSIAnt12); | 900 | AR_RxRSSIAnt12); |
900 | } | 901 | } |
901 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) | 902 | if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) |
902 | ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); | 903 | rs->rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); |
903 | else | 904 | else |
904 | ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID; | 905 | rs->rs_keyix = ATH9K_RXKEYIX_INVALID; |
905 | 906 | ||
906 | ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads)); | 907 | rs->rs_rate = RXSTATUS_RATE(ah, (&ads)); |
907 | ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; | 908 | rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; |
908 | 909 | ||
909 | ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; | 910 | rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; |
910 | ds->ds_rxstat.rs_moreaggr = | 911 | rs->rs_moreaggr = |
911 | (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; | 912 | (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; |
912 | ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); | 913 | rs->rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); |
913 | ds->ds_rxstat.rs_flags = | 914 | rs->rs_flags = |
914 | (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; | 915 | (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; |
915 | ds->ds_rxstat.rs_flags |= | 916 | rs->rs_flags |= |
916 | (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; | 917 | (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; |
917 | 918 | ||
918 | if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) | 919 | if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) |
919 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE; | 920 | rs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE; |
920 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) | 921 | if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) |
921 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST; | 922 | rs->rs_flags |= ATH9K_RX_DELIM_CRC_POST; |
922 | if (ads.ds_rxstatus8 & AR_DecryptBusyErr) | 923 | if (ads.ds_rxstatus8 & AR_DecryptBusyErr) |
923 | ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY; | 924 | rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; |
924 | 925 | ||
925 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { | 926 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { |
926 | if (ads.ds_rxstatus8 & AR_CRCErr) | 927 | if (ads.ds_rxstatus8 & AR_CRCErr) |
927 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC; | 928 | rs->rs_status |= ATH9K_RXERR_CRC; |
928 | else if (ads.ds_rxstatus8 & AR_PHYErr) { | 929 | else if (ads.ds_rxstatus8 & AR_PHYErr) { |
929 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY; | 930 | rs->rs_status |= ATH9K_RXERR_PHY; |
930 | phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); | 931 | phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); |
931 | ds->ds_rxstat.rs_phyerr = phyerr; | 932 | rs->rs_phyerr = phyerr; |
932 | } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) | 933 | } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) |
933 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT; | 934 | rs->rs_status |= ATH9K_RXERR_DECRYPT; |
934 | else if (ads.ds_rxstatus8 & AR_MichaelErr) | 935 | else if (ads.ds_rxstatus8 & AR_MichaelErr) |
935 | ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC; | 936 | rs->rs_status |= ATH9K_RXERR_MIC; |
936 | } | 937 | } |
937 | 938 | ||
938 | return 0; | 939 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index a5e543bd2271..68dbd7a8ddca 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -233,18 +233,9 @@ struct ath_desc { | |||
233 | u32 ds_ctl0; | 233 | u32 ds_ctl0; |
234 | u32 ds_ctl1; | 234 | u32 ds_ctl1; |
235 | u32 ds_hw[20]; | 235 | u32 ds_hw[20]; |
236 | union { | ||
237 | struct ath_tx_status tx; | ||
238 | struct ath_rx_status rx; | ||
239 | void *stats; | ||
240 | } ds_us; | ||
241 | void *ds_vdata; | 236 | void *ds_vdata; |
242 | } __packed; | 237 | } __packed; |
243 | 238 | ||
244 | #define ds_txstat ds_us.tx | ||
245 | #define ds_rxstat ds_us.rx | ||
246 | #define ds_stat ds_us.stats | ||
247 | |||
248 | #define ATH9K_TXDESC_CLRDMASK 0x0001 | 239 | #define ATH9K_TXDESC_CLRDMASK 0x0001 |
249 | #define ATH9K_TXDESC_NOACK 0x0002 | 240 | #define ATH9K_TXDESC_NOACK 0x0002 |
250 | #define ATH9K_TXDESC_RTSENA 0x0004 | 241 | #define ATH9K_TXDESC_RTSENA 0x0004 |
@@ -702,7 +693,8 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
702 | u32 segLen, bool firstSeg, | 693 | u32 segLen, bool firstSeg, |
703 | bool lastSeg, const struct ath_desc *ds0); | 694 | bool lastSeg, const struct ath_desc *ds0); |
704 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); | 695 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); |
705 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds); | 696 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
697 | struct ath_tx_status *ts); | ||
706 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | 698 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, |
707 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, | 699 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, |
708 | u32 keyIx, enum ath9k_key_type keyType, u32 flags); | 700 | u32 keyIx, enum ath9k_key_type keyType, u32 flags); |
@@ -732,7 +724,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, | |||
732 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); | 724 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); |
733 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); | 725 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); |
734 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | 726 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
735 | u32 pa, struct ath_desc *nds, u64 tsf); | 727 | struct ath_rx_status *rs, u64 tsf); |
736 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | 728 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, |
737 | u32 size, u32 flags); | 729 | u32 size, u32 flags); |
738 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); | 730 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 115e1aeedb59..f7ef11407e27 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -225,7 +225,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
225 | 225 | ||
226 | ath_cache_conf_rate(sc, &hw->conf); | 226 | ath_cache_conf_rate(sc, &hw->conf); |
227 | ath_update_txpow(sc); | 227 | ath_update_txpow(sc); |
228 | ath9k_hw_set_interrupts(ah, sc->imask); | 228 | ath9k_hw_set_interrupts(ah, ah->imask); |
229 | 229 | ||
230 | ps_restore: | 230 | ps_restore: |
231 | ath9k_ps_restore(sc); | 231 | ath9k_ps_restore(sc); |
@@ -434,7 +434,7 @@ void ath9k_tasklet(unsigned long data) | |||
434 | ath_gen_timer_isr(sc->sc_ah); | 434 | ath_gen_timer_isr(sc->sc_ah); |
435 | 435 | ||
436 | /* re-enable hardware interrupt */ | 436 | /* re-enable hardware interrupt */ |
437 | ath9k_hw_set_interrupts(ah, sc->imask); | 437 | ath9k_hw_set_interrupts(ah, ah->imask); |
438 | ath9k_ps_restore(sc); | 438 | ath9k_ps_restore(sc); |
439 | } | 439 | } |
440 | 440 | ||
@@ -477,7 +477,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
477 | * value to insure we only process bits we requested. | 477 | * value to insure we only process bits we requested. |
478 | */ | 478 | */ |
479 | ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ | 479 | ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ |
480 | status &= sc->imask; /* discard unasked-for bits */ | 480 | status &= ah->imask; /* discard unasked-for bits */ |
481 | 481 | ||
482 | /* | 482 | /* |
483 | * If there are no status bits set, then this interrupt was not | 483 | * If there are no status bits set, then this interrupt was not |
@@ -518,7 +518,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
518 | * the interrupt. | 518 | * the interrupt. |
519 | */ | 519 | */ |
520 | ath9k_hw_procmibevent(ah); | 520 | ath9k_hw_procmibevent(ah); |
521 | ath9k_hw_set_interrupts(ah, sc->imask); | 521 | ath9k_hw_set_interrupts(ah, ah->imask); |
522 | } | 522 | } |
523 | 523 | ||
524 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 524 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
@@ -536,7 +536,7 @@ chip_reset: | |||
536 | 536 | ||
537 | if (sched) { | 537 | if (sched) { |
538 | /* turn off every interrupt except SWBA */ | 538 | /* turn off every interrupt except SWBA */ |
539 | ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA)); | 539 | ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA)); |
540 | tasklet_schedule(&sc->intr_tq); | 540 | tasklet_schedule(&sc->intr_tq); |
541 | } | 541 | } |
542 | 542 | ||
@@ -887,7 +887,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
887 | ath_beacon_config(sc, NULL); /* restart beacons */ | 887 | ath_beacon_config(sc, NULL); /* restart beacons */ |
888 | 888 | ||
889 | /* Re-Enable interrupts */ | 889 | /* Re-Enable interrupts */ |
890 | ath9k_hw_set_interrupts(ah, sc->imask); | 890 | ath9k_hw_set_interrupts(ah, ah->imask); |
891 | 891 | ||
892 | /* Enable LED */ | 892 | /* Enable LED */ |
893 | ath9k_hw_cfg_output(ah, ah->led_pin, | 893 | ath9k_hw_cfg_output(ah, ah->led_pin, |
@@ -977,7 +977,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
977 | if (sc->sc_flags & SC_OP_BEACONS) | 977 | if (sc->sc_flags & SC_OP_BEACONS) |
978 | ath_beacon_config(sc, NULL); /* restart beacons */ | 978 | ath_beacon_config(sc, NULL); /* restart beacons */ |
979 | 979 | ||
980 | ath9k_hw_set_interrupts(ah, sc->imask); | 980 | ath9k_hw_set_interrupts(ah, ah->imask); |
981 | 981 | ||
982 | if (retry_tx) { | 982 | if (retry_tx) { |
983 | int i; | 983 | int i; |
@@ -1162,23 +1162,23 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1162 | } | 1162 | } |
1163 | 1163 | ||
1164 | /* Setup our intr mask. */ | 1164 | /* Setup our intr mask. */ |
1165 | sc->imask = ATH9K_INT_RX | ATH9K_INT_TX | 1165 | ah->imask = ATH9K_INT_RX | ATH9K_INT_TX |
1166 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | 1166 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN |
1167 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; | 1167 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; |
1168 | 1168 | ||
1169 | if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) | 1169 | if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) |
1170 | sc->imask |= ATH9K_INT_GTT; | 1170 | ah->imask |= ATH9K_INT_GTT; |
1171 | 1171 | ||
1172 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 1172 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
1173 | sc->imask |= ATH9K_INT_CST; | 1173 | ah->imask |= ATH9K_INT_CST; |
1174 | 1174 | ||
1175 | ath_cache_conf_rate(sc, &hw->conf); | 1175 | ath_cache_conf_rate(sc, &hw->conf); |
1176 | 1176 | ||
1177 | sc->sc_flags &= ~SC_OP_INVALID; | 1177 | sc->sc_flags &= ~SC_OP_INVALID; |
1178 | 1178 | ||
1179 | /* Disable BMISS interrupt when we're not associated */ | 1179 | /* Disable BMISS interrupt when we're not associated */ |
1180 | sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | 1180 | ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); |
1181 | ath9k_hw_set_interrupts(ah, sc->imask); | 1181 | ath9k_hw_set_interrupts(ah, ah->imask); |
1182 | 1182 | ||
1183 | ieee80211_wake_queues(hw); | 1183 | ieee80211_wake_queues(hw); |
1184 | 1184 | ||
@@ -1372,14 +1372,15 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1372 | { | 1372 | { |
1373 | struct ath_wiphy *aphy = hw->priv; | 1373 | struct ath_wiphy *aphy = hw->priv; |
1374 | struct ath_softc *sc = aphy->sc; | 1374 | struct ath_softc *sc = aphy->sc; |
1375 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1375 | struct ath_hw *ah = sc->sc_ah; |
1376 | struct ath_common *common = ath9k_hw_common(ah); | ||
1376 | struct ath_vif *avp = (void *)vif->drv_priv; | 1377 | struct ath_vif *avp = (void *)vif->drv_priv; |
1377 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; | 1378 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; |
1378 | int ret = 0; | 1379 | int ret = 0; |
1379 | 1380 | ||
1380 | mutex_lock(&sc->mutex); | 1381 | mutex_lock(&sc->mutex); |
1381 | 1382 | ||
1382 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && | 1383 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && |
1383 | sc->nvifs > 0) { | 1384 | sc->nvifs > 0) { |
1384 | ret = -ENOBUFS; | 1385 | ret = -ENOBUFS; |
1385 | goto out; | 1386 | goto out; |
@@ -1414,19 +1415,19 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1414 | 1415 | ||
1415 | sc->nvifs++; | 1416 | sc->nvifs++; |
1416 | 1417 | ||
1417 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 1418 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) |
1418 | ath9k_set_bssid_mask(hw); | 1419 | ath9k_set_bssid_mask(hw); |
1419 | 1420 | ||
1420 | if (sc->nvifs > 1) | 1421 | if (sc->nvifs > 1) |
1421 | goto out; /* skip global settings for secondary vif */ | 1422 | goto out; /* skip global settings for secondary vif */ |
1422 | 1423 | ||
1423 | if (ic_opmode == NL80211_IFTYPE_AP) { | 1424 | if (ic_opmode == NL80211_IFTYPE_AP) { |
1424 | ath9k_hw_set_tsfadjust(sc->sc_ah, 1); | 1425 | ath9k_hw_set_tsfadjust(ah, 1); |
1425 | sc->sc_flags |= SC_OP_TSF_RESET; | 1426 | sc->sc_flags |= SC_OP_TSF_RESET; |
1426 | } | 1427 | } |
1427 | 1428 | ||
1428 | /* Set the device opmode */ | 1429 | /* Set the device opmode */ |
1429 | sc->sc_ah->opmode = ic_opmode; | 1430 | ah->opmode = ic_opmode; |
1430 | 1431 | ||
1431 | /* | 1432 | /* |
1432 | * Enable MIB interrupts when there are hardware phy counters. | 1433 | * Enable MIB interrupts when there are hardware phy counters. |
@@ -1435,11 +1436,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1435 | if ((vif->type == NL80211_IFTYPE_STATION) || | 1436 | if ((vif->type == NL80211_IFTYPE_STATION) || |
1436 | (vif->type == NL80211_IFTYPE_ADHOC) || | 1437 | (vif->type == NL80211_IFTYPE_ADHOC) || |
1437 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { | 1438 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { |
1438 | sc->imask |= ATH9K_INT_MIB; | 1439 | ah->imask |= ATH9K_INT_MIB; |
1439 | sc->imask |= ATH9K_INT_TSFOOR; | 1440 | ah->imask |= ATH9K_INT_TSFOOR; |
1440 | } | 1441 | } |
1441 | 1442 | ||
1442 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 1443 | ath9k_hw_set_interrupts(ah, ah->imask); |
1443 | 1444 | ||
1444 | if (vif->type == NL80211_IFTYPE_AP || | 1445 | if (vif->type == NL80211_IFTYPE_AP || |
1445 | vif->type == NL80211_IFTYPE_ADHOC || | 1446 | vif->type == NL80211_IFTYPE_ADHOC || |
@@ -1495,15 +1496,16 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1495 | 1496 | ||
1496 | void ath9k_enable_ps(struct ath_softc *sc) | 1497 | void ath9k_enable_ps(struct ath_softc *sc) |
1497 | { | 1498 | { |
1499 | struct ath_hw *ah = sc->sc_ah; | ||
1500 | |||
1498 | sc->ps_enabled = true; | 1501 | sc->ps_enabled = true; |
1499 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | 1502 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { |
1500 | if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { | 1503 | if ((ah->imask & ATH9K_INT_TIM_TIMER) == 0) { |
1501 | sc->imask |= ATH9K_INT_TIM_TIMER; | 1504 | ah->imask |= ATH9K_INT_TIM_TIMER; |
1502 | ath9k_hw_set_interrupts(sc->sc_ah, | 1505 | ath9k_hw_set_interrupts(ah, ah->imask); |
1503 | sc->imask); | ||
1504 | } | 1506 | } |
1505 | } | 1507 | } |
1506 | ath9k_hw_setrxabort(sc->sc_ah, 1); | 1508 | ath9k_hw_setrxabort(ah, 1); |
1507 | } | 1509 | } |
1508 | 1510 | ||
1509 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 1511 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
@@ -1579,10 +1581,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1579 | PS_WAIT_FOR_CAB | | 1581 | PS_WAIT_FOR_CAB | |
1580 | PS_WAIT_FOR_PSPOLL_DATA | | 1582 | PS_WAIT_FOR_PSPOLL_DATA | |
1581 | PS_WAIT_FOR_TX_ACK); | 1583 | PS_WAIT_FOR_TX_ACK); |
1582 | if (sc->imask & ATH9K_INT_TIM_TIMER) { | 1584 | if (ah->imask & ATH9K_INT_TIM_TIMER) { |
1583 | sc->imask &= ~ATH9K_INT_TIM_TIMER; | 1585 | ah->imask &= ~ATH9K_INT_TIM_TIMER; |
1584 | ath9k_hw_set_interrupts(sc->sc_ah, | 1586 | ath9k_hw_set_interrupts(sc->sc_ah, |
1585 | sc->imask); | 1587 | ah->imask); |
1586 | } | 1588 | } |
1587 | } | 1589 | } |
1588 | } | 1590 | } |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 9441c6718a30..1ec836cf1c0d 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -88,6 +88,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) | |||
88 | } | 88 | } |
89 | 89 | ||
90 | static const struct ath_bus_ops ath_pci_bus_ops = { | 90 | static const struct ath_bus_ops ath_pci_bus_ops = { |
91 | .ath_bus_type = ATH_PCI, | ||
91 | .read_cachesize = ath_pci_read_cachesize, | 92 | .read_cachesize = ath_pci_read_cachesize, |
92 | .eeprom_read = ath_pci_eeprom_read, | 93 | .eeprom_read = ath_pci_eeprom_read, |
93 | .bt_coex_prep = ath_pci_bt_coex_prep, | 94 | .bt_coex_prep = ath_pci_bt_coex_prep, |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index 0999a495fd46..0132e4c9a9f9 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -503,6 +503,8 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, | |||
503 | #define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 | 503 | #define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 |
504 | 504 | ||
505 | #define AR_PHY_TX_PWRCTRL7 0xa274 | 505 | #define AR_PHY_TX_PWRCTRL7 0xa274 |
506 | #define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000 | ||
507 | #define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13 | ||
506 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 | 508 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 |
507 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 | 509 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 |
508 | 510 | ||
@@ -513,8 +515,16 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, | |||
513 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 | 515 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 |
514 | 516 | ||
515 | #define AR_PHY_TX_GAIN_TBL1 0xa300 | 517 | #define AR_PHY_TX_GAIN_TBL1 0xa300 |
516 | #define AR_PHY_TX_GAIN 0x0007F000 | 518 | #define AR_PHY_TX_GAIN_CLC 0x0000001E |
517 | #define AR_PHY_TX_GAIN_S 12 | 519 | #define AR_PHY_TX_GAIN_CLC_S 1 |
520 | #define AR_PHY_TX_GAIN 0x0007F000 | ||
521 | #define AR_PHY_TX_GAIN_S 12 | ||
522 | |||
523 | #define AR_PHY_CLC_TBL1 0xa35c | ||
524 | #define AR_PHY_CLC_I0 0x07ff0000 | ||
525 | #define AR_PHY_CLC_I0_S 16 | ||
526 | #define AR_PHY_CLC_Q0 0x0000ffd0 | ||
527 | #define AR_PHY_CLC_Q0_S 5 | ||
518 | 528 | ||
519 | #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 | 529 | #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 |
520 | #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 | 530 | #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 |
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 36083dde863d..3d8d40cdc99e 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h | |||
@@ -176,9 +176,9 @@ struct ath_rate_priv { | |||
176 | #define ATH_TX_INFO_UNDERRUN (1 << 4) | 176 | #define ATH_TX_INFO_UNDERRUN (1 << 4) |
177 | 177 | ||
178 | enum ath9k_internal_frame_type { | 178 | enum ath9k_internal_frame_type { |
179 | ATH9K_NOT_INTERNAL, | 179 | ATH9K_IFT_NOT_INTERNAL, |
180 | ATH9K_INT_PAUSE, | 180 | ATH9K_IFT_PAUSE, |
181 | ATH9K_INT_UNPAUSE | 181 | ATH9K_IFT_UNPAUSE |
182 | }; | 182 | }; |
183 | 183 | ||
184 | int ath_rate_control_register(void); | 184 | int ath_rate_control_register(void); |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 1ca42e5148c8..94560e2fe376 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -477,7 +477,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
477 | 477 | ||
478 | struct ath_buf *bf; | 478 | struct ath_buf *bf; |
479 | struct ath_desc *ds; | 479 | struct ath_desc *ds; |
480 | struct ath_rx_status *rx_stats; | ||
481 | struct sk_buff *skb = NULL, *requeue_skb; | 480 | struct sk_buff *skb = NULL, *requeue_skb; |
482 | struct ieee80211_rx_status *rxs; | 481 | struct ieee80211_rx_status *rxs; |
483 | struct ath_hw *ah = sc->sc_ah; | 482 | struct ath_hw *ah = sc->sc_ah; |
@@ -491,6 +490,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
491 | struct ieee80211_hdr *hdr; | 490 | struct ieee80211_hdr *hdr; |
492 | int retval; | 491 | int retval; |
493 | bool decrypt_error = false; | 492 | bool decrypt_error = false; |
493 | struct ath_rx_status rs; | ||
494 | 494 | ||
495 | spin_lock_bh(&sc->rx.rxbuflock); | 495 | spin_lock_bh(&sc->rx.rxbuflock); |
496 | 496 | ||
@@ -518,14 +518,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
518 | * on. All this is necessary because of our use of | 518 | * on. All this is necessary because of our use of |
519 | * a self-linked list to avoid rx overruns. | 519 | * a self-linked list to avoid rx overruns. |
520 | */ | 520 | */ |
521 | retval = ath9k_hw_rxprocdesc(ah, ds, | 521 | memset(&rs, 0, sizeof(rs)); |
522 | bf->bf_daddr, | 522 | retval = ath9k_hw_rxprocdesc(ah, ds, &rs, 0); |
523 | PA2DESC(sc, ds->ds_link), | ||
524 | 0); | ||
525 | if (retval == -EINPROGRESS) { | 523 | if (retval == -EINPROGRESS) { |
524 | struct ath_rx_status trs; | ||
526 | struct ath_buf *tbf; | 525 | struct ath_buf *tbf; |
527 | struct ath_desc *tds; | 526 | struct ath_desc *tds; |
528 | 527 | ||
528 | memset(&trs, 0, sizeof(trs)); | ||
529 | if (list_is_last(&bf->list, &sc->rx.rxbuf)) { | 529 | if (list_is_last(&bf->list, &sc->rx.rxbuf)) { |
530 | sc->rx.rxlink = NULL; | 530 | sc->rx.rxlink = NULL; |
531 | break; | 531 | break; |
@@ -545,8 +545,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
545 | */ | 545 | */ |
546 | 546 | ||
547 | tds = tbf->bf_desc; | 547 | tds = tbf->bf_desc; |
548 | retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr, | 548 | retval = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); |
549 | PA2DESC(sc, tds->ds_link), 0); | ||
550 | if (retval == -EINPROGRESS) { | 549 | if (retval == -EINPROGRESS) { |
551 | break; | 550 | break; |
552 | } | 551 | } |
@@ -569,9 +568,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
569 | rxs = IEEE80211_SKB_RXCB(skb); | 568 | rxs = IEEE80211_SKB_RXCB(skb); |
570 | 569 | ||
571 | hw = ath_get_virt_hw(sc, hdr); | 570 | hw = ath_get_virt_hw(sc, hdr); |
572 | rx_stats = &ds->ds_rxstat; | ||
573 | 571 | ||
574 | ath_debug_stat_rx(sc, bf); | 572 | ath_debug_stat_rx(sc, &rs); |
575 | 573 | ||
576 | /* | 574 | /* |
577 | * If we're asked to flush receive queue, directly | 575 | * If we're asked to flush receive queue, directly |
@@ -580,7 +578,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
580 | if (flush) | 578 | if (flush) |
581 | goto requeue; | 579 | goto requeue; |
582 | 580 | ||
583 | retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, rx_stats, | 581 | retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, &rs, |
584 | rxs, &decrypt_error); | 582 | rxs, &decrypt_error); |
585 | if (retval) | 583 | if (retval) |
586 | goto requeue; | 584 | goto requeue; |
@@ -601,9 +599,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
601 | common->rx_bufsize, | 599 | common->rx_bufsize, |
602 | DMA_FROM_DEVICE); | 600 | DMA_FROM_DEVICE); |
603 | 601 | ||
604 | skb_put(skb, rx_stats->rs_datalen); | 602 | skb_put(skb, rs.rs_datalen); |
605 | 603 | ||
606 | ath9k_cmn_rx_skb_postprocess(common, skb, rx_stats, | 604 | ath9k_cmn_rx_skb_postprocess(common, skb, &rs, |
607 | rxs, decrypt_error); | 605 | rxs, decrypt_error); |
608 | 606 | ||
609 | /* We will now give hardware our shiny new allocated skb */ | 607 | /* We will now give hardware our shiny new allocated skb */ |
@@ -626,9 +624,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
626 | * change the default rx antenna if rx diversity chooses the | 624 | * change the default rx antenna if rx diversity chooses the |
627 | * other antenna 3 times in a row. | 625 | * other antenna 3 times in a row. |
628 | */ | 626 | */ |
629 | if (sc->rx.defant != ds->ds_rxstat.rs_antenna) { | 627 | if (sc->rx.defant != rs.rs_antenna) { |
630 | if (++sc->rx.rxotherant >= 3) | 628 | if (++sc->rx.rxotherant >= 3) |
631 | ath_setdefantenna(sc, rx_stats->rs_antenna); | 629 | ath_setdefantenna(sc, rs.rs_antenna); |
632 | } else { | 630 | } else { |
633 | sc->rx.rxotherant = 0; | 631 | sc->rx.rxotherant = 0; |
634 | } | 632 | } |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 198e41dd38a6..7e36ad7421b7 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -679,7 +679,7 @@ | |||
679 | 679 | ||
680 | #define AR_WA 0x4004 | 680 | #define AR_WA 0x4004 |
681 | #define AR_WA_D3_L1_DISABLE (1 << 14) | 681 | #define AR_WA_D3_L1_DISABLE (1 << 14) |
682 | #define AR9285_WA_DEFAULT 0x004a05cb | 682 | #define AR9285_WA_DEFAULT 0x004a050b |
683 | #define AR9280_WA_DEFAULT 0x0040073b | 683 | #define AR9280_WA_DEFAULT 0x0040073b |
684 | #define AR_WA_DEFAULT 0x0000073f | 684 | #define AR_WA_DEFAULT 0x0000073f |
685 | 685 | ||
@@ -845,6 +845,10 @@ | |||
845 | (AR_SREV_9271(_ah) && \ | 845 | (AR_SREV_9271(_ah) && \ |
846 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) | 846 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) |
847 | 847 | ||
848 | #define AR_SREV_9285E_20(_ah) \ | ||
849 | (AR_SREV_9285_12_OR_LATER(_ah) && \ | ||
850 | ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) | ||
851 | |||
848 | #define AR_RADIO_SREV_MAJOR 0xf0 | 852 | #define AR_RADIO_SREV_MAJOR 0xf0 |
849 | #define AR_RAD5133_SREV_MAJOR 0xc0 | 853 | #define AR_RAD5133_SREV_MAJOR 0xc0 |
850 | #define AR_RAD2133_SREV_MAJOR 0xd0 | 854 | #define AR_RAD2133_SREV_MAJOR 0xd0 |
@@ -1181,6 +1185,13 @@ enum { | |||
1181 | #define AR9285_AN_RF2G4_DB2_4 0x00003800 | 1185 | #define AR9285_AN_RF2G4_DB2_4 0x00003800 |
1182 | #define AR9285_AN_RF2G4_DB2_4_S 11 | 1186 | #define AR9285_AN_RF2G4_DB2_4_S 11 |
1183 | 1187 | ||
1188 | #define AR9285_RF2G5 0x7830 | ||
1189 | #define AR9285_RF2G5_IC50TX 0xfffff8ff | ||
1190 | #define AR9285_RF2G5_IC50TX_SET 0x00000400 | ||
1191 | #define AR9285_RF2G5_IC50TX_XE_SET 0x00000500 | ||
1192 | #define AR9285_RF2G5_IC50TX_CLEAR 0x00000700 | ||
1193 | #define AR9285_RF2G5_IC50TX_CLEAR_S 8 | ||
1194 | |||
1184 | /* AR9271 : 0x7828, 0x782c different setting from AR9285 */ | 1195 | /* AR9271 : 0x7828, 0x782c different setting from AR9285 */ |
1185 | #define AR9271_AN_RF2G3_OB_cck 0x001C0000 | 1196 | #define AR9271_AN_RF2G3_OB_cck 0x001C0000 |
1186 | #define AR9271_AN_RF2G3_OB_cck_S 18 | 1197 | #define AR9271_AN_RF2G3_OB_cck_S 18 |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 00c0e21a4af7..105ad40968f6 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -220,7 +220,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy, | |||
220 | 220 | ||
221 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | 221 | memset(&txctl, 0, sizeof(struct ath_tx_control)); |
222 | txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; | 222 | txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; |
223 | txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE; | 223 | txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; |
224 | 224 | ||
225 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) | 225 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) |
226 | goto exit; | 226 | goto exit; |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 818dea0164ec..f2ff18cf3e60 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -169,7 +169,7 @@ void ath9k_wmi_tasklet(unsigned long data) | |||
169 | break; | 169 | break; |
170 | } | 170 | } |
171 | 171 | ||
172 | dev_kfree_skb_any(skb); | 172 | kfree_skb(skb); |
173 | } | 173 | } |
174 | 174 | ||
175 | static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) | 175 | static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) |
@@ -207,13 +207,13 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, | |||
207 | ath9k_wmi_rsp_callback(wmi, skb); | 207 | ath9k_wmi_rsp_callback(wmi, skb); |
208 | 208 | ||
209 | free_skb: | 209 | free_skb: |
210 | dev_kfree_skb_any(skb); | 210 | kfree_skb(skb); |
211 | } | 211 | } |
212 | 212 | ||
213 | static void ath9k_wmi_ctrl_tx(void *priv, struct sk_buff *skb, | 213 | static void ath9k_wmi_ctrl_tx(void *priv, struct sk_buff *skb, |
214 | enum htc_endpoint_id epid, bool txok) | 214 | enum htc_endpoint_id epid, bool txok) |
215 | { | 215 | { |
216 | dev_kfree_skb_any(skb); | 216 | kfree_skb(skb); |
217 | } | 217 | } |
218 | 218 | ||
219 | int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, | 219 | int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi, |
@@ -269,7 +269,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | |||
269 | if (!wmi) | 269 | if (!wmi) |
270 | return -EINVAL; | 270 | return -EINVAL; |
271 | 271 | ||
272 | skb = dev_alloc_skb(headroom + cmd_len); | 272 | skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC); |
273 | if (!skb) | 273 | if (!skb) |
274 | return -ENOMEM; | 274 | return -ENOMEM; |
275 | 275 | ||
@@ -313,7 +313,7 @@ out: | |||
313 | ath_print(common, ATH_DBG_WMI, | 313 | ath_print(common, ATH_DBG_WMI, |
314 | "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); | 314 | "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); |
315 | mutex_unlock(&wmi->op_mutex); | 315 | mutex_unlock(&wmi->op_mutex); |
316 | dev_kfree_skb_any(skb); | 316 | kfree_skb(skb); |
317 | 317 | ||
318 | return ret; | 318 | return ret; |
319 | } | 319 | } |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index a3b6cf20f8a1..02df4cbf179f 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -59,15 +59,14 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, | |||
59 | struct ath_atx_tid *tid, | 59 | struct ath_atx_tid *tid, |
60 | struct list_head *bf_head); | 60 | struct list_head *bf_head); |
61 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 61 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
62 | struct ath_txq *txq, | 62 | struct ath_txq *txq, struct list_head *bf_q, |
63 | struct list_head *bf_q, | 63 | struct ath_tx_status *ts, int txok, int sendbar); |
64 | int txok, int sendbar); | ||
65 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | 64 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, |
66 | struct list_head *head); | 65 | struct list_head *head); |
67 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); | 66 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); |
68 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | 67 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, |
69 | int txok); | 68 | struct ath_tx_status *ts, int txok); |
70 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | 69 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, |
71 | int nbad, int txok, bool update_rc); | 70 | int nbad, int txok, bool update_rc); |
72 | 71 | ||
73 | enum { | 72 | enum { |
@@ -223,6 +222,9 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
223 | { | 222 | { |
224 | struct ath_buf *bf; | 223 | struct ath_buf *bf; |
225 | struct list_head bf_head; | 224 | struct list_head bf_head; |
225 | struct ath_tx_status ts; | ||
226 | |||
227 | memset(&ts, 0, sizeof(ts)); | ||
226 | INIT_LIST_HEAD(&bf_head); | 228 | INIT_LIST_HEAD(&bf_head); |
227 | 229 | ||
228 | for (;;) { | 230 | for (;;) { |
@@ -236,7 +238,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
236 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | 238 | ath_tx_update_baw(sc, tid, bf->bf_seqno); |
237 | 239 | ||
238 | spin_unlock(&txq->axq_lock); | 240 | spin_unlock(&txq->axq_lock); |
239 | ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); | 241 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); |
240 | spin_lock(&txq->axq_lock); | 242 | spin_lock(&txq->axq_lock); |
241 | } | 243 | } |
242 | 244 | ||
@@ -286,7 +288,7 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) | |||
286 | 288 | ||
287 | static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | 289 | static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, |
288 | struct ath_buf *bf, struct list_head *bf_q, | 290 | struct ath_buf *bf, struct list_head *bf_q, |
289 | int txok) | 291 | struct ath_tx_status *ts, int txok) |
290 | { | 292 | { |
291 | struct ath_node *an = NULL; | 293 | struct ath_node *an = NULL; |
292 | struct sk_buff *skb; | 294 | struct sk_buff *skb; |
@@ -296,7 +298,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
296 | struct ieee80211_tx_info *tx_info; | 298 | struct ieee80211_tx_info *tx_info; |
297 | struct ath_atx_tid *tid = NULL; | 299 | struct ath_atx_tid *tid = NULL; |
298 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; | 300 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; |
299 | struct ath_desc *ds = bf_last->bf_desc; | ||
300 | struct list_head bf_head, bf_pending; | 301 | struct list_head bf_head, bf_pending; |
301 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; | 302 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; |
302 | u32 ba[WME_BA_BMP_SIZE >> 5]; | 303 | u32 ba[WME_BA_BMP_SIZE >> 5]; |
@@ -325,10 +326,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
325 | memset(ba, 0, WME_BA_BMP_SIZE >> 3); | 326 | memset(ba, 0, WME_BA_BMP_SIZE >> 3); |
326 | 327 | ||
327 | if (isaggr && txok) { | 328 | if (isaggr && txok) { |
328 | if (ATH_DS_TX_BA(ds)) { | 329 | if (ts->ts_flags & ATH9K_TX_BA) { |
329 | seq_st = ATH_DS_BA_SEQ(ds); | 330 | seq_st = ts->ts_seqnum; |
330 | memcpy(ba, ATH_DS_BA_BITMAP(ds), | 331 | memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); |
331 | WME_BA_BMP_SIZE >> 3); | ||
332 | } else { | 332 | } else { |
333 | /* | 333 | /* |
334 | * AR5416 can become deaf/mute when BA | 334 | * AR5416 can become deaf/mute when BA |
@@ -345,7 +345,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
345 | INIT_LIST_HEAD(&bf_pending); | 345 | INIT_LIST_HEAD(&bf_pending); |
346 | INIT_LIST_HEAD(&bf_head); | 346 | INIT_LIST_HEAD(&bf_head); |
347 | 347 | ||
348 | nbad = ath_tx_num_badfrms(sc, bf, txok); | 348 | nbad = ath_tx_num_badfrms(sc, bf, ts, txok); |
349 | while (bf) { | 349 | while (bf) { |
350 | txfail = txpending = 0; | 350 | txfail = txpending = 0; |
351 | bf_next = bf->bf_next; | 351 | bf_next = bf->bf_next; |
@@ -359,7 +359,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
359 | acked_cnt++; | 359 | acked_cnt++; |
360 | } else { | 360 | } else { |
361 | if (!(tid->state & AGGR_CLEANUP) && | 361 | if (!(tid->state & AGGR_CLEANUP) && |
362 | ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { | 362 | ts->ts_flags != ATH9K_TX_SW_ABORTED) { |
363 | if (bf->bf_retries < ATH_MAX_SW_RETRIES) { | 363 | if (bf->bf_retries < ATH_MAX_SW_RETRIES) { |
364 | ath_tx_set_retry(sc, txq, bf); | 364 | ath_tx_set_retry(sc, txq, bf); |
365 | txpending = 1; | 365 | txpending = 1; |
@@ -402,13 +402,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
402 | spin_unlock_bh(&txq->axq_lock); | 402 | spin_unlock_bh(&txq->axq_lock); |
403 | 403 | ||
404 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { | 404 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { |
405 | ath_tx_rc_status(bf, ds, nbad, txok, true); | 405 | ath_tx_rc_status(bf, ts, nbad, txok, true); |
406 | rc_update = false; | 406 | rc_update = false; |
407 | } else { | 407 | } else { |
408 | ath_tx_rc_status(bf, ds, nbad, txok, false); | 408 | ath_tx_rc_status(bf, ts, nbad, txok, false); |
409 | } | 409 | } |
410 | 410 | ||
411 | ath_tx_complete_buf(sc, bf, txq, &bf_head, !txfail, sendbar); | 411 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, |
412 | !txfail, sendbar); | ||
412 | } else { | 413 | } else { |
413 | /* retry the un-acked ones */ | 414 | /* retry the un-acked ones */ |
414 | if (bf->bf_next == NULL && bf_last->bf_stale) { | 415 | if (bf->bf_next == NULL && bf_last->bf_stale) { |
@@ -426,10 +427,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
426 | spin_unlock_bh(&txq->axq_lock); | 427 | spin_unlock_bh(&txq->axq_lock); |
427 | 428 | ||
428 | bf->bf_state.bf_type |= BUF_XRETRY; | 429 | bf->bf_state.bf_type |= BUF_XRETRY; |
429 | ath_tx_rc_status(bf, ds, nbad, | 430 | ath_tx_rc_status(bf, ts, nbad, |
430 | 0, false); | 431 | 0, false); |
431 | ath_tx_complete_buf(sc, bf, txq, | 432 | ath_tx_complete_buf(sc, bf, txq, |
432 | &bf_head, 0, 0); | 433 | &bf_head, ts, 0, 0); |
433 | break; | 434 | break; |
434 | } | 435 | } |
435 | 436 | ||
@@ -752,8 +753,11 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
752 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 753 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
753 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); | 754 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); |
754 | struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; | 755 | struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; |
756 | struct ath_tx_status ts; | ||
755 | struct ath_buf *bf; | 757 | struct ath_buf *bf; |
756 | struct list_head bf_head; | 758 | struct list_head bf_head; |
759 | |||
760 | memset(&ts, 0, sizeof(ts)); | ||
757 | INIT_LIST_HEAD(&bf_head); | 761 | INIT_LIST_HEAD(&bf_head); |
758 | 762 | ||
759 | if (txtid->state & AGGR_CLEANUP) | 763 | if (txtid->state & AGGR_CLEANUP) |
@@ -780,7 +784,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
780 | } | 784 | } |
781 | list_move_tail(&bf->list, &bf_head); | 785 | list_move_tail(&bf->list, &bf_head); |
782 | ath_tx_update_baw(sc, txtid, bf->bf_seqno); | 786 | ath_tx_update_baw(sc, txtid, bf->bf_seqno); |
783 | ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); | 787 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); |
784 | } | 788 | } |
785 | spin_unlock_bh(&txq->axq_lock); | 789 | spin_unlock_bh(&txq->axq_lock); |
786 | 790 | ||
@@ -1028,6 +1032,11 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1028 | { | 1032 | { |
1029 | struct ath_buf *bf, *lastbf; | 1033 | struct ath_buf *bf, *lastbf; |
1030 | struct list_head bf_head; | 1034 | struct list_head bf_head; |
1035 | struct ath_tx_status ts; | ||
1036 | |||
1037 | memset(&ts, 0, sizeof(ts)); | ||
1038 | if (!retry_tx) | ||
1039 | ts.ts_flags = ATH9K_TX_SW_ABORTED; | ||
1031 | 1040 | ||
1032 | INIT_LIST_HEAD(&bf_head); | 1041 | INIT_LIST_HEAD(&bf_head); |
1033 | 1042 | ||
@@ -1053,9 +1062,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1053 | } | 1062 | } |
1054 | 1063 | ||
1055 | lastbf = bf->bf_lastbf; | 1064 | lastbf = bf->bf_lastbf; |
1056 | if (!retry_tx) | ||
1057 | lastbf->bf_desc->ds_txstat.ts_flags = | ||
1058 | ATH9K_TX_SW_ABORTED; | ||
1059 | 1065 | ||
1060 | /* remove ath_buf's of the same mpdu from txq */ | 1066 | /* remove ath_buf's of the same mpdu from txq */ |
1061 | list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); | 1067 | list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); |
@@ -1064,9 +1070,9 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1064 | spin_unlock_bh(&txq->axq_lock); | 1070 | spin_unlock_bh(&txq->axq_lock); |
1065 | 1071 | ||
1066 | if (bf_isampdu(bf)) | 1072 | if (bf_isampdu(bf)) |
1067 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0); | 1073 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0); |
1068 | else | 1074 | else |
1069 | ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); | 1075 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); |
1070 | } | 1076 | } |
1071 | 1077 | ||
1072 | spin_lock_bh(&txq->axq_lock); | 1078 | spin_lock_bh(&txq->axq_lock); |
@@ -1568,12 +1574,12 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1568 | 1574 | ||
1569 | tx_info->pad[0] = 0; | 1575 | tx_info->pad[0] = 0; |
1570 | switch (txctl->frame_type) { | 1576 | switch (txctl->frame_type) { |
1571 | case ATH9K_NOT_INTERNAL: | 1577 | case ATH9K_IFT_NOT_INTERNAL: |
1572 | break; | 1578 | break; |
1573 | case ATH9K_INT_PAUSE: | 1579 | case ATH9K_IFT_PAUSE: |
1574 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; | 1580 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; |
1575 | /* fall through */ | 1581 | /* fall through */ |
1576 | case ATH9K_INT_UNPAUSE: | 1582 | case ATH9K_IFT_UNPAUSE: |
1577 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; | 1583 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; |
1578 | break; | 1584 | break; |
1579 | } | 1585 | } |
@@ -1852,9 +1858,8 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1852 | } | 1858 | } |
1853 | 1859 | ||
1854 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1860 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
1855 | struct ath_txq *txq, | 1861 | struct ath_txq *txq, struct list_head *bf_q, |
1856 | struct list_head *bf_q, | 1862 | struct ath_tx_status *ts, int txok, int sendbar) |
1857 | int txok, int sendbar) | ||
1858 | { | 1863 | { |
1859 | struct sk_buff *skb = bf->bf_mpdu; | 1864 | struct sk_buff *skb = bf->bf_mpdu; |
1860 | unsigned long flags; | 1865 | unsigned long flags; |
@@ -1872,7 +1877,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1872 | 1877 | ||
1873 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); | 1878 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); |
1874 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); | 1879 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); |
1875 | ath_debug_stat_tx(sc, txq, bf); | 1880 | ath_debug_stat_tx(sc, txq, bf, ts); |
1876 | 1881 | ||
1877 | /* | 1882 | /* |
1878 | * Return the list of ath_buf of this mpdu to free queue | 1883 | * Return the list of ath_buf of this mpdu to free queue |
@@ -1883,23 +1888,21 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1883 | } | 1888 | } |
1884 | 1889 | ||
1885 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | 1890 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, |
1886 | int txok) | 1891 | struct ath_tx_status *ts, int txok) |
1887 | { | 1892 | { |
1888 | struct ath_buf *bf_last = bf->bf_lastbf; | ||
1889 | struct ath_desc *ds = bf_last->bf_desc; | ||
1890 | u16 seq_st = 0; | 1893 | u16 seq_st = 0; |
1891 | u32 ba[WME_BA_BMP_SIZE >> 5]; | 1894 | u32 ba[WME_BA_BMP_SIZE >> 5]; |
1892 | int ba_index; | 1895 | int ba_index; |
1893 | int nbad = 0; | 1896 | int nbad = 0; |
1894 | int isaggr = 0; | 1897 | int isaggr = 0; |
1895 | 1898 | ||
1896 | if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) | 1899 | if (ts->ts_flags == ATH9K_TX_SW_ABORTED) |
1897 | return 0; | 1900 | return 0; |
1898 | 1901 | ||
1899 | isaggr = bf_isaggr(bf); | 1902 | isaggr = bf_isaggr(bf); |
1900 | if (isaggr) { | 1903 | if (isaggr) { |
1901 | seq_st = ATH_DS_BA_SEQ(ds); | 1904 | seq_st = ts->ts_seqnum; |
1902 | memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); | 1905 | memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); |
1903 | } | 1906 | } |
1904 | 1907 | ||
1905 | while (bf) { | 1908 | while (bf) { |
@@ -1913,7 +1916,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | |||
1913 | return nbad; | 1916 | return nbad; |
1914 | } | 1917 | } |
1915 | 1918 | ||
1916 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | 1919 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, |
1917 | int nbad, int txok, bool update_rc) | 1920 | int nbad, int txok, bool update_rc) |
1918 | { | 1921 | { |
1919 | struct sk_buff *skb = bf->bf_mpdu; | 1922 | struct sk_buff *skb = bf->bf_mpdu; |
@@ -1923,24 +1926,24 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | |||
1923 | u8 i, tx_rateindex; | 1926 | u8 i, tx_rateindex; |
1924 | 1927 | ||
1925 | if (txok) | 1928 | if (txok) |
1926 | tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; | 1929 | tx_info->status.ack_signal = ts->ts_rssi; |
1927 | 1930 | ||
1928 | tx_rateindex = ds->ds_txstat.ts_rateindex; | 1931 | tx_rateindex = ts->ts_rateindex; |
1929 | WARN_ON(tx_rateindex >= hw->max_rates); | 1932 | WARN_ON(tx_rateindex >= hw->max_rates); |
1930 | 1933 | ||
1931 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | 1934 | if (ts->ts_status & ATH9K_TXERR_FILT) |
1932 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 1935 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
1933 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) | 1936 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) |
1934 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU; | 1937 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU; |
1935 | 1938 | ||
1936 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | 1939 | if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && |
1937 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { | 1940 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { |
1938 | if (ieee80211_is_data(hdr->frame_control)) { | 1941 | if (ieee80211_is_data(hdr->frame_control)) { |
1939 | if (ds->ds_txstat.ts_flags & | 1942 | if (ts->ts_flags & |
1940 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) | 1943 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) |
1941 | tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; | 1944 | tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; |
1942 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) || | 1945 | if ((ts->ts_status & ATH9K_TXERR_XRETRY) || |
1943 | (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)) | 1946 | (ts->ts_status & ATH9K_TXERR_FIFO)) |
1944 | tx_info->pad[0] |= ATH_TX_INFO_XRETRY; | 1947 | tx_info->pad[0] |= ATH_TX_INFO_XRETRY; |
1945 | tx_info->status.ampdu_len = bf->bf_nframes; | 1948 | tx_info->status.ampdu_len = bf->bf_nframes; |
1946 | tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; | 1949 | tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; |
@@ -1978,6 +1981,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1978 | struct ath_buf *bf, *lastbf, *bf_held = NULL; | 1981 | struct ath_buf *bf, *lastbf, *bf_held = NULL; |
1979 | struct list_head bf_head; | 1982 | struct list_head bf_head; |
1980 | struct ath_desc *ds; | 1983 | struct ath_desc *ds; |
1984 | struct ath_tx_status ts; | ||
1981 | int txok; | 1985 | int txok; |
1982 | int status; | 1986 | int status; |
1983 | 1987 | ||
@@ -2017,7 +2021,8 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2017 | lastbf = bf->bf_lastbf; | 2021 | lastbf = bf->bf_lastbf; |
2018 | ds = lastbf->bf_desc; | 2022 | ds = lastbf->bf_desc; |
2019 | 2023 | ||
2020 | status = ath9k_hw_txprocdesc(ah, ds); | 2024 | memset(&ts, 0, sizeof(ts)); |
2025 | status = ath9k_hw_txprocdesc(ah, ds, &ts); | ||
2021 | if (status == -EINPROGRESS) { | 2026 | if (status == -EINPROGRESS) { |
2022 | spin_unlock_bh(&txq->axq_lock); | 2027 | spin_unlock_bh(&txq->axq_lock); |
2023 | break; | 2028 | break; |
@@ -2028,7 +2033,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2028 | * can disable RX. | 2033 | * can disable RX. |
2029 | */ | 2034 | */ |
2030 | if (bf->bf_isnullfunc && | 2035 | if (bf->bf_isnullfunc && |
2031 | (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { | 2036 | (ts.ts_status & ATH9K_TX_ACKED)) { |
2032 | if ((sc->ps_flags & PS_ENABLED)) | 2037 | if ((sc->ps_flags & PS_ENABLED)) |
2033 | ath9k_enable_ps(sc); | 2038 | ath9k_enable_ps(sc); |
2034 | else | 2039 | else |
@@ -2047,7 +2052,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2047 | &txq->axq_q, lastbf->list.prev); | 2052 | &txq->axq_q, lastbf->list.prev); |
2048 | 2053 | ||
2049 | txq->axq_depth--; | 2054 | txq->axq_depth--; |
2050 | txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK); | 2055 | txok = !(ts.ts_status & ATH9K_TXERR_MASK); |
2051 | txq->axq_tx_inprogress = false; | 2056 | txq->axq_tx_inprogress = false; |
2052 | spin_unlock_bh(&txq->axq_lock); | 2057 | spin_unlock_bh(&txq->axq_lock); |
2053 | 2058 | ||
@@ -2062,16 +2067,16 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2062 | * This frame is sent out as a single frame. | 2067 | * This frame is sent out as a single frame. |
2063 | * Use hardware retry status for this frame. | 2068 | * Use hardware retry status for this frame. |
2064 | */ | 2069 | */ |
2065 | bf->bf_retries = ds->ds_txstat.ts_longretry; | 2070 | bf->bf_retries = ts.ts_longretry; |
2066 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) | 2071 | if (ts.ts_status & ATH9K_TXERR_XRETRY) |
2067 | bf->bf_state.bf_type |= BUF_XRETRY; | 2072 | bf->bf_state.bf_type |= BUF_XRETRY; |
2068 | ath_tx_rc_status(bf, ds, 0, txok, true); | 2073 | ath_tx_rc_status(bf, &ts, 0, txok, true); |
2069 | } | 2074 | } |
2070 | 2075 | ||
2071 | if (bf_isampdu(bf)) | 2076 | if (bf_isampdu(bf)) |
2072 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); | 2077 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok); |
2073 | else | 2078 | else |
2074 | ath_tx_complete_buf(sc, bf, txq, &bf_head, txok, 0); | 2079 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); |
2075 | 2080 | ||
2076 | ath_wake_mac80211_queue(sc, txq); | 2081 | ath_wake_mac80211_queue(sc, txq); |
2077 | 2082 | ||
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index ecc9eb01f4fa..a8f81ea09f14 100644 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c | |||
@@ -19,8 +19,8 @@ | |||
19 | #include "ath.h" | 19 | #include "ath.h" |
20 | #include "reg.h" | 20 | #include "reg.h" |
21 | 21 | ||
22 | #define REG_READ common->ops->read | 22 | #define REG_READ (common->ops->read) |
23 | #define REG_WRITE common->ops->write | 23 | #define REG_WRITE (common->ops->write) |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * ath_hw_set_bssid_mask - filter out bssids we listen | 26 | * ath_hw_set_bssid_mask - filter out bssids we listen |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 00489c40be0c..24d59883d944 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -50,6 +50,7 @@ | |||
50 | 50 | ||
51 | #define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ | 51 | #define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ |
52 | ATH9K_5GHZ_5470_5850 | 52 | ATH9K_5GHZ_5470_5850 |
53 | |||
53 | /* This one skips what we call "mid band" */ | 54 | /* This one skips what we call "mid band" */ |
54 | #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ | 55 | #define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ |
55 | ATH9K_5GHZ_5725_5850 | 56 | ATH9K_5GHZ_5725_5850 |
@@ -360,7 +361,7 @@ EXPORT_SYMBOL(ath_reg_notifier_apply); | |||
360 | 361 | ||
361 | static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) | 362 | static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) |
362 | { | 363 | { |
363 | u16 rd = ath_regd_get_eepromRD(reg); | 364 | u16 rd = ath_regd_get_eepromRD(reg); |
364 | int i; | 365 | int i; |
365 | 366 | ||
366 | if (rd & COUNTRY_ERD_FLAG) { | 367 | if (rd & COUNTRY_ERD_FLAG) { |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index c4dc369ce703..3d6b33775964 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -105,7 +105,7 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, | |||
105 | } | 105 | } |
106 | 106 | ||
107 | static void b43_chantab_radio_upload(struct b43_wldev *dev, | 107 | static void b43_chantab_radio_upload(struct b43_wldev *dev, |
108 | const struct b43_nphy_channeltab_entry *e) | 108 | const struct b43_nphy_channeltab_entry_rev2 *e) |
109 | { | 109 | { |
110 | b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref); | 110 | b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref); |
111 | b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); | 111 | b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); |
@@ -142,7 +142,7 @@ static void b43_chantab_radio_upload(struct b43_wldev *dev, | |||
142 | } | 142 | } |
143 | 143 | ||
144 | static void b43_chantab_phy_upload(struct b43_wldev *dev, | 144 | static void b43_chantab_phy_upload(struct b43_wldev *dev, |
145 | const struct b43_nphy_channeltab_entry *e) | 145 | const struct b43_phy_n_sfo_cfg *e) |
146 | { | 146 | { |
147 | b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); | 147 | b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); |
148 | b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); | 148 | b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); |
@@ -160,16 +160,16 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
160 | 160 | ||
161 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ | 161 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ |
162 | static void b43_radio_2055_setup(struct b43_wldev *dev, | 162 | static void b43_radio_2055_setup(struct b43_wldev *dev, |
163 | const struct b43_nphy_channeltab_entry *e) | 163 | const struct b43_nphy_channeltab_entry_rev2 *e) |
164 | { | 164 | { |
165 | B43_WARN_ON(dev->phy.rev >= 3); | 165 | B43_WARN_ON(dev->phy.rev >= 3); |
166 | 166 | ||
167 | b43_chantab_radio_upload(dev, e); | 167 | b43_chantab_radio_upload(dev, e); |
168 | udelay(50); | 168 | udelay(50); |
169 | b43_radio_write(dev, B2055_VCO_CAL10, 5); | 169 | b43_radio_write(dev, B2055_VCO_CAL10, 0x05); |
170 | b43_radio_write(dev, B2055_VCO_CAL10, 45); | 170 | b43_radio_write(dev, B2055_VCO_CAL10, 0x45); |
171 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ | 171 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ |
172 | b43_radio_write(dev, B2055_VCO_CAL10, 65); | 172 | b43_radio_write(dev, B2055_VCO_CAL10, 0x65); |
173 | udelay(300); | 173 | udelay(300); |
174 | } | 174 | } |
175 | 175 | ||
@@ -255,6 +255,16 @@ static void b43_radio_init2055(struct b43_wldev *dev) | |||
255 | } | 255 | } |
256 | 256 | ||
257 | /* | 257 | /* |
258 | * Initialize a Broadcom 2056 N-radio | ||
259 | * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init | ||
260 | */ | ||
261 | static void b43_radio_init2056(struct b43_wldev *dev) | ||
262 | { | ||
263 | /* TODO */ | ||
264 | } | ||
265 | |||
266 | |||
267 | /* | ||
258 | * Upload the N-PHY tables. | 268 | * Upload the N-PHY tables. |
259 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables | 269 | * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables |
260 | */ | 270 | */ |
@@ -2791,7 +2801,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, | |||
2791 | } | 2801 | } |
2792 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, | 2802 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, |
2793 | buffer); | 2803 | buffer); |
2794 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2, | 2804 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2, |
2795 | buffer); | 2805 | buffer); |
2796 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, | 2806 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, |
2797 | buffer); | 2807 | buffer); |
@@ -3261,7 +3271,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3261 | 3271 | ||
3262 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ | 3272 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ |
3263 | static void b43_nphy_chanspec_setup(struct b43_wldev *dev, | 3273 | static void b43_nphy_chanspec_setup(struct b43_wldev *dev, |
3264 | const struct b43_nphy_channeltab_entry *e, | 3274 | const struct b43_phy_n_sfo_cfg *e, |
3265 | struct b43_chanspec chanspec) | 3275 | struct b43_chanspec chanspec) |
3266 | { | 3276 | { |
3267 | struct b43_phy *phy = &dev->phy; | 3277 | struct b43_phy *phy = &dev->phy; |
@@ -3327,13 +3337,21 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev, | |||
3327 | { | 3337 | { |
3328 | struct b43_phy_n *nphy = dev->phy.n; | 3338 | struct b43_phy_n *nphy = dev->phy.n; |
3329 | 3339 | ||
3330 | const struct b43_nphy_channeltab_entry *tabent; | 3340 | const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; |
3341 | const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; | ||
3331 | 3342 | ||
3332 | u8 tmp; | 3343 | u8 tmp; |
3333 | u8 channel = chanspec.channel; | 3344 | u8 channel = chanspec.channel; |
3334 | 3345 | ||
3335 | if (dev->phy.rev >= 3) { | 3346 | if (dev->phy.rev >= 3) { |
3336 | /* TODO */ | 3347 | /* TODO */ |
3348 | tabent_r3 = NULL; | ||
3349 | if (!tabent_r3) | ||
3350 | return -ESRCH; | ||
3351 | } else { | ||
3352 | tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel); | ||
3353 | if (!tabent_r2) | ||
3354 | return -ESRCH; | ||
3337 | } | 3355 | } |
3338 | 3356 | ||
3339 | nphy->radio_chanspec = chanspec; | 3357 | nphy->radio_chanspec = chanspec; |
@@ -3354,17 +3372,13 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev, | |||
3354 | if (dev->phy.rev >= 3) { | 3372 | if (dev->phy.rev >= 3) { |
3355 | tmp = (chanspec.b_freq == 1) ? 4 : 0; | 3373 | tmp = (chanspec.b_freq == 1) ? 4 : 0; |
3356 | b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); | 3374 | b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); |
3357 | /* TODO: PHY Radio2056 Setup (chan_info_ptr[i]) */ | 3375 | /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */ |
3358 | /* TODO: N PHY Chanspec Setup (chan_info_ptr[i]) */ | 3376 | b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec); |
3359 | } else { | 3377 | } else { |
3360 | tabent = b43_nphy_get_chantabent(dev, channel); | ||
3361 | if (!tabent) | ||
3362 | return -ESRCH; | ||
3363 | |||
3364 | tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; | 3378 | tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; |
3365 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); | 3379 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); |
3366 | b43_radio_2055_setup(dev, tabent); | 3380 | b43_radio_2055_setup(dev, tabent_r2); |
3367 | b43_nphy_chanspec_setup(dev, tabent, chanspec); | 3381 | b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec); |
3368 | } | 3382 | } |
3369 | 3383 | ||
3370 | return 0; | 3384 | return 0; |
@@ -3474,6 +3488,8 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | |||
3474 | static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | 3488 | static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, |
3475 | bool blocked) | 3489 | bool blocked) |
3476 | { | 3490 | { |
3491 | struct b43_phy_n *nphy = dev->phy.n; | ||
3492 | |||
3477 | if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) | 3493 | if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) |
3478 | b43err(dev->wl, "MAC not suspended\n"); | 3494 | b43err(dev->wl, "MAC not suspended\n"); |
3479 | 3495 | ||
@@ -3499,8 +3515,8 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | |||
3499 | } | 3515 | } |
3500 | } else { | 3516 | } else { |
3501 | if (dev->phy.rev >= 3) { | 3517 | if (dev->phy.rev >= 3) { |
3502 | /* TODO: b43_radio_init2056(dev); */ | 3518 | b43_radio_init2056(dev); |
3503 | /* TODO: PHY Set Channel Spec (dev, radio_chanspec) */ | 3519 | b43_nphy_set_chanspec(dev, nphy->radio_chanspec); |
3504 | } else { | 3520 | } else { |
3505 | b43_radio_init2055(dev); | 3521 | b43_radio_init2055(dev); |
3506 | } | 3522 | } |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index a00d509150f7..d96e870ab8fe 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -318,14 +318,14 @@ void b2055_upload_inittab(struct b43_wldev *dev, | |||
318 | .radio_c2_tx_mxbgtrim = r21 | 318 | .radio_c2_tx_mxbgtrim = r21 |
319 | 319 | ||
320 | #define PHYREGS(r0, r1, r2, r3, r4, r5) \ | 320 | #define PHYREGS(r0, r1, r2, r3, r4, r5) \ |
321 | .phy_bw1a = r0, \ | 321 | .phy_regs.phy_bw1a = r0, \ |
322 | .phy_bw2 = r1, \ | 322 | .phy_regs.phy_bw2 = r1, \ |
323 | .phy_bw3 = r2, \ | 323 | .phy_regs.phy_bw3 = r2, \ |
324 | .phy_bw4 = r3, \ | 324 | .phy_regs.phy_bw4 = r3, \ |
325 | .phy_bw5 = r4, \ | 325 | .phy_regs.phy_bw5 = r4, \ |
326 | .phy_bw6 = r5 | 326 | .phy_regs.phy_bw6 = r5 |
327 | 327 | ||
328 | static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { | 328 | static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab[] = { |
329 | { .channel = 184, | 329 | { .channel = 184, |
330 | .freq = 4920, /* MHz */ | 330 | .freq = 4920, /* MHz */ |
331 | .unk2 = 3280, | 331 | .unk2 = 3280, |
@@ -1320,10 +1320,10 @@ static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { | |||
1320 | }, | 1320 | }, |
1321 | }; | 1321 | }; |
1322 | 1322 | ||
1323 | const struct b43_nphy_channeltab_entry * | 1323 | const struct b43_nphy_channeltab_entry_rev2 * |
1324 | b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel) | 1324 | b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel) |
1325 | { | 1325 | { |
1326 | const struct b43_nphy_channeltab_entry *e; | 1326 | const struct b43_nphy_channeltab_entry_rev2 *e; |
1327 | unsigned int i; | 1327 | unsigned int i; |
1328 | 1328 | ||
1329 | for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) { | 1329 | for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) { |
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index b23036f7dc19..8fc1da9f8fe5 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h | |||
@@ -13,9 +13,13 @@ struct b43_phy_n_sfo_cfg { | |||
13 | u16 phy_bw6; | 13 | u16 phy_bw6; |
14 | }; | 14 | }; |
15 | 15 | ||
16 | struct b43_nphy_channeltab_entry { | 16 | struct b43_nphy_channeltab_entry_rev2 { |
17 | /* The channel number */ | 17 | /* The channel number */ |
18 | u8 channel; | 18 | u8 channel; |
19 | /* The channel frequency in MHz */ | ||
20 | u16 freq; | ||
21 | /* An unknown value */ | ||
22 | u16 unk2; | ||
19 | /* Radio register values on channelswitch */ | 23 | /* Radio register values on channelswitch */ |
20 | u8 radio_pll_ref; | 24 | u8 radio_pll_ref; |
21 | u8 radio_rf_pllmod0; | 25 | u8 radio_rf_pllmod0; |
@@ -40,16 +44,18 @@ struct b43_nphy_channeltab_entry { | |||
40 | u8 radio_c2_tx_pgapadtn; | 44 | u8 radio_c2_tx_pgapadtn; |
41 | u8 radio_c2_tx_mxbgtrim; | 45 | u8 radio_c2_tx_mxbgtrim; |
42 | /* PHY register values on channelswitch */ | 46 | /* PHY register values on channelswitch */ |
43 | u16 phy_bw1a; | 47 | struct b43_phy_n_sfo_cfg phy_regs; |
44 | u16 phy_bw2; | 48 | }; |
45 | u16 phy_bw3; | 49 | |
46 | u16 phy_bw4; | 50 | struct b43_nphy_channeltab_entry_rev3 { |
47 | u16 phy_bw5; | 51 | /* The channel number */ |
48 | u16 phy_bw6; | 52 | u8 channel; |
49 | /* The channel frequency in MHz */ | 53 | /* The channel frequency in MHz */ |
50 | u16 freq; | 54 | u16 freq; |
51 | /* An unknown value */ | 55 | /* Radio register values on channelswitch */ |
52 | u16 unk2; | 56 | /* TODO */ |
57 | /* PHY register values on channelswitch */ | ||
58 | struct b43_phy_n_sfo_cfg phy_regs; | ||
53 | }; | 59 | }; |
54 | 60 | ||
55 | 61 | ||
@@ -86,8 +92,8 @@ void b2055_upload_inittab(struct b43_wldev *dev, | |||
86 | 92 | ||
87 | /* Get the NPHY Channel Switch Table entry for a channel number. | 93 | /* Get the NPHY Channel Switch Table entry for a channel number. |
88 | * Returns NULL on failure to find an entry. */ | 94 | * Returns NULL on failure to find an entry. */ |
89 | const struct b43_nphy_channeltab_entry * | 95 | const struct b43_nphy_channeltab_entry_rev2 * |
90 | b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); | 96 | b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel); |
91 | 97 | ||
92 | 98 | ||
93 | /* The N-PHY tables. */ | 99 | /* The N-PHY tables. */ |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index fe63bf21c67e..2088ac029b35 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -2140,7 +2140,7 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) | |||
2140 | DECLARE_SSID_BUF(ssid); | 2140 | DECLARE_SSID_BUF(ssid); |
2141 | 2141 | ||
2142 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, | 2142 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, |
2143 | "disassociated: '%s' %pM \n", | 2143 | "disassociated: '%s' %pM\n", |
2144 | print_ssid(ssid, priv->essid, priv->essid_len), | 2144 | print_ssid(ssid, priv->essid, priv->essid_len), |
2145 | priv->bssid); | 2145 | priv->bssid); |
2146 | 2146 | ||
@@ -3285,7 +3285,7 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) | |||
3285 | 3285 | ||
3286 | if (inta & IPW2100_INTA_PARITY_ERROR) { | 3286 | if (inta & IPW2100_INTA_PARITY_ERROR) { |
3287 | printk(KERN_ERR DRV_NAME | 3287 | printk(KERN_ERR DRV_NAME |
3288 | ": ***** PARITY ERROR INTERRUPT !!!! \n"); | 3288 | ": ***** PARITY ERROR INTERRUPT !!!!\n"); |
3289 | priv->inta_other++; | 3289 | priv->inta_other++; |
3290 | write_register(dev, IPW_REG_INTA, IPW2100_INTA_PARITY_ERROR); | 3290 | write_register(dev, IPW_REG_INTA, IPW2100_INTA_PARITY_ERROR); |
3291 | } | 3291 | } |
@@ -6753,7 +6753,7 @@ static int ipw2100_wx_set_freq(struct net_device *dev, | |||
6753 | err = -EOPNOTSUPP; | 6753 | err = -EOPNOTSUPP; |
6754 | goto done; | 6754 | goto done; |
6755 | } else { /* Set the channel */ | 6755 | } else { /* Set the channel */ |
6756 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); | 6756 | IPW_DEBUG_WX("SET Freq/Channel -> %d\n", fwrq->m); |
6757 | err = ipw2100_set_channel(priv, fwrq->m, 0); | 6757 | err = ipw2100_set_channel(priv, fwrq->m, 0); |
6758 | } | 6758 | } |
6759 | 6759 | ||
@@ -6782,7 +6782,7 @@ static int ipw2100_wx_get_freq(struct net_device *dev, | |||
6782 | else | 6782 | else |
6783 | wrqu->freq.m = 0; | 6783 | wrqu->freq.m = 0; |
6784 | 6784 | ||
6785 | IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); | 6785 | IPW_DEBUG_WX("GET Freq/Channel -> %d\n", priv->channel); |
6786 | return 0; | 6786 | return 0; |
6787 | 6787 | ||
6788 | } | 6788 | } |
@@ -6794,7 +6794,7 @@ static int ipw2100_wx_set_mode(struct net_device *dev, | |||
6794 | struct ipw2100_priv *priv = libipw_priv(dev); | 6794 | struct ipw2100_priv *priv = libipw_priv(dev); |
6795 | int err = 0; | 6795 | int err = 0; |
6796 | 6796 | ||
6797 | IPW_DEBUG_WX("SET Mode -> %d \n", wrqu->mode); | 6797 | IPW_DEBUG_WX("SET Mode -> %d\n", wrqu->mode); |
6798 | 6798 | ||
6799 | if (wrqu->mode == priv->ieee->iw_mode) | 6799 | if (wrqu->mode == priv->ieee->iw_mode) |
6800 | return 0; | 6800 | return 0; |
@@ -7149,7 +7149,7 @@ static int ipw2100_wx_set_nick(struct net_device *dev, | |||
7149 | memset(priv->nick, 0, sizeof(priv->nick)); | 7149 | memset(priv->nick, 0, sizeof(priv->nick)); |
7150 | memcpy(priv->nick, extra, wrqu->data.length); | 7150 | memcpy(priv->nick, extra, wrqu->data.length); |
7151 | 7151 | ||
7152 | IPW_DEBUG_WX("SET Nickname -> %s \n", priv->nick); | 7152 | IPW_DEBUG_WX("SET Nickname -> %s\n", priv->nick); |
7153 | 7153 | ||
7154 | return 0; | 7154 | return 0; |
7155 | } | 7155 | } |
@@ -7168,7 +7168,7 @@ static int ipw2100_wx_get_nick(struct net_device *dev, | |||
7168 | memcpy(extra, priv->nick, wrqu->data.length); | 7168 | memcpy(extra, priv->nick, wrqu->data.length); |
7169 | wrqu->data.flags = 1; /* active */ | 7169 | wrqu->data.flags = 1; /* active */ |
7170 | 7170 | ||
7171 | IPW_DEBUG_WX("GET Nickname -> %s \n", extra); | 7171 | IPW_DEBUG_WX("GET Nickname -> %s\n", extra); |
7172 | 7172 | ||
7173 | return 0; | 7173 | return 0; |
7174 | } | 7174 | } |
@@ -7207,7 +7207,7 @@ static int ipw2100_wx_set_rate(struct net_device *dev, | |||
7207 | 7207 | ||
7208 | err = ipw2100_set_tx_rates(priv, rate, 0); | 7208 | err = ipw2100_set_tx_rates(priv, rate, 0); |
7209 | 7209 | ||
7210 | IPW_DEBUG_WX("SET Rate -> %04X \n", rate); | 7210 | IPW_DEBUG_WX("SET Rate -> %04X\n", rate); |
7211 | done: | 7211 | done: |
7212 | mutex_unlock(&priv->action_mutex); | 7212 | mutex_unlock(&priv->action_mutex); |
7213 | return err; | 7213 | return err; |
@@ -7258,7 +7258,7 @@ static int ipw2100_wx_get_rate(struct net_device *dev, | |||
7258 | wrqu->bitrate.value = 0; | 7258 | wrqu->bitrate.value = 0; |
7259 | } | 7259 | } |
7260 | 7260 | ||
7261 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); | 7261 | IPW_DEBUG_WX("GET Rate -> %d\n", wrqu->bitrate.value); |
7262 | 7262 | ||
7263 | done: | 7263 | done: |
7264 | mutex_unlock(&priv->action_mutex); | 7264 | mutex_unlock(&priv->action_mutex); |
@@ -7294,7 +7294,7 @@ static int ipw2100_wx_set_rts(struct net_device *dev, | |||
7294 | 7294 | ||
7295 | err = ipw2100_set_rts_threshold(priv, value); | 7295 | err = ipw2100_set_rts_threshold(priv, value); |
7296 | 7296 | ||
7297 | IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value); | 7297 | IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X\n", value); |
7298 | done: | 7298 | done: |
7299 | mutex_unlock(&priv->action_mutex); | 7299 | mutex_unlock(&priv->action_mutex); |
7300 | return err; | 7300 | return err; |
@@ -7316,7 +7316,7 @@ static int ipw2100_wx_get_rts(struct net_device *dev, | |||
7316 | /* If RTS is set to the default value, then it is disabled */ | 7316 | /* If RTS is set to the default value, then it is disabled */ |
7317 | wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0; | 7317 | wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0; |
7318 | 7318 | ||
7319 | IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X \n", wrqu->rts.value); | 7319 | IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X\n", wrqu->rts.value); |
7320 | 7320 | ||
7321 | return 0; | 7321 | return 0; |
7322 | } | 7322 | } |
@@ -7355,7 +7355,7 @@ static int ipw2100_wx_set_txpow(struct net_device *dev, | |||
7355 | 7355 | ||
7356 | err = ipw2100_set_tx_power(priv, value); | 7356 | err = ipw2100_set_tx_power(priv, value); |
7357 | 7357 | ||
7358 | IPW_DEBUG_WX("SET TX Power -> %d \n", value); | 7358 | IPW_DEBUG_WX("SET TX Power -> %d\n", value); |
7359 | 7359 | ||
7360 | done: | 7360 | done: |
7361 | mutex_unlock(&priv->action_mutex); | 7361 | mutex_unlock(&priv->action_mutex); |
@@ -7384,7 +7384,7 @@ static int ipw2100_wx_get_txpow(struct net_device *dev, | |||
7384 | 7384 | ||
7385 | wrqu->txpower.flags = IW_TXPOW_DBM; | 7385 | wrqu->txpower.flags = IW_TXPOW_DBM; |
7386 | 7386 | ||
7387 | IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->txpower.value); | 7387 | IPW_DEBUG_WX("GET TX Power -> %d\n", wrqu->txpower.value); |
7388 | 7388 | ||
7389 | return 0; | 7389 | return 0; |
7390 | } | 7390 | } |
@@ -7414,7 +7414,7 @@ static int ipw2100_wx_set_frag(struct net_device *dev, | |||
7414 | priv->frag_threshold = priv->ieee->fts; | 7414 | priv->frag_threshold = priv->ieee->fts; |
7415 | } | 7415 | } |
7416 | 7416 | ||
7417 | IPW_DEBUG_WX("SET Frag Threshold -> %d \n", priv->ieee->fts); | 7417 | IPW_DEBUG_WX("SET Frag Threshold -> %d\n", priv->ieee->fts); |
7418 | 7418 | ||
7419 | return 0; | 7419 | return 0; |
7420 | } | 7420 | } |
@@ -7432,7 +7432,7 @@ static int ipw2100_wx_get_frag(struct net_device *dev, | |||
7432 | wrqu->frag.fixed = 0; /* no auto select */ | 7432 | wrqu->frag.fixed = 0; /* no auto select */ |
7433 | wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0; | 7433 | wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0; |
7434 | 7434 | ||
7435 | IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); | 7435 | IPW_DEBUG_WX("GET Frag Threshold -> %d\n", wrqu->frag.value); |
7436 | 7436 | ||
7437 | return 0; | 7437 | return 0; |
7438 | } | 7438 | } |
@@ -7458,14 +7458,14 @@ static int ipw2100_wx_set_retry(struct net_device *dev, | |||
7458 | 7458 | ||
7459 | if (wrqu->retry.flags & IW_RETRY_SHORT) { | 7459 | if (wrqu->retry.flags & IW_RETRY_SHORT) { |
7460 | err = ipw2100_set_short_retry(priv, wrqu->retry.value); | 7460 | err = ipw2100_set_short_retry(priv, wrqu->retry.value); |
7461 | IPW_DEBUG_WX("SET Short Retry Limit -> %d \n", | 7461 | IPW_DEBUG_WX("SET Short Retry Limit -> %d\n", |
7462 | wrqu->retry.value); | 7462 | wrqu->retry.value); |
7463 | goto done; | 7463 | goto done; |
7464 | } | 7464 | } |
7465 | 7465 | ||
7466 | if (wrqu->retry.flags & IW_RETRY_LONG) { | 7466 | if (wrqu->retry.flags & IW_RETRY_LONG) { |
7467 | err = ipw2100_set_long_retry(priv, wrqu->retry.value); | 7467 | err = ipw2100_set_long_retry(priv, wrqu->retry.value); |
7468 | IPW_DEBUG_WX("SET Long Retry Limit -> %d \n", | 7468 | IPW_DEBUG_WX("SET Long Retry Limit -> %d\n", |
7469 | wrqu->retry.value); | 7469 | wrqu->retry.value); |
7470 | goto done; | 7470 | goto done; |
7471 | } | 7471 | } |
@@ -7474,7 +7474,7 @@ static int ipw2100_wx_set_retry(struct net_device *dev, | |||
7474 | if (!err) | 7474 | if (!err) |
7475 | err = ipw2100_set_long_retry(priv, wrqu->retry.value); | 7475 | err = ipw2100_set_long_retry(priv, wrqu->retry.value); |
7476 | 7476 | ||
7477 | IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value); | 7477 | IPW_DEBUG_WX("SET Both Retry Limits -> %d\n", wrqu->retry.value); |
7478 | 7478 | ||
7479 | done: | 7479 | done: |
7480 | mutex_unlock(&priv->action_mutex); | 7480 | mutex_unlock(&priv->action_mutex); |
@@ -7508,7 +7508,7 @@ static int ipw2100_wx_get_retry(struct net_device *dev, | |||
7508 | wrqu->retry.value = priv->short_retry_limit; | 7508 | wrqu->retry.value = priv->short_retry_limit; |
7509 | } | 7509 | } |
7510 | 7510 | ||
7511 | IPW_DEBUG_WX("GET Retry -> %d \n", wrqu->retry.value); | 7511 | IPW_DEBUG_WX("GET Retry -> %d\n", wrqu->retry.value); |
7512 | 7512 | ||
7513 | return 0; | 7513 | return 0; |
7514 | } | 7514 | } |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 7266730680bc..82de71a3aea7 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -459,7 +459,7 @@ static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) | |||
459 | { | 459 | { |
460 | u32 word; | 460 | u32 word; |
461 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); | 461 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); |
462 | IPW_DEBUG_IO(" reg = 0x%8X : \n", reg); | 462 | IPW_DEBUG_IO(" reg = 0x%8X :\n", reg); |
463 | word = _ipw_read32(priv, IPW_INDIRECT_DATA); | 463 | word = _ipw_read32(priv, IPW_INDIRECT_DATA); |
464 | return (word >> ((reg & 0x3) * 8)) & 0xff; | 464 | return (word >> ((reg & 0x3) * 8)) & 0xff; |
465 | } | 465 | } |
@@ -473,7 +473,7 @@ static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) | |||
473 | 473 | ||
474 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); | 474 | _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); |
475 | value = _ipw_read32(priv, IPW_INDIRECT_DATA); | 475 | value = _ipw_read32(priv, IPW_INDIRECT_DATA); |
476 | IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value); | 476 | IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x\n", reg, value); |
477 | return value; | 477 | return value; |
478 | } | 478 | } |
479 | 479 | ||
@@ -2349,16 +2349,25 @@ static void ipw_bg_adapter_restart(struct work_struct *work) | |||
2349 | mutex_unlock(&priv->mutex); | 2349 | mutex_unlock(&priv->mutex); |
2350 | } | 2350 | } |
2351 | 2351 | ||
2352 | #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) | 2352 | static void ipw_abort_scan(struct ipw_priv *priv); |
2353 | |||
2354 | #define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) | ||
2353 | 2355 | ||
2354 | static void ipw_scan_check(void *data) | 2356 | static void ipw_scan_check(void *data) |
2355 | { | 2357 | { |
2356 | struct ipw_priv *priv = data; | 2358 | struct ipw_priv *priv = data; |
2357 | if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { | 2359 | |
2360 | if (priv->status & STATUS_SCAN_ABORTING) { | ||
2358 | IPW_DEBUG_SCAN("Scan completion watchdog resetting " | 2361 | IPW_DEBUG_SCAN("Scan completion watchdog resetting " |
2359 | "adapter after (%dms).\n", | 2362 | "adapter after (%dms).\n", |
2360 | jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); | 2363 | jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); |
2361 | queue_work(priv->workqueue, &priv->adapter_restart); | 2364 | queue_work(priv->workqueue, &priv->adapter_restart); |
2365 | } else if (priv->status & STATUS_SCANNING) { | ||
2366 | IPW_DEBUG_SCAN("Scan completion watchdog aborting scan " | ||
2367 | "after (%dms).\n", | ||
2368 | jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); | ||
2369 | ipw_abort_scan(priv); | ||
2370 | queue_delayed_work(priv->workqueue, &priv->scan_check, HZ); | ||
2362 | } | 2371 | } |
2363 | } | 2372 | } |
2364 | 2373 | ||
@@ -2739,7 +2748,7 @@ static inline void ipw_fw_dma_reset_command_blocks(struct ipw_priv *priv) | |||
2739 | static int ipw_fw_dma_enable(struct ipw_priv *priv) | 2748 | static int ipw_fw_dma_enable(struct ipw_priv *priv) |
2740 | { /* start dma engine but no transfers yet */ | 2749 | { /* start dma engine but no transfers yet */ |
2741 | 2750 | ||
2742 | IPW_DEBUG_FW(">> : \n"); | 2751 | IPW_DEBUG_FW(">> :\n"); |
2743 | 2752 | ||
2744 | /* Start the dma */ | 2753 | /* Start the dma */ |
2745 | ipw_fw_dma_reset_command_blocks(priv); | 2754 | ipw_fw_dma_reset_command_blocks(priv); |
@@ -2747,7 +2756,7 @@ static int ipw_fw_dma_enable(struct ipw_priv *priv) | |||
2747 | /* Write CB base address */ | 2756 | /* Write CB base address */ |
2748 | ipw_write_reg32(priv, IPW_DMA_I_CB_BASE, IPW_SHARED_SRAM_DMA_CONTROL); | 2757 | ipw_write_reg32(priv, IPW_DMA_I_CB_BASE, IPW_SHARED_SRAM_DMA_CONTROL); |
2749 | 2758 | ||
2750 | IPW_DEBUG_FW("<< : \n"); | 2759 | IPW_DEBUG_FW("<< :\n"); |
2751 | return 0; | 2760 | return 0; |
2752 | } | 2761 | } |
2753 | 2762 | ||
@@ -2762,7 +2771,7 @@ static void ipw_fw_dma_abort(struct ipw_priv *priv) | |||
2762 | ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); | 2771 | ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); |
2763 | priv->sram_desc.last_cb_index = 0; | 2772 | priv->sram_desc.last_cb_index = 0; |
2764 | 2773 | ||
2765 | IPW_DEBUG_FW("<< \n"); | 2774 | IPW_DEBUG_FW("<<\n"); |
2766 | } | 2775 | } |
2767 | 2776 | ||
2768 | static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index, | 2777 | static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index, |
@@ -2813,29 +2822,29 @@ static void ipw_fw_dma_dump_command_block(struct ipw_priv *priv) | |||
2813 | 2822 | ||
2814 | IPW_DEBUG_FW(">> :\n"); | 2823 | IPW_DEBUG_FW(">> :\n"); |
2815 | address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); | 2824 | address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); |
2816 | IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address); | 2825 | IPW_DEBUG_FW_INFO("Current CB is 0x%x\n", address); |
2817 | 2826 | ||
2818 | /* Read the DMA Controlor register */ | 2827 | /* Read the DMA Controlor register */ |
2819 | register_value = ipw_read_reg32(priv, IPW_DMA_I_DMA_CONTROL); | 2828 | register_value = ipw_read_reg32(priv, IPW_DMA_I_DMA_CONTROL); |
2820 | IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x \n", register_value); | 2829 | IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x\n", register_value); |
2821 | 2830 | ||
2822 | /* Print the CB values */ | 2831 | /* Print the CB values */ |
2823 | cb_fields_address = address; | 2832 | cb_fields_address = address; |
2824 | register_value = ipw_read_reg32(priv, cb_fields_address); | 2833 | register_value = ipw_read_reg32(priv, cb_fields_address); |
2825 | IPW_DEBUG_FW_INFO("Current CB ControlField is 0x%x \n", register_value); | 2834 | IPW_DEBUG_FW_INFO("Current CB Control Field is 0x%x\n", register_value); |
2826 | 2835 | ||
2827 | cb_fields_address += sizeof(u32); | 2836 | cb_fields_address += sizeof(u32); |
2828 | register_value = ipw_read_reg32(priv, cb_fields_address); | 2837 | register_value = ipw_read_reg32(priv, cb_fields_address); |
2829 | IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x \n", register_value); | 2838 | IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x\n", register_value); |
2830 | 2839 | ||
2831 | cb_fields_address += sizeof(u32); | 2840 | cb_fields_address += sizeof(u32); |
2832 | register_value = ipw_read_reg32(priv, cb_fields_address); | 2841 | register_value = ipw_read_reg32(priv, cb_fields_address); |
2833 | IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x \n", | 2842 | IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x\n", |
2834 | register_value); | 2843 | register_value); |
2835 | 2844 | ||
2836 | cb_fields_address += sizeof(u32); | 2845 | cb_fields_address += sizeof(u32); |
2837 | register_value = ipw_read_reg32(priv, cb_fields_address); | 2846 | register_value = ipw_read_reg32(priv, cb_fields_address); |
2838 | IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x \n", register_value); | 2847 | IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x\n", register_value); |
2839 | 2848 | ||
2840 | IPW_DEBUG_FW(">> :\n"); | 2849 | IPW_DEBUG_FW(">> :\n"); |
2841 | } | 2850 | } |
@@ -2851,7 +2860,7 @@ static int ipw_fw_dma_command_block_index(struct ipw_priv *priv) | |||
2851 | current_cb_index = (current_cb_address - IPW_SHARED_SRAM_DMA_CONTROL) / | 2860 | current_cb_index = (current_cb_address - IPW_SHARED_SRAM_DMA_CONTROL) / |
2852 | sizeof(struct command_block); | 2861 | sizeof(struct command_block); |
2853 | 2862 | ||
2854 | IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n", | 2863 | IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X\n", |
2855 | current_cb_index, current_cb_address); | 2864 | current_cb_index, current_cb_address); |
2856 | 2865 | ||
2857 | IPW_DEBUG_FW(">> :\n"); | 2866 | IPW_DEBUG_FW(">> :\n"); |
@@ -2910,7 +2919,7 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address, | |||
2910 | int ret, i; | 2919 | int ret, i; |
2911 | u32 size; | 2920 | u32 size; |
2912 | 2921 | ||
2913 | IPW_DEBUG_FW(">> \n"); | 2922 | IPW_DEBUG_FW(">>\n"); |
2914 | IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n", | 2923 | IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n", |
2915 | nr, dest_address, len); | 2924 | nr, dest_address, len); |
2916 | 2925 | ||
@@ -2927,7 +2936,7 @@ static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address, | |||
2927 | IPW_DEBUG_FW_INFO(": Added new cb\n"); | 2936 | IPW_DEBUG_FW_INFO(": Added new cb\n"); |
2928 | } | 2937 | } |
2929 | 2938 | ||
2930 | IPW_DEBUG_FW("<< \n"); | 2939 | IPW_DEBUG_FW("<<\n"); |
2931 | return 0; | 2940 | return 0; |
2932 | } | 2941 | } |
2933 | 2942 | ||
@@ -2936,7 +2945,7 @@ static int ipw_fw_dma_wait(struct ipw_priv *priv) | |||
2936 | u32 current_index = 0, previous_index; | 2945 | u32 current_index = 0, previous_index; |
2937 | u32 watchdog = 0; | 2946 | u32 watchdog = 0; |
2938 | 2947 | ||
2939 | IPW_DEBUG_FW(">> : \n"); | 2948 | IPW_DEBUG_FW(">> :\n"); |
2940 | 2949 | ||
2941 | current_index = ipw_fw_dma_command_block_index(priv); | 2950 | current_index = ipw_fw_dma_command_block_index(priv); |
2942 | IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n", | 2951 | IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n", |
@@ -2965,7 +2974,7 @@ static int ipw_fw_dma_wait(struct ipw_priv *priv) | |||
2965 | ipw_set_bit(priv, IPW_RESET_REG, | 2974 | ipw_set_bit(priv, IPW_RESET_REG, |
2966 | IPW_RESET_REG_MASTER_DISABLED | IPW_RESET_REG_STOP_MASTER); | 2975 | IPW_RESET_REG_MASTER_DISABLED | IPW_RESET_REG_STOP_MASTER); |
2967 | 2976 | ||
2968 | IPW_DEBUG_FW("<< dmaWaitSync \n"); | 2977 | IPW_DEBUG_FW("<< dmaWaitSync\n"); |
2969 | return 0; | 2978 | return 0; |
2970 | } | 2979 | } |
2971 | 2980 | ||
@@ -3026,7 +3035,7 @@ static int ipw_stop_master(struct ipw_priv *priv) | |||
3026 | { | 3035 | { |
3027 | int rc; | 3036 | int rc; |
3028 | 3037 | ||
3029 | IPW_DEBUG_TRACE(">> \n"); | 3038 | IPW_DEBUG_TRACE(">>\n"); |
3030 | /* stop master. typical delay - 0 */ | 3039 | /* stop master. typical delay - 0 */ |
3031 | ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); | 3040 | ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); |
3032 | 3041 | ||
@@ -3045,7 +3054,7 @@ static int ipw_stop_master(struct ipw_priv *priv) | |||
3045 | 3054 | ||
3046 | static void ipw_arc_release(struct ipw_priv *priv) | 3055 | static void ipw_arc_release(struct ipw_priv *priv) |
3047 | { | 3056 | { |
3048 | IPW_DEBUG_TRACE(">> \n"); | 3057 | IPW_DEBUG_TRACE(">>\n"); |
3049 | mdelay(5); | 3058 | mdelay(5); |
3050 | 3059 | ||
3051 | ipw_clear_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); | 3060 | ipw_clear_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); |
@@ -3067,7 +3076,7 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) | |||
3067 | 3076 | ||
3068 | image = (__le16 *) data; | 3077 | image = (__le16 *) data; |
3069 | 3078 | ||
3070 | IPW_DEBUG_TRACE(">> \n"); | 3079 | IPW_DEBUG_TRACE(">>\n"); |
3071 | 3080 | ||
3072 | rc = ipw_stop_master(priv); | 3081 | rc = ipw_stop_master(priv); |
3073 | 3082 | ||
@@ -3181,7 +3190,7 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) | |||
3181 | void **virts; | 3190 | void **virts; |
3182 | dma_addr_t *phys; | 3191 | dma_addr_t *phys; |
3183 | 3192 | ||
3184 | IPW_DEBUG_TRACE("<< : \n"); | 3193 | IPW_DEBUG_TRACE("<< :\n"); |
3185 | 3194 | ||
3186 | virts = kmalloc(sizeof(void *) * CB_NUMBER_OF_ELEMENTS_SMALL, | 3195 | virts = kmalloc(sizeof(void *) * CB_NUMBER_OF_ELEMENTS_SMALL, |
3187 | GFP_KERNEL); | 3196 | GFP_KERNEL); |
@@ -4482,7 +4491,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4482 | case CMAS_ASSOCIATED:{ | 4491 | case CMAS_ASSOCIATED:{ |
4483 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4492 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
4484 | IPW_DL_ASSOC, | 4493 | IPW_DL_ASSOC, |
4485 | "associated: '%s' %pM \n", | 4494 | "associated: '%s' %pM\n", |
4486 | print_ssid(ssid, priv->essid, | 4495 | print_ssid(ssid, priv->essid, |
4487 | priv->essid_len), | 4496 | priv->essid_len), |
4488 | priv->bssid); | 4497 | priv->bssid); |
@@ -4563,7 +4572,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4563 | IPW_DL_ASSOC, | 4572 | IPW_DL_ASSOC, |
4564 | "deauthenticated: '%s' " | 4573 | "deauthenticated: '%s' " |
4565 | "%pM" | 4574 | "%pM" |
4566 | ": (0x%04X) - %s \n", | 4575 | ": (0x%04X) - %s\n", |
4567 | print_ssid(ssid, | 4576 | print_ssid(ssid, |
4568 | priv-> | 4577 | priv-> |
4569 | essid, | 4578 | essid, |
@@ -4614,7 +4623,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4614 | 4623 | ||
4615 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4624 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
4616 | IPW_DL_ASSOC, | 4625 | IPW_DL_ASSOC, |
4617 | "disassociated: '%s' %pM \n", | 4626 | "disassociated: '%s' %pM\n", |
4618 | print_ssid(ssid, priv->essid, | 4627 | print_ssid(ssid, priv->essid, |
4619 | priv->essid_len), | 4628 | priv->essid_len), |
4620 | priv->bssid); | 4629 | priv->bssid); |
@@ -4652,7 +4661,7 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4652 | switch (auth->state) { | 4661 | switch (auth->state) { |
4653 | case CMAS_AUTHENTICATED: | 4662 | case CMAS_AUTHENTICATED: |
4654 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, | 4663 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, |
4655 | "authenticated: '%s' %pM \n", | 4664 | "authenticated: '%s' %pM\n", |
4656 | print_ssid(ssid, priv->essid, | 4665 | print_ssid(ssid, priv->essid, |
4657 | priv->essid_len), | 4666 | priv->essid_len), |
4658 | priv->bssid); | 4667 | priv->bssid); |
@@ -6925,7 +6934,7 @@ static u8 ipw_qos_current_mode(struct ipw_priv * priv) | |||
6925 | } else { | 6934 | } else { |
6926 | mode = priv->ieee->mode; | 6935 | mode = priv->ieee->mode; |
6927 | } | 6936 | } |
6928 | IPW_DEBUG_QOS("QoS network/card mode %d \n", mode); | 6937 | IPW_DEBUG_QOS("QoS network/card mode %d\n", mode); |
6929 | return mode; | 6938 | return mode; |
6930 | } | 6939 | } |
6931 | 6940 | ||
@@ -6965,7 +6974,7 @@ static int ipw_qos_handle_probe_response(struct ipw_priv *priv, | |||
6965 | &def_parameters_OFDM, size); | 6974 | &def_parameters_OFDM, size); |
6966 | 6975 | ||
6967 | if ((network->qos_data.active == 1) && (active_network == 1)) { | 6976 | if ((network->qos_data.active == 1) && (active_network == 1)) { |
6968 | IPW_DEBUG_QOS("QoS was disabled call qos_activate \n"); | 6977 | IPW_DEBUG_QOS("QoS was disabled call qos_activate\n"); |
6969 | schedule_work(&priv->qos_activate); | 6978 | schedule_work(&priv->qos_activate); |
6970 | } | 6979 | } |
6971 | 6980 | ||
@@ -7542,7 +7551,7 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
7542 | return err; | 7551 | return err; |
7543 | } | 7552 | } |
7544 | 7553 | ||
7545 | IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM \n", | 7554 | IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n", |
7546 | print_ssid(ssid, priv->essid, priv->essid_len), | 7555 | print_ssid(ssid, priv->essid, priv->essid_len), |
7547 | priv->bssid); | 7556 | priv->bssid); |
7548 | 7557 | ||
@@ -8793,7 +8802,7 @@ static int ipw_wx_set_freq(struct net_device *dev, | |||
8793 | } | 8802 | } |
8794 | } | 8803 | } |
8795 | 8804 | ||
8796 | IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); | 8805 | IPW_DEBUG_WX("SET Freq/Channel -> %d\n", fwrq->m); |
8797 | mutex_lock(&priv->mutex); | 8806 | mutex_lock(&priv->mutex); |
8798 | ret = ipw_set_channel(priv, channel); | 8807 | ret = ipw_set_channel(priv, channel); |
8799 | mutex_unlock(&priv->mutex); | 8808 | mutex_unlock(&priv->mutex); |
@@ -8835,7 +8844,7 @@ static int ipw_wx_get_freq(struct net_device *dev, | |||
8835 | wrqu->freq.m = 0; | 8844 | wrqu->freq.m = 0; |
8836 | 8845 | ||
8837 | mutex_unlock(&priv->mutex); | 8846 | mutex_unlock(&priv->mutex); |
8838 | IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); | 8847 | IPW_DEBUG_WX("GET Freq/Channel -> %d\n", priv->channel); |
8839 | return 0; | 8848 | return 0; |
8840 | } | 8849 | } |
8841 | 8850 | ||
@@ -9230,7 +9239,7 @@ static int ipw_wx_get_sens(struct net_device *dev, | |||
9230 | wrqu->sens.value = priv->roaming_threshold; | 9239 | wrqu->sens.value = priv->roaming_threshold; |
9231 | mutex_unlock(&priv->mutex); | 9240 | mutex_unlock(&priv->mutex); |
9232 | 9241 | ||
9233 | IPW_DEBUG_WX("GET roaming threshold -> %s %d \n", | 9242 | IPW_DEBUG_WX("GET roaming threshold -> %s %d\n", |
9234 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); | 9243 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); |
9235 | 9244 | ||
9236 | return 0; | 9245 | return 0; |
@@ -9358,7 +9367,7 @@ static int ipw_wx_get_rate(struct net_device *dev, | |||
9358 | wrqu->bitrate.value = priv->last_rate; | 9367 | wrqu->bitrate.value = priv->last_rate; |
9359 | wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0; | 9368 | wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0; |
9360 | mutex_unlock(&priv->mutex); | 9369 | mutex_unlock(&priv->mutex); |
9361 | IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); | 9370 | IPW_DEBUG_WX("GET Rate -> %d\n", wrqu->bitrate.value); |
9362 | return 0; | 9371 | return 0; |
9363 | } | 9372 | } |
9364 | 9373 | ||
@@ -9381,7 +9390,7 @@ static int ipw_wx_set_rts(struct net_device *dev, | |||
9381 | 9390 | ||
9382 | ipw_send_rts_threshold(priv, priv->rts_threshold); | 9391 | ipw_send_rts_threshold(priv, priv->rts_threshold); |
9383 | mutex_unlock(&priv->mutex); | 9392 | mutex_unlock(&priv->mutex); |
9384 | IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold); | 9393 | IPW_DEBUG_WX("SET RTS Threshold -> %d\n", priv->rts_threshold); |
9385 | return 0; | 9394 | return 0; |
9386 | } | 9395 | } |
9387 | 9396 | ||
@@ -9395,7 +9404,7 @@ static int ipw_wx_get_rts(struct net_device *dev, | |||
9395 | wrqu->rts.fixed = 0; /* no auto select */ | 9404 | wrqu->rts.fixed = 0; /* no auto select */ |
9396 | wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); | 9405 | wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); |
9397 | mutex_unlock(&priv->mutex); | 9406 | mutex_unlock(&priv->mutex); |
9398 | IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value); | 9407 | IPW_DEBUG_WX("GET RTS Threshold -> %d\n", wrqu->rts.value); |
9399 | return 0; | 9408 | return 0; |
9400 | } | 9409 | } |
9401 | 9410 | ||
@@ -9445,7 +9454,7 @@ static int ipw_wx_get_txpow(struct net_device *dev, | |||
9445 | wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; | 9454 | wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; |
9446 | mutex_unlock(&priv->mutex); | 9455 | mutex_unlock(&priv->mutex); |
9447 | 9456 | ||
9448 | IPW_DEBUG_WX("GET TX Power -> %s %d \n", | 9457 | IPW_DEBUG_WX("GET TX Power -> %s %d\n", |
9449 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); | 9458 | wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); |
9450 | 9459 | ||
9451 | return 0; | 9460 | return 0; |
@@ -9471,7 +9480,7 @@ static int ipw_wx_set_frag(struct net_device *dev, | |||
9471 | 9480 | ||
9472 | ipw_send_frag_threshold(priv, wrqu->frag.value); | 9481 | ipw_send_frag_threshold(priv, wrqu->frag.value); |
9473 | mutex_unlock(&priv->mutex); | 9482 | mutex_unlock(&priv->mutex); |
9474 | IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value); | 9483 | IPW_DEBUG_WX("SET Frag Threshold -> %d\n", wrqu->frag.value); |
9475 | return 0; | 9484 | return 0; |
9476 | } | 9485 | } |
9477 | 9486 | ||
@@ -9485,7 +9494,7 @@ static int ipw_wx_get_frag(struct net_device *dev, | |||
9485 | wrqu->frag.fixed = 0; /* no auto select */ | 9494 | wrqu->frag.fixed = 0; /* no auto select */ |
9486 | wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); | 9495 | wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); |
9487 | mutex_unlock(&priv->mutex); | 9496 | mutex_unlock(&priv->mutex); |
9488 | IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); | 9497 | IPW_DEBUG_WX("GET Frag Threshold -> %d\n", wrqu->frag.value); |
9489 | 9498 | ||
9490 | return 0; | 9499 | return 0; |
9491 | } | 9500 | } |
@@ -9549,7 +9558,7 @@ static int ipw_wx_get_retry(struct net_device *dev, | |||
9549 | } | 9558 | } |
9550 | mutex_unlock(&priv->mutex); | 9559 | mutex_unlock(&priv->mutex); |
9551 | 9560 | ||
9552 | IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value); | 9561 | IPW_DEBUG_WX("GET retry -> %d\n", wrqu->retry.value); |
9553 | 9562 | ||
9554 | return 0; | 9563 | return 0; |
9555 | } | 9564 | } |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index e31a5ccebea2..a684a72eb6e9 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -10,6 +10,8 @@ CFLAGS_iwl-devtrace.o := -I$(src) | |||
10 | # AGN | 10 | # AGN |
11 | obj-$(CONFIG_IWLAGN) += iwlagn.o | 11 | obj-$(CONFIG_IWLAGN) += iwlagn.o |
12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o | 12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o |
13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o | ||
14 | iwlagn-objs += iwl-agn-lib.o | ||
13 | 15 | ||
14 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 16 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
15 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o | 17 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 9e392896005d..9a0191a5ea35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-agn.h" | 45 | #include "iwl-agn.h" |
46 | #include "iwl-helpers.h" | 46 | #include "iwl-helpers.h" |
47 | #include "iwl-5000-hw.h" | 47 | #include "iwl-agn-hw.h" |
48 | #include "iwl-agn-led.h" | 48 | #include "iwl-agn-led.h" |
49 | 49 | ||
50 | /* Highest firmware API version supported */ | 50 | /* Highest firmware API version supported */ |
@@ -118,7 +118,7 @@ static struct iwl_sensitivity_ranges iwl1000_sensitivity = { | |||
118 | static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | 118 | static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) |
119 | { | 119 | { |
120 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 120 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
121 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | 121 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
122 | priv->cfg->num_of_queues = | 122 | priv->cfg->num_of_queues = |
123 | priv->cfg->mod_params->num_of_queues; | 123 | priv->cfg->mod_params->num_of_queues; |
124 | 124 | ||
@@ -126,13 +126,13 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
126 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 126 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
127 | priv->hw_params.scd_bc_tbls_size = | 127 | priv->hw_params.scd_bc_tbls_size = |
128 | priv->cfg->num_of_queues * | 128 | priv->cfg->num_of_queues * |
129 | sizeof(struct iwl5000_scd_bc_tbl); | 129 | sizeof(struct iwlagn_scd_bc_tbl); |
130 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 130 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
131 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 131 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
132 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 132 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
133 | 133 | ||
134 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | 134 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
135 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | 135 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
136 | 136 | ||
137 | priv->hw_params.max_bsm_size = 0; | 137 | priv->hw_params.max_bsm_size = 0; |
138 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 138 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
@@ -162,25 +162,25 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
162 | 162 | ||
163 | static struct iwl_lib_ops iwl1000_lib = { | 163 | static struct iwl_lib_ops iwl1000_lib = { |
164 | .set_hw_params = iwl1000_hw_set_hw_params, | 164 | .set_hw_params = iwl1000_hw_set_hw_params, |
165 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 165 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
166 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 166 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
167 | .txq_set_sched = iwl5000_txq_set_sched, | 167 | .txq_set_sched = iwlagn_txq_set_sched, |
168 | .txq_agg_enable = iwl5000_txq_agg_enable, | 168 | .txq_agg_enable = iwlagn_txq_agg_enable, |
169 | .txq_agg_disable = iwl5000_txq_agg_disable, | 169 | .txq_agg_disable = iwlagn_txq_agg_disable, |
170 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 170 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
171 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 171 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
172 | .txq_init = iwl_hw_tx_queue_init, | 172 | .txq_init = iwl_hw_tx_queue_init, |
173 | .rx_handler_setup = iwl5000_rx_handler_setup, | 173 | .rx_handler_setup = iwlagn_rx_handler_setup, |
174 | .setup_deferred_work = iwl5000_setup_deferred_work, | 174 | .setup_deferred_work = iwlagn_setup_deferred_work, |
175 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 175 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
176 | .load_ucode = iwl5000_load_ucode, | 176 | .load_ucode = iwlagn_load_ucode, |
177 | .dump_nic_event_log = iwl_dump_nic_event_log, | 177 | .dump_nic_event_log = iwl_dump_nic_event_log, |
178 | .dump_nic_error_log = iwl_dump_nic_error_log, | 178 | .dump_nic_error_log = iwl_dump_nic_error_log, |
179 | .dump_csr = iwl_dump_csr, | 179 | .dump_csr = iwl_dump_csr, |
180 | .dump_fh = iwl_dump_fh, | 180 | .dump_fh = iwl_dump_fh, |
181 | .init_alive_start = iwl5000_init_alive_start, | 181 | .init_alive_start = iwlagn_init_alive_start, |
182 | .alive_notify = iwl5000_alive_notify, | 182 | .alive_notify = iwlagn_alive_notify, |
183 | .send_tx_power = iwl5000_send_tx_power, | 183 | .send_tx_power = iwlagn_send_tx_power, |
184 | .update_chain_flags = iwl_update_chain_flags, | 184 | .update_chain_flags = iwl_update_chain_flags, |
185 | .apm_ops = { | 185 | .apm_ops = { |
186 | .init = iwl_apm_init, | 186 | .init = iwl_apm_init, |
@@ -190,25 +190,25 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
190 | }, | 190 | }, |
191 | .eeprom_ops = { | 191 | .eeprom_ops = { |
192 | .regulatory_bands = { | 192 | .regulatory_bands = { |
193 | EEPROM_5000_REG_BAND_1_CHANNELS, | 193 | EEPROM_REG_BAND_1_CHANNELS, |
194 | EEPROM_5000_REG_BAND_2_CHANNELS, | 194 | EEPROM_REG_BAND_2_CHANNELS, |
195 | EEPROM_5000_REG_BAND_3_CHANNELS, | 195 | EEPROM_REG_BAND_3_CHANNELS, |
196 | EEPROM_5000_REG_BAND_4_CHANNELS, | 196 | EEPROM_REG_BAND_4_CHANNELS, |
197 | EEPROM_5000_REG_BAND_5_CHANNELS, | 197 | EEPROM_REG_BAND_5_CHANNELS, |
198 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 198 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
199 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 199 | EEPROM_REG_BAND_52_HT40_CHANNELS |
200 | }, | 200 | }, |
201 | .verify_signature = iwlcore_eeprom_verify_signature, | 201 | .verify_signature = iwlcore_eeprom_verify_signature, |
202 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 202 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
203 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 203 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
204 | .calib_version = iwl5000_eeprom_calib_version, | 204 | .calib_version = iwlagn_eeprom_calib_version, |
205 | .query_addr = iwl5000_eeprom_query_addr, | 205 | .query_addr = iwlagn_eeprom_query_addr, |
206 | }, | 206 | }, |
207 | .post_associate = iwl_post_associate, | 207 | .post_associate = iwl_post_associate, |
208 | .isr = iwl_isr_ict, | 208 | .isr = iwl_isr_ict, |
209 | .config_ap = iwl_config_ap, | 209 | .config_ap = iwl_config_ap, |
210 | .temp_ops = { | 210 | .temp_ops = { |
211 | .temperature = iwl5000_temperature, | 211 | .temperature = iwlagn_temperature, |
212 | .set_ct_kill = iwl1000_set_ct_threshold, | 212 | .set_ct_kill = iwl1000_set_ct_threshold, |
213 | }, | 213 | }, |
214 | .add_bcast_station = iwl_add_bcast_station, | 214 | .add_bcast_station = iwl_add_bcast_station, |
@@ -218,10 +218,10 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
218 | }; | 218 | }; |
219 | 219 | ||
220 | static const struct iwl_ops iwl1000_ops = { | 220 | static const struct iwl_ops iwl1000_ops = { |
221 | .ucode = &iwl5000_ucode, | 221 | .ucode = &iwlagn_ucode, |
222 | .lib = &iwl1000_lib, | 222 | .lib = &iwl1000_lib, |
223 | .hcmd = &iwl5000_hcmd, | 223 | .hcmd = &iwlagn_hcmd, |
224 | .utils = &iwl5000_hcmd_utils, | 224 | .utils = &iwlagn_hcmd_utils, |
225 | .led = &iwlagn_led_ops, | 225 | .led = &iwlagn_led_ops, |
226 | }; | 226 | }; |
227 | 227 | ||
@@ -234,10 +234,10 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
234 | .ops = &iwl1000_ops, | 234 | .ops = &iwl1000_ops, |
235 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 235 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
236 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | 236 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
237 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 237 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, |
238 | .num_of_queues = IWL50_NUM_QUEUES, | 238 | .num_of_queues = IWLAGN_NUM_QUEUES, |
239 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 239 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
240 | .mod_params = &iwl50_mod_params, | 240 | .mod_params = &iwlagn_mod_params, |
241 | .valid_tx_ant = ANT_A, | 241 | .valid_tx_ant = ANT_A, |
242 | .valid_rx_ant = ANT_AB, | 242 | .valid_rx_ant = ANT_AB, |
243 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 243 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -253,6 +253,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
253 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 253 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
254 | .chain_noise_scale = 1000, | 254 | .chain_noise_scale = 1000, |
255 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 255 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
256 | .max_event_log_size = 128, | ||
256 | }; | 257 | }; |
257 | 258 | ||
258 | struct iwl_cfg iwl1000_bg_cfg = { | 259 | struct iwl_cfg iwl1000_bg_cfg = { |
@@ -264,10 +265,10 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
264 | .ops = &iwl1000_ops, | 265 | .ops = &iwl1000_ops, |
265 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 266 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
266 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | 267 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
267 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 268 | .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, |
268 | .num_of_queues = IWL50_NUM_QUEUES, | 269 | .num_of_queues = IWLAGN_NUM_QUEUES, |
269 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 270 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
270 | .mod_params = &iwl50_mod_params, | 271 | .mod_params = &iwlagn_mod_params, |
271 | .valid_tx_ant = ANT_A, | 272 | .valid_tx_ant = ANT_A, |
272 | .valid_rx_ant = ANT_AB, | 273 | .valid_rx_ant = ANT_AB, |
273 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 274 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -282,6 +283,7 @@ struct iwl_cfg iwl1000_bg_cfg = { | |||
282 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | 283 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, |
283 | .chain_noise_scale = 1000, | 284 | .chain_noise_scale = 1000, |
284 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 285 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
286 | .max_event_log_size = 128, | ||
285 | }; | 287 | }; |
286 | 288 | ||
287 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); | 289 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 074f42a7dcad..91bcb4e3cdfb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h | |||
@@ -71,10 +71,6 @@ | |||
71 | 71 | ||
72 | #include "iwl-eeprom.h" | 72 | #include "iwl-eeprom.h" |
73 | 73 | ||
74 | /* Time constants */ | ||
75 | #define SHORT_SLOT_TIME 9 | ||
76 | #define LONG_SLOT_TIME 20 | ||
77 | |||
78 | /* RSSI to dBm */ | 74 | /* RSSI to dBm */ |
79 | #define IWL39_RSSI_OFFSET 95 | 75 | #define IWL39_RSSI_OFFSET 95 |
80 | 76 | ||
@@ -230,7 +226,6 @@ struct iwl3945_eeprom { | |||
230 | 226 | ||
231 | /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ | 227 | /* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ |
232 | #define IWL39_NUM_QUEUES 5 | 228 | #define IWL39_NUM_QUEUES 5 |
233 | #define IWL_NUM_SCAN_RATES (2) | ||
234 | 229 | ||
235 | #define IWL_DEFAULT_TX_RETRY 15 | 230 | #define IWL_DEFAULT_TX_RETRY 15 |
236 | 231 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 8f85a0db5c39..32eb4709acac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c | |||
@@ -342,7 +342,7 @@ void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 s | |||
342 | struct ieee80211_supported_band *sband; | 342 | struct ieee80211_supported_band *sband; |
343 | int i; | 343 | int i; |
344 | 344 | ||
345 | IWL_DEBUG_INFO(priv, "enter \n"); | 345 | IWL_DEBUG_INFO(priv, "enter\n"); |
346 | if (sta_id == priv->hw_params.bcast_sta_id) | 346 | if (sta_id == priv->hw_params.bcast_sta_id) |
347 | goto out; | 347 | goto out; |
348 | 348 | ||
@@ -648,7 +648,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, | |||
648 | unsigned long flags; | 648 | unsigned long flags; |
649 | u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; | 649 | u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; |
650 | s8 max_rate_idx = -1; | 650 | s8 max_rate_idx = -1; |
651 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 651 | struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; |
652 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 652 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
653 | 653 | ||
654 | IWL_DEBUG_RATE(priv, "enter\n"); | 654 | IWL_DEBUG_RATE(priv, "enter\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7ac6cec006d0..bde3b4cbab9d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -192,12 +192,12 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) | |||
192 | } | 192 | } |
193 | 193 | ||
194 | #ifdef CONFIG_IWLWIFI_DEBUG | 194 | #ifdef CONFIG_IWLWIFI_DEBUG |
195 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x | 195 | #define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x |
196 | 196 | ||
197 | static const char *iwl3945_get_tx_fail_reason(u32 status) | 197 | static const char *iwl3945_get_tx_fail_reason(u32 status) |
198 | { | 198 | { |
199 | switch (status & TX_STATUS_MSK) { | 199 | switch (status & TX_STATUS_MSK) { |
200 | case TX_STATUS_SUCCESS: | 200 | case TX_3945_STATUS_SUCCESS: |
201 | return "SUCCESS"; | 201 | return "SUCCESS"; |
202 | TX_STATUS_ENTRY(SHORT_LIMIT); | 202 | TX_STATUS_ENTRY(SHORT_LIMIT); |
203 | TX_STATUS_ENTRY(LONG_LIMIT); | 203 | TX_STATUS_ENTRY(LONG_LIMIT); |
@@ -487,7 +487,7 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, | |||
487 | * but you can hack it to show more, if you'd like to. */ | 487 | * but you can hack it to show more, if you'd like to. */ |
488 | if (dataframe) | 488 | if (dataframe) |
489 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | 489 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " |
490 | "len=%u, rssi=%d, chnl=%d, rate=%d, \n", | 490 | "len=%u, rssi=%d, chnl=%d, rate=%d,\n", |
491 | title, le16_to_cpu(fc), header->addr1[5], | 491 | title, le16_to_cpu(fc), header->addr1[5], |
492 | length, rssi, channel, rate); | 492 | length, rssi, channel, rate); |
493 | else { | 493 | else { |
@@ -549,7 +549,6 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
549 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 549 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
550 | u16 len = le16_to_cpu(rx_hdr->len); | 550 | u16 len = le16_to_cpu(rx_hdr->len); |
551 | struct sk_buff *skb; | 551 | struct sk_buff *skb; |
552 | int ret; | ||
553 | __le16 fc = hdr->frame_control; | 552 | __le16 fc = hdr->frame_control; |
554 | 553 | ||
555 | /* We received data from the HW, so stop the watchdog */ | 554 | /* We received data from the HW, so stop the watchdog */ |
@@ -566,9 +565,9 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
566 | return; | 565 | return; |
567 | } | 566 | } |
568 | 567 | ||
569 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); | 568 | skb = dev_alloc_skb(128); |
570 | if (!skb) { | 569 | if (!skb) { |
571 | IWL_ERR(priv, "alloc_skb failed\n"); | 570 | IWL_ERR(priv, "dev_alloc_skb failed\n"); |
572 | return; | 571 | return; |
573 | } | 572 | } |
574 | 573 | ||
@@ -577,37 +576,13 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
577 | (struct ieee80211_hdr *)rxb_addr(rxb), | 576 | (struct ieee80211_hdr *)rxb_addr(rxb), |
578 | le32_to_cpu(rx_end->status), stats); | 577 | le32_to_cpu(rx_end->status), stats); |
579 | 578 | ||
580 | skb_reserve(skb, IWL_LINK_HDR_MAX); | ||
581 | skb_add_rx_frag(skb, 0, rxb->page, | 579 | skb_add_rx_frag(skb, 0, rxb->page, |
582 | (void *)rx_hdr->payload - (void *)pkt, len); | 580 | (void *)rx_hdr->payload - (void *)pkt, len); |
583 | 581 | ||
584 | /* mac80211 currently doesn't support paged SKB. Convert it to | ||
585 | * linear SKB for management frame and data frame requires | ||
586 | * software decryption or software defragementation. */ | ||
587 | if (ieee80211_is_mgmt(fc) || | ||
588 | ieee80211_has_protected(fc) || | ||
589 | ieee80211_has_morefrags(fc) || | ||
590 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) | ||
591 | ret = skb_linearize(skb); | ||
592 | else | ||
593 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
594 | 0 : -ENOMEM; | ||
595 | |||
596 | if (ret) { | ||
597 | kfree_skb(skb); | ||
598 | goto out; | ||
599 | } | ||
600 | |||
601 | /* | ||
602 | * XXX: We cannot touch the page and its virtual memory (pkt) after | ||
603 | * here. It might have already been freed by the above skb change. | ||
604 | */ | ||
605 | |||
606 | iwl_update_stats(priv, false, fc, len); | 582 | iwl_update_stats(priv, false, fc, len); |
607 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | 583 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); |
608 | 584 | ||
609 | ieee80211_rx(priv->hw, skb); | 585 | ieee80211_rx(priv->hw, skb); |
610 | out: | ||
611 | priv->alloc_rxb_page--; | 586 | priv->alloc_rxb_page--; |
612 | rxb->page = NULL; | 587 | rxb->page = NULL; |
613 | } | 588 | } |
@@ -623,9 +598,8 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
623 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); | 598 | struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); |
624 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); | 599 | struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); |
625 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); | 600 | struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); |
626 | int snr; | 601 | u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg); |
627 | u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); | 602 | u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff); |
628 | u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); | ||
629 | u8 network_packet; | 603 | u8 network_packet; |
630 | 604 | ||
631 | rx_status.flag = 0; | 605 | rx_status.flag = 0; |
@@ -663,43 +637,19 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
663 | /* Convert 3945's rssi indicator to dBm */ | 637 | /* Convert 3945's rssi indicator to dBm */ |
664 | rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; | 638 | rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; |
665 | 639 | ||
666 | /* Set default noise value to -127 */ | 640 | IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n", |
667 | if (priv->last_rx_noise == 0) | 641 | rx_status.signal, rx_stats_sig_avg, |
668 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 642 | rx_stats_noise_diff); |
669 | |||
670 | /* 3945 provides noise info for OFDM frames only. | ||
671 | * sig_avg and noise_diff are measured by the 3945's digital signal | ||
672 | * processor (DSP), and indicate linear levels of signal level and | ||
673 | * distortion/noise within the packet preamble after | ||
674 | * automatic gain control (AGC). sig_avg should stay fairly | ||
675 | * constant if the radio's AGC is working well. | ||
676 | * Since these values are linear (not dB or dBm), linear | ||
677 | * signal-to-noise ratio (SNR) is (sig_avg / noise_diff). | ||
678 | * Convert linear SNR to dB SNR, then subtract that from rssi dBm | ||
679 | * to obtain noise level in dBm. | ||
680 | * Calculate rx_status.signal (quality indicator in %) based on SNR. */ | ||
681 | if (rx_stats_noise_diff) { | ||
682 | snr = rx_stats_sig_avg / rx_stats_noise_diff; | ||
683 | rx_status.noise = rx_status.signal - | ||
684 | iwl3945_calc_db_from_ratio(snr); | ||
685 | } else { | ||
686 | rx_status.noise = priv->last_rx_noise; | ||
687 | } | ||
688 | |||
689 | |||
690 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n", | ||
691 | rx_status.signal, rx_status.noise, | ||
692 | rx_stats_sig_avg, rx_stats_noise_diff); | ||
693 | 643 | ||
694 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 644 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
695 | 645 | ||
696 | network_packet = iwl3945_is_network_packet(priv, header); | 646 | network_packet = iwl3945_is_network_packet(priv, header); |
697 | 647 | ||
698 | IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", | 648 | IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n", |
699 | network_packet ? '*' : ' ', | 649 | network_packet ? '*' : ' ', |
700 | le16_to_cpu(rx_hdr->channel), | 650 | le16_to_cpu(rx_hdr->channel), |
701 | rx_status.signal, rx_status.signal, | 651 | rx_status.signal, rx_status.signal, |
702 | rx_status.noise, rx_status.rate_idx); | 652 | rx_status.rate_idx); |
703 | 653 | ||
704 | /* Set "1" to report good data frames in groups of 100 */ | 654 | /* Set "1" to report good data frames in groups of 100 */ |
705 | iwl3945_dbg_report_frame(priv, pkt, header, 1); | 655 | iwl3945_dbg_report_frame(priv, pkt, header, 1); |
@@ -710,7 +660,6 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
710 | le32_to_cpu(rx_end->beacon_timestamp); | 660 | le32_to_cpu(rx_end->beacon_timestamp); |
711 | priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp); | 661 | priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp); |
712 | priv->_3945.last_rx_rssi = rx_status.signal; | 662 | priv->_3945.last_rx_rssi = rx_status.signal; |
713 | priv->last_rx_noise = rx_status.noise; | ||
714 | } | 663 | } |
715 | 664 | ||
716 | iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); | 665 | iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); |
@@ -1050,7 +999,7 @@ static void iwl3945_nic_config(struct iwl_priv *priv) | |||
1050 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); | 999 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); |
1051 | 1000 | ||
1052 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) | 1001 | if (rev_id & PCI_CFG_REV_ID_BIT_RTP) |
1053 | IWL_DEBUG_INFO(priv, "RTP type \n"); | 1002 | IWL_DEBUG_INFO(priv, "RTP type\n"); |
1054 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { | 1003 | else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { |
1055 | IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); | 1004 | IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); |
1056 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 1005 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
@@ -2822,6 +2771,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2822 | .broken_powersave = true, | 2771 | .broken_powersave = true, |
2823 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2772 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
2824 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 2773 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
2774 | .max_event_log_size = 512, | ||
2825 | }; | 2775 | }; |
2826 | 2776 | ||
2827 | static struct iwl_cfg iwl3945_abg_cfg = { | 2777 | static struct iwl_cfg iwl3945_abg_cfg = { |
@@ -2841,6 +2791,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2841 | .broken_powersave = true, | 2791 | .broken_powersave = true, |
2842 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2792 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
2843 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 2793 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
2794 | .max_event_log_size = 512, | ||
2844 | }; | 2795 | }; |
2845 | 2796 | ||
2846 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { | 2797 | DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 67ef562e8db1..cd4b61ae25b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h | |||
@@ -81,26 +81,6 @@ | |||
81 | */ | 81 | */ |
82 | #define IWL49_FIRST_AMPDU_QUEUE 7 | 82 | #define IWL49_FIRST_AMPDU_QUEUE 7 |
83 | 83 | ||
84 | /* Time constants */ | ||
85 | #define SHORT_SLOT_TIME 9 | ||
86 | #define LONG_SLOT_TIME 20 | ||
87 | |||
88 | /* RSSI to dBm */ | ||
89 | #define IWL49_RSSI_OFFSET 44 | ||
90 | |||
91 | |||
92 | /* PCI registers */ | ||
93 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | ||
94 | |||
95 | /* PCI register values */ | ||
96 | #define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 | ||
97 | #define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 | ||
98 | |||
99 | #define IWL_NUM_SCAN_RATES (2) | ||
100 | |||
101 | #define IWL_DEFAULT_TX_RETRY 15 | ||
102 | |||
103 | |||
104 | /* Sizes and addresses for instruction and data memory (SRAM) in | 84 | /* Sizes and addresses for instruction and data memory (SRAM) in |
105 | * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ | 85 | * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ |
106 | #define IWL49_RTC_INST_LOWER_BOUND (0x000000) | 86 | #define IWL49_RTC_INST_LOWER_BOUND (0x000000) |
@@ -393,10 +373,6 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) | |||
393 | * location(s) in command (struct iwl4965_txpowertable_cmd). | 373 | * location(s) in command (struct iwl4965_txpowertable_cmd). |
394 | */ | 374 | */ |
395 | 375 | ||
396 | /* Limit range of txpower output target to be between these values */ | ||
397 | #define IWL_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */ | ||
398 | #define IWL_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ | ||
399 | |||
400 | /** | 376 | /** |
401 | * When MIMO is used (2 transmitters operating simultaneously), driver should | 377 | * When MIMO is used (2 transmitters operating simultaneously), driver should |
402 | * limit each transmitter to deliver a max of 3 dB below the regulatory limit | 378 | * limit each transmitter to deliver a max of 3 dB below the regulatory limit |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 89aba76e4a2c..2e3cda75f3ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "iwl-calib.h" | 46 | #include "iwl-calib.h" |
47 | #include "iwl-sta.h" | 47 | #include "iwl-sta.h" |
48 | #include "iwl-agn-led.h" | 48 | #include "iwl-agn-led.h" |
49 | #include "iwl-agn.h" | ||
49 | 50 | ||
50 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | 51 | static int iwl4965_send_tx_power(struct iwl_priv *priv); |
51 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | 52 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); |
@@ -60,14 +61,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | |||
60 | #define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode" | 61 | #define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode" |
61 | #define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api) | 62 | #define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api) |
62 | 63 | ||
63 | |||
64 | /* module parameters */ | ||
65 | static struct iwl_mod_params iwl4965_mod_params = { | ||
66 | .amsdu_size_8K = 1, | ||
67 | .restart_fw = 1, | ||
68 | /* the rest are 0 by default */ | ||
69 | }; | ||
70 | |||
71 | /* check contents of special bootstrap uCode SRAM */ | 64 | /* check contents of special bootstrap uCode SRAM */ |
72 | static int iwl4965_verify_bsm(struct iwl_priv *priv) | 65 | static int iwl4965_verify_bsm(struct iwl_priv *priv) |
73 | { | 66 | { |
@@ -417,7 +410,7 @@ static void iwl4965_gain_computation(struct iwl_priv *priv, | |||
417 | sizeof(cmd), &cmd); | 410 | sizeof(cmd), &cmd); |
418 | if (ret) | 411 | if (ret) |
419 | IWL_DEBUG_CALIB(priv, "fail sending cmd " | 412 | IWL_DEBUG_CALIB(priv, "fail sending cmd " |
420 | "REPLY_PHY_CALIBRATION_CMD \n"); | 413 | "REPLY_PHY_CALIBRATION_CMD\n"); |
421 | 414 | ||
422 | /* TODO we might want recalculate | 415 | /* TODO we might want recalculate |
423 | * rx_chain in rxon cmd */ | 416 | * rx_chain in rxon cmd */ |
@@ -1619,19 +1612,19 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) | |||
1619 | 1612 | ||
1620 | /* get absolute value */ | 1613 | /* get absolute value */ |
1621 | if (temp_diff < 0) { | 1614 | if (temp_diff < 0) { |
1622 | IWL_DEBUG_POWER(priv, "Getting cooler, delta %d, \n", temp_diff); | 1615 | IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff); |
1623 | temp_diff = -temp_diff; | 1616 | temp_diff = -temp_diff; |
1624 | } else if (temp_diff == 0) | 1617 | } else if (temp_diff == 0) |
1625 | IWL_DEBUG_POWER(priv, "Same temp, \n"); | 1618 | IWL_DEBUG_POWER(priv, "Temperature unchanged\n"); |
1626 | else | 1619 | else |
1627 | IWL_DEBUG_POWER(priv, "Getting warmer, delta %d, \n", temp_diff); | 1620 | IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff); |
1628 | 1621 | ||
1629 | if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { | 1622 | if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { |
1630 | IWL_DEBUG_POWER(priv, "Thermal txpower calib not needed\n"); | 1623 | IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n"); |
1631 | return 0; | 1624 | return 0; |
1632 | } | 1625 | } |
1633 | 1626 | ||
1634 | IWL_DEBUG_POWER(priv, "Thermal txpower calib needed\n"); | 1627 | IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n"); |
1635 | 1628 | ||
1636 | return 1; | 1629 | return 1; |
1637 | } | 1630 | } |
@@ -1880,7 +1873,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
1880 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1873 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1881 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1874 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1882 | info->flags |= iwl_tx_status_to_mac80211(status); | 1875 | info->flags |= iwl_tx_status_to_mac80211(status); |
1883 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 1876 | iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); |
1884 | /* FIXME: code repetition end */ | 1877 | /* FIXME: code repetition end */ |
1885 | 1878 | ||
1886 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | 1879 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", |
@@ -2020,7 +2013,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2020 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | 2013 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); |
2021 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " | 2014 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " |
2022 | "%d index %d\n", scd_ssn , index); | 2015 | "%d index %d\n", scd_ssn , index); |
2023 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2016 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); |
2024 | if (qc) | 2017 | if (qc) |
2025 | iwl_free_tfds_in_queue(priv, sta_id, | 2018 | iwl_free_tfds_in_queue(priv, sta_id, |
2026 | tid, freed); | 2019 | tid, freed); |
@@ -2037,7 +2030,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2037 | } else { | 2030 | } else { |
2038 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 2031 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
2039 | info->flags |= iwl_tx_status_to_mac80211(status); | 2032 | info->flags |= iwl_tx_status_to_mac80211(status); |
2040 | iwl_hwrate_to_tx_control(priv, | 2033 | iwlagn_hwrate_to_tx_control(priv, |
2041 | le32_to_cpu(tx_resp->rate_n_flags), | 2034 | le32_to_cpu(tx_resp->rate_n_flags), |
2042 | info); | 2035 | info); |
2043 | 2036 | ||
@@ -2048,7 +2041,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2048 | le32_to_cpu(tx_resp->rate_n_flags), | 2041 | le32_to_cpu(tx_resp->rate_n_flags), |
2049 | tx_resp->failure_frame); | 2042 | tx_resp->failure_frame); |
2050 | 2043 | ||
2051 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | 2044 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); |
2052 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | 2045 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
2053 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | 2046 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); |
2054 | else if (sta_id == IWL_INVALID_STATION) | 2047 | else if (sta_id == IWL_INVALID_STATION) |
@@ -2059,10 +2052,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2059 | iwl_wake_queue(priv, txq_id); | 2052 | iwl_wake_queue(priv, txq_id); |
2060 | } | 2053 | } |
2061 | if (qc && likely(sta_id != IWL_INVALID_STATION)) | 2054 | if (qc && likely(sta_id != IWL_INVALID_STATION)) |
2062 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | 2055 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); |
2063 | 2056 | ||
2064 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | 2057 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
2065 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
2066 | } | 2058 | } |
2067 | 2059 | ||
2068 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | 2060 | static int iwl4965_calc_rssi(struct iwl_priv *priv, |
@@ -2096,7 +2088,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, | |||
2096 | 2088 | ||
2097 | /* dBm = max_rssi dB - agc dB - constant. | 2089 | /* dBm = max_rssi dB - agc dB - constant. |
2098 | * Higher AGC (higher radio gain) means lower signal. */ | 2090 | * Higher AGC (higher radio gain) means lower signal. */ |
2099 | return max_rssi - agc - IWL49_RSSI_OFFSET; | 2091 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; |
2100 | } | 2092 | } |
2101 | 2093 | ||
2102 | 2094 | ||
@@ -2104,7 +2096,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv, | |||
2104 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) | 2096 | static void iwl4965_rx_handler_setup(struct iwl_priv *priv) |
2105 | { | 2097 | { |
2106 | /* Legacy Rx frames */ | 2098 | /* Legacy Rx frames */ |
2107 | priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx; | 2099 | priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx; |
2108 | /* Tx response */ | 2100 | /* Tx response */ |
2109 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; | 2101 | priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; |
2110 | } | 2102 | } |
@@ -2247,7 +2239,7 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2247 | .ops = &iwl4965_ops, | 2239 | .ops = &iwl4965_ops, |
2248 | .num_of_queues = IWL49_NUM_QUEUES, | 2240 | .num_of_queues = IWL49_NUM_QUEUES, |
2249 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, | 2241 | .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, |
2250 | .mod_params = &iwl4965_mod_params, | 2242 | .mod_params = &iwlagn_mod_params, |
2251 | .valid_tx_ant = ANT_AB, | 2243 | .valid_tx_ant = ANT_AB, |
2252 | .valid_rx_ant = ANT_ABC, | 2244 | .valid_rx_ant = ANT_ABC, |
2253 | .pll_cfg_val = 0, | 2245 | .pll_cfg_val = 0, |
@@ -2260,27 +2252,11 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2260 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | 2252 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, |
2261 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 2253 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
2262 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 2254 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
2255 | .temperature_kelvin = true, | ||
2256 | .off_channel_workaround = true, | ||
2257 | .max_event_log_size = 512, | ||
2263 | }; | 2258 | }; |
2264 | 2259 | ||
2265 | /* Module firmware */ | 2260 | /* Module firmware */ |
2266 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); | 2261 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); |
2267 | 2262 | ||
2268 | module_param_named(antenna, iwl4965_mod_params.antenna, int, S_IRUGO); | ||
2269 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | ||
2270 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO); | ||
2271 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | ||
2272 | module_param_named( | ||
2273 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, S_IRUGO); | ||
2274 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | ||
2275 | |||
2276 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO); | ||
2277 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | ||
2278 | /* 11n */ | ||
2279 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO); | ||
2280 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | ||
2281 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, | ||
2282 | int, S_IRUGO); | ||
2283 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | ||
2284 | |||
2285 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, S_IRUGO); | ||
2286 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h index 714e032f6217..146e6431ae95 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h | |||
@@ -68,25 +68,6 @@ | |||
68 | #ifndef __iwl_5000_hw_h__ | 68 | #ifndef __iwl_5000_hw_h__ |
69 | #define __iwl_5000_hw_h__ | 69 | #define __iwl_5000_hw_h__ |
70 | 70 | ||
71 | #define IWL50_RTC_INST_LOWER_BOUND (0x000000) | ||
72 | #define IWL50_RTC_INST_UPPER_BOUND (0x020000) | ||
73 | |||
74 | #define IWL50_RTC_DATA_LOWER_BOUND (0x800000) | ||
75 | #define IWL50_RTC_DATA_UPPER_BOUND (0x80C000) | ||
76 | |||
77 | #define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - \ | ||
78 | IWL50_RTC_INST_LOWER_BOUND) | ||
79 | #define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - \ | ||
80 | IWL50_RTC_DATA_LOWER_BOUND) | ||
81 | |||
82 | /* EEPROM */ | ||
83 | #define IWL_5000_EEPROM_IMG_SIZE 2048 | ||
84 | |||
85 | #define IWL50_CMD_FIFO_NUM 7 | ||
86 | #define IWL50_NUM_QUEUES 20 | ||
87 | #define IWL50_NUM_AMPDU_QUEUES 10 | ||
88 | #define IWL50_FIRST_AMPDU_QUEUE 10 | ||
89 | |||
90 | /* 5150 only */ | 71 | /* 5150 only */ |
91 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) | 72 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) |
92 | 73 | ||
@@ -103,19 +84,5 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | |||
103 | return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); | 84 | return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); |
104 | } | 85 | } |
105 | 86 | ||
106 | /* Fixed (non-configurable) rx data from phy */ | ||
107 | |||
108 | /** | ||
109 | * struct iwl5000_schedq_bc_tbl scheduler byte count table | ||
110 | * base physical address of iwl5000_shared | ||
111 | * is provided to SCD_DRAM_BASE_ADDR | ||
112 | * @tfd_offset 0-12 - tx command byte count | ||
113 | * 12-16 - station index | ||
114 | */ | ||
115 | struct iwl5000_scd_bc_tbl { | ||
116 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; | ||
117 | } __attribute__ ((packed)); | ||
118 | |||
119 | |||
120 | #endif /* __iwl_5000_hw_h__ */ | 87 | #endif /* __iwl_5000_hw_h__ */ |
121 | 88 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 2267cad49cbf..e967cfcac224 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -19,6 +19,7 @@ | |||
19 | * file called LICENSE. | 19 | * file called LICENSE. |
20 | * | 20 | * |
21 | * Contact Information: | 21 | * Contact Information: |
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
22 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
23 | * | 24 | * |
24 | *****************************************************************************/ | 25 | *****************************************************************************/ |
@@ -45,8 +46,8 @@ | |||
45 | #include "iwl-helpers.h" | 46 | #include "iwl-helpers.h" |
46 | #include "iwl-agn.h" | 47 | #include "iwl-agn.h" |
47 | #include "iwl-agn-led.h" | 48 | #include "iwl-agn-led.h" |
49 | #include "iwl-agn-hw.h" | ||
48 | #include "iwl-5000-hw.h" | 50 | #include "iwl-5000-hw.h" |
49 | #include "iwl-6000-hw.h" | ||
50 | 51 | ||
51 | /* Highest firmware API version supported */ | 52 | /* Highest firmware API version supported */ |
52 | #define IWL5000_UCODE_API_MAX 2 | 53 | #define IWL5000_UCODE_API_MAX 2 |
@@ -64,21 +65,8 @@ | |||
64 | #define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" | 65 | #define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" |
65 | #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) | 66 | #define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) |
66 | 67 | ||
67 | static const s8 iwl5000_default_queue_to_tx_fifo[] = { | ||
68 | IWL_TX_FIFO_VO, | ||
69 | IWL_TX_FIFO_VI, | ||
70 | IWL_TX_FIFO_BE, | ||
71 | IWL_TX_FIFO_BK, | ||
72 | IWL50_CMD_FIFO_NUM, | ||
73 | IWL_TX_FIFO_UNUSED, | ||
74 | IWL_TX_FIFO_UNUSED, | ||
75 | IWL_TX_FIFO_UNUSED, | ||
76 | IWL_TX_FIFO_UNUSED, | ||
77 | IWL_TX_FIFO_UNUSED, | ||
78 | }; | ||
79 | |||
80 | /* NIC configuration for 5000 series */ | 68 | /* NIC configuration for 5000 series */ |
81 | void iwl5000_nic_config(struct iwl_priv *priv) | 69 | static void iwl5000_nic_config(struct iwl_priv *priv) |
82 | { | 70 | { |
83 | unsigned long flags; | 71 | unsigned long flags; |
84 | u16 radio_cfg; | 72 | u16 radio_cfg; |
@@ -111,162 +99,6 @@ void iwl5000_nic_config(struct iwl_priv *priv) | |||
111 | spin_unlock_irqrestore(&priv->lock, flags); | 99 | spin_unlock_irqrestore(&priv->lock, flags); |
112 | } | 100 | } |
113 | 101 | ||
114 | |||
115 | /* | ||
116 | * EEPROM | ||
117 | */ | ||
118 | static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | ||
119 | { | ||
120 | u16 offset = 0; | ||
121 | |||
122 | if ((address & INDIRECT_ADDRESS) == 0) | ||
123 | return address; | ||
124 | |||
125 | switch (address & INDIRECT_TYPE_MSK) { | ||
126 | case INDIRECT_HOST: | ||
127 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); | ||
128 | break; | ||
129 | case INDIRECT_GENERAL: | ||
130 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); | ||
131 | break; | ||
132 | case INDIRECT_REGULATORY: | ||
133 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); | ||
134 | break; | ||
135 | case INDIRECT_CALIBRATION: | ||
136 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); | ||
137 | break; | ||
138 | case INDIRECT_PROCESS_ADJST: | ||
139 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); | ||
140 | break; | ||
141 | case INDIRECT_OTHERS: | ||
142 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); | ||
143 | break; | ||
144 | default: | ||
145 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
146 | address & INDIRECT_TYPE_MSK); | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | /* translate the offset from words to byte */ | ||
151 | return (address & ADDRESS_MSK) + (offset << 1); | ||
152 | } | ||
153 | |||
154 | u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv) | ||
155 | { | ||
156 | struct iwl_eeprom_calib_hdr { | ||
157 | u8 version; | ||
158 | u8 pa_type; | ||
159 | u16 voltage; | ||
160 | } *hdr; | ||
161 | |||
162 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
163 | EEPROM_5000_CALIB_ALL); | ||
164 | return hdr->version; | ||
165 | |||
166 | } | ||
167 | |||
168 | static void iwl5000_gain_computation(struct iwl_priv *priv, | ||
169 | u32 average_noise[NUM_RX_CHAINS], | ||
170 | u16 min_average_noise_antenna_i, | ||
171 | u32 min_average_noise, | ||
172 | u8 default_chain) | ||
173 | { | ||
174 | int i; | ||
175 | s32 delta_g; | ||
176 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
177 | |||
178 | /* | ||
179 | * Find Gain Code for the chains based on "default chain" | ||
180 | */ | ||
181 | for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { | ||
182 | if ((data->disconn_array[i])) { | ||
183 | data->delta_gain_code[i] = 0; | ||
184 | continue; | ||
185 | } | ||
186 | |||
187 | delta_g = (priv->cfg->chain_noise_scale * | ||
188 | ((s32)average_noise[default_chain] - | ||
189 | (s32)average_noise[i])) / 1500; | ||
190 | |||
191 | /* bound gain by 2 bits value max, 3rd bit is sign */ | ||
192 | data->delta_gain_code[i] = | ||
193 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | ||
194 | |||
195 | if (delta_g < 0) | ||
196 | /* | ||
197 | * set negative sign ... | ||
198 | * note to Intel developers: This is uCode API format, | ||
199 | * not the format of any internal device registers. | ||
200 | * Do not change this format for e.g. 6050 or similar | ||
201 | * devices. Change format only if more resolution | ||
202 | * (i.e. more than 2 bits magnitude) is needed. | ||
203 | */ | ||
204 | data->delta_gain_code[i] |= (1 << 2); | ||
205 | } | ||
206 | |||
207 | IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", | ||
208 | data->delta_gain_code[1], data->delta_gain_code[2]); | ||
209 | |||
210 | if (!data->radio_write) { | ||
211 | struct iwl_calib_chain_noise_gain_cmd cmd; | ||
212 | |||
213 | memset(&cmd, 0, sizeof(cmd)); | ||
214 | |||
215 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; | ||
216 | cmd.hdr.first_group = 0; | ||
217 | cmd.hdr.groups_num = 1; | ||
218 | cmd.hdr.data_valid = 1; | ||
219 | cmd.delta_gain_1 = data->delta_gain_code[1]; | ||
220 | cmd.delta_gain_2 = data->delta_gain_code[2]; | ||
221 | iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, | ||
222 | sizeof(cmd), &cmd, NULL); | ||
223 | |||
224 | data->radio_write = 1; | ||
225 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | ||
226 | } | ||
227 | |||
228 | data->chain_noise_a = 0; | ||
229 | data->chain_noise_b = 0; | ||
230 | data->chain_noise_c = 0; | ||
231 | data->chain_signal_a = 0; | ||
232 | data->chain_signal_b = 0; | ||
233 | data->chain_signal_c = 0; | ||
234 | data->beacon_count = 0; | ||
235 | } | ||
236 | |||
237 | static void iwl5000_chain_noise_reset(struct iwl_priv *priv) | ||
238 | { | ||
239 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
240 | int ret; | ||
241 | |||
242 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | ||
243 | struct iwl_calib_chain_noise_reset_cmd cmd; | ||
244 | memset(&cmd, 0, sizeof(cmd)); | ||
245 | |||
246 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | ||
247 | cmd.hdr.first_group = 0; | ||
248 | cmd.hdr.groups_num = 1; | ||
249 | cmd.hdr.data_valid = 1; | ||
250 | ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | ||
251 | sizeof(cmd), &cmd); | ||
252 | if (ret) | ||
253 | IWL_ERR(priv, | ||
254 | "Could not send REPLY_PHY_CALIBRATION_CMD\n"); | ||
255 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; | ||
256 | IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
261 | __le32 *tx_flags) | ||
262 | { | ||
263 | if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
264 | (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
265 | *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; | ||
266 | else | ||
267 | *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; | ||
268 | } | ||
269 | |||
270 | static struct iwl_sensitivity_ranges iwl5000_sensitivity = { | 102 | static struct iwl_sensitivity_ranges iwl5000_sensitivity = { |
271 | .min_nrg_cck = 95, | 103 | .min_nrg_cck = 95, |
272 | .max_nrg_cck = 0, /* not used, set to 0 */ | 104 | .max_nrg_cck = 0, /* not used, set to 0 */ |
@@ -318,14 +150,6 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = { | |||
318 | .nrg_th_cca = 62, | 150 | .nrg_th_cca = 62, |
319 | }; | 151 | }; |
320 | 152 | ||
321 | const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | ||
322 | size_t offset) | ||
323 | { | ||
324 | u32 address = eeprom_indirect_address(priv, offset); | ||
325 | BUG_ON(address >= priv->cfg->eeprom_size); | ||
326 | return &priv->eeprom[address]; | ||
327 | } | ||
328 | |||
329 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) | 153 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) |
330 | { | 154 | { |
331 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; | 155 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; |
@@ -341,351 +165,10 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | |||
341 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; | 165 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; |
342 | } | 166 | } |
343 | 167 | ||
344 | /* | 168 | static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) |
345 | * Calibration | ||
346 | */ | ||
347 | static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) | ||
348 | { | ||
349 | struct iwl_calib_xtal_freq_cmd cmd; | ||
350 | __le16 *xtal_calib = | ||
351 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); | ||
352 | |||
353 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; | ||
354 | cmd.hdr.first_group = 0; | ||
355 | cmd.hdr.groups_num = 1; | ||
356 | cmd.hdr.data_valid = 1; | ||
357 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | ||
358 | cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); | ||
359 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], | ||
360 | (u8 *)&cmd, sizeof(cmd)); | ||
361 | } | ||
362 | |||
363 | static int iwl5000_send_calib_cfg(struct iwl_priv *priv) | ||
364 | { | ||
365 | struct iwl_calib_cfg_cmd calib_cfg_cmd; | ||
366 | struct iwl_host_cmd cmd = { | ||
367 | .id = CALIBRATION_CFG_CMD, | ||
368 | .len = sizeof(struct iwl_calib_cfg_cmd), | ||
369 | .data = &calib_cfg_cmd, | ||
370 | }; | ||
371 | |||
372 | memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); | ||
373 | calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; | ||
374 | calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; | ||
375 | calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; | ||
376 | calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; | ||
377 | |||
378 | return iwl_send_cmd(priv, &cmd); | ||
379 | } | ||
380 | |||
381 | static void iwl5000_rx_calib_result(struct iwl_priv *priv, | ||
382 | struct iwl_rx_mem_buffer *rxb) | ||
383 | { | ||
384 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
385 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | ||
386 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
387 | int index; | ||
388 | |||
389 | /* reduce the size of the length field itself */ | ||
390 | len -= 4; | ||
391 | |||
392 | /* Define the order in which the results will be sent to the runtime | ||
393 | * uCode. iwl_send_calib_results sends them in a row according to their | ||
394 | * index. We sort them here */ | ||
395 | switch (hdr->op_code) { | ||
396 | case IWL_PHY_CALIBRATE_DC_CMD: | ||
397 | index = IWL_CALIB_DC; | ||
398 | break; | ||
399 | case IWL_PHY_CALIBRATE_LO_CMD: | ||
400 | index = IWL_CALIB_LO; | ||
401 | break; | ||
402 | case IWL_PHY_CALIBRATE_TX_IQ_CMD: | ||
403 | index = IWL_CALIB_TX_IQ; | ||
404 | break; | ||
405 | case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: | ||
406 | index = IWL_CALIB_TX_IQ_PERD; | ||
407 | break; | ||
408 | case IWL_PHY_CALIBRATE_BASE_BAND_CMD: | ||
409 | index = IWL_CALIB_BASE_BAND; | ||
410 | break; | ||
411 | default: | ||
412 | IWL_ERR(priv, "Unknown calibration notification %d\n", | ||
413 | hdr->op_code); | ||
414 | return; | ||
415 | } | ||
416 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); | ||
417 | } | ||
418 | |||
419 | static void iwl5000_rx_calib_complete(struct iwl_priv *priv, | ||
420 | struct iwl_rx_mem_buffer *rxb) | ||
421 | { | ||
422 | IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); | ||
423 | queue_work(priv->workqueue, &priv->restart); | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | * ucode | ||
428 | */ | ||
429 | static int iwl5000_load_section(struct iwl_priv *priv, const char *name, | ||
430 | struct fw_desc *image, u32 dst_addr) | ||
431 | { | ||
432 | dma_addr_t phy_addr = image->p_addr; | ||
433 | u32 byte_cnt = image->len; | ||
434 | int ret; | ||
435 | |||
436 | priv->ucode_write_complete = 0; | ||
437 | |||
438 | iwl_write_direct32(priv, | ||
439 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
440 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
441 | |||
442 | iwl_write_direct32(priv, | ||
443 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | ||
444 | |||
445 | iwl_write_direct32(priv, | ||
446 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | ||
447 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
448 | |||
449 | iwl_write_direct32(priv, | ||
450 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | ||
451 | (iwl_get_dma_hi_addr(phy_addr) | ||
452 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | ||
453 | |||
454 | iwl_write_direct32(priv, | ||
455 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | ||
456 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | ||
457 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | ||
458 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
459 | |||
460 | iwl_write_direct32(priv, | ||
461 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
462 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
463 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | ||
464 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | ||
465 | |||
466 | IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); | ||
467 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | ||
468 | priv->ucode_write_complete, 5 * HZ); | ||
469 | if (ret == -ERESTARTSYS) { | ||
470 | IWL_ERR(priv, "Could not load the %s uCode section due " | ||
471 | "to interrupt\n", name); | ||
472 | return ret; | ||
473 | } | ||
474 | if (!ret) { | ||
475 | IWL_ERR(priv, "Could not load the %s uCode section\n", | ||
476 | name); | ||
477 | return -ETIMEDOUT; | ||
478 | } | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static int iwl5000_load_given_ucode(struct iwl_priv *priv, | ||
484 | struct fw_desc *inst_image, | ||
485 | struct fw_desc *data_image) | ||
486 | { | ||
487 | int ret = 0; | ||
488 | |||
489 | ret = iwl5000_load_section(priv, "INST", inst_image, | ||
490 | IWL50_RTC_INST_LOWER_BOUND); | ||
491 | if (ret) | ||
492 | return ret; | ||
493 | |||
494 | return iwl5000_load_section(priv, "DATA", data_image, | ||
495 | IWL50_RTC_DATA_LOWER_BOUND); | ||
496 | } | ||
497 | |||
498 | int iwl5000_load_ucode(struct iwl_priv *priv) | ||
499 | { | ||
500 | int ret = 0; | ||
501 | |||
502 | /* check whether init ucode should be loaded, or rather runtime ucode */ | ||
503 | if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { | ||
504 | IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); | ||
505 | ret = iwl5000_load_given_ucode(priv, | ||
506 | &priv->ucode_init, &priv->ucode_init_data); | ||
507 | if (!ret) { | ||
508 | IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); | ||
509 | priv->ucode_type = UCODE_INIT; | ||
510 | } | ||
511 | } else { | ||
512 | IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " | ||
513 | "Loading runtime ucode...\n"); | ||
514 | ret = iwl5000_load_given_ucode(priv, | ||
515 | &priv->ucode_code, &priv->ucode_data); | ||
516 | if (!ret) { | ||
517 | IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); | ||
518 | priv->ucode_type = UCODE_RT; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | return ret; | ||
523 | } | ||
524 | |||
525 | void iwl5000_init_alive_start(struct iwl_priv *priv) | ||
526 | { | ||
527 | int ret = 0; | ||
528 | |||
529 | /* Check alive response for "valid" sign from uCode */ | ||
530 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | ||
531 | /* We had an error bringing up the hardware, so take it | ||
532 | * all the way back down so we can try again */ | ||
533 | IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); | ||
534 | goto restart; | ||
535 | } | ||
536 | |||
537 | /* initialize uCode was loaded... verify inst image. | ||
538 | * This is a paranoid check, because we would not have gotten the | ||
539 | * "initialize" alive if code weren't properly loaded. */ | ||
540 | if (iwl_verify_ucode(priv)) { | ||
541 | /* Runtime instruction load was bad; | ||
542 | * take it all the way back down so we can try again */ | ||
543 | IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); | ||
544 | goto restart; | ||
545 | } | ||
546 | |||
547 | ret = priv->cfg->ops->lib->alive_notify(priv); | ||
548 | if (ret) { | ||
549 | IWL_WARN(priv, | ||
550 | "Could not complete ALIVE transition: %d\n", ret); | ||
551 | goto restart; | ||
552 | } | ||
553 | |||
554 | iwl5000_send_calib_cfg(priv); | ||
555 | return; | ||
556 | |||
557 | restart: | ||
558 | /* real restart (first load init_ucode) */ | ||
559 | queue_work(priv->workqueue, &priv->restart); | ||
560 | } | ||
561 | |||
562 | static void iwl5000_set_wr_ptrs(struct iwl_priv *priv, | ||
563 | int txq_id, u32 index) | ||
564 | { | ||
565 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
566 | (index & 0xff) | (txq_id << 8)); | ||
567 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); | ||
568 | } | ||
569 | |||
570 | static void iwl5000_tx_queue_set_status(struct iwl_priv *priv, | ||
571 | struct iwl_tx_queue *txq, | ||
572 | int tx_fifo_id, int scd_retry) | ||
573 | { | ||
574 | int txq_id = txq->q.id; | ||
575 | int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; | ||
576 | |||
577 | iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
578 | (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | | ||
579 | (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | | ||
580 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | | ||
581 | IWL50_SCD_QUEUE_STTS_REG_MSK); | ||
582 | |||
583 | txq->sched_retry = scd_retry; | ||
584 | |||
585 | IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", | ||
586 | active ? "Activate" : "Deactivate", | ||
587 | scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); | ||
588 | } | ||
589 | |||
590 | int iwl5000_alive_notify(struct iwl_priv *priv) | ||
591 | { | ||
592 | u32 a; | ||
593 | unsigned long flags; | ||
594 | int i, chan; | ||
595 | u32 reg_val; | ||
596 | |||
597 | spin_lock_irqsave(&priv->lock, flags); | ||
598 | |||
599 | priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); | ||
600 | a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; | ||
601 | for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; | ||
602 | a += 4) | ||
603 | iwl_write_targ_mem(priv, a, 0); | ||
604 | for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; | ||
605 | a += 4) | ||
606 | iwl_write_targ_mem(priv, a, 0); | ||
607 | for (; a < priv->scd_base_addr + | ||
608 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
609 | iwl_write_targ_mem(priv, a, 0); | ||
610 | |||
611 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, | ||
612 | priv->scd_bc_tbls.dma >> 10); | ||
613 | |||
614 | /* Enable DMA channel */ | ||
615 | for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) | ||
616 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
617 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
618 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
619 | |||
620 | /* Update FH chicken bits */ | ||
621 | reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); | ||
622 | iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, | ||
623 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
624 | |||
625 | iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, | ||
626 | IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); | ||
627 | iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); | ||
628 | |||
629 | /* initiate the queues */ | ||
630 | for (i = 0; i < priv->hw_params.max_txq_num; i++) { | ||
631 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); | ||
632 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
633 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
634 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
635 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
636 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
637 | sizeof(u32), | ||
638 | ((SCD_WIN_SIZE << | ||
639 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
640 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
641 | ((SCD_FRAME_LIMIT << | ||
642 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
643 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
644 | } | ||
645 | |||
646 | iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, | ||
647 | IWL_MASK(0, priv->hw_params.max_txq_num)); | ||
648 | |||
649 | /* Activate all Tx DMA/FIFO channels */ | ||
650 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); | ||
651 | |||
652 | iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | ||
653 | |||
654 | /* make sure all queue are not stopped */ | ||
655 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
656 | for (i = 0; i < 4; i++) | ||
657 | atomic_set(&priv->queue_stop_count[i], 0); | ||
658 | |||
659 | /* reset to 0 to enable all the queue first */ | ||
660 | priv->txq_ctx_active_msk = 0; | ||
661 | /* map qos queues to fifos one-to-one */ | ||
662 | BUILD_BUG_ON(ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo) != 10); | ||
663 | |||
664 | for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { | ||
665 | int ac = iwl5000_default_queue_to_tx_fifo[i]; | ||
666 | |||
667 | iwl_txq_ctx_activate(priv, i); | ||
668 | |||
669 | if (ac == IWL_TX_FIFO_UNUSED) | ||
670 | continue; | ||
671 | |||
672 | iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | ||
673 | } | ||
674 | |||
675 | spin_unlock_irqrestore(&priv->lock, flags); | ||
676 | |||
677 | iwl_send_wimax_coex(priv); | ||
678 | |||
679 | iwl5000_set_Xtal_calib(priv); | ||
680 | iwl_send_calib_results(priv); | ||
681 | |||
682 | return 0; | ||
683 | } | ||
684 | |||
685 | int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | ||
686 | { | 169 | { |
687 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 170 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
688 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | 171 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
689 | priv->cfg->num_of_queues = | 172 | priv->cfg->num_of_queues = |
690 | priv->cfg->mod_params->num_of_queues; | 173 | priv->cfg->mod_params->num_of_queues; |
691 | 174 | ||
@@ -693,13 +176,13 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
693 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 176 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
694 | priv->hw_params.scd_bc_tbls_size = | 177 | priv->hw_params.scd_bc_tbls_size = |
695 | priv->cfg->num_of_queues * | 178 | priv->cfg->num_of_queues * |
696 | sizeof(struct iwl5000_scd_bc_tbl); | 179 | sizeof(struct iwlagn_scd_bc_tbl); |
697 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 180 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
698 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 181 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
699 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 182 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
700 | 183 | ||
701 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | 184 | priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; |
702 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | 185 | priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; |
703 | 186 | ||
704 | priv->hw_params.max_bsm_size = 0; | 187 | priv->hw_params.max_bsm_size = 0; |
705 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 188 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
@@ -740,547 +223,6 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
740 | return 0; | 223 | return 0; |
741 | } | 224 | } |
742 | 225 | ||
743 | /** | ||
744 | * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | ||
745 | */ | ||
746 | void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
747 | struct iwl_tx_queue *txq, | ||
748 | u16 byte_cnt) | ||
749 | { | ||
750 | struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
751 | int write_ptr = txq->q.write_ptr; | ||
752 | int txq_id = txq->q.id; | ||
753 | u8 sec_ctl = 0; | ||
754 | u8 sta_id = 0; | ||
755 | u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | ||
756 | __le16 bc_ent; | ||
757 | |||
758 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | ||
759 | |||
760 | if (txq_id != IWL_CMD_QUEUE_NUM) { | ||
761 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; | ||
762 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; | ||
763 | |||
764 | switch (sec_ctl & TX_CMD_SEC_MSK) { | ||
765 | case TX_CMD_SEC_CCM: | ||
766 | len += CCMP_MIC_LEN; | ||
767 | break; | ||
768 | case TX_CMD_SEC_TKIP: | ||
769 | len += TKIP_ICV_LEN; | ||
770 | break; | ||
771 | case TX_CMD_SEC_WEP: | ||
772 | len += WEP_IV_LEN + WEP_ICV_LEN; | ||
773 | break; | ||
774 | } | ||
775 | } | ||
776 | |||
777 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); | ||
778 | |||
779 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | ||
780 | |||
781 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
782 | scd_bc_tbl[txq_id]. | ||
783 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | ||
784 | } | ||
785 | |||
786 | void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
787 | struct iwl_tx_queue *txq) | ||
788 | { | ||
789 | struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
790 | int txq_id = txq->q.id; | ||
791 | int read_ptr = txq->q.read_ptr; | ||
792 | u8 sta_id = 0; | ||
793 | __le16 bc_ent; | ||
794 | |||
795 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); | ||
796 | |||
797 | if (txq_id != IWL_CMD_QUEUE_NUM) | ||
798 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | ||
799 | |||
800 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | ||
801 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; | ||
802 | |||
803 | if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
804 | scd_bc_tbl[txq_id]. | ||
805 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | ||
806 | } | ||
807 | |||
808 | static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | ||
809 | u16 txq_id) | ||
810 | { | ||
811 | u32 tbl_dw_addr; | ||
812 | u32 tbl_dw; | ||
813 | u16 scd_q2ratid; | ||
814 | |||
815 | scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; | ||
816 | |||
817 | tbl_dw_addr = priv->scd_base_addr + | ||
818 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); | ||
819 | |||
820 | tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); | ||
821 | |||
822 | if (txq_id & 0x1) | ||
823 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); | ||
824 | else | ||
825 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); | ||
826 | |||
827 | iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); | ||
828 | |||
829 | return 0; | ||
830 | } | ||
831 | static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) | ||
832 | { | ||
833 | /* Simply stop the queue, but don't change any configuration; | ||
834 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ | ||
835 | iwl_write_prph(priv, | ||
836 | IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
837 | (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
838 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
839 | } | ||
840 | |||
841 | int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
842 | int tx_fifo, int sta_id, int tid, u16 ssn_idx) | ||
843 | { | ||
844 | unsigned long flags; | ||
845 | u16 ra_tid; | ||
846 | |||
847 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | ||
848 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
849 | <= txq_id)) { | ||
850 | IWL_WARN(priv, | ||
851 | "queue number out of range: %d, must be %d to %d\n", | ||
852 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | ||
853 | IWL50_FIRST_AMPDU_QUEUE + | ||
854 | priv->cfg->num_of_ampdu_queues - 1); | ||
855 | return -EINVAL; | ||
856 | } | ||
857 | |||
858 | ra_tid = BUILD_RAxTID(sta_id, tid); | ||
859 | |||
860 | /* Modify device's station table to Tx this TID */ | ||
861 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | ||
862 | |||
863 | spin_lock_irqsave(&priv->lock, flags); | ||
864 | |||
865 | /* Stop this Tx queue before configuring it */ | ||
866 | iwl5000_tx_queue_stop_scheduler(priv, txq_id); | ||
867 | |||
868 | /* Map receiver-address / traffic-ID to this queue */ | ||
869 | iwl5000_tx_queue_set_q2ratid(priv, ra_tid, txq_id); | ||
870 | |||
871 | /* Set this queue as a chain-building queue */ | ||
872 | iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<<txq_id)); | ||
873 | |||
874 | /* enable aggregations for the queue */ | ||
875 | iwl_set_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1<<txq_id)); | ||
876 | |||
877 | /* Place first TFD at index corresponding to start sequence number. | ||
878 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | ||
879 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
880 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
881 | iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
882 | |||
883 | /* Set up Tx window size and frame limit for this queue */ | ||
884 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
885 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + | ||
886 | sizeof(u32), | ||
887 | ((SCD_WIN_SIZE << | ||
888 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
889 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
890 | ((SCD_FRAME_LIMIT << | ||
891 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
892 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
893 | |||
894 | iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
895 | |||
896 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | ||
897 | iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); | ||
898 | |||
899 | spin_unlock_irqrestore(&priv->lock, flags); | ||
900 | |||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
905 | u16 ssn_idx, u8 tx_fifo) | ||
906 | { | ||
907 | if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || | ||
908 | (IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
909 | <= txq_id)) { | ||
910 | IWL_ERR(priv, | ||
911 | "queue number out of range: %d, must be %d to %d\n", | ||
912 | txq_id, IWL50_FIRST_AMPDU_QUEUE, | ||
913 | IWL50_FIRST_AMPDU_QUEUE + | ||
914 | priv->cfg->num_of_ampdu_queues - 1); | ||
915 | return -EINVAL; | ||
916 | } | ||
917 | |||
918 | iwl5000_tx_queue_stop_scheduler(priv, txq_id); | ||
919 | |||
920 | iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); | ||
921 | |||
922 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
923 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
924 | /* supposes that ssn_idx is valid (!= 0xFFF) */ | ||
925 | iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
926 | |||
927 | iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
928 | iwl_txq_ctx_deactivate(priv, txq_id); | ||
929 | iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); | ||
930 | |||
931 | return 0; | ||
932 | } | ||
933 | |||
934 | u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | ||
935 | { | ||
936 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | ||
937 | struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; | ||
938 | memcpy(addsta, cmd, size); | ||
939 | /* resrved in 5000 */ | ||
940 | addsta->rate_n_flags = cpu_to_le16(0); | ||
941 | return size; | ||
942 | } | ||
943 | |||
944 | |||
945 | /* | ||
946 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | ||
947 | * must be called under priv->lock and mac access | ||
948 | */ | ||
949 | void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) | ||
950 | { | ||
951 | iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); | ||
952 | } | ||
953 | |||
954 | |||
955 | static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) | ||
956 | { | ||
957 | return le32_to_cpup((__le32 *)&tx_resp->status + | ||
958 | tx_resp->frame_count) & MAX_SN; | ||
959 | } | ||
960 | |||
961 | static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | ||
962 | struct iwl_ht_agg *agg, | ||
963 | struct iwl5000_tx_resp *tx_resp, | ||
964 | int txq_id, u16 start_idx) | ||
965 | { | ||
966 | u16 status; | ||
967 | struct agg_tx_status *frame_status = &tx_resp->status; | ||
968 | struct ieee80211_tx_info *info = NULL; | ||
969 | struct ieee80211_hdr *hdr = NULL; | ||
970 | u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
971 | int i, sh, idx; | ||
972 | u16 seq; | ||
973 | |||
974 | if (agg->wait_for_ba) | ||
975 | IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); | ||
976 | |||
977 | agg->frame_count = tx_resp->frame_count; | ||
978 | agg->start_idx = start_idx; | ||
979 | agg->rate_n_flags = rate_n_flags; | ||
980 | agg->bitmap = 0; | ||
981 | |||
982 | /* # frames attempted by Tx command */ | ||
983 | if (agg->frame_count == 1) { | ||
984 | /* Only one frame was attempted; no block-ack will arrive */ | ||
985 | status = le16_to_cpu(frame_status[0].status); | ||
986 | idx = start_idx; | ||
987 | |||
988 | /* FIXME: code repetition */ | ||
989 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | ||
990 | agg->frame_count, agg->start_idx, idx); | ||
991 | |||
992 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | ||
993 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
994 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
995 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
996 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | ||
997 | |||
998 | /* FIXME: code repetition end */ | ||
999 | |||
1000 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | ||
1001 | status & 0xff, tx_resp->failure_frame); | ||
1002 | IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); | ||
1003 | |||
1004 | agg->wait_for_ba = 0; | ||
1005 | } else { | ||
1006 | /* Two or more frames were attempted; expect block-ack */ | ||
1007 | u64 bitmap = 0; | ||
1008 | int start = agg->start_idx; | ||
1009 | |||
1010 | /* Construct bit-map of pending frames within Tx window */ | ||
1011 | for (i = 0; i < agg->frame_count; i++) { | ||
1012 | u16 sc; | ||
1013 | status = le16_to_cpu(frame_status[i].status); | ||
1014 | seq = le16_to_cpu(frame_status[i].sequence); | ||
1015 | idx = SEQ_TO_INDEX(seq); | ||
1016 | txq_id = SEQ_TO_QUEUE(seq); | ||
1017 | |||
1018 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | ||
1019 | AGG_TX_STATE_ABORT_MSK)) | ||
1020 | continue; | ||
1021 | |||
1022 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", | ||
1023 | agg->frame_count, txq_id, idx); | ||
1024 | |||
1025 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | ||
1026 | if (!hdr) { | ||
1027 | IWL_ERR(priv, | ||
1028 | "BUG_ON idx doesn't point to valid skb" | ||
1029 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
1030 | return -1; | ||
1031 | } | ||
1032 | |||
1033 | sc = le16_to_cpu(hdr->seq_ctrl); | ||
1034 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | ||
1035 | IWL_ERR(priv, | ||
1036 | "BUG_ON idx doesn't match seq control" | ||
1037 | " idx=%d, seq_idx=%d, seq=%d\n", | ||
1038 | idx, SEQ_TO_SN(sc), | ||
1039 | hdr->seq_ctrl); | ||
1040 | return -1; | ||
1041 | } | ||
1042 | |||
1043 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", | ||
1044 | i, idx, SEQ_TO_SN(sc)); | ||
1045 | |||
1046 | sh = idx - start; | ||
1047 | if (sh > 64) { | ||
1048 | sh = (start - idx) + 0xff; | ||
1049 | bitmap = bitmap << sh; | ||
1050 | sh = 0; | ||
1051 | start = idx; | ||
1052 | } else if (sh < -64) | ||
1053 | sh = 0xff - (start - idx); | ||
1054 | else if (sh < 0) { | ||
1055 | sh = start - idx; | ||
1056 | start = idx; | ||
1057 | bitmap = bitmap << sh; | ||
1058 | sh = 0; | ||
1059 | } | ||
1060 | bitmap |= 1ULL << sh; | ||
1061 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", | ||
1062 | start, (unsigned long long)bitmap); | ||
1063 | } | ||
1064 | |||
1065 | agg->bitmap = bitmap; | ||
1066 | agg->start_idx = start; | ||
1067 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", | ||
1068 | agg->frame_count, agg->start_idx, | ||
1069 | (unsigned long long)agg->bitmap); | ||
1070 | |||
1071 | if (bitmap) | ||
1072 | agg->wait_for_ba = 1; | ||
1073 | } | ||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | ||
1078 | struct iwl_rx_mem_buffer *rxb) | ||
1079 | { | ||
1080 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1081 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
1082 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
1083 | int index = SEQ_TO_INDEX(sequence); | ||
1084 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1085 | struct ieee80211_tx_info *info; | ||
1086 | struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
1087 | u32 status = le16_to_cpu(tx_resp->status.status); | ||
1088 | int tid; | ||
1089 | int sta_id; | ||
1090 | int freed; | ||
1091 | |||
1092 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | ||
1093 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | ||
1094 | "is out of range [0-%d] %d %d\n", txq_id, | ||
1095 | index, txq->q.n_bd, txq->q.write_ptr, | ||
1096 | txq->q.read_ptr); | ||
1097 | return; | ||
1098 | } | ||
1099 | |||
1100 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | ||
1101 | memset(&info->status, 0, sizeof(info->status)); | ||
1102 | |||
1103 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; | ||
1104 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; | ||
1105 | |||
1106 | if (txq->sched_retry) { | ||
1107 | const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp); | ||
1108 | struct iwl_ht_agg *agg = NULL; | ||
1109 | |||
1110 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
1111 | |||
1112 | iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | ||
1113 | |||
1114 | /* check if BAR is needed */ | ||
1115 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) | ||
1116 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
1117 | |||
1118 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | ||
1119 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | ||
1120 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " | ||
1121 | "scd_ssn=%d idx=%d txq=%d swq=%d\n", | ||
1122 | scd_ssn , index, txq_id, txq->swq_id); | ||
1123 | |||
1124 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | ||
1125 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1126 | |||
1127 | if (priv->mac80211_registered && | ||
1128 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
1129 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { | ||
1130 | if (agg->state == IWL_AGG_OFF) | ||
1131 | iwl_wake_queue(priv, txq_id); | ||
1132 | else | ||
1133 | iwl_wake_queue(priv, txq->swq_id); | ||
1134 | } | ||
1135 | } | ||
1136 | } else { | ||
1137 | BUG_ON(txq_id != txq->swq_id); | ||
1138 | |||
1139 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
1140 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
1141 | iwl_hwrate_to_tx_control(priv, | ||
1142 | le32_to_cpu(tx_resp->rate_n_flags), | ||
1143 | info); | ||
1144 | |||
1145 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " | ||
1146 | "0x%x retries %d\n", | ||
1147 | txq_id, | ||
1148 | iwl_get_tx_fail_reason(status), status, | ||
1149 | le32_to_cpu(tx_resp->rate_n_flags), | ||
1150 | tx_resp->failure_frame); | ||
1151 | |||
1152 | freed = iwl_tx_queue_reclaim(priv, txq_id, index); | ||
1153 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1154 | |||
1155 | if (priv->mac80211_registered && | ||
1156 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | ||
1157 | iwl_wake_queue(priv, txq_id); | ||
1158 | } | ||
1159 | |||
1160 | iwl_txq_check_empty(priv, sta_id, tid, txq_id); | ||
1161 | |||
1162 | if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) | ||
1163 | IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); | ||
1164 | } | ||
1165 | |||
1166 | /* Currently 5000 is the superset of everything */ | ||
1167 | u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) | ||
1168 | { | ||
1169 | return len; | ||
1170 | } | ||
1171 | |||
1172 | void iwl5000_setup_deferred_work(struct iwl_priv *priv) | ||
1173 | { | ||
1174 | /* in 5000 the tx power calibration is done in uCode */ | ||
1175 | priv->disable_tx_power_cal = 1; | ||
1176 | } | ||
1177 | |||
1178 | void iwl5000_rx_handler_setup(struct iwl_priv *priv) | ||
1179 | { | ||
1180 | /* init calibration handlers */ | ||
1181 | priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = | ||
1182 | iwl5000_rx_calib_result; | ||
1183 | priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = | ||
1184 | iwl5000_rx_calib_complete; | ||
1185 | priv->rx_handlers[REPLY_TX] = iwl5000_rx_reply_tx; | ||
1186 | } | ||
1187 | |||
1188 | |||
1189 | int iwl5000_hw_valid_rtc_data_addr(u32 addr) | ||
1190 | { | ||
1191 | return (addr >= IWL50_RTC_DATA_LOWER_BOUND) && | ||
1192 | (addr < IWL50_RTC_DATA_UPPER_BOUND); | ||
1193 | } | ||
1194 | |||
1195 | static int iwl5000_send_rxon_assoc(struct iwl_priv *priv) | ||
1196 | { | ||
1197 | int ret = 0; | ||
1198 | struct iwl5000_rxon_assoc_cmd rxon_assoc; | ||
1199 | const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; | ||
1200 | const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; | ||
1201 | |||
1202 | if ((rxon1->flags == rxon2->flags) && | ||
1203 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
1204 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
1205 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
1206 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
1207 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
1208 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
1209 | (rxon1->ofdm_ht_triple_stream_basic_rates == | ||
1210 | rxon2->ofdm_ht_triple_stream_basic_rates) && | ||
1211 | (rxon1->acquisition_data == rxon2->acquisition_data) && | ||
1212 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
1213 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
1214 | IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); | ||
1215 | return 0; | ||
1216 | } | ||
1217 | |||
1218 | rxon_assoc.flags = priv->staging_rxon.flags; | ||
1219 | rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; | ||
1220 | rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; | ||
1221 | rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; | ||
1222 | rxon_assoc.reserved1 = 0; | ||
1223 | rxon_assoc.reserved2 = 0; | ||
1224 | rxon_assoc.reserved3 = 0; | ||
1225 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
1226 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates; | ||
1227 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
1228 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; | ||
1229 | rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; | ||
1230 | rxon_assoc.ofdm_ht_triple_stream_basic_rates = | ||
1231 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; | ||
1232 | rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; | ||
1233 | |||
1234 | ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, | ||
1235 | sizeof(rxon_assoc), &rxon_assoc, NULL); | ||
1236 | if (ret) | ||
1237 | return ret; | ||
1238 | |||
1239 | return ret; | ||
1240 | } | ||
1241 | int iwl5000_send_tx_power(struct iwl_priv *priv) | ||
1242 | { | ||
1243 | struct iwl5000_tx_power_dbm_cmd tx_power_cmd; | ||
1244 | u8 tx_ant_cfg_cmd; | ||
1245 | |||
1246 | /* half dBm need to multiply */ | ||
1247 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | ||
1248 | |||
1249 | if (priv->tx_power_lmt_in_half_dbm && | ||
1250 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
1251 | /* | ||
1252 | * For the newer devices which using enhanced/extend tx power | ||
1253 | * table in EEPROM, the format is in half dBm. driver need to | ||
1254 | * convert to dBm format before report to mac80211. | ||
1255 | * By doing so, there is a possibility of 1/2 dBm resolution | ||
1256 | * lost. driver will perform "round-up" operation before | ||
1257 | * reporting, but it will cause 1/2 dBm tx power over the | ||
1258 | * regulatory limit. Perform the checking here, if the | ||
1259 | * "tx_power_user_lmt" is higher than EEPROM value (in | ||
1260 | * half-dBm format), lower the tx power based on EEPROM | ||
1261 | */ | ||
1262 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | ||
1263 | } | ||
1264 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; | ||
1265 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | ||
1266 | |||
1267 | if (IWL_UCODE_API(priv->ucode_ver) == 1) | ||
1268 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; | ||
1269 | else | ||
1270 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; | ||
1271 | |||
1272 | return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, | ||
1273 | sizeof(tx_power_cmd), &tx_power_cmd, | ||
1274 | NULL); | ||
1275 | } | ||
1276 | |||
1277 | void iwl5000_temperature(struct iwl_priv *priv) | ||
1278 | { | ||
1279 | /* store temperature from statistics (in Celsius) */ | ||
1280 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); | ||
1281 | iwl_tt_handler(priv); | ||
1282 | } | ||
1283 | |||
1284 | static void iwl5150_temperature(struct iwl_priv *priv) | 226 | static void iwl5150_temperature(struct iwl_priv *priv) |
1285 | { | 227 | { |
1286 | u32 vt = 0; | 228 | u32 vt = 0; |
@@ -1293,100 +235,6 @@ static void iwl5150_temperature(struct iwl_priv *priv) | |||
1293 | iwl_tt_handler(priv); | 235 | iwl_tt_handler(priv); |
1294 | } | 236 | } |
1295 | 237 | ||
1296 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
1297 | int iwl5000_calc_rssi(struct iwl_priv *priv, | ||
1298 | struct iwl_rx_phy_res *rx_resp) | ||
1299 | { | ||
1300 | /* data from PHY/DSP regarding signal strength, etc., | ||
1301 | * contents are always there, not configurable by host | ||
1302 | */ | ||
1303 | struct iwl5000_non_cfg_phy *ncphy = | ||
1304 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | ||
1305 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | ||
1306 | u8 agc; | ||
1307 | |||
1308 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | ||
1309 | agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; | ||
1310 | |||
1311 | /* Find max rssi among 3 possible receivers. | ||
1312 | * These values are measured by the digital signal processor (DSP). | ||
1313 | * They should stay fairly constant even as the signal strength varies, | ||
1314 | * if the radio's automatic gain control (AGC) is working right. | ||
1315 | * AGC value (see below) will provide the "interesting" info. | ||
1316 | */ | ||
1317 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | ||
1318 | rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; | ||
1319 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | ||
1320 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | ||
1321 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | ||
1322 | |||
1323 | max_rssi = max_t(u32, rssi_a, rssi_b); | ||
1324 | max_rssi = max_t(u32, max_rssi, rssi_c); | ||
1325 | |||
1326 | IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
1327 | rssi_a, rssi_b, rssi_c, max_rssi, agc); | ||
1328 | |||
1329 | /* dBm = max_rssi dB - agc dB - constant. | ||
1330 | * Higher AGC (higher radio gain) means lower signal. */ | ||
1331 | return max_rssi - agc - IWL49_RSSI_OFFSET; | ||
1332 | } | ||
1333 | |||
1334 | static int iwl5000_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | ||
1335 | { | ||
1336 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | ||
1337 | .valid = cpu_to_le32(valid_tx_ant), | ||
1338 | }; | ||
1339 | |||
1340 | if (IWL_UCODE_API(priv->ucode_ver) > 1) { | ||
1341 | IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); | ||
1342 | return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, | ||
1343 | sizeof(struct iwl_tx_ant_config_cmd), | ||
1344 | &tx_ant_cmd); | ||
1345 | } else { | ||
1346 | IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); | ||
1347 | return -EOPNOTSUPP; | ||
1348 | } | ||
1349 | } | ||
1350 | |||
1351 | |||
1352 | #define IWL5000_UCODE_GET(item) \ | ||
1353 | static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
1354 | u32 api_ver) \ | ||
1355 | { \ | ||
1356 | if (api_ver <= 2) \ | ||
1357 | return le32_to_cpu(ucode->u.v1.item); \ | ||
1358 | return le32_to_cpu(ucode->u.v2.item); \ | ||
1359 | } | ||
1360 | |||
1361 | static u32 iwl5000_ucode_get_header_size(u32 api_ver) | ||
1362 | { | ||
1363 | if (api_ver <= 2) | ||
1364 | return UCODE_HEADER_SIZE(1); | ||
1365 | return UCODE_HEADER_SIZE(2); | ||
1366 | } | ||
1367 | |||
1368 | static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
1369 | u32 api_ver) | ||
1370 | { | ||
1371 | if (api_ver <= 2) | ||
1372 | return 0; | ||
1373 | return le32_to_cpu(ucode->u.v2.build); | ||
1374 | } | ||
1375 | |||
1376 | static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
1377 | u32 api_ver) | ||
1378 | { | ||
1379 | if (api_ver <= 2) | ||
1380 | return (u8 *) ucode->u.v1.data; | ||
1381 | return (u8 *) ucode->u.v2.data; | ||
1382 | } | ||
1383 | |||
1384 | IWL5000_UCODE_GET(inst_size); | ||
1385 | IWL5000_UCODE_GET(data_size); | ||
1386 | IWL5000_UCODE_GET(init_size); | ||
1387 | IWL5000_UCODE_GET(init_data_size); | ||
1388 | IWL5000_UCODE_GET(boot_size); | ||
1389 | |||
1390 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 238 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) |
1391 | { | 239 | { |
1392 | struct iwl5000_channel_switch_cmd cmd; | 240 | struct iwl5000_channel_switch_cmd cmd; |
@@ -1419,54 +267,27 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
1419 | return iwl_send_cmd_sync(priv, &hcmd); | 267 | return iwl_send_cmd_sync(priv, &hcmd); |
1420 | } | 268 | } |
1421 | 269 | ||
1422 | struct iwl_hcmd_ops iwl5000_hcmd = { | 270 | static struct iwl_lib_ops iwl5000_lib = { |
1423 | .rxon_assoc = iwl5000_send_rxon_assoc, | ||
1424 | .commit_rxon = iwl_commit_rxon, | ||
1425 | .set_rxon_chain = iwl_set_rxon_chain, | ||
1426 | .set_tx_ant = iwl5000_send_tx_ant_config, | ||
1427 | }; | ||
1428 | |||
1429 | struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | ||
1430 | .get_hcmd_size = iwl5000_get_hcmd_size, | ||
1431 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, | ||
1432 | .gain_computation = iwl5000_gain_computation, | ||
1433 | .chain_noise_reset = iwl5000_chain_noise_reset, | ||
1434 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, | ||
1435 | .calc_rssi = iwl5000_calc_rssi, | ||
1436 | }; | ||
1437 | |||
1438 | struct iwl_ucode_ops iwl5000_ucode = { | ||
1439 | .get_header_size = iwl5000_ucode_get_header_size, | ||
1440 | .get_build = iwl5000_ucode_get_build, | ||
1441 | .get_inst_size = iwl5000_ucode_get_inst_size, | ||
1442 | .get_data_size = iwl5000_ucode_get_data_size, | ||
1443 | .get_init_size = iwl5000_ucode_get_init_size, | ||
1444 | .get_init_data_size = iwl5000_ucode_get_init_data_size, | ||
1445 | .get_boot_size = iwl5000_ucode_get_boot_size, | ||
1446 | .get_data = iwl5000_ucode_get_data, | ||
1447 | }; | ||
1448 | |||
1449 | struct iwl_lib_ops iwl5000_lib = { | ||
1450 | .set_hw_params = iwl5000_hw_set_hw_params, | 271 | .set_hw_params = iwl5000_hw_set_hw_params, |
1451 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 272 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
1452 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 273 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
1453 | .txq_set_sched = iwl5000_txq_set_sched, | 274 | .txq_set_sched = iwlagn_txq_set_sched, |
1454 | .txq_agg_enable = iwl5000_txq_agg_enable, | 275 | .txq_agg_enable = iwlagn_txq_agg_enable, |
1455 | .txq_agg_disable = iwl5000_txq_agg_disable, | 276 | .txq_agg_disable = iwlagn_txq_agg_disable, |
1456 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 277 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
1457 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 278 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
1458 | .txq_init = iwl_hw_tx_queue_init, | 279 | .txq_init = iwl_hw_tx_queue_init, |
1459 | .rx_handler_setup = iwl5000_rx_handler_setup, | 280 | .rx_handler_setup = iwlagn_rx_handler_setup, |
1460 | .setup_deferred_work = iwl5000_setup_deferred_work, | 281 | .setup_deferred_work = iwlagn_setup_deferred_work, |
1461 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 282 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
1462 | .dump_nic_event_log = iwl_dump_nic_event_log, | 283 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1463 | .dump_nic_error_log = iwl_dump_nic_error_log, | 284 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1464 | .dump_csr = iwl_dump_csr, | 285 | .dump_csr = iwl_dump_csr, |
1465 | .dump_fh = iwl_dump_fh, | 286 | .dump_fh = iwl_dump_fh, |
1466 | .load_ucode = iwl5000_load_ucode, | 287 | .load_ucode = iwlagn_load_ucode, |
1467 | .init_alive_start = iwl5000_init_alive_start, | 288 | .init_alive_start = iwlagn_init_alive_start, |
1468 | .alive_notify = iwl5000_alive_notify, | 289 | .alive_notify = iwlagn_alive_notify, |
1469 | .send_tx_power = iwl5000_send_tx_power, | 290 | .send_tx_power = iwlagn_send_tx_power, |
1470 | .update_chain_flags = iwl_update_chain_flags, | 291 | .update_chain_flags = iwl_update_chain_flags, |
1471 | .set_channel_switch = iwl5000_hw_channel_switch, | 292 | .set_channel_switch = iwl5000_hw_channel_switch, |
1472 | .apm_ops = { | 293 | .apm_ops = { |
@@ -1477,25 +298,25 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1477 | }, | 298 | }, |
1478 | .eeprom_ops = { | 299 | .eeprom_ops = { |
1479 | .regulatory_bands = { | 300 | .regulatory_bands = { |
1480 | EEPROM_5000_REG_BAND_1_CHANNELS, | 301 | EEPROM_REG_BAND_1_CHANNELS, |
1481 | EEPROM_5000_REG_BAND_2_CHANNELS, | 302 | EEPROM_REG_BAND_2_CHANNELS, |
1482 | EEPROM_5000_REG_BAND_3_CHANNELS, | 303 | EEPROM_REG_BAND_3_CHANNELS, |
1483 | EEPROM_5000_REG_BAND_4_CHANNELS, | 304 | EEPROM_REG_BAND_4_CHANNELS, |
1484 | EEPROM_5000_REG_BAND_5_CHANNELS, | 305 | EEPROM_REG_BAND_5_CHANNELS, |
1485 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 306 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
1486 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 307 | EEPROM_REG_BAND_52_HT40_CHANNELS |
1487 | }, | 308 | }, |
1488 | .verify_signature = iwlcore_eeprom_verify_signature, | 309 | .verify_signature = iwlcore_eeprom_verify_signature, |
1489 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 310 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
1490 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 311 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
1491 | .calib_version = iwl5000_eeprom_calib_version, | 312 | .calib_version = iwlagn_eeprom_calib_version, |
1492 | .query_addr = iwl5000_eeprom_query_addr, | 313 | .query_addr = iwlagn_eeprom_query_addr, |
1493 | }, | 314 | }, |
1494 | .post_associate = iwl_post_associate, | 315 | .post_associate = iwl_post_associate, |
1495 | .isr = iwl_isr_ict, | 316 | .isr = iwl_isr_ict, |
1496 | .config_ap = iwl_config_ap, | 317 | .config_ap = iwl_config_ap, |
1497 | .temp_ops = { | 318 | .temp_ops = { |
1498 | .temperature = iwl5000_temperature, | 319 | .temperature = iwlagn_temperature, |
1499 | .set_ct_kill = iwl5000_set_ct_threshold, | 320 | .set_ct_kill = iwl5000_set_ct_threshold, |
1500 | }, | 321 | }, |
1501 | .add_bcast_station = iwl_add_bcast_station, | 322 | .add_bcast_station = iwl_add_bcast_station, |
@@ -1506,24 +327,24 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1506 | 327 | ||
1507 | static struct iwl_lib_ops iwl5150_lib = { | 328 | static struct iwl_lib_ops iwl5150_lib = { |
1508 | .set_hw_params = iwl5000_hw_set_hw_params, | 329 | .set_hw_params = iwl5000_hw_set_hw_params, |
1509 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 330 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
1510 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 331 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
1511 | .txq_set_sched = iwl5000_txq_set_sched, | 332 | .txq_set_sched = iwlagn_txq_set_sched, |
1512 | .txq_agg_enable = iwl5000_txq_agg_enable, | 333 | .txq_agg_enable = iwlagn_txq_agg_enable, |
1513 | .txq_agg_disable = iwl5000_txq_agg_disable, | 334 | .txq_agg_disable = iwlagn_txq_agg_disable, |
1514 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 335 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
1515 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 336 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
1516 | .txq_init = iwl_hw_tx_queue_init, | 337 | .txq_init = iwl_hw_tx_queue_init, |
1517 | .rx_handler_setup = iwl5000_rx_handler_setup, | 338 | .rx_handler_setup = iwlagn_rx_handler_setup, |
1518 | .setup_deferred_work = iwl5000_setup_deferred_work, | 339 | .setup_deferred_work = iwlagn_setup_deferred_work, |
1519 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 340 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
1520 | .dump_nic_event_log = iwl_dump_nic_event_log, | 341 | .dump_nic_event_log = iwl_dump_nic_event_log, |
1521 | .dump_nic_error_log = iwl_dump_nic_error_log, | 342 | .dump_nic_error_log = iwl_dump_nic_error_log, |
1522 | .dump_csr = iwl_dump_csr, | 343 | .dump_csr = iwl_dump_csr, |
1523 | .load_ucode = iwl5000_load_ucode, | 344 | .load_ucode = iwlagn_load_ucode, |
1524 | .init_alive_start = iwl5000_init_alive_start, | 345 | .init_alive_start = iwlagn_init_alive_start, |
1525 | .alive_notify = iwl5000_alive_notify, | 346 | .alive_notify = iwlagn_alive_notify, |
1526 | .send_tx_power = iwl5000_send_tx_power, | 347 | .send_tx_power = iwlagn_send_tx_power, |
1527 | .update_chain_flags = iwl_update_chain_flags, | 348 | .update_chain_flags = iwl_update_chain_flags, |
1528 | .set_channel_switch = iwl5000_hw_channel_switch, | 349 | .set_channel_switch = iwl5000_hw_channel_switch, |
1529 | .apm_ops = { | 350 | .apm_ops = { |
@@ -1534,19 +355,19 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1534 | }, | 355 | }, |
1535 | .eeprom_ops = { | 356 | .eeprom_ops = { |
1536 | .regulatory_bands = { | 357 | .regulatory_bands = { |
1537 | EEPROM_5000_REG_BAND_1_CHANNELS, | 358 | EEPROM_REG_BAND_1_CHANNELS, |
1538 | EEPROM_5000_REG_BAND_2_CHANNELS, | 359 | EEPROM_REG_BAND_2_CHANNELS, |
1539 | EEPROM_5000_REG_BAND_3_CHANNELS, | 360 | EEPROM_REG_BAND_3_CHANNELS, |
1540 | EEPROM_5000_REG_BAND_4_CHANNELS, | 361 | EEPROM_REG_BAND_4_CHANNELS, |
1541 | EEPROM_5000_REG_BAND_5_CHANNELS, | 362 | EEPROM_REG_BAND_5_CHANNELS, |
1542 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 363 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
1543 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 364 | EEPROM_REG_BAND_52_HT40_CHANNELS |
1544 | }, | 365 | }, |
1545 | .verify_signature = iwlcore_eeprom_verify_signature, | 366 | .verify_signature = iwlcore_eeprom_verify_signature, |
1546 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 367 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
1547 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 368 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
1548 | .calib_version = iwl5000_eeprom_calib_version, | 369 | .calib_version = iwlagn_eeprom_calib_version, |
1549 | .query_addr = iwl5000_eeprom_query_addr, | 370 | .query_addr = iwlagn_eeprom_query_addr, |
1550 | }, | 371 | }, |
1551 | .post_associate = iwl_post_associate, | 372 | .post_associate = iwl_post_associate, |
1552 | .isr = iwl_isr_ict, | 373 | .isr = iwl_isr_ict, |
@@ -1562,28 +383,21 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1562 | }; | 383 | }; |
1563 | 384 | ||
1564 | static const struct iwl_ops iwl5000_ops = { | 385 | static const struct iwl_ops iwl5000_ops = { |
1565 | .ucode = &iwl5000_ucode, | 386 | .ucode = &iwlagn_ucode, |
1566 | .lib = &iwl5000_lib, | 387 | .lib = &iwl5000_lib, |
1567 | .hcmd = &iwl5000_hcmd, | 388 | .hcmd = &iwlagn_hcmd, |
1568 | .utils = &iwl5000_hcmd_utils, | 389 | .utils = &iwlagn_hcmd_utils, |
1569 | .led = &iwlagn_led_ops, | 390 | .led = &iwlagn_led_ops, |
1570 | }; | 391 | }; |
1571 | 392 | ||
1572 | static const struct iwl_ops iwl5150_ops = { | 393 | static const struct iwl_ops iwl5150_ops = { |
1573 | .ucode = &iwl5000_ucode, | 394 | .ucode = &iwlagn_ucode, |
1574 | .lib = &iwl5150_lib, | 395 | .lib = &iwl5150_lib, |
1575 | .hcmd = &iwl5000_hcmd, | 396 | .hcmd = &iwlagn_hcmd, |
1576 | .utils = &iwl5000_hcmd_utils, | 397 | .utils = &iwlagn_hcmd_utils, |
1577 | .led = &iwlagn_led_ops, | 398 | .led = &iwlagn_led_ops, |
1578 | }; | 399 | }; |
1579 | 400 | ||
1580 | struct iwl_mod_params iwl50_mod_params = { | ||
1581 | .amsdu_size_8K = 1, | ||
1582 | .restart_fw = 1, | ||
1583 | /* the rest are 0 by default */ | ||
1584 | }; | ||
1585 | |||
1586 | |||
1587 | struct iwl_cfg iwl5300_agn_cfg = { | 401 | struct iwl_cfg iwl5300_agn_cfg = { |
1588 | .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", | 402 | .name = "Intel(R) Ultimate N WiFi Link 5300 AGN", |
1589 | .fw_name_pre = IWL5000_FW_PRE, | 403 | .fw_name_pre = IWL5000_FW_PRE, |
@@ -1591,12 +405,12 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1591 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 405 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1592 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 406 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1593 | .ops = &iwl5000_ops, | 407 | .ops = &iwl5000_ops, |
1594 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 408 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1595 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 409 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1596 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 410 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1597 | .num_of_queues = IWL50_NUM_QUEUES, | 411 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1598 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 412 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1599 | .mod_params = &iwl50_mod_params, | 413 | .mod_params = &iwlagn_mod_params, |
1600 | .valid_tx_ant = ANT_ABC, | 414 | .valid_tx_ant = ANT_ABC, |
1601 | .valid_rx_ant = ANT_ABC, | 415 | .valid_rx_ant = ANT_ABC, |
1602 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 416 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1609,6 +423,7 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1609 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 423 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1610 | .chain_noise_scale = 1000, | 424 | .chain_noise_scale = 1000, |
1611 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 425 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
426 | .max_event_log_size = 512, | ||
1612 | }; | 427 | }; |
1613 | 428 | ||
1614 | struct iwl_cfg iwl5100_bgn_cfg = { | 429 | struct iwl_cfg iwl5100_bgn_cfg = { |
@@ -1618,12 +433,12 @@ struct iwl_cfg iwl5100_bgn_cfg = { | |||
1618 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 433 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1619 | .sku = IWL_SKU_G|IWL_SKU_N, | 434 | .sku = IWL_SKU_G|IWL_SKU_N, |
1620 | .ops = &iwl5000_ops, | 435 | .ops = &iwl5000_ops, |
1621 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 436 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1622 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 437 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1623 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 438 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1624 | .num_of_queues = IWL50_NUM_QUEUES, | 439 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1625 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 440 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1626 | .mod_params = &iwl50_mod_params, | 441 | .mod_params = &iwlagn_mod_params, |
1627 | .valid_tx_ant = ANT_B, | 442 | .valid_tx_ant = ANT_B, |
1628 | .valid_rx_ant = ANT_AB, | 443 | .valid_rx_ant = ANT_AB, |
1629 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 444 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1636,6 +451,7 @@ struct iwl_cfg iwl5100_bgn_cfg = { | |||
1636 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 451 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1637 | .chain_noise_scale = 1000, | 452 | .chain_noise_scale = 1000, |
1638 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 453 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
454 | .max_event_log_size = 512, | ||
1639 | }; | 455 | }; |
1640 | 456 | ||
1641 | struct iwl_cfg iwl5100_abg_cfg = { | 457 | struct iwl_cfg iwl5100_abg_cfg = { |
@@ -1645,12 +461,12 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1645 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 461 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1646 | .sku = IWL_SKU_A|IWL_SKU_G, | 462 | .sku = IWL_SKU_A|IWL_SKU_G, |
1647 | .ops = &iwl5000_ops, | 463 | .ops = &iwl5000_ops, |
1648 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 464 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1649 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 465 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1650 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 466 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1651 | .num_of_queues = IWL50_NUM_QUEUES, | 467 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1652 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 468 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1653 | .mod_params = &iwl50_mod_params, | 469 | .mod_params = &iwlagn_mod_params, |
1654 | .valid_tx_ant = ANT_B, | 470 | .valid_tx_ant = ANT_B, |
1655 | .valid_rx_ant = ANT_AB, | 471 | .valid_rx_ant = ANT_AB, |
1656 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 472 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1661,6 +477,7 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1661 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 477 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1662 | .chain_noise_scale = 1000, | 478 | .chain_noise_scale = 1000, |
1663 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 479 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
480 | .max_event_log_size = 512, | ||
1664 | }; | 481 | }; |
1665 | 482 | ||
1666 | struct iwl_cfg iwl5100_agn_cfg = { | 483 | struct iwl_cfg iwl5100_agn_cfg = { |
@@ -1670,12 +487,12 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1670 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 487 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1671 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 488 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1672 | .ops = &iwl5000_ops, | 489 | .ops = &iwl5000_ops, |
1673 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 490 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1674 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 491 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
1675 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 492 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
1676 | .num_of_queues = IWL50_NUM_QUEUES, | 493 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1677 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 494 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1678 | .mod_params = &iwl50_mod_params, | 495 | .mod_params = &iwlagn_mod_params, |
1679 | .valid_tx_ant = ANT_B, | 496 | .valid_tx_ant = ANT_B, |
1680 | .valid_rx_ant = ANT_AB, | 497 | .valid_rx_ant = ANT_AB, |
1681 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 498 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1688,6 +505,7 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1688 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 505 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1689 | .chain_noise_scale = 1000, | 506 | .chain_noise_scale = 1000, |
1690 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 507 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
508 | .max_event_log_size = 512, | ||
1691 | }; | 509 | }; |
1692 | 510 | ||
1693 | struct iwl_cfg iwl5350_agn_cfg = { | 511 | struct iwl_cfg iwl5350_agn_cfg = { |
@@ -1697,12 +515,12 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1697 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 515 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1698 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 516 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1699 | .ops = &iwl5000_ops, | 517 | .ops = &iwl5000_ops, |
1700 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 518 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1701 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 519 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1702 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 520 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1703 | .num_of_queues = IWL50_NUM_QUEUES, | 521 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1704 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 522 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1705 | .mod_params = &iwl50_mod_params, | 523 | .mod_params = &iwlagn_mod_params, |
1706 | .valid_tx_ant = ANT_ABC, | 524 | .valid_tx_ant = ANT_ABC, |
1707 | .valid_rx_ant = ANT_ABC, | 525 | .valid_rx_ant = ANT_ABC, |
1708 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 526 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1715,6 +533,7 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1715 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 533 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1716 | .chain_noise_scale = 1000, | 534 | .chain_noise_scale = 1000, |
1717 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 535 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
536 | .max_event_log_size = 512, | ||
1718 | }; | 537 | }; |
1719 | 538 | ||
1720 | struct iwl_cfg iwl5150_agn_cfg = { | 539 | struct iwl_cfg iwl5150_agn_cfg = { |
@@ -1724,12 +543,12 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1724 | .ucode_api_min = IWL5150_UCODE_API_MIN, | 543 | .ucode_api_min = IWL5150_UCODE_API_MIN, |
1725 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 544 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
1726 | .ops = &iwl5150_ops, | 545 | .ops = &iwl5150_ops, |
1727 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 546 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1728 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 547 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1729 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 548 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1730 | .num_of_queues = IWL50_NUM_QUEUES, | 549 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1731 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 550 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1732 | .mod_params = &iwl50_mod_params, | 551 | .mod_params = &iwlagn_mod_params, |
1733 | .valid_tx_ant = ANT_A, | 552 | .valid_tx_ant = ANT_A, |
1734 | .valid_rx_ant = ANT_AB, | 553 | .valid_rx_ant = ANT_AB, |
1735 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 554 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1742,6 +561,7 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1742 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 561 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1743 | .chain_noise_scale = 1000, | 562 | .chain_noise_scale = 1000, |
1744 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 563 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
564 | .max_event_log_size = 512, | ||
1745 | }; | 565 | }; |
1746 | 566 | ||
1747 | struct iwl_cfg iwl5150_abg_cfg = { | 567 | struct iwl_cfg iwl5150_abg_cfg = { |
@@ -1751,12 +571,12 @@ struct iwl_cfg iwl5150_abg_cfg = { | |||
1751 | .ucode_api_min = IWL5150_UCODE_API_MIN, | 571 | .ucode_api_min = IWL5150_UCODE_API_MIN, |
1752 | .sku = IWL_SKU_A|IWL_SKU_G, | 572 | .sku = IWL_SKU_A|IWL_SKU_G, |
1753 | .ops = &iwl5150_ops, | 573 | .ops = &iwl5150_ops, |
1754 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 574 | .eeprom_size = IWLAGN_EEPROM_IMG_SIZE, |
1755 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | 575 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, |
1756 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | 576 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, |
1757 | .num_of_queues = IWL50_NUM_QUEUES, | 577 | .num_of_queues = IWLAGN_NUM_QUEUES, |
1758 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 578 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
1759 | .mod_params = &iwl50_mod_params, | 579 | .mod_params = &iwlagn_mod_params, |
1760 | .valid_tx_ant = ANT_A, | 580 | .valid_tx_ant = ANT_A, |
1761 | .valid_rx_ant = ANT_AB, | 581 | .valid_rx_ant = ANT_AB, |
1762 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 582 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
@@ -1767,20 +587,8 @@ struct iwl_cfg iwl5150_abg_cfg = { | |||
1767 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, | 587 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
1768 | .chain_noise_scale = 1000, | 588 | .chain_noise_scale = 1000, |
1769 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 589 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
590 | .max_event_log_size = 512, | ||
1770 | }; | 591 | }; |
1771 | 592 | ||
1772 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); | 593 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); |
1773 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); | 594 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); |
1774 | |||
1775 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, S_IRUGO); | ||
1776 | MODULE_PARM_DESC(swcrypto50, | ||
1777 | "using software crypto engine (default 0 [hardware])\n"); | ||
1778 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, S_IRUGO); | ||
1779 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); | ||
1780 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, S_IRUGO); | ||
1781 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); | ||
1782 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, | ||
1783 | int, S_IRUGO); | ||
1784 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); | ||
1785 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, S_IRUGO); | ||
1786 | MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index d75799946a7e..dd03384432f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-agn.h" | 45 | #include "iwl-agn.h" |
46 | #include "iwl-helpers.h" | 46 | #include "iwl-helpers.h" |
47 | #include "iwl-5000-hw.h" | 47 | #include "iwl-agn-hw.h" |
48 | #include "iwl-6000-hw.h" | 48 | #include "iwl-6000-hw.h" |
49 | #include "iwl-agn-led.h" | 49 | #include "iwl-agn-led.h" |
50 | 50 | ||
@@ -57,6 +57,7 @@ | |||
57 | #define IWL6050_UCODE_API_MIN 4 | 57 | #define IWL6050_UCODE_API_MIN 4 |
58 | 58 | ||
59 | #define IWL6000_FW_PRE "iwlwifi-6000-" | 59 | #define IWL6000_FW_PRE "iwlwifi-6000-" |
60 | #define IWL6000_G2_FW_PRE "iwlwifi-6005-" | ||
60 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" | 61 | #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" |
61 | #define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) | 62 | #define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) |
62 | 63 | ||
@@ -137,7 +138,7 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | |||
137 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | 138 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) |
138 | { | 139 | { |
139 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && | 140 | if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES && |
140 | priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES) | 141 | priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES) |
141 | priv->cfg->num_of_queues = | 142 | priv->cfg->num_of_queues = |
142 | priv->cfg->mod_params->num_of_queues; | 143 | priv->cfg->mod_params->num_of_queues; |
143 | 144 | ||
@@ -145,7 +146,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |||
145 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | 146 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; |
146 | priv->hw_params.scd_bc_tbls_size = | 147 | priv->hw_params.scd_bc_tbls_size = |
147 | priv->cfg->num_of_queues * | 148 | priv->cfg->num_of_queues * |
148 | sizeof(struct iwl5000_scd_bc_tbl); | 149 | sizeof(struct iwlagn_scd_bc_tbl); |
149 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | 150 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); |
150 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 151 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
151 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 152 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
@@ -226,25 +227,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel) | |||
226 | 227 | ||
227 | static struct iwl_lib_ops iwl6000_lib = { | 228 | static struct iwl_lib_ops iwl6000_lib = { |
228 | .set_hw_params = iwl6000_hw_set_hw_params, | 229 | .set_hw_params = iwl6000_hw_set_hw_params, |
229 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 230 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
230 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 231 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
231 | .txq_set_sched = iwl5000_txq_set_sched, | 232 | .txq_set_sched = iwlagn_txq_set_sched, |
232 | .txq_agg_enable = iwl5000_txq_agg_enable, | 233 | .txq_agg_enable = iwlagn_txq_agg_enable, |
233 | .txq_agg_disable = iwl5000_txq_agg_disable, | 234 | .txq_agg_disable = iwlagn_txq_agg_disable, |
234 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 235 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
235 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 236 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
236 | .txq_init = iwl_hw_tx_queue_init, | 237 | .txq_init = iwl_hw_tx_queue_init, |
237 | .rx_handler_setup = iwl5000_rx_handler_setup, | 238 | .rx_handler_setup = iwlagn_rx_handler_setup, |
238 | .setup_deferred_work = iwl5000_setup_deferred_work, | 239 | .setup_deferred_work = iwlagn_setup_deferred_work, |
239 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 240 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
240 | .load_ucode = iwl5000_load_ucode, | 241 | .load_ucode = iwlagn_load_ucode, |
241 | .dump_nic_event_log = iwl_dump_nic_event_log, | 242 | .dump_nic_event_log = iwl_dump_nic_event_log, |
242 | .dump_nic_error_log = iwl_dump_nic_error_log, | 243 | .dump_nic_error_log = iwl_dump_nic_error_log, |
243 | .dump_csr = iwl_dump_csr, | 244 | .dump_csr = iwl_dump_csr, |
244 | .dump_fh = iwl_dump_fh, | 245 | .dump_fh = iwl_dump_fh, |
245 | .init_alive_start = iwl5000_init_alive_start, | 246 | .init_alive_start = iwlagn_init_alive_start, |
246 | .alive_notify = iwl5000_alive_notify, | 247 | .alive_notify = iwlagn_alive_notify, |
247 | .send_tx_power = iwl5000_send_tx_power, | 248 | .send_tx_power = iwlagn_send_tx_power, |
248 | .update_chain_flags = iwl_update_chain_flags, | 249 | .update_chain_flags = iwl_update_chain_flags, |
249 | .set_channel_switch = iwl6000_hw_channel_switch, | 250 | .set_channel_switch = iwl6000_hw_channel_switch, |
250 | .apm_ops = { | 251 | .apm_ops = { |
@@ -255,26 +256,26 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
255 | }, | 256 | }, |
256 | .eeprom_ops = { | 257 | .eeprom_ops = { |
257 | .regulatory_bands = { | 258 | .regulatory_bands = { |
258 | EEPROM_5000_REG_BAND_1_CHANNELS, | 259 | EEPROM_REG_BAND_1_CHANNELS, |
259 | EEPROM_5000_REG_BAND_2_CHANNELS, | 260 | EEPROM_REG_BAND_2_CHANNELS, |
260 | EEPROM_5000_REG_BAND_3_CHANNELS, | 261 | EEPROM_REG_BAND_3_CHANNELS, |
261 | EEPROM_5000_REG_BAND_4_CHANNELS, | 262 | EEPROM_REG_BAND_4_CHANNELS, |
262 | EEPROM_5000_REG_BAND_5_CHANNELS, | 263 | EEPROM_REG_BAND_5_CHANNELS, |
263 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 264 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
264 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 265 | EEPROM_REG_BAND_52_HT40_CHANNELS |
265 | }, | 266 | }, |
266 | .verify_signature = iwlcore_eeprom_verify_signature, | 267 | .verify_signature = iwlcore_eeprom_verify_signature, |
267 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 268 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
268 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 269 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
269 | .calib_version = iwl5000_eeprom_calib_version, | 270 | .calib_version = iwlagn_eeprom_calib_version, |
270 | .query_addr = iwl5000_eeprom_query_addr, | 271 | .query_addr = iwlagn_eeprom_query_addr, |
271 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | 272 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, |
272 | }, | 273 | }, |
273 | .post_associate = iwl_post_associate, | 274 | .post_associate = iwl_post_associate, |
274 | .isr = iwl_isr_ict, | 275 | .isr = iwl_isr_ict, |
275 | .config_ap = iwl_config_ap, | 276 | .config_ap = iwl_config_ap, |
276 | .temp_ops = { | 277 | .temp_ops = { |
277 | .temperature = iwl5000_temperature, | 278 | .temperature = iwlagn_temperature, |
278 | .set_ct_kill = iwl6000_set_ct_threshold, | 279 | .set_ct_kill = iwl6000_set_ct_threshold, |
279 | }, | 280 | }, |
280 | .add_bcast_station = iwl_add_bcast_station, | 281 | .add_bcast_station = iwl_add_bcast_station, |
@@ -284,34 +285,34 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
284 | }; | 285 | }; |
285 | 286 | ||
286 | static const struct iwl_ops iwl6000_ops = { | 287 | static const struct iwl_ops iwl6000_ops = { |
287 | .ucode = &iwl5000_ucode, | 288 | .ucode = &iwlagn_ucode, |
288 | .lib = &iwl6000_lib, | 289 | .lib = &iwl6000_lib, |
289 | .hcmd = &iwl5000_hcmd, | 290 | .hcmd = &iwlagn_hcmd, |
290 | .utils = &iwl5000_hcmd_utils, | 291 | .utils = &iwlagn_hcmd_utils, |
291 | .led = &iwlagn_led_ops, | 292 | .led = &iwlagn_led_ops, |
292 | }; | 293 | }; |
293 | 294 | ||
294 | static struct iwl_lib_ops iwl6050_lib = { | 295 | static struct iwl_lib_ops iwl6050_lib = { |
295 | .set_hw_params = iwl6000_hw_set_hw_params, | 296 | .set_hw_params = iwl6000_hw_set_hw_params, |
296 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 297 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, |
297 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 298 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, |
298 | .txq_set_sched = iwl5000_txq_set_sched, | 299 | .txq_set_sched = iwlagn_txq_set_sched, |
299 | .txq_agg_enable = iwl5000_txq_agg_enable, | 300 | .txq_agg_enable = iwlagn_txq_agg_enable, |
300 | .txq_agg_disable = iwl5000_txq_agg_disable, | 301 | .txq_agg_disable = iwlagn_txq_agg_disable, |
301 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 302 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
302 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 303 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
303 | .txq_init = iwl_hw_tx_queue_init, | 304 | .txq_init = iwl_hw_tx_queue_init, |
304 | .rx_handler_setup = iwl5000_rx_handler_setup, | 305 | .rx_handler_setup = iwlagn_rx_handler_setup, |
305 | .setup_deferred_work = iwl5000_setup_deferred_work, | 306 | .setup_deferred_work = iwlagn_setup_deferred_work, |
306 | .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, | 307 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
307 | .load_ucode = iwl5000_load_ucode, | 308 | .load_ucode = iwlagn_load_ucode, |
308 | .dump_nic_event_log = iwl_dump_nic_event_log, | 309 | .dump_nic_event_log = iwl_dump_nic_event_log, |
309 | .dump_nic_error_log = iwl_dump_nic_error_log, | 310 | .dump_nic_error_log = iwl_dump_nic_error_log, |
310 | .dump_csr = iwl_dump_csr, | 311 | .dump_csr = iwl_dump_csr, |
311 | .dump_fh = iwl_dump_fh, | 312 | .dump_fh = iwl_dump_fh, |
312 | .init_alive_start = iwl5000_init_alive_start, | 313 | .init_alive_start = iwlagn_init_alive_start, |
313 | .alive_notify = iwl5000_alive_notify, | 314 | .alive_notify = iwlagn_alive_notify, |
314 | .send_tx_power = iwl5000_send_tx_power, | 315 | .send_tx_power = iwlagn_send_tx_power, |
315 | .update_chain_flags = iwl_update_chain_flags, | 316 | .update_chain_flags = iwl_update_chain_flags, |
316 | .set_channel_switch = iwl6000_hw_channel_switch, | 317 | .set_channel_switch = iwl6000_hw_channel_switch, |
317 | .apm_ops = { | 318 | .apm_ops = { |
@@ -322,26 +323,26 @@ static struct iwl_lib_ops iwl6050_lib = { | |||
322 | }, | 323 | }, |
323 | .eeprom_ops = { | 324 | .eeprom_ops = { |
324 | .regulatory_bands = { | 325 | .regulatory_bands = { |
325 | EEPROM_5000_REG_BAND_1_CHANNELS, | 326 | EEPROM_REG_BAND_1_CHANNELS, |
326 | EEPROM_5000_REG_BAND_2_CHANNELS, | 327 | EEPROM_REG_BAND_2_CHANNELS, |
327 | EEPROM_5000_REG_BAND_3_CHANNELS, | 328 | EEPROM_REG_BAND_3_CHANNELS, |
328 | EEPROM_5000_REG_BAND_4_CHANNELS, | 329 | EEPROM_REG_BAND_4_CHANNELS, |
329 | EEPROM_5000_REG_BAND_5_CHANNELS, | 330 | EEPROM_REG_BAND_5_CHANNELS, |
330 | EEPROM_5000_REG_BAND_24_HT40_CHANNELS, | 331 | EEPROM_REG_BAND_24_HT40_CHANNELS, |
331 | EEPROM_5000_REG_BAND_52_HT40_CHANNELS | 332 | EEPROM_REG_BAND_52_HT40_CHANNELS |
332 | }, | 333 | }, |
333 | .verify_signature = iwlcore_eeprom_verify_signature, | 334 | .verify_signature = iwlcore_eeprom_verify_signature, |
334 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | 335 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, |
335 | .release_semaphore = iwlcore_eeprom_release_semaphore, | 336 | .release_semaphore = iwlcore_eeprom_release_semaphore, |
336 | .calib_version = iwl5000_eeprom_calib_version, | 337 | .calib_version = iwlagn_eeprom_calib_version, |
337 | .query_addr = iwl5000_eeprom_query_addr, | 338 | .query_addr = iwlagn_eeprom_query_addr, |
338 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, | 339 | .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, |
339 | }, | 340 | }, |
340 | .post_associate = iwl_post_associate, | 341 | .post_associate = iwl_post_associate, |
341 | .isr = iwl_isr_ict, | 342 | .isr = iwl_isr_ict, |
342 | .config_ap = iwl_config_ap, | 343 | .config_ap = iwl_config_ap, |
343 | .temp_ops = { | 344 | .temp_ops = { |
344 | .temperature = iwl5000_temperature, | 345 | .temperature = iwlagn_temperature, |
345 | .set_ct_kill = iwl6000_set_ct_threshold, | 346 | .set_ct_kill = iwl6000_set_ct_threshold, |
346 | .set_calib_version = iwl6050_set_calib_version, | 347 | .set_calib_version = iwl6050_set_calib_version, |
347 | }, | 348 | }, |
@@ -352,16 +353,50 @@ static struct iwl_lib_ops iwl6050_lib = { | |||
352 | }; | 353 | }; |
353 | 354 | ||
354 | static const struct iwl_ops iwl6050_ops = { | 355 | static const struct iwl_ops iwl6050_ops = { |
355 | .ucode = &iwl5000_ucode, | 356 | .ucode = &iwlagn_ucode, |
356 | .lib = &iwl6050_lib, | 357 | .lib = &iwl6050_lib, |
357 | .hcmd = &iwl5000_hcmd, | 358 | .hcmd = &iwlagn_hcmd, |
358 | .utils = &iwl5000_hcmd_utils, | 359 | .utils = &iwlagn_hcmd_utils, |
359 | .led = &iwlagn_led_ops, | 360 | .led = &iwlagn_led_ops, |
360 | }; | 361 | }; |
361 | 362 | ||
362 | /* | 363 | /* |
363 | * "i": Internal configuration, use internal Power Amplifier | 364 | * "i": Internal configuration, use internal Power Amplifier |
364 | */ | 365 | */ |
366 | struct iwl_cfg iwl6000i_g2_2agn_cfg = { | ||
367 | .name = "6000 Series 2x2 AGN Gen2", | ||
368 | .fw_name_pre = IWL6000_G2_FW_PRE, | ||
369 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
370 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
371 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
372 | .ops = &iwl6000_ops, | ||
373 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
374 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
375 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, | ||
376 | .num_of_queues = IWLAGN_NUM_QUEUES, | ||
377 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, | ||
378 | .mod_params = &iwlagn_mod_params, | ||
379 | .valid_tx_ant = ANT_AB, | ||
380 | .valid_rx_ant = ANT_AB, | ||
381 | .pll_cfg_val = 0, | ||
382 | .set_l0s = true, | ||
383 | .use_bsm = false, | ||
384 | .pa_type = IWL_PA_INTERNAL, | ||
385 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
386 | .shadow_ram_support = true, | ||
387 | .ht_greenfield_support = true, | ||
388 | .led_compensation = 51, | ||
389 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
390 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
391 | .supports_idle = true, | ||
392 | .adv_thermal_throttle = true, | ||
393 | .support_ct_kill_exit = true, | ||
394 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | ||
395 | .chain_noise_scale = 1000, | ||
396 | .monitor_recover_period = IWL_MONITORING_PERIOD, | ||
397 | .max_event_log_size = 1024, | ||
398 | }; | ||
399 | |||
365 | struct iwl_cfg iwl6000i_2agn_cfg = { | 400 | struct iwl_cfg iwl6000i_2agn_cfg = { |
366 | .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", | 401 | .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN", |
367 | .fw_name_pre = IWL6000_FW_PRE, | 402 | .fw_name_pre = IWL6000_FW_PRE, |
@@ -371,10 +406,10 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
371 | .ops = &iwl6000_ops, | 406 | .ops = &iwl6000_ops, |
372 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 407 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
373 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 408 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
374 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 409 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
375 | .num_of_queues = IWL50_NUM_QUEUES, | 410 | .num_of_queues = IWLAGN_NUM_QUEUES, |
376 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 411 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
377 | .mod_params = &iwl50_mod_params, | 412 | .mod_params = &iwlagn_mod_params, |
378 | .valid_tx_ant = ANT_BC, | 413 | .valid_tx_ant = ANT_BC, |
379 | .valid_rx_ant = ANT_BC, | 414 | .valid_rx_ant = ANT_BC, |
380 | .pll_cfg_val = 0, | 415 | .pll_cfg_val = 0, |
@@ -393,6 +428,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
393 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 428 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
394 | .chain_noise_scale = 1000, | 429 | .chain_noise_scale = 1000, |
395 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 430 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
431 | .max_event_log_size = 1024, | ||
396 | }; | 432 | }; |
397 | 433 | ||
398 | struct iwl_cfg iwl6000i_2abg_cfg = { | 434 | struct iwl_cfg iwl6000i_2abg_cfg = { |
@@ -404,10 +440,10 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
404 | .ops = &iwl6000_ops, | 440 | .ops = &iwl6000_ops, |
405 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 441 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
406 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 442 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
407 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 443 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
408 | .num_of_queues = IWL50_NUM_QUEUES, | 444 | .num_of_queues = IWLAGN_NUM_QUEUES, |
409 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 445 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
410 | .mod_params = &iwl50_mod_params, | 446 | .mod_params = &iwlagn_mod_params, |
411 | .valid_tx_ant = ANT_BC, | 447 | .valid_tx_ant = ANT_BC, |
412 | .valid_rx_ant = ANT_BC, | 448 | .valid_rx_ant = ANT_BC, |
413 | .pll_cfg_val = 0, | 449 | .pll_cfg_val = 0, |
@@ -425,6 +461,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = { | |||
425 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 461 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
426 | .chain_noise_scale = 1000, | 462 | .chain_noise_scale = 1000, |
427 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 463 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
464 | .max_event_log_size = 1024, | ||
428 | }; | 465 | }; |
429 | 466 | ||
430 | struct iwl_cfg iwl6000i_2bg_cfg = { | 467 | struct iwl_cfg iwl6000i_2bg_cfg = { |
@@ -436,10 +473,10 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
436 | .ops = &iwl6000_ops, | 473 | .ops = &iwl6000_ops, |
437 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 474 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
438 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 475 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
439 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 476 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
440 | .num_of_queues = IWL50_NUM_QUEUES, | 477 | .num_of_queues = IWLAGN_NUM_QUEUES, |
441 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 478 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
442 | .mod_params = &iwl50_mod_params, | 479 | .mod_params = &iwlagn_mod_params, |
443 | .valid_tx_ant = ANT_BC, | 480 | .valid_tx_ant = ANT_BC, |
444 | .valid_rx_ant = ANT_BC, | 481 | .valid_rx_ant = ANT_BC, |
445 | .pll_cfg_val = 0, | 482 | .pll_cfg_val = 0, |
@@ -457,6 +494,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = { | |||
457 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 494 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
458 | .chain_noise_scale = 1000, | 495 | .chain_noise_scale = 1000, |
459 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 496 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
497 | .max_event_log_size = 1024, | ||
460 | }; | 498 | }; |
461 | 499 | ||
462 | struct iwl_cfg iwl6050_2agn_cfg = { | 500 | struct iwl_cfg iwl6050_2agn_cfg = { |
@@ -468,10 +506,10 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
468 | .ops = &iwl6050_ops, | 506 | .ops = &iwl6050_ops, |
469 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 507 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
470 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 508 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
471 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 509 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, |
472 | .num_of_queues = IWL50_NUM_QUEUES, | 510 | .num_of_queues = IWLAGN_NUM_QUEUES, |
473 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 511 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
474 | .mod_params = &iwl50_mod_params, | 512 | .mod_params = &iwlagn_mod_params, |
475 | .valid_tx_ant = ANT_AB, | 513 | .valid_tx_ant = ANT_AB, |
476 | .valid_rx_ant = ANT_AB, | 514 | .valid_rx_ant = ANT_AB, |
477 | .pll_cfg_val = 0, | 515 | .pll_cfg_val = 0, |
@@ -490,6 +528,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
490 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 528 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
491 | .chain_noise_scale = 1500, | 529 | .chain_noise_scale = 1500, |
492 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 530 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
531 | .max_event_log_size = 1024, | ||
493 | }; | 532 | }; |
494 | 533 | ||
495 | struct iwl_cfg iwl6050_2abg_cfg = { | 534 | struct iwl_cfg iwl6050_2abg_cfg = { |
@@ -501,10 +540,10 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
501 | .ops = &iwl6050_ops, | 540 | .ops = &iwl6050_ops, |
502 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 541 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
503 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | 542 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, |
504 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 543 | .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, |
505 | .num_of_queues = IWL50_NUM_QUEUES, | 544 | .num_of_queues = IWLAGN_NUM_QUEUES, |
506 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 545 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
507 | .mod_params = &iwl50_mod_params, | 546 | .mod_params = &iwlagn_mod_params, |
508 | .valid_tx_ant = ANT_AB, | 547 | .valid_tx_ant = ANT_AB, |
509 | .valid_rx_ant = ANT_AB, | 548 | .valid_rx_ant = ANT_AB, |
510 | .pll_cfg_val = 0, | 549 | .pll_cfg_val = 0, |
@@ -522,6 +561,7 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
522 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 561 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
523 | .chain_noise_scale = 1500, | 562 | .chain_noise_scale = 1500, |
524 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 563 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
564 | .max_event_log_size = 1024, | ||
525 | }; | 565 | }; |
526 | 566 | ||
527 | struct iwl_cfg iwl6000_3agn_cfg = { | 567 | struct iwl_cfg iwl6000_3agn_cfg = { |
@@ -533,10 +573,10 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
533 | .ops = &iwl6000_ops, | 573 | .ops = &iwl6000_ops, |
534 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 574 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
535 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | 575 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
536 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 576 | .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, |
537 | .num_of_queues = IWL50_NUM_QUEUES, | 577 | .num_of_queues = IWLAGN_NUM_QUEUES, |
538 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | 578 | .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, |
539 | .mod_params = &iwl50_mod_params, | 579 | .mod_params = &iwlagn_mod_params, |
540 | .valid_tx_ant = ANT_ABC, | 580 | .valid_tx_ant = ANT_ABC, |
541 | .valid_rx_ant = ANT_ABC, | 581 | .valid_rx_ant = ANT_ABC, |
542 | .pll_cfg_val = 0, | 582 | .pll_cfg_val = 0, |
@@ -555,6 +595,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
555 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | 595 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, |
556 | .chain_noise_scale = 1000, | 596 | .chain_noise_scale = 1000, |
557 | .monitor_recover_period = IWL_MONITORING_PERIOD, | 597 | .monitor_recover_period = IWL_MONITORING_PERIOD, |
598 | .max_event_log_size = 1024, | ||
558 | }; | 599 | }; |
559 | 600 | ||
560 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 601 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c new file mode 100644 index 000000000000..28bc8f8ba981 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -0,0 +1,274 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-agn.h" | ||
39 | |||
40 | static int iwlagn_send_rxon_assoc(struct iwl_priv *priv) | ||
41 | { | ||
42 | int ret = 0; | ||
43 | struct iwl5000_rxon_assoc_cmd rxon_assoc; | ||
44 | const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; | ||
45 | const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; | ||
46 | |||
47 | if ((rxon1->flags == rxon2->flags) && | ||
48 | (rxon1->filter_flags == rxon2->filter_flags) && | ||
49 | (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && | ||
50 | (rxon1->ofdm_ht_single_stream_basic_rates == | ||
51 | rxon2->ofdm_ht_single_stream_basic_rates) && | ||
52 | (rxon1->ofdm_ht_dual_stream_basic_rates == | ||
53 | rxon2->ofdm_ht_dual_stream_basic_rates) && | ||
54 | (rxon1->ofdm_ht_triple_stream_basic_rates == | ||
55 | rxon2->ofdm_ht_triple_stream_basic_rates) && | ||
56 | (rxon1->acquisition_data == rxon2->acquisition_data) && | ||
57 | (rxon1->rx_chain == rxon2->rx_chain) && | ||
58 | (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { | ||
59 | IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | rxon_assoc.flags = priv->staging_rxon.flags; | ||
64 | rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; | ||
65 | rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; | ||
66 | rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; | ||
67 | rxon_assoc.reserved1 = 0; | ||
68 | rxon_assoc.reserved2 = 0; | ||
69 | rxon_assoc.reserved3 = 0; | ||
70 | rxon_assoc.ofdm_ht_single_stream_basic_rates = | ||
71 | priv->staging_rxon.ofdm_ht_single_stream_basic_rates; | ||
72 | rxon_assoc.ofdm_ht_dual_stream_basic_rates = | ||
73 | priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; | ||
74 | rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; | ||
75 | rxon_assoc.ofdm_ht_triple_stream_basic_rates = | ||
76 | priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; | ||
77 | rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; | ||
78 | |||
79 | ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, | ||
80 | sizeof(rxon_assoc), &rxon_assoc, NULL); | ||
81 | if (ret) | ||
82 | return ret; | ||
83 | |||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | ||
88 | { | ||
89 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | ||
90 | .valid = cpu_to_le32(valid_tx_ant), | ||
91 | }; | ||
92 | |||
93 | if (IWL_UCODE_API(priv->ucode_ver) > 1) { | ||
94 | IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); | ||
95 | return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, | ||
96 | sizeof(struct iwl_tx_ant_config_cmd), | ||
97 | &tx_ant_cmd); | ||
98 | } else { | ||
99 | IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); | ||
100 | return -EOPNOTSUPP; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | /* Currently this is the superset of everything */ | ||
105 | static u16 iwlagn_get_hcmd_size(u8 cmd_id, u16 len) | ||
106 | { | ||
107 | return len; | ||
108 | } | ||
109 | |||
110 | static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | ||
111 | { | ||
112 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | ||
113 | struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; | ||
114 | memcpy(addsta, cmd, size); | ||
115 | /* resrved in 5000 */ | ||
116 | addsta->rate_n_flags = cpu_to_le16(0); | ||
117 | return size; | ||
118 | } | ||
119 | |||
120 | static void iwlagn_gain_computation(struct iwl_priv *priv, | ||
121 | u32 average_noise[NUM_RX_CHAINS], | ||
122 | u16 min_average_noise_antenna_i, | ||
123 | u32 min_average_noise, | ||
124 | u8 default_chain) | ||
125 | { | ||
126 | int i; | ||
127 | s32 delta_g; | ||
128 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
129 | |||
130 | /* | ||
131 | * Find Gain Code for the chains based on "default chain" | ||
132 | */ | ||
133 | for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { | ||
134 | if ((data->disconn_array[i])) { | ||
135 | data->delta_gain_code[i] = 0; | ||
136 | continue; | ||
137 | } | ||
138 | |||
139 | delta_g = (priv->cfg->chain_noise_scale * | ||
140 | ((s32)average_noise[default_chain] - | ||
141 | (s32)average_noise[i])) / 1500; | ||
142 | |||
143 | /* bound gain by 2 bits value max, 3rd bit is sign */ | ||
144 | data->delta_gain_code[i] = | ||
145 | min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | ||
146 | |||
147 | if (delta_g < 0) | ||
148 | /* | ||
149 | * set negative sign ... | ||
150 | * note to Intel developers: This is uCode API format, | ||
151 | * not the format of any internal device registers. | ||
152 | * Do not change this format for e.g. 6050 or similar | ||
153 | * devices. Change format only if more resolution | ||
154 | * (i.e. more than 2 bits magnitude) is needed. | ||
155 | */ | ||
156 | data->delta_gain_code[i] |= (1 << 2); | ||
157 | } | ||
158 | |||
159 | IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", | ||
160 | data->delta_gain_code[1], data->delta_gain_code[2]); | ||
161 | |||
162 | if (!data->radio_write) { | ||
163 | struct iwl_calib_chain_noise_gain_cmd cmd; | ||
164 | |||
165 | memset(&cmd, 0, sizeof(cmd)); | ||
166 | |||
167 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; | ||
168 | cmd.hdr.first_group = 0; | ||
169 | cmd.hdr.groups_num = 1; | ||
170 | cmd.hdr.data_valid = 1; | ||
171 | cmd.delta_gain_1 = data->delta_gain_code[1]; | ||
172 | cmd.delta_gain_2 = data->delta_gain_code[2]; | ||
173 | iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, | ||
174 | sizeof(cmd), &cmd, NULL); | ||
175 | |||
176 | data->radio_write = 1; | ||
177 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | ||
178 | } | ||
179 | |||
180 | data->chain_noise_a = 0; | ||
181 | data->chain_noise_b = 0; | ||
182 | data->chain_noise_c = 0; | ||
183 | data->chain_signal_a = 0; | ||
184 | data->chain_signal_b = 0; | ||
185 | data->chain_signal_c = 0; | ||
186 | data->beacon_count = 0; | ||
187 | } | ||
188 | |||
189 | static void iwlagn_chain_noise_reset(struct iwl_priv *priv) | ||
190 | { | ||
191 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | ||
192 | int ret; | ||
193 | |||
194 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | ||
195 | struct iwl_calib_chain_noise_reset_cmd cmd; | ||
196 | memset(&cmd, 0, sizeof(cmd)); | ||
197 | |||
198 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | ||
199 | cmd.hdr.first_group = 0; | ||
200 | cmd.hdr.groups_num = 1; | ||
201 | cmd.hdr.data_valid = 1; | ||
202 | ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | ||
203 | sizeof(cmd), &cmd); | ||
204 | if (ret) | ||
205 | IWL_ERR(priv, | ||
206 | "Could not send REPLY_PHY_CALIBRATION_CMD\n"); | ||
207 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; | ||
208 | IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
213 | __le32 *tx_flags) | ||
214 | { | ||
215 | if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
216 | (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
217 | *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; | ||
218 | else | ||
219 | *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; | ||
220 | } | ||
221 | |||
222 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
223 | static int iwlagn_calc_rssi(struct iwl_priv *priv, | ||
224 | struct iwl_rx_phy_res *rx_resp) | ||
225 | { | ||
226 | /* data from PHY/DSP regarding signal strength, etc., | ||
227 | * contents are always there, not configurable by host | ||
228 | */ | ||
229 | struct iwl5000_non_cfg_phy *ncphy = | ||
230 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | ||
231 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | ||
232 | u8 agc; | ||
233 | |||
234 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | ||
235 | agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; | ||
236 | |||
237 | /* Find max rssi among 3 possible receivers. | ||
238 | * These values are measured by the digital signal processor (DSP). | ||
239 | * They should stay fairly constant even as the signal strength varies, | ||
240 | * if the radio's automatic gain control (AGC) is working right. | ||
241 | * AGC value (see below) will provide the "interesting" info. | ||
242 | */ | ||
243 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | ||
244 | rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; | ||
245 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | ||
246 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | ||
247 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | ||
248 | |||
249 | max_rssi = max_t(u32, rssi_a, rssi_b); | ||
250 | max_rssi = max_t(u32, max_rssi, rssi_c); | ||
251 | |||
252 | IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", | ||
253 | rssi_a, rssi_b, rssi_c, max_rssi, agc); | ||
254 | |||
255 | /* dBm = max_rssi dB - agc dB - constant. | ||
256 | * Higher AGC (higher radio gain) means lower signal. */ | ||
257 | return max_rssi - agc - IWLAGN_RSSI_OFFSET; | ||
258 | } | ||
259 | |||
260 | struct iwl_hcmd_ops iwlagn_hcmd = { | ||
261 | .rxon_assoc = iwlagn_send_rxon_assoc, | ||
262 | .commit_rxon = iwl_commit_rxon, | ||
263 | .set_rxon_chain = iwl_set_rxon_chain, | ||
264 | .set_tx_ant = iwlagn_send_tx_ant_config, | ||
265 | }; | ||
266 | |||
267 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { | ||
268 | .get_hcmd_size = iwlagn_get_hcmd_size, | ||
269 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, | ||
270 | .gain_computation = iwlagn_gain_computation, | ||
271 | .chain_noise_reset = iwlagn_chain_noise_reset, | ||
272 | .rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag, | ||
273 | .calc_rssi = iwlagn_calc_rssi, | ||
274 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h new file mode 100644 index 000000000000..f9a3fbb6338f --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h | |||
@@ -0,0 +1,118 @@ | |||
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 - 2010 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 - 2010 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 | * Please use this file (iwl-agn-hw.h) only for hardware-related definitions. | ||
65 | */ | ||
66 | |||
67 | #ifndef __iwl_agn_hw_h__ | ||
68 | #define __iwl_agn_hw_h__ | ||
69 | |||
70 | #define IWLAGN_RTC_INST_LOWER_BOUND (0x000000) | ||
71 | #define IWLAGN_RTC_INST_UPPER_BOUND (0x020000) | ||
72 | |||
73 | #define IWLAGN_RTC_DATA_LOWER_BOUND (0x800000) | ||
74 | #define IWLAGN_RTC_DATA_UPPER_BOUND (0x80C000) | ||
75 | |||
76 | #define IWLAGN_RTC_INST_SIZE (IWLAGN_RTC_INST_UPPER_BOUND - \ | ||
77 | IWLAGN_RTC_INST_LOWER_BOUND) | ||
78 | #define IWLAGN_RTC_DATA_SIZE (IWLAGN_RTC_DATA_UPPER_BOUND - \ | ||
79 | IWLAGN_RTC_DATA_LOWER_BOUND) | ||
80 | |||
81 | /* RSSI to dBm */ | ||
82 | #define IWLAGN_RSSI_OFFSET 44 | ||
83 | |||
84 | /* PCI registers */ | ||
85 | #define PCI_CFG_RETRY_TIMEOUT 0x041 | ||
86 | |||
87 | /* PCI register values */ | ||
88 | #define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 | ||
89 | #define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 | ||
90 | |||
91 | #define IWLAGN_DEFAULT_TX_RETRY 15 | ||
92 | |||
93 | /* Limit range of txpower output target to be between these values */ | ||
94 | #define IWLAGN_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm: 1 milliwatt */ | ||
95 | #define IWLAGN_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ | ||
96 | |||
97 | /* EEPROM */ | ||
98 | #define IWLAGN_EEPROM_IMG_SIZE 2048 | ||
99 | |||
100 | #define IWLAGN_CMD_FIFO_NUM 7 | ||
101 | #define IWLAGN_NUM_QUEUES 20 | ||
102 | #define IWLAGN_NUM_AMPDU_QUEUES 10 | ||
103 | #define IWLAGN_FIRST_AMPDU_QUEUE 10 | ||
104 | |||
105 | /* Fixed (non-configurable) rx data from phy */ | ||
106 | |||
107 | /** | ||
108 | * struct iwlagn_schedq_bc_tbl scheduler byte count table | ||
109 | * base physical address provided by SCD_DRAM_BASE_ADDR | ||
110 | * @tfd_offset 0-12 - tx command byte count | ||
111 | * 12-16 - station index | ||
112 | */ | ||
113 | struct iwlagn_scd_bc_tbl { | ||
114 | __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; | ||
115 | } __attribute__ ((packed)); | ||
116 | |||
117 | |||
118 | #endif /* __iwl_agn_hw_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index 4c5395eae956..a273e373b7b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c | |||
@@ -141,13 +141,14 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
141 | { | 141 | { |
142 | struct iwl_priv *priv = data; | 142 | struct iwl_priv *priv = data; |
143 | u32 inta, inta_mask; | 143 | u32 inta, inta_mask; |
144 | unsigned long flags; | ||
144 | #ifdef CONFIG_IWLWIFI_DEBUG | 145 | #ifdef CONFIG_IWLWIFI_DEBUG |
145 | u32 inta_fh; | 146 | u32 inta_fh; |
146 | #endif | 147 | #endif |
147 | if (!priv) | 148 | if (!priv) |
148 | return IRQ_NONE; | 149 | return IRQ_NONE; |
149 | 150 | ||
150 | spin_lock(&priv->lock); | 151 | spin_lock_irqsave(&priv->lock, flags); |
151 | 152 | ||
152 | /* Disable (but don't clear!) interrupts here to avoid | 153 | /* Disable (but don't clear!) interrupts here to avoid |
153 | * back-to-back ISRs and sporadic interrupts from our NIC. | 154 | * back-to-back ISRs and sporadic interrupts from our NIC. |
@@ -190,7 +191,7 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
190 | iwl_enable_interrupts(priv); | 191 | iwl_enable_interrupts(priv); |
191 | 192 | ||
192 | unplugged: | 193 | unplugged: |
193 | spin_unlock(&priv->lock); | 194 | spin_unlock_irqrestore(&priv->lock, flags); |
194 | return IRQ_HANDLED; | 195 | return IRQ_HANDLED; |
195 | 196 | ||
196 | none: | 197 | none: |
@@ -199,7 +200,7 @@ static irqreturn_t iwl_isr(int irq, void *data) | |||
199 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) | 200 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) |
200 | iwl_enable_interrupts(priv); | 201 | iwl_enable_interrupts(priv); |
201 | 202 | ||
202 | spin_unlock(&priv->lock); | 203 | spin_unlock_irqrestore(&priv->lock, flags); |
203 | return IRQ_NONE; | 204 | return IRQ_NONE; |
204 | } | 205 | } |
205 | 206 | ||
@@ -216,6 +217,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
216 | struct iwl_priv *priv = data; | 217 | struct iwl_priv *priv = data; |
217 | u32 inta, inta_mask; | 218 | u32 inta, inta_mask; |
218 | u32 val = 0; | 219 | u32 val = 0; |
220 | unsigned long flags; | ||
219 | 221 | ||
220 | if (!priv) | 222 | if (!priv) |
221 | return IRQ_NONE; | 223 | return IRQ_NONE; |
@@ -226,7 +228,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
226 | if (!priv->_agn.use_ict) | 228 | if (!priv->_agn.use_ict) |
227 | return iwl_isr(irq, data); | 229 | return iwl_isr(irq, data); |
228 | 230 | ||
229 | spin_lock(&priv->lock); | 231 | spin_lock_irqsave(&priv->lock, flags); |
230 | 232 | ||
231 | /* Disable (but don't clear!) interrupts here to avoid | 233 | /* Disable (but don't clear!) interrupts here to avoid |
232 | * back-to-back ISRs and sporadic interrupts from our NIC. | 234 | * back-to-back ISRs and sporadic interrupts from our NIC. |
@@ -290,7 +292,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
290 | iwl_enable_interrupts(priv); | 292 | iwl_enable_interrupts(priv); |
291 | } | 293 | } |
292 | 294 | ||
293 | spin_unlock(&priv->lock); | 295 | spin_unlock_irqrestore(&priv->lock, flags); |
294 | return IRQ_HANDLED; | 296 | return IRQ_HANDLED; |
295 | 297 | ||
296 | none: | 298 | none: |
@@ -300,6 +302,6 @@ irqreturn_t iwl_isr_ict(int irq, void *data) | |||
300 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) | 302 | if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->_agn.inta) |
301 | iwl_enable_interrupts(priv); | 303 | iwl_enable_interrupts(priv); |
302 | 304 | ||
303 | spin_unlock(&priv->lock); | 305 | spin_unlock_irqrestore(&priv->lock, flags); |
304 | return IRQ_NONE; | 306 | return IRQ_NONE; |
305 | } | 307 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c new file mode 100644 index 000000000000..c465c8590833 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -0,0 +1,1113 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #include <linux/etherdevice.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | #include "iwl-agn-hw.h" | ||
40 | #include "iwl-agn.h" | ||
41 | |||
42 | static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) | ||
43 | { | ||
44 | return le32_to_cpup((__le32 *)&tx_resp->status + | ||
45 | tx_resp->frame_count) & MAX_SN; | ||
46 | } | ||
47 | |||
48 | static int iwlagn_tx_status_reply_tx(struct iwl_priv *priv, | ||
49 | struct iwl_ht_agg *agg, | ||
50 | struct iwl5000_tx_resp *tx_resp, | ||
51 | int txq_id, u16 start_idx) | ||
52 | { | ||
53 | u16 status; | ||
54 | struct agg_tx_status *frame_status = &tx_resp->status; | ||
55 | struct ieee80211_tx_info *info = NULL; | ||
56 | struct ieee80211_hdr *hdr = NULL; | ||
57 | u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); | ||
58 | int i, sh, idx; | ||
59 | u16 seq; | ||
60 | |||
61 | if (agg->wait_for_ba) | ||
62 | IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); | ||
63 | |||
64 | agg->frame_count = tx_resp->frame_count; | ||
65 | agg->start_idx = start_idx; | ||
66 | agg->rate_n_flags = rate_n_flags; | ||
67 | agg->bitmap = 0; | ||
68 | |||
69 | /* # frames attempted by Tx command */ | ||
70 | if (agg->frame_count == 1) { | ||
71 | /* Only one frame was attempted; no block-ack will arrive */ | ||
72 | status = le16_to_cpu(frame_status[0].status); | ||
73 | idx = start_idx; | ||
74 | |||
75 | /* FIXME: code repetition */ | ||
76 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", | ||
77 | agg->frame_count, agg->start_idx, idx); | ||
78 | |||
79 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | ||
80 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
81 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
82 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
83 | iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info); | ||
84 | |||
85 | /* FIXME: code repetition end */ | ||
86 | |||
87 | IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", | ||
88 | status & 0xff, tx_resp->failure_frame); | ||
89 | IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); | ||
90 | |||
91 | agg->wait_for_ba = 0; | ||
92 | } else { | ||
93 | /* Two or more frames were attempted; expect block-ack */ | ||
94 | u64 bitmap = 0; | ||
95 | int start = agg->start_idx; | ||
96 | |||
97 | /* Construct bit-map of pending frames within Tx window */ | ||
98 | for (i = 0; i < agg->frame_count; i++) { | ||
99 | u16 sc; | ||
100 | status = le16_to_cpu(frame_status[i].status); | ||
101 | seq = le16_to_cpu(frame_status[i].sequence); | ||
102 | idx = SEQ_TO_INDEX(seq); | ||
103 | txq_id = SEQ_TO_QUEUE(seq); | ||
104 | |||
105 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | ||
106 | AGG_TX_STATE_ABORT_MSK)) | ||
107 | continue; | ||
108 | |||
109 | IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", | ||
110 | agg->frame_count, txq_id, idx); | ||
111 | |||
112 | hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); | ||
113 | if (!hdr) { | ||
114 | IWL_ERR(priv, | ||
115 | "BUG_ON idx doesn't point to valid skb" | ||
116 | " idx=%d, txq_id=%d\n", idx, txq_id); | ||
117 | return -1; | ||
118 | } | ||
119 | |||
120 | sc = le16_to_cpu(hdr->seq_ctrl); | ||
121 | if (idx != (SEQ_TO_SN(sc) & 0xff)) { | ||
122 | IWL_ERR(priv, | ||
123 | "BUG_ON idx doesn't match seq control" | ||
124 | " idx=%d, seq_idx=%d, seq=%d\n", | ||
125 | idx, SEQ_TO_SN(sc), | ||
126 | hdr->seq_ctrl); | ||
127 | return -1; | ||
128 | } | ||
129 | |||
130 | IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", | ||
131 | i, idx, SEQ_TO_SN(sc)); | ||
132 | |||
133 | sh = idx - start; | ||
134 | if (sh > 64) { | ||
135 | sh = (start - idx) + 0xff; | ||
136 | bitmap = bitmap << sh; | ||
137 | sh = 0; | ||
138 | start = idx; | ||
139 | } else if (sh < -64) | ||
140 | sh = 0xff - (start - idx); | ||
141 | else if (sh < 0) { | ||
142 | sh = start - idx; | ||
143 | start = idx; | ||
144 | bitmap = bitmap << sh; | ||
145 | sh = 0; | ||
146 | } | ||
147 | bitmap |= 1ULL << sh; | ||
148 | IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", | ||
149 | start, (unsigned long long)bitmap); | ||
150 | } | ||
151 | |||
152 | agg->bitmap = bitmap; | ||
153 | agg->start_idx = start; | ||
154 | IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", | ||
155 | agg->frame_count, agg->start_idx, | ||
156 | (unsigned long long)agg->bitmap); | ||
157 | |||
158 | if (bitmap) | ||
159 | agg->wait_for_ba = 1; | ||
160 | } | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | void iwl_check_abort_status(struct iwl_priv *priv, | ||
165 | u8 frame_count, u32 status) | ||
166 | { | ||
167 | if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) { | ||
168 | IWL_ERR(priv, "TODO: Implement Tx flush command!!!\n"); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static void iwlagn_rx_reply_tx(struct iwl_priv *priv, | ||
173 | struct iwl_rx_mem_buffer *rxb) | ||
174 | { | ||
175 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
176 | u16 sequence = le16_to_cpu(pkt->hdr.sequence); | ||
177 | int txq_id = SEQ_TO_QUEUE(sequence); | ||
178 | int index = SEQ_TO_INDEX(sequence); | ||
179 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
180 | struct ieee80211_tx_info *info; | ||
181 | struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | ||
182 | u32 status = le16_to_cpu(tx_resp->status.status); | ||
183 | int tid; | ||
184 | int sta_id; | ||
185 | int freed; | ||
186 | |||
187 | if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { | ||
188 | IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " | ||
189 | "is out of range [0-%d] %d %d\n", txq_id, | ||
190 | index, txq->q.n_bd, txq->q.write_ptr, | ||
191 | txq->q.read_ptr); | ||
192 | return; | ||
193 | } | ||
194 | |||
195 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | ||
196 | memset(&info->status, 0, sizeof(info->status)); | ||
197 | |||
198 | tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; | ||
199 | sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; | ||
200 | |||
201 | if (txq->sched_retry) { | ||
202 | const u32 scd_ssn = iwlagn_get_scd_ssn(tx_resp); | ||
203 | struct iwl_ht_agg *agg = NULL; | ||
204 | |||
205 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
206 | |||
207 | iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); | ||
208 | |||
209 | /* check if BAR is needed */ | ||
210 | if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) | ||
211 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
212 | |||
213 | if (txq->q.read_ptr != (scd_ssn & 0xff)) { | ||
214 | index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); | ||
215 | IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " | ||
216 | "scd_ssn=%d idx=%d txq=%d swq=%d\n", | ||
217 | scd_ssn , index, txq_id, txq->swq_id); | ||
218 | |||
219 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); | ||
220 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
221 | |||
222 | if (priv->mac80211_registered && | ||
223 | (iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
224 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { | ||
225 | if (agg->state == IWL_AGG_OFF) | ||
226 | iwl_wake_queue(priv, txq_id); | ||
227 | else | ||
228 | iwl_wake_queue(priv, txq->swq_id); | ||
229 | } | ||
230 | } | ||
231 | } else { | ||
232 | BUG_ON(txq_id != txq->swq_id); | ||
233 | |||
234 | info->status.rates[0].count = tx_resp->failure_frame + 1; | ||
235 | info->flags |= iwl_tx_status_to_mac80211(status); | ||
236 | iwlagn_hwrate_to_tx_control(priv, | ||
237 | le32_to_cpu(tx_resp->rate_n_flags), | ||
238 | info); | ||
239 | |||
240 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " | ||
241 | "0x%x retries %d\n", | ||
242 | txq_id, | ||
243 | iwl_get_tx_fail_reason(status), status, | ||
244 | le32_to_cpu(tx_resp->rate_n_flags), | ||
245 | tx_resp->failure_frame); | ||
246 | |||
247 | freed = iwlagn_tx_queue_reclaim(priv, txq_id, index); | ||
248 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
249 | |||
250 | if (priv->mac80211_registered && | ||
251 | (iwl_queue_space(&txq->q) > txq->q.low_mark)) | ||
252 | iwl_wake_queue(priv, txq_id); | ||
253 | } | ||
254 | |||
255 | iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); | ||
256 | |||
257 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | ||
258 | } | ||
259 | |||
260 | void iwlagn_rx_handler_setup(struct iwl_priv *priv) | ||
261 | { | ||
262 | /* init calibration handlers */ | ||
263 | priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = | ||
264 | iwlagn_rx_calib_result; | ||
265 | priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = | ||
266 | iwlagn_rx_calib_complete; | ||
267 | priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx; | ||
268 | } | ||
269 | |||
270 | void iwlagn_setup_deferred_work(struct iwl_priv *priv) | ||
271 | { | ||
272 | /* in agn, the tx power calibration is done in uCode */ | ||
273 | priv->disable_tx_power_cal = 1; | ||
274 | } | ||
275 | |||
276 | int iwlagn_hw_valid_rtc_data_addr(u32 addr) | ||
277 | { | ||
278 | return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) && | ||
279 | (addr < IWLAGN_RTC_DATA_UPPER_BOUND); | ||
280 | } | ||
281 | |||
282 | int iwlagn_send_tx_power(struct iwl_priv *priv) | ||
283 | { | ||
284 | struct iwl5000_tx_power_dbm_cmd tx_power_cmd; | ||
285 | u8 tx_ant_cfg_cmd; | ||
286 | |||
287 | /* half dBm need to multiply */ | ||
288 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | ||
289 | |||
290 | if (priv->tx_power_lmt_in_half_dbm && | ||
291 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
292 | /* | ||
293 | * For the newer devices which using enhanced/extend tx power | ||
294 | * table in EEPROM, the format is in half dBm. driver need to | ||
295 | * convert to dBm format before report to mac80211. | ||
296 | * By doing so, there is a possibility of 1/2 dBm resolution | ||
297 | * lost. driver will perform "round-up" operation before | ||
298 | * reporting, but it will cause 1/2 dBm tx power over the | ||
299 | * regulatory limit. Perform the checking here, if the | ||
300 | * "tx_power_user_lmt" is higher than EEPROM value (in | ||
301 | * half-dBm format), lower the tx power based on EEPROM | ||
302 | */ | ||
303 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | ||
304 | } | ||
305 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; | ||
306 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | ||
307 | |||
308 | if (IWL_UCODE_API(priv->ucode_ver) == 1) | ||
309 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; | ||
310 | else | ||
311 | tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; | ||
312 | |||
313 | return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, | ||
314 | sizeof(tx_power_cmd), &tx_power_cmd, | ||
315 | NULL); | ||
316 | } | ||
317 | |||
318 | void iwlagn_temperature(struct iwl_priv *priv) | ||
319 | { | ||
320 | /* store temperature from statistics (in Celsius) */ | ||
321 | priv->temperature = le32_to_cpu(priv->statistics.general.temperature); | ||
322 | iwl_tt_handler(priv); | ||
323 | } | ||
324 | |||
325 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv) | ||
326 | { | ||
327 | struct iwl_eeprom_calib_hdr { | ||
328 | u8 version; | ||
329 | u8 pa_type; | ||
330 | u16 voltage; | ||
331 | } *hdr; | ||
332 | |||
333 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | ||
334 | EEPROM_5000_CALIB_ALL); | ||
335 | return hdr->version; | ||
336 | |||
337 | } | ||
338 | |||
339 | /* | ||
340 | * EEPROM | ||
341 | */ | ||
342 | static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | ||
343 | { | ||
344 | u16 offset = 0; | ||
345 | |||
346 | if ((address & INDIRECT_ADDRESS) == 0) | ||
347 | return address; | ||
348 | |||
349 | switch (address & INDIRECT_TYPE_MSK) { | ||
350 | case INDIRECT_HOST: | ||
351 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); | ||
352 | break; | ||
353 | case INDIRECT_GENERAL: | ||
354 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); | ||
355 | break; | ||
356 | case INDIRECT_REGULATORY: | ||
357 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); | ||
358 | break; | ||
359 | case INDIRECT_CALIBRATION: | ||
360 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); | ||
361 | break; | ||
362 | case INDIRECT_PROCESS_ADJST: | ||
363 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); | ||
364 | break; | ||
365 | case INDIRECT_OTHERS: | ||
366 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); | ||
367 | break; | ||
368 | default: | ||
369 | IWL_ERR(priv, "illegal indirect type: 0x%X\n", | ||
370 | address & INDIRECT_TYPE_MSK); | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | /* translate the offset from words to byte */ | ||
375 | return (address & ADDRESS_MSK) + (offset << 1); | ||
376 | } | ||
377 | |||
378 | const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, | ||
379 | size_t offset) | ||
380 | { | ||
381 | u32 address = eeprom_indirect_address(priv, offset); | ||
382 | BUG_ON(address >= priv->cfg->eeprom_size); | ||
383 | return &priv->eeprom[address]; | ||
384 | } | ||
385 | |||
386 | struct iwl_mod_params iwlagn_mod_params = { | ||
387 | .amsdu_size_8K = 1, | ||
388 | .restart_fw = 1, | ||
389 | /* the rest are 0 by default */ | ||
390 | }; | ||
391 | |||
392 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
393 | { | ||
394 | unsigned long flags; | ||
395 | int i; | ||
396 | spin_lock_irqsave(&rxq->lock, flags); | ||
397 | INIT_LIST_HEAD(&rxq->rx_free); | ||
398 | INIT_LIST_HEAD(&rxq->rx_used); | ||
399 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
400 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
401 | /* In the reset function, these buffers may have been allocated | ||
402 | * to an SKB, so we need to unmap and free potential storage */ | ||
403 | if (rxq->pool[i].page != NULL) { | ||
404 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
405 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
406 | PCI_DMA_FROMDEVICE); | ||
407 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
408 | rxq->pool[i].page = NULL; | ||
409 | } | ||
410 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
411 | } | ||
412 | |||
413 | for (i = 0; i < RX_QUEUE_SIZE; i++) | ||
414 | rxq->queue[i] = NULL; | ||
415 | |||
416 | /* Set us so that we have processed and used all buffers, but have | ||
417 | * not restocked the Rx queue with fresh buffers */ | ||
418 | rxq->read = rxq->write = 0; | ||
419 | rxq->write_actual = 0; | ||
420 | rxq->free_count = 0; | ||
421 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
422 | } | ||
423 | |||
424 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
425 | { | ||
426 | u32 rb_size; | ||
427 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | ||
428 | u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ | ||
429 | |||
430 | if (!priv->cfg->use_isr_legacy) | ||
431 | rb_timeout = RX_RB_TIMEOUT; | ||
432 | |||
433 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
434 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | ||
435 | else | ||
436 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | ||
437 | |||
438 | /* Stop Rx DMA */ | ||
439 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
440 | |||
441 | /* Reset driver's Rx queue write index */ | ||
442 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | ||
443 | |||
444 | /* Tell device where to find RBD circular buffer in DRAM */ | ||
445 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
446 | (u32)(rxq->dma_addr >> 8)); | ||
447 | |||
448 | /* Tell device where in DRAM to update its Rx status */ | ||
449 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
450 | rxq->rb_stts_dma >> 4); | ||
451 | |||
452 | /* Enable Rx DMA | ||
453 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in | ||
454 | * the credit mechanism in 5000 HW RX FIFO | ||
455 | * Direct rx interrupts to hosts | ||
456 | * Rx buffer size 4 or 8k | ||
457 | * RB timeout 0x10 | ||
458 | * 256 RBDs | ||
459 | */ | ||
460 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
461 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | ||
462 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | ||
463 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | ||
464 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | | ||
465 | rb_size| | ||
466 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | ||
467 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | ||
468 | |||
469 | /* Set interrupt coalescing timer to default (2048 usecs) */ | ||
470 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | int iwlagn_hw_nic_init(struct iwl_priv *priv) | ||
476 | { | ||
477 | unsigned long flags; | ||
478 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
479 | int ret; | ||
480 | |||
481 | /* nic_init */ | ||
482 | spin_lock_irqsave(&priv->lock, flags); | ||
483 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
484 | |||
485 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | ||
486 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
487 | |||
488 | spin_unlock_irqrestore(&priv->lock, flags); | ||
489 | |||
490 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | ||
491 | |||
492 | priv->cfg->ops->lib->apm_ops.config(priv); | ||
493 | |||
494 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
495 | if (!rxq->bd) { | ||
496 | ret = iwl_rx_queue_alloc(priv); | ||
497 | if (ret) { | ||
498 | IWL_ERR(priv, "Unable to initialize Rx queue\n"); | ||
499 | return -ENOMEM; | ||
500 | } | ||
501 | } else | ||
502 | iwlagn_rx_queue_reset(priv, rxq); | ||
503 | |||
504 | iwlagn_rx_replenish(priv); | ||
505 | |||
506 | iwlagn_rx_init(priv, rxq); | ||
507 | |||
508 | spin_lock_irqsave(&priv->lock, flags); | ||
509 | |||
510 | rxq->need_update = 1; | ||
511 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
512 | |||
513 | spin_unlock_irqrestore(&priv->lock, flags); | ||
514 | |||
515 | /* Allocate or reset and init all Tx and Command queues */ | ||
516 | if (!priv->txq) { | ||
517 | ret = iwlagn_txq_ctx_alloc(priv); | ||
518 | if (ret) | ||
519 | return ret; | ||
520 | } else | ||
521 | iwlagn_txq_ctx_reset(priv); | ||
522 | |||
523 | set_bit(STATUS_INIT, &priv->status); | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | /** | ||
529 | * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | ||
530 | */ | ||
531 | static inline __le32 iwlagn_dma_addr2rbd_ptr(struct iwl_priv *priv, | ||
532 | dma_addr_t dma_addr) | ||
533 | { | ||
534 | return cpu_to_le32((u32)(dma_addr >> 8)); | ||
535 | } | ||
536 | |||
537 | /** | ||
538 | * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool | ||
539 | * | ||
540 | * If there are slots in the RX queue that need to be restocked, | ||
541 | * and we have free pre-allocated buffers, fill the ranks as much | ||
542 | * as we can, pulling from rx_free. | ||
543 | * | ||
544 | * This moves the 'write' index forward to catch up with 'processed', and | ||
545 | * also updates the memory address in the firmware to reference the new | ||
546 | * target buffer. | ||
547 | */ | ||
548 | void iwlagn_rx_queue_restock(struct iwl_priv *priv) | ||
549 | { | ||
550 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
551 | struct list_head *element; | ||
552 | struct iwl_rx_mem_buffer *rxb; | ||
553 | unsigned long flags; | ||
554 | |||
555 | spin_lock_irqsave(&rxq->lock, flags); | ||
556 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | ||
557 | /* The overwritten rxb must be a used one */ | ||
558 | rxb = rxq->queue[rxq->write]; | ||
559 | BUG_ON(rxb && rxb->page); | ||
560 | |||
561 | /* Get next free Rx buffer, remove from free list */ | ||
562 | element = rxq->rx_free.next; | ||
563 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
564 | list_del(element); | ||
565 | |||
566 | /* Point to Rx buffer via next RBD in circular buffer */ | ||
567 | rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(priv, | ||
568 | rxb->page_dma); | ||
569 | rxq->queue[rxq->write] = rxb; | ||
570 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | ||
571 | rxq->free_count--; | ||
572 | } | ||
573 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
574 | /* If the pre-allocated buffer pool is dropping low, schedule to | ||
575 | * refill it */ | ||
576 | if (rxq->free_count <= RX_LOW_WATERMARK) | ||
577 | queue_work(priv->workqueue, &priv->rx_replenish); | ||
578 | |||
579 | |||
580 | /* If we've added more space for the firmware to place data, tell it. | ||
581 | * Increment device's write pointer in multiples of 8. */ | ||
582 | if (rxq->write_actual != (rxq->write & ~0x7)) { | ||
583 | spin_lock_irqsave(&rxq->lock, flags); | ||
584 | rxq->need_update = 1; | ||
585 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
586 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | /** | ||
591 | * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free | ||
592 | * | ||
593 | * When moving to rx_free an SKB is allocated for the slot. | ||
594 | * | ||
595 | * Also restock the Rx queue via iwl_rx_queue_restock. | ||
596 | * This is called as a scheduled work item (except for during initialization) | ||
597 | */ | ||
598 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority) | ||
599 | { | ||
600 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
601 | struct list_head *element; | ||
602 | struct iwl_rx_mem_buffer *rxb; | ||
603 | struct page *page; | ||
604 | unsigned long flags; | ||
605 | gfp_t gfp_mask = priority; | ||
606 | |||
607 | while (1) { | ||
608 | spin_lock_irqsave(&rxq->lock, flags); | ||
609 | if (list_empty(&rxq->rx_used)) { | ||
610 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
611 | return; | ||
612 | } | ||
613 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
614 | |||
615 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
616 | gfp_mask |= __GFP_NOWARN; | ||
617 | |||
618 | if (priv->hw_params.rx_page_order > 0) | ||
619 | gfp_mask |= __GFP_COMP; | ||
620 | |||
621 | /* Alloc a new receive buffer */ | ||
622 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); | ||
623 | if (!page) { | ||
624 | if (net_ratelimit()) | ||
625 | IWL_DEBUG_INFO(priv, "alloc_pages failed, " | ||
626 | "order: %d\n", | ||
627 | priv->hw_params.rx_page_order); | ||
628 | |||
629 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
630 | net_ratelimit()) | ||
631 | IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", | ||
632 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
633 | rxq->free_count); | ||
634 | /* We don't reschedule replenish work here -- we will | ||
635 | * call the restock method and if it still needs | ||
636 | * more buffers it will schedule replenish */ | ||
637 | return; | ||
638 | } | ||
639 | |||
640 | spin_lock_irqsave(&rxq->lock, flags); | ||
641 | |||
642 | if (list_empty(&rxq->rx_used)) { | ||
643 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
644 | __free_pages(page, priv->hw_params.rx_page_order); | ||
645 | return; | ||
646 | } | ||
647 | element = rxq->rx_used.next; | ||
648 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
649 | list_del(element); | ||
650 | |||
651 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
652 | |||
653 | BUG_ON(rxb->page); | ||
654 | rxb->page = page; | ||
655 | /* Get physical address of the RB */ | ||
656 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, | ||
657 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
658 | PCI_DMA_FROMDEVICE); | ||
659 | /* dma address must be no more than 36 bits */ | ||
660 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); | ||
661 | /* and also 256 byte aligned! */ | ||
662 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); | ||
663 | |||
664 | spin_lock_irqsave(&rxq->lock, flags); | ||
665 | |||
666 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
667 | rxq->free_count++; | ||
668 | priv->alloc_rxb_page++; | ||
669 | |||
670 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
671 | } | ||
672 | } | ||
673 | |||
674 | void iwlagn_rx_replenish(struct iwl_priv *priv) | ||
675 | { | ||
676 | unsigned long flags; | ||
677 | |||
678 | iwlagn_rx_allocate(priv, GFP_KERNEL); | ||
679 | |||
680 | spin_lock_irqsave(&priv->lock, flags); | ||
681 | iwlagn_rx_queue_restock(priv); | ||
682 | spin_unlock_irqrestore(&priv->lock, flags); | ||
683 | } | ||
684 | |||
685 | void iwlagn_rx_replenish_now(struct iwl_priv *priv) | ||
686 | { | ||
687 | iwlagn_rx_allocate(priv, GFP_ATOMIC); | ||
688 | |||
689 | iwlagn_rx_queue_restock(priv); | ||
690 | } | ||
691 | |||
692 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | ||
693 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL | ||
694 | * This free routine walks the list of POOL entries and if SKB is set to | ||
695 | * non NULL it is unmapped and freed | ||
696 | */ | ||
697 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
698 | { | ||
699 | int i; | ||
700 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | ||
701 | if (rxq->pool[i].page != NULL) { | ||
702 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
703 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
704 | PCI_DMA_FROMDEVICE); | ||
705 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
706 | rxq->pool[i].page = NULL; | ||
707 | } | ||
708 | } | ||
709 | |||
710 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | ||
711 | rxq->dma_addr); | ||
712 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | ||
713 | rxq->rb_stts, rxq->rb_stts_dma); | ||
714 | rxq->bd = NULL; | ||
715 | rxq->rb_stts = NULL; | ||
716 | } | ||
717 | |||
718 | int iwlagn_rxq_stop(struct iwl_priv *priv) | ||
719 | { | ||
720 | |||
721 | /* stop Rx DMA */ | ||
722 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
723 | iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, | ||
724 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | ||
725 | |||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | ||
730 | { | ||
731 | int idx = 0; | ||
732 | int band_offset = 0; | ||
733 | |||
734 | /* HT rate format: mac80211 wants an MCS number, which is just LSB */ | ||
735 | if (rate_n_flags & RATE_MCS_HT_MSK) { | ||
736 | idx = (rate_n_flags & 0xff); | ||
737 | return idx; | ||
738 | /* Legacy rate format, search for match in table */ | ||
739 | } else { | ||
740 | if (band == IEEE80211_BAND_5GHZ) | ||
741 | band_offset = IWL_FIRST_OFDM_RATE; | ||
742 | for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) | ||
743 | if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) | ||
744 | return idx - band_offset; | ||
745 | } | ||
746 | |||
747 | return -1; | ||
748 | } | ||
749 | |||
750 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
751 | static inline int iwlagn_calc_rssi(struct iwl_priv *priv, | ||
752 | struct iwl_rx_phy_res *rx_resp) | ||
753 | { | ||
754 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | ||
755 | } | ||
756 | |||
757 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
758 | /** | ||
759 | * iwlagn_dbg_report_frame - dump frame to syslog during debug sessions | ||
760 | * | ||
761 | * You may hack this function to show different aspects of received frames, | ||
762 | * including selective frame dumps. | ||
763 | * group100 parameter selects whether to show 1 out of 100 good data frames. | ||
764 | * All beacon and probe response frames are printed. | ||
765 | */ | ||
766 | static void iwlagn_dbg_report_frame(struct iwl_priv *priv, | ||
767 | struct iwl_rx_phy_res *phy_res, u16 length, | ||
768 | struct ieee80211_hdr *header, int group100) | ||
769 | { | ||
770 | u32 to_us; | ||
771 | u32 print_summary = 0; | ||
772 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
773 | u32 hundred = 0; | ||
774 | u32 dataframe = 0; | ||
775 | __le16 fc; | ||
776 | u16 seq_ctl; | ||
777 | u16 channel; | ||
778 | u16 phy_flags; | ||
779 | u32 rate_n_flags; | ||
780 | u32 tsf_low; | ||
781 | int rssi; | ||
782 | |||
783 | if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) | ||
784 | return; | ||
785 | |||
786 | /* MAC header */ | ||
787 | fc = header->frame_control; | ||
788 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
789 | |||
790 | /* metadata */ | ||
791 | channel = le16_to_cpu(phy_res->channel); | ||
792 | phy_flags = le16_to_cpu(phy_res->phy_flags); | ||
793 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
794 | |||
795 | /* signal statistics */ | ||
796 | rssi = iwlagn_calc_rssi(priv, phy_res); | ||
797 | tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; | ||
798 | |||
799 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
800 | |||
801 | /* if data frame is to us and all is good, | ||
802 | * (optionally) print summary for only 1 out of every 100 */ | ||
803 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
804 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
805 | dataframe = 1; | ||
806 | if (!group100) | ||
807 | print_summary = 1; /* print each frame */ | ||
808 | else if (priv->framecnt_to_us < 100) { | ||
809 | priv->framecnt_to_us++; | ||
810 | print_summary = 0; | ||
811 | } else { | ||
812 | priv->framecnt_to_us = 0; | ||
813 | print_summary = 1; | ||
814 | hundred = 1; | ||
815 | } | ||
816 | } else { | ||
817 | /* print summary for all other frames */ | ||
818 | print_summary = 1; | ||
819 | } | ||
820 | |||
821 | if (print_summary) { | ||
822 | char *title; | ||
823 | int rate_idx; | ||
824 | u32 bitrate; | ||
825 | |||
826 | if (hundred) | ||
827 | title = "100Frames"; | ||
828 | else if (ieee80211_has_retry(fc)) | ||
829 | title = "Retry"; | ||
830 | else if (ieee80211_is_assoc_resp(fc)) | ||
831 | title = "AscRsp"; | ||
832 | else if (ieee80211_is_reassoc_resp(fc)) | ||
833 | title = "RasRsp"; | ||
834 | else if (ieee80211_is_probe_resp(fc)) { | ||
835 | title = "PrbRsp"; | ||
836 | print_dump = 1; /* dump frame contents */ | ||
837 | } else if (ieee80211_is_beacon(fc)) { | ||
838 | title = "Beacon"; | ||
839 | print_dump = 1; /* dump frame contents */ | ||
840 | } else if (ieee80211_is_atim(fc)) | ||
841 | title = "ATIM"; | ||
842 | else if (ieee80211_is_auth(fc)) | ||
843 | title = "Auth"; | ||
844 | else if (ieee80211_is_deauth(fc)) | ||
845 | title = "DeAuth"; | ||
846 | else if (ieee80211_is_disassoc(fc)) | ||
847 | title = "DisAssoc"; | ||
848 | else | ||
849 | title = "Frame"; | ||
850 | |||
851 | rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | ||
852 | if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { | ||
853 | bitrate = 0; | ||
854 | WARN_ON_ONCE(1); | ||
855 | } else { | ||
856 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
857 | } | ||
858 | |||
859 | /* print frame summary. | ||
860 | * MAC addresses show just the last byte (for brevity), | ||
861 | * but you can hack it to show more, if you'd like to. */ | ||
862 | if (dataframe) | ||
863 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
864 | "len=%u, rssi=%d, chnl=%d, rate=%u,\n", | ||
865 | title, le16_to_cpu(fc), header->addr1[5], | ||
866 | length, rssi, channel, bitrate); | ||
867 | else { | ||
868 | /* src/dst addresses assume managed mode */ | ||
869 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " | ||
870 | "len=%u, rssi=%d, tim=%lu usec, " | ||
871 | "phy=0x%02x, chnl=%d\n", | ||
872 | title, le16_to_cpu(fc), header->addr1[5], | ||
873 | header->addr3[5], length, rssi, | ||
874 | tsf_low - priv->scan_start_tsf, | ||
875 | phy_flags, channel); | ||
876 | } | ||
877 | } | ||
878 | if (print_dump) | ||
879 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | ||
880 | } | ||
881 | #endif | ||
882 | |||
883 | static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
884 | { | ||
885 | u32 decrypt_out = 0; | ||
886 | |||
887 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
888 | RX_RES_STATUS_STATION_FOUND) | ||
889 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
890 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
891 | |||
892 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
893 | |||
894 | /* packet was not encrypted */ | ||
895 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
896 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
897 | return decrypt_out; | ||
898 | |||
899 | /* packet was encrypted with unknown alg */ | ||
900 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
901 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
902 | return decrypt_out; | ||
903 | |||
904 | /* decryption was not done in HW */ | ||
905 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
906 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
907 | return decrypt_out; | ||
908 | |||
909 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
910 | |||
911 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
912 | /* alg is CCM: check MIC only */ | ||
913 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
914 | /* Bad MIC */ | ||
915 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
916 | else | ||
917 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
918 | |||
919 | break; | ||
920 | |||
921 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
922 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
923 | /* Bad TTAK */ | ||
924 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
925 | break; | ||
926 | } | ||
927 | /* fall through if TTAK OK */ | ||
928 | default: | ||
929 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
930 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
931 | else | ||
932 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
933 | break; | ||
934 | }; | ||
935 | |||
936 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
937 | decrypt_in, decrypt_out); | ||
938 | |||
939 | return decrypt_out; | ||
940 | } | ||
941 | |||
942 | static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
943 | struct ieee80211_hdr *hdr, | ||
944 | u16 len, | ||
945 | u32 ampdu_status, | ||
946 | struct iwl_rx_mem_buffer *rxb, | ||
947 | struct ieee80211_rx_status *stats) | ||
948 | { | ||
949 | struct sk_buff *skb; | ||
950 | __le16 fc = hdr->frame_control; | ||
951 | |||
952 | /* We only process data packets if the interface is open */ | ||
953 | if (unlikely(!priv->is_open)) { | ||
954 | IWL_DEBUG_DROP_LIMIT(priv, | ||
955 | "Dropping packet while interface is not open.\n"); | ||
956 | return; | ||
957 | } | ||
958 | |||
959 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
960 | if (!priv->cfg->mod_params->sw_crypto && | ||
961 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
962 | return; | ||
963 | |||
964 | skb = dev_alloc_skb(128); | ||
965 | if (!skb) { | ||
966 | IWL_ERR(priv, "dev_alloc_skb failed\n"); | ||
967 | return; | ||
968 | } | ||
969 | |||
970 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
971 | |||
972 | iwl_update_stats(priv, false, fc, len); | ||
973 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
974 | |||
975 | ieee80211_rx(priv->hw, skb); | ||
976 | priv->alloc_rxb_page--; | ||
977 | rxb->page = NULL; | ||
978 | } | ||
979 | |||
980 | /* Called for REPLY_RX (legacy ABG frames), or | ||
981 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
982 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||
983 | struct iwl_rx_mem_buffer *rxb) | ||
984 | { | ||
985 | struct ieee80211_hdr *header; | ||
986 | struct ieee80211_rx_status rx_status; | ||
987 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
988 | struct iwl_rx_phy_res *phy_res; | ||
989 | __le32 rx_pkt_status; | ||
990 | struct iwl4965_rx_mpdu_res_start *amsdu; | ||
991 | u32 len; | ||
992 | u32 ampdu_status; | ||
993 | u32 rate_n_flags; | ||
994 | |||
995 | /** | ||
996 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
997 | * REPLY_RX: physical layer info is in this buffer | ||
998 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
999 | * command and cached in priv->last_phy_res | ||
1000 | * | ||
1001 | * Here we set up local variables depending on which command is | ||
1002 | * received. | ||
1003 | */ | ||
1004 | if (pkt->hdr.cmd == REPLY_RX) { | ||
1005 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
1006 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
1007 | + phy_res->cfg_phy_cnt); | ||
1008 | |||
1009 | len = le16_to_cpu(phy_res->byte_count); | ||
1010 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1011 | phy_res->cfg_phy_cnt + len); | ||
1012 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1013 | } else { | ||
1014 | if (!priv->_agn.last_phy_res_valid) { | ||
1015 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1016 | return; | ||
1017 | } | ||
1018 | phy_res = &priv->_agn.last_phy_res; | ||
1019 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1020 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1021 | len = le16_to_cpu(amsdu->byte_count); | ||
1022 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1023 | ampdu_status = iwlagn_translate_rx_status(priv, | ||
1024 | le32_to_cpu(rx_pkt_status)); | ||
1025 | } | ||
1026 | |||
1027 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1028 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1029 | phy_res->cfg_phy_cnt); | ||
1030 | return; | ||
1031 | } | ||
1032 | |||
1033 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1034 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1035 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1036 | le32_to_cpu(rx_pkt_status)); | ||
1037 | return; | ||
1038 | } | ||
1039 | |||
1040 | /* This will be used in several places later */ | ||
1041 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1042 | |||
1043 | /* rx_status carries information about the packet to mac80211 */ | ||
1044 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1045 | rx_status.freq = | ||
1046 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); | ||
1047 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1048 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1049 | rx_status.rate_idx = | ||
1050 | iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1051 | rx_status.flag = 0; | ||
1052 | |||
1053 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1054 | * this W/A doesn't propagate it to the mac80211 */ | ||
1055 | /*rx_status.flag |= RX_FLAG_TSFT;*/ | ||
1056 | |||
1057 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1058 | |||
1059 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1060 | rx_status.signal = iwlagn_calc_rssi(priv, phy_res); | ||
1061 | |||
1062 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1063 | /* Set "1" to report good data frames in groups of 100 */ | ||
1064 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | ||
1065 | iwlagn_dbg_report_frame(priv, phy_res, len, header, 1); | ||
1066 | #endif | ||
1067 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1068 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n", | ||
1069 | rx_status.signal, (unsigned long long)rx_status.mactime); | ||
1070 | |||
1071 | /* | ||
1072 | * "antenna number" | ||
1073 | * | ||
1074 | * It seems that the antenna field in the phy flags value | ||
1075 | * is actually a bit field. This is undefined by radiotap, | ||
1076 | * it wants an actual antenna number but I always get "7" | ||
1077 | * for most legacy frames I receive indicating that the | ||
1078 | * same frame was received on all three RX chains. | ||
1079 | * | ||
1080 | * I think this field should be removed in favor of a | ||
1081 | * new 802.11n radiotap field "RX chains" that is defined | ||
1082 | * as a bitmask. | ||
1083 | */ | ||
1084 | rx_status.antenna = | ||
1085 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1086 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1087 | |||
1088 | /* set the preamble flag if appropriate */ | ||
1089 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1090 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1091 | |||
1092 | /* Set up the HT phy flags */ | ||
1093 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1094 | rx_status.flag |= RX_FLAG_HT; | ||
1095 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1096 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1097 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1098 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1099 | |||
1100 | iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1101 | rxb, &rx_status); | ||
1102 | } | ||
1103 | |||
1104 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1105 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1106 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1107 | struct iwl_rx_mem_buffer *rxb) | ||
1108 | { | ||
1109 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1110 | priv->_agn.last_phy_res_valid = true; | ||
1111 | memcpy(&priv->_agn.last_phy_res, pkt->u.raw, | ||
1112 | sizeof(struct iwl_rx_phy_res)); | ||
1113 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 0de80914be77..f7d85a2173c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -2003,7 +2003,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2003 | /* rates available for this association, and for modulation mode */ | 2003 | /* rates available for this association, and for modulation mode */ |
2004 | rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); | 2004 | rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); |
2005 | 2005 | ||
2006 | IWL_DEBUG_RATE(priv, "mask 0x%04X \n", rate_mask); | 2006 | IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask); |
2007 | 2007 | ||
2008 | /* mask with station rate restriction */ | 2008 | /* mask with station rate restriction */ |
2009 | if (is_legacy(tbl->lq_type)) { | 2009 | if (is_legacy(tbl->lq_type)) { |
@@ -2410,7 +2410,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2410 | 2410 | ||
2411 | struct sk_buff *skb = txrc->skb; | 2411 | struct sk_buff *skb = txrc->skb; |
2412 | struct ieee80211_supported_band *sband = txrc->sband; | 2412 | struct ieee80211_supported_band *sband = txrc->sband; |
2413 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2413 | struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r; |
2414 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2414 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2415 | struct iwl_lq_sta *lq_sta = priv_sta; | 2415 | struct iwl_lq_sta *lq_sta = priv_sta; |
2416 | int rate_idx; | 2416 | int rate_idx; |
@@ -2934,8 +2934,6 @@ static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, | |||
2934 | desc += sprintf(buff+desc, | 2934 | desc += sprintf(buff+desc, |
2935 | "Bit Rate= %d Mb/s\n", | 2935 | "Bit Rate= %d Mb/s\n", |
2936 | iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); | 2936 | iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); |
2937 | desc += sprintf(buff+desc, "Noise Level= %d dBm\n", | ||
2938 | priv->last_rx_noise); | ||
2939 | 2937 | ||
2940 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); | 2938 | ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); |
2941 | return ret; | 2939 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c new file mode 100644 index 000000000000..3077eac58880 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -0,0 +1,1333 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-sta.h" | ||
38 | #include "iwl-io.h" | ||
39 | #include "iwl-helpers.h" | ||
40 | #include "iwl-agn-hw.h" | ||
41 | #include "iwl-agn.h" | ||
42 | |||
43 | /* | ||
44 | * mac80211 queues, ACs, hardware queues, FIFOs. | ||
45 | * | ||
46 | * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues | ||
47 | * | ||
48 | * Mac80211 uses the following numbers, which we get as from it | ||
49 | * by way of skb_get_queue_mapping(skb): | ||
50 | * | ||
51 | * VO 0 | ||
52 | * VI 1 | ||
53 | * BE 2 | ||
54 | * BK 3 | ||
55 | * | ||
56 | * | ||
57 | * Regular (not A-MPDU) frames are put into hardware queues corresponding | ||
58 | * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their | ||
59 | * own queue per aggregation session (RA/TID combination), such queues are | ||
60 | * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In | ||
61 | * order to map frames to the right queue, we also need an AC->hw queue | ||
62 | * mapping. This is implemented here. | ||
63 | * | ||
64 | * Due to the way hw queues are set up (by the hw specific modules like | ||
65 | * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity | ||
66 | * mapping. | ||
67 | */ | ||
68 | |||
69 | static const u8 tid_to_ac[] = { | ||
70 | /* this matches the mac80211 numbers */ | ||
71 | 2, 3, 3, 2, 1, 1, 0, 0 | ||
72 | }; | ||
73 | |||
74 | static const u8 ac_to_fifo[] = { | ||
75 | IWL_TX_FIFO_VO, | ||
76 | IWL_TX_FIFO_VI, | ||
77 | IWL_TX_FIFO_BE, | ||
78 | IWL_TX_FIFO_BK, | ||
79 | }; | ||
80 | |||
81 | static inline int get_fifo_from_ac(u8 ac) | ||
82 | { | ||
83 | return ac_to_fifo[ac]; | ||
84 | } | ||
85 | |||
86 | static inline int get_fifo_from_tid(u16 tid) | ||
87 | { | ||
88 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | ||
89 | return get_fifo_from_ac(tid_to_ac[tid]); | ||
90 | |||
91 | /* no support for TIDs 8-15 yet */ | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | ||
97 | */ | ||
98 | void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
99 | struct iwl_tx_queue *txq, | ||
100 | u16 byte_cnt) | ||
101 | { | ||
102 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
103 | int write_ptr = txq->q.write_ptr; | ||
104 | int txq_id = txq->q.id; | ||
105 | u8 sec_ctl = 0; | ||
106 | u8 sta_id = 0; | ||
107 | u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | ||
108 | __le16 bc_ent; | ||
109 | |||
110 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | ||
111 | |||
112 | if (txq_id != IWL_CMD_QUEUE_NUM) { | ||
113 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; | ||
114 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; | ||
115 | |||
116 | switch (sec_ctl & TX_CMD_SEC_MSK) { | ||
117 | case TX_CMD_SEC_CCM: | ||
118 | len += CCMP_MIC_LEN; | ||
119 | break; | ||
120 | case TX_CMD_SEC_TKIP: | ||
121 | len += TKIP_ICV_LEN; | ||
122 | break; | ||
123 | case TX_CMD_SEC_WEP: | ||
124 | len += WEP_IV_LEN + WEP_ICV_LEN; | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); | ||
130 | |||
131 | scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; | ||
132 | |||
133 | if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
134 | scd_bc_tbl[txq_id]. | ||
135 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | ||
136 | } | ||
137 | |||
138 | void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
139 | struct iwl_tx_queue *txq) | ||
140 | { | ||
141 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | ||
142 | int txq_id = txq->q.id; | ||
143 | int read_ptr = txq->q.read_ptr; | ||
144 | u8 sta_id = 0; | ||
145 | __le16 bc_ent; | ||
146 | |||
147 | WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); | ||
148 | |||
149 | if (txq_id != IWL_CMD_QUEUE_NUM) | ||
150 | sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; | ||
151 | |||
152 | bc_ent = cpu_to_le16(1 | (sta_id << 12)); | ||
153 | scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; | ||
154 | |||
155 | if (read_ptr < TFD_QUEUE_SIZE_BC_DUP) | ||
156 | scd_bc_tbl[txq_id]. | ||
157 | tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; | ||
158 | } | ||
159 | |||
160 | static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, | ||
161 | u16 txq_id) | ||
162 | { | ||
163 | u32 tbl_dw_addr; | ||
164 | u32 tbl_dw; | ||
165 | u16 scd_q2ratid; | ||
166 | |||
167 | scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; | ||
168 | |||
169 | tbl_dw_addr = priv->scd_base_addr + | ||
170 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); | ||
171 | |||
172 | tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); | ||
173 | |||
174 | if (txq_id & 0x1) | ||
175 | tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); | ||
176 | else | ||
177 | tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); | ||
178 | |||
179 | iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) | ||
185 | { | ||
186 | /* Simply stop the queue, but don't change any configuration; | ||
187 | * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ | ||
188 | iwl_write_prph(priv, | ||
189 | IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
190 | (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| | ||
191 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); | ||
192 | } | ||
193 | |||
194 | void iwlagn_set_wr_ptrs(struct iwl_priv *priv, | ||
195 | int txq_id, u32 index) | ||
196 | { | ||
197 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, | ||
198 | (index & 0xff) | (txq_id << 8)); | ||
199 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); | ||
200 | } | ||
201 | |||
202 | void iwlagn_tx_queue_set_status(struct iwl_priv *priv, | ||
203 | struct iwl_tx_queue *txq, | ||
204 | int tx_fifo_id, int scd_retry) | ||
205 | { | ||
206 | int txq_id = txq->q.id; | ||
207 | int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; | ||
208 | |||
209 | iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), | ||
210 | (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | | ||
211 | (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | | ||
212 | (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | | ||
213 | IWL50_SCD_QUEUE_STTS_REG_MSK); | ||
214 | |||
215 | txq->sched_retry = scd_retry; | ||
216 | |||
217 | IWL_DEBUG_INFO(priv, "%s %s Queue %d on FIFO %d\n", | ||
218 | active ? "Activate" : "Deactivate", | ||
219 | scd_retry ? "BA" : "AC/CMD", txq_id, tx_fifo_id); | ||
220 | } | ||
221 | |||
222 | int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
223 | int tx_fifo, int sta_id, int tid, u16 ssn_idx) | ||
224 | { | ||
225 | unsigned long flags; | ||
226 | u16 ra_tid; | ||
227 | |||
228 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || | ||
229 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
230 | <= txq_id)) { | ||
231 | IWL_WARN(priv, | ||
232 | "queue number out of range: %d, must be %d to %d\n", | ||
233 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | ||
234 | IWLAGN_FIRST_AMPDU_QUEUE + | ||
235 | priv->cfg->num_of_ampdu_queues - 1); | ||
236 | return -EINVAL; | ||
237 | } | ||
238 | |||
239 | ra_tid = BUILD_RAxTID(sta_id, tid); | ||
240 | |||
241 | /* Modify device's station table to Tx this TID */ | ||
242 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); | ||
243 | |||
244 | spin_lock_irqsave(&priv->lock, flags); | ||
245 | |||
246 | /* Stop this Tx queue before configuring it */ | ||
247 | iwlagn_tx_queue_stop_scheduler(priv, txq_id); | ||
248 | |||
249 | /* Map receiver-address / traffic-ID to this queue */ | ||
250 | iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id); | ||
251 | |||
252 | /* Set this queue as a chain-building queue */ | ||
253 | iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<<txq_id)); | ||
254 | |||
255 | /* enable aggregations for the queue */ | ||
256 | iwl_set_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1<<txq_id)); | ||
257 | |||
258 | /* Place first TFD at index corresponding to start sequence number. | ||
259 | * Assumes that ssn_idx is valid (!= 0xFFF) */ | ||
260 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
261 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
262 | iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
263 | |||
264 | /* Set up Tx window size and frame limit for this queue */ | ||
265 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
266 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + | ||
267 | sizeof(u32), | ||
268 | ((SCD_WIN_SIZE << | ||
269 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
270 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
271 | ((SCD_FRAME_LIMIT << | ||
272 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
273 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
274 | |||
275 | iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
276 | |||
277 | /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ | ||
278 | iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); | ||
279 | |||
280 | spin_unlock_irqrestore(&priv->lock, flags); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
286 | u16 ssn_idx, u8 tx_fifo) | ||
287 | { | ||
288 | if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) || | ||
289 | (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues | ||
290 | <= txq_id)) { | ||
291 | IWL_ERR(priv, | ||
292 | "queue number out of range: %d, must be %d to %d\n", | ||
293 | txq_id, IWLAGN_FIRST_AMPDU_QUEUE, | ||
294 | IWLAGN_FIRST_AMPDU_QUEUE + | ||
295 | priv->cfg->num_of_ampdu_queues - 1); | ||
296 | return -EINVAL; | ||
297 | } | ||
298 | |||
299 | iwlagn_tx_queue_stop_scheduler(priv, txq_id); | ||
300 | |||
301 | iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); | ||
302 | |||
303 | priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); | ||
304 | priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); | ||
305 | /* supposes that ssn_idx is valid (!= 0xFFF) */ | ||
306 | iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx); | ||
307 | |||
308 | iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); | ||
309 | iwl_txq_ctx_deactivate(priv, txq_id); | ||
310 | iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask | ||
317 | * must be called under priv->lock and mac access | ||
318 | */ | ||
319 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask) | ||
320 | { | ||
321 | iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); | ||
322 | } | ||
323 | |||
324 | static inline int get_queue_from_ac(u16 ac) | ||
325 | { | ||
326 | return ac; | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * handle build REPLY_TX command notification. | ||
331 | */ | ||
332 | static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, | ||
333 | struct iwl_tx_cmd *tx_cmd, | ||
334 | struct ieee80211_tx_info *info, | ||
335 | struct ieee80211_hdr *hdr, | ||
336 | u8 std_id) | ||
337 | { | ||
338 | __le16 fc = hdr->frame_control; | ||
339 | __le32 tx_flags = tx_cmd->tx_flags; | ||
340 | |||
341 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
342 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | ||
343 | tx_flags |= TX_CMD_FLG_ACK_MSK; | ||
344 | if (ieee80211_is_mgmt(fc)) | ||
345 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
346 | if (ieee80211_is_probe_resp(fc) && | ||
347 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) | ||
348 | tx_flags |= TX_CMD_FLG_TSF_MSK; | ||
349 | } else { | ||
350 | tx_flags &= (~TX_CMD_FLG_ACK_MSK); | ||
351 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
352 | } | ||
353 | |||
354 | if (ieee80211_is_back_req(fc)) | ||
355 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
356 | |||
357 | |||
358 | tx_cmd->sta_id = std_id; | ||
359 | if (ieee80211_has_morefrags(fc)) | ||
360 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | ||
361 | |||
362 | if (ieee80211_is_data_qos(fc)) { | ||
363 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
364 | tx_cmd->tid_tspec = qc[0] & 0xf; | ||
365 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
366 | } else { | ||
367 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
368 | } | ||
369 | |||
370 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); | ||
371 | |||
372 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | ||
373 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
374 | |||
375 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | ||
376 | if (ieee80211_is_mgmt(fc)) { | ||
377 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | ||
378 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); | ||
379 | else | ||
380 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); | ||
381 | } else { | ||
382 | tx_cmd->timeout.pm_frame_timeout = 0; | ||
383 | } | ||
384 | |||
385 | tx_cmd->driver_txop = 0; | ||
386 | tx_cmd->tx_flags = tx_flags; | ||
387 | tx_cmd->next_frame_len = 0; | ||
388 | } | ||
389 | |||
390 | #define RTS_DFAULT_RETRY_LIMIT 60 | ||
391 | |||
392 | static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, | ||
393 | struct iwl_tx_cmd *tx_cmd, | ||
394 | struct ieee80211_tx_info *info, | ||
395 | __le16 fc) | ||
396 | { | ||
397 | u32 rate_flags; | ||
398 | int rate_idx; | ||
399 | u8 rts_retry_limit; | ||
400 | u8 data_retry_limit; | ||
401 | u8 rate_plcp; | ||
402 | |||
403 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
404 | if (ieee80211_is_probe_resp(fc)) | ||
405 | data_retry_limit = 3; | ||
406 | else | ||
407 | data_retry_limit = IWLAGN_DEFAULT_TX_RETRY; | ||
408 | tx_cmd->data_retry_limit = data_retry_limit; | ||
409 | |||
410 | /* Set retry limit on RTS packets */ | ||
411 | rts_retry_limit = RTS_DFAULT_RETRY_LIMIT; | ||
412 | if (data_retry_limit < rts_retry_limit) | ||
413 | rts_retry_limit = data_retry_limit; | ||
414 | tx_cmd->rts_retry_limit = rts_retry_limit; | ||
415 | |||
416 | /* DATA packets will use the uCode station table for rate/antenna | ||
417 | * selection */ | ||
418 | if (ieee80211_is_data(fc)) { | ||
419 | tx_cmd->initial_rate_index = 0; | ||
420 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | /** | ||
425 | * If the current TX rate stored in mac80211 has the MCS bit set, it's | ||
426 | * not really a TX rate. Thus, we use the lowest supported rate for | ||
427 | * this band. Also use the lowest supported rate if the stored rate | ||
428 | * index is invalid. | ||
429 | */ | ||
430 | rate_idx = info->control.rates[0].idx; | ||
431 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | ||
432 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | ||
433 | rate_idx = rate_lowest_index(&priv->bands[info->band], | ||
434 | info->control.sta); | ||
435 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | ||
436 | if (info->band == IEEE80211_BAND_5GHZ) | ||
437 | rate_idx += IWL_FIRST_OFDM_RATE; | ||
438 | /* Get PLCP rate for tx_cmd->rate_n_flags */ | ||
439 | rate_plcp = iwl_rates[rate_idx].plcp; | ||
440 | /* Zero out flags for this packet */ | ||
441 | rate_flags = 0; | ||
442 | |||
443 | /* Set CCK flag as needed */ | ||
444 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | ||
445 | rate_flags |= RATE_MCS_CCK_MSK; | ||
446 | |||
447 | /* Set up RTS and CTS flags for certain packets */ | ||
448 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
449 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
450 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
451 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
452 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
453 | if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { | ||
454 | tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
455 | tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
456 | } | ||
457 | break; | ||
458 | default: | ||
459 | break; | ||
460 | } | ||
461 | |||
462 | /* Set up antennas */ | ||
463 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | ||
464 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
465 | |||
466 | /* Set the rate in the TX cmd */ | ||
467 | tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); | ||
468 | } | ||
469 | |||
470 | static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | ||
471 | struct ieee80211_tx_info *info, | ||
472 | struct iwl_tx_cmd *tx_cmd, | ||
473 | struct sk_buff *skb_frag, | ||
474 | int sta_id) | ||
475 | { | ||
476 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | ||
477 | |||
478 | switch (keyconf->alg) { | ||
479 | case ALG_CCMP: | ||
480 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | ||
481 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | ||
482 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
483 | tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; | ||
484 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | ||
485 | break; | ||
486 | |||
487 | case ALG_TKIP: | ||
488 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | ||
489 | ieee80211_get_tkip_key(keyconf, skb_frag, | ||
490 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); | ||
491 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | ||
492 | break; | ||
493 | |||
494 | case ALG_WEP: | ||
495 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | | ||
496 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
497 | |||
498 | if (keyconf->keylen == WEP_KEY_LEN_128) | ||
499 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
500 | |||
501 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | ||
502 | |||
503 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | ||
504 | "with key %d\n", keyconf->keyidx); | ||
505 | break; | ||
506 | |||
507 | default: | ||
508 | IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); | ||
509 | break; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | /* | ||
514 | * start REPLY_TX command process | ||
515 | */ | ||
516 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||
517 | { | ||
518 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
519 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
520 | struct ieee80211_sta *sta = info->control.sta; | ||
521 | struct iwl_station_priv *sta_priv = NULL; | ||
522 | struct iwl_tx_queue *txq; | ||
523 | struct iwl_queue *q; | ||
524 | struct iwl_device_cmd *out_cmd; | ||
525 | struct iwl_cmd_meta *out_meta; | ||
526 | struct iwl_tx_cmd *tx_cmd; | ||
527 | int swq_id, txq_id; | ||
528 | dma_addr_t phys_addr; | ||
529 | dma_addr_t txcmd_phys; | ||
530 | dma_addr_t scratch_phys; | ||
531 | u16 len, len_org, firstlen, secondlen; | ||
532 | u16 seq_number = 0; | ||
533 | __le16 fc; | ||
534 | u8 hdr_len; | ||
535 | u8 sta_id; | ||
536 | u8 wait_write_ptr = 0; | ||
537 | u8 tid = 0; | ||
538 | u8 *qc = NULL; | ||
539 | unsigned long flags; | ||
540 | |||
541 | spin_lock_irqsave(&priv->lock, flags); | ||
542 | if (iwl_is_rfkill(priv)) { | ||
543 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | ||
544 | goto drop_unlock; | ||
545 | } | ||
546 | |||
547 | fc = hdr->frame_control; | ||
548 | |||
549 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
550 | if (ieee80211_is_auth(fc)) | ||
551 | IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); | ||
552 | else if (ieee80211_is_assoc_req(fc)) | ||
553 | IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); | ||
554 | else if (ieee80211_is_reassoc_req(fc)) | ||
555 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | ||
556 | #endif | ||
557 | |||
558 | hdr_len = ieee80211_hdrlen(fc); | ||
559 | |||
560 | /* Find (or create) index into station table for destination station */ | ||
561 | if (info->flags & IEEE80211_TX_CTL_INJECTED) | ||
562 | sta_id = priv->hw_params.bcast_sta_id; | ||
563 | else | ||
564 | sta_id = iwl_get_sta_id(priv, hdr); | ||
565 | if (sta_id == IWL_INVALID_STATION) { | ||
566 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | ||
567 | hdr->addr1); | ||
568 | goto drop_unlock; | ||
569 | } | ||
570 | |||
571 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | ||
572 | |||
573 | if (sta) | ||
574 | sta_priv = (void *)sta->drv_priv; | ||
575 | |||
576 | if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && | ||
577 | sta_priv->asleep) { | ||
578 | WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); | ||
579 | /* | ||
580 | * This sends an asynchronous command to the device, | ||
581 | * but we can rely on it being processed before the | ||
582 | * next frame is processed -- and the next frame to | ||
583 | * this station is the one that will consume this | ||
584 | * counter. | ||
585 | * For now set the counter to just 1 since we do not | ||
586 | * support uAPSD yet. | ||
587 | */ | ||
588 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | ||
589 | } | ||
590 | |||
591 | txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); | ||
592 | if (ieee80211_is_data_qos(fc)) { | ||
593 | qc = ieee80211_get_qos_ctl(hdr); | ||
594 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
595 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
596 | goto drop_unlock; | ||
597 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | ||
598 | seq_number &= IEEE80211_SCTL_SEQ; | ||
599 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
600 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
601 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
602 | seq_number += 0x10; | ||
603 | /* aggregation is on for this <sta,tid> */ | ||
604 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
605 | priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { | ||
606 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | txq = &priv->txq[txq_id]; | ||
611 | swq_id = txq->swq_id; | ||
612 | q = &txq->q; | ||
613 | |||
614 | if (unlikely(iwl_queue_space(q) < q->high_mark)) | ||
615 | goto drop_unlock; | ||
616 | |||
617 | if (ieee80211_is_data_qos(fc)) | ||
618 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
619 | |||
620 | /* Set up driver data for this TFD */ | ||
621 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | ||
622 | txq->txb[q->write_ptr].skb[0] = skb; | ||
623 | |||
624 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
625 | out_cmd = txq->cmd[q->write_ptr]; | ||
626 | out_meta = &txq->meta[q->write_ptr]; | ||
627 | tx_cmd = &out_cmd->cmd.tx; | ||
628 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | ||
629 | memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); | ||
630 | |||
631 | /* | ||
632 | * Set up the Tx-command (not MAC!) header. | ||
633 | * Store the chosen Tx queue and TFD index within the sequence field; | ||
634 | * after Tx, uCode's Tx response will return this value so driver can | ||
635 | * locate the frame within the tx queue and do post-tx processing. | ||
636 | */ | ||
637 | out_cmd->hdr.cmd = REPLY_TX; | ||
638 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
639 | INDEX_TO_SEQ(q->write_ptr))); | ||
640 | |||
641 | /* Copy MAC header from skb into command buffer */ | ||
642 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
643 | |||
644 | |||
645 | /* Total # bytes to be transmitted */ | ||
646 | len = (u16)skb->len; | ||
647 | tx_cmd->len = cpu_to_le16(len); | ||
648 | |||
649 | if (info->control.hw_key) | ||
650 | iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); | ||
651 | |||
652 | /* TODO need this for burst mode later on */ | ||
653 | iwlagn_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); | ||
654 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | ||
655 | |||
656 | iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, fc); | ||
657 | |||
658 | iwl_update_stats(priv, true, fc, len); | ||
659 | /* | ||
660 | * Use the first empty entry in this queue's command buffer array | ||
661 | * to contain the Tx command and MAC header concatenated together | ||
662 | * (payload data will be in another buffer). | ||
663 | * Size of this varies, due to varying MAC header length. | ||
664 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
665 | * of the MAC header (device reads on dword boundaries). | ||
666 | * We'll tell device about this padding later. | ||
667 | */ | ||
668 | len = sizeof(struct iwl_tx_cmd) + | ||
669 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
670 | |||
671 | len_org = len; | ||
672 | firstlen = len = (len + 3) & ~3; | ||
673 | |||
674 | if (len_org != len) | ||
675 | len_org = 1; | ||
676 | else | ||
677 | len_org = 0; | ||
678 | |||
679 | /* Tell NIC about any 2-byte padding after MAC header */ | ||
680 | if (len_org) | ||
681 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | ||
682 | |||
683 | /* Physical address of this Tx command's header (not MAC header!), | ||
684 | * within command buffer array. */ | ||
685 | txcmd_phys = pci_map_single(priv->pci_dev, | ||
686 | &out_cmd->hdr, len, | ||
687 | PCI_DMA_BIDIRECTIONAL); | ||
688 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
689 | pci_unmap_len_set(out_meta, len, len); | ||
690 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
691 | * first entry */ | ||
692 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
693 | txcmd_phys, len, 1, 0); | ||
694 | |||
695 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | ||
696 | txq->need_update = 1; | ||
697 | if (qc) | ||
698 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
699 | } else { | ||
700 | wait_write_ptr = 1; | ||
701 | txq->need_update = 0; | ||
702 | } | ||
703 | |||
704 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
705 | * if any (802.11 null frames have no payload). */ | ||
706 | secondlen = len = skb->len - hdr_len; | ||
707 | if (len) { | ||
708 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | ||
709 | len, PCI_DMA_TODEVICE); | ||
710 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
711 | phys_addr, len, | ||
712 | 0, 0); | ||
713 | } | ||
714 | |||
715 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
716 | offsetof(struct iwl_tx_cmd, scratch); | ||
717 | |||
718 | len = sizeof(struct iwl_tx_cmd) + | ||
719 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
720 | /* take back ownership of DMA buffer to enable update */ | ||
721 | pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, | ||
722 | len, PCI_DMA_BIDIRECTIONAL); | ||
723 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
724 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
725 | |||
726 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", | ||
727 | le16_to_cpu(out_cmd->hdr.sequence)); | ||
728 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); | ||
729 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | ||
730 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | ||
731 | |||
732 | /* Set up entry for this TFD in Tx byte-count array */ | ||
733 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
734 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, | ||
735 | le16_to_cpu(tx_cmd->len)); | ||
736 | |||
737 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, | ||
738 | len, PCI_DMA_BIDIRECTIONAL); | ||
739 | |||
740 | trace_iwlwifi_dev_tx(priv, | ||
741 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | ||
742 | sizeof(struct iwl_tfd), | ||
743 | &out_cmd->hdr, firstlen, | ||
744 | skb->data + hdr_len, secondlen); | ||
745 | |||
746 | /* Tell device the write index *just past* this latest filled TFD */ | ||
747 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
748 | iwl_txq_update_write_ptr(priv, txq); | ||
749 | spin_unlock_irqrestore(&priv->lock, flags); | ||
750 | |||
751 | /* | ||
752 | * At this point the frame is "transmitted" successfully | ||
753 | * and we will get a TX status notification eventually, | ||
754 | * regardless of the value of ret. "ret" only indicates | ||
755 | * whether or not we should update the write pointer. | ||
756 | */ | ||
757 | |||
758 | /* avoid atomic ops if it isn't an associated client */ | ||
759 | if (sta_priv && sta_priv->client) | ||
760 | atomic_inc(&sta_priv->pending_frames); | ||
761 | |||
762 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { | ||
763 | if (wait_write_ptr) { | ||
764 | spin_lock_irqsave(&priv->lock, flags); | ||
765 | txq->need_update = 1; | ||
766 | iwl_txq_update_write_ptr(priv, txq); | ||
767 | spin_unlock_irqrestore(&priv->lock, flags); | ||
768 | } else { | ||
769 | iwl_stop_queue(priv, txq->swq_id); | ||
770 | } | ||
771 | } | ||
772 | |||
773 | return 0; | ||
774 | |||
775 | drop_unlock: | ||
776 | spin_unlock_irqrestore(&priv->lock, flags); | ||
777 | return -1; | ||
778 | } | ||
779 | |||
780 | static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv, | ||
781 | struct iwl_dma_ptr *ptr, size_t size) | ||
782 | { | ||
783 | ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, | ||
784 | GFP_KERNEL); | ||
785 | if (!ptr->addr) | ||
786 | return -ENOMEM; | ||
787 | ptr->size = size; | ||
788 | return 0; | ||
789 | } | ||
790 | |||
791 | static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv, | ||
792 | struct iwl_dma_ptr *ptr) | ||
793 | { | ||
794 | if (unlikely(!ptr->addr)) | ||
795 | return; | ||
796 | |||
797 | dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); | ||
798 | memset(ptr, 0, sizeof(*ptr)); | ||
799 | } | ||
800 | |||
801 | /** | ||
802 | * iwlagn_hw_txq_ctx_free - Free TXQ Context | ||
803 | * | ||
804 | * Destroy all TX DMA queues and structures | ||
805 | */ | ||
806 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) | ||
807 | { | ||
808 | int txq_id; | ||
809 | |||
810 | /* Tx queues */ | ||
811 | if (priv->txq) { | ||
812 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
813 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
814 | iwl_cmd_queue_free(priv); | ||
815 | else | ||
816 | iwl_tx_queue_free(priv, txq_id); | ||
817 | } | ||
818 | iwlagn_free_dma_ptr(priv, &priv->kw); | ||
819 | |||
820 | iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
821 | |||
822 | /* free tx queue structure */ | ||
823 | iwl_free_txq_mem(priv); | ||
824 | } | ||
825 | |||
826 | /** | ||
827 | * iwlagn_txq_ctx_alloc - allocate TX queue context | ||
828 | * Allocate all Tx DMA structures and initialize them | ||
829 | * | ||
830 | * @param priv | ||
831 | * @return error code | ||
832 | */ | ||
833 | int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) | ||
834 | { | ||
835 | int ret; | ||
836 | int txq_id, slots_num; | ||
837 | unsigned long flags; | ||
838 | |||
839 | /* Free all tx/cmd queues and keep-warm buffer */ | ||
840 | iwlagn_hw_txq_ctx_free(priv); | ||
841 | |||
842 | ret = iwlagn_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
843 | priv->hw_params.scd_bc_tbls_size); | ||
844 | if (ret) { | ||
845 | IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); | ||
846 | goto error_bc_tbls; | ||
847 | } | ||
848 | /* Alloc keep-warm buffer */ | ||
849 | ret = iwlagn_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); | ||
850 | if (ret) { | ||
851 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | ||
852 | goto error_kw; | ||
853 | } | ||
854 | |||
855 | /* allocate tx queue structure */ | ||
856 | ret = iwl_alloc_txq_mem(priv); | ||
857 | if (ret) | ||
858 | goto error; | ||
859 | |||
860 | spin_lock_irqsave(&priv->lock, flags); | ||
861 | |||
862 | /* Turn off all Tx DMA fifos */ | ||
863 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
864 | |||
865 | /* Tell NIC where to find the "keep warm" buffer */ | ||
866 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
867 | |||
868 | spin_unlock_irqrestore(&priv->lock, flags); | ||
869 | |||
870 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
871 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
872 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | ||
873 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
874 | ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | ||
875 | txq_id); | ||
876 | if (ret) { | ||
877 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | ||
878 | goto error; | ||
879 | } | ||
880 | } | ||
881 | |||
882 | return ret; | ||
883 | |||
884 | error: | ||
885 | iwlagn_hw_txq_ctx_free(priv); | ||
886 | iwlagn_free_dma_ptr(priv, &priv->kw); | ||
887 | error_kw: | ||
888 | iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
889 | error_bc_tbls: | ||
890 | return ret; | ||
891 | } | ||
892 | |||
893 | void iwlagn_txq_ctx_reset(struct iwl_priv *priv) | ||
894 | { | ||
895 | int txq_id, slots_num; | ||
896 | unsigned long flags; | ||
897 | |||
898 | spin_lock_irqsave(&priv->lock, flags); | ||
899 | |||
900 | /* Turn off all Tx DMA fifos */ | ||
901 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
902 | |||
903 | /* Tell NIC where to find the "keep warm" buffer */ | ||
904 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
905 | |||
906 | spin_unlock_irqrestore(&priv->lock, flags); | ||
907 | |||
908 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
909 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
910 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | ||
911 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
912 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
913 | } | ||
914 | } | ||
915 | |||
916 | /** | ||
917 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels | ||
918 | */ | ||
919 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | ||
920 | { | ||
921 | int ch; | ||
922 | unsigned long flags; | ||
923 | |||
924 | /* Turn off all Tx DMA fifos */ | ||
925 | spin_lock_irqsave(&priv->lock, flags); | ||
926 | |||
927 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
928 | |||
929 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
930 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | ||
931 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
932 | iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | ||
933 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
934 | 1000); | ||
935 | } | ||
936 | spin_unlock_irqrestore(&priv->lock, flags); | ||
937 | } | ||
938 | |||
939 | /* | ||
940 | * Find first available (lowest unused) Tx Queue, mark it "active". | ||
941 | * Called only when finding queue for aggregation. | ||
942 | * Should never return anything < 7, because they should already | ||
943 | * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) | ||
944 | */ | ||
945 | static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) | ||
946 | { | ||
947 | int txq_id; | ||
948 | |||
949 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
950 | if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) | ||
951 | return txq_id; | ||
952 | return -1; | ||
953 | } | ||
954 | |||
955 | int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) | ||
956 | { | ||
957 | int sta_id; | ||
958 | int tx_fifo; | ||
959 | int txq_id; | ||
960 | int ret; | ||
961 | unsigned long flags; | ||
962 | struct iwl_tid_data *tid_data; | ||
963 | |||
964 | tx_fifo = get_fifo_from_tid(tid); | ||
965 | if (unlikely(tx_fifo < 0)) | ||
966 | return tx_fifo; | ||
967 | |||
968 | IWL_WARN(priv, "%s on ra = %pM tid = %d\n", | ||
969 | __func__, ra, tid); | ||
970 | |||
971 | sta_id = iwl_find_station(priv, ra); | ||
972 | if (sta_id == IWL_INVALID_STATION) { | ||
973 | IWL_ERR(priv, "Start AGG on invalid station\n"); | ||
974 | return -ENXIO; | ||
975 | } | ||
976 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
977 | return -EINVAL; | ||
978 | |||
979 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { | ||
980 | IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); | ||
981 | return -ENXIO; | ||
982 | } | ||
983 | |||
984 | txq_id = iwlagn_txq_ctx_activate_free(priv); | ||
985 | if (txq_id == -1) { | ||
986 | IWL_ERR(priv, "No free aggregation queue available\n"); | ||
987 | return -ENXIO; | ||
988 | } | ||
989 | |||
990 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
991 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
992 | *ssn = SEQ_TO_SN(tid_data->seq_number); | ||
993 | tid_data->agg.txq_id = txq_id; | ||
994 | priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); | ||
995 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
996 | |||
997 | ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, | ||
998 | sta_id, tid, *ssn); | ||
999 | if (ret) | ||
1000 | return ret; | ||
1001 | |||
1002 | if (tid_data->tfds_in_queue == 0) { | ||
1003 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1004 | tid_data->agg.state = IWL_AGG_ON; | ||
1005 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1006 | } else { | ||
1007 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", | ||
1008 | tid_data->tfds_in_queue); | ||
1009 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | ||
1010 | } | ||
1011 | return ret; | ||
1012 | } | ||
1013 | |||
1014 | int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | ||
1015 | { | ||
1016 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | ||
1017 | struct iwl_tid_data *tid_data; | ||
1018 | int write_ptr, read_ptr; | ||
1019 | unsigned long flags; | ||
1020 | |||
1021 | if (!ra) { | ||
1022 | IWL_ERR(priv, "ra = NULL\n"); | ||
1023 | return -EINVAL; | ||
1024 | } | ||
1025 | |||
1026 | tx_fifo_id = get_fifo_from_tid(tid); | ||
1027 | if (unlikely(tx_fifo_id < 0)) | ||
1028 | return tx_fifo_id; | ||
1029 | |||
1030 | sta_id = iwl_find_station(priv, ra); | ||
1031 | |||
1032 | if (sta_id == IWL_INVALID_STATION) { | ||
1033 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); | ||
1034 | return -ENXIO; | ||
1035 | } | ||
1036 | |||
1037 | if (priv->stations[sta_id].tid[tid].agg.state == | ||
1038 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | ||
1039 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | ||
1040 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1041 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) | ||
1046 | IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); | ||
1047 | |||
1048 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1049 | ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; | ||
1050 | txq_id = tid_data->agg.txq_id; | ||
1051 | write_ptr = priv->txq[txq_id].q.write_ptr; | ||
1052 | read_ptr = priv->txq[txq_id].q.read_ptr; | ||
1053 | |||
1054 | /* The queue is not empty */ | ||
1055 | if (write_ptr != read_ptr) { | ||
1056 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); | ||
1057 | priv->stations[sta_id].tid[tid].agg.state = | ||
1058 | IWL_EMPTYING_HW_QUEUE_DELBA; | ||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1063 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1064 | |||
1065 | spin_lock_irqsave(&priv->lock, flags); | ||
1066 | /* | ||
1067 | * the only reason this call can fail is queue number out of range, | ||
1068 | * which can happen if uCode is reloaded and all the station | ||
1069 | * information are lost. if it is outside the range, there is no need | ||
1070 | * to deactivate the uCode queue, just return "success" to allow | ||
1071 | * mac80211 to clean up it own data. | ||
1072 | */ | ||
1073 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | ||
1074 | tx_fifo_id); | ||
1075 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1076 | |||
1077 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1078 | |||
1079 | return 0; | ||
1080 | } | ||
1081 | |||
1082 | int iwlagn_txq_check_empty(struct iwl_priv *priv, | ||
1083 | int sta_id, u8 tid, int txq_id) | ||
1084 | { | ||
1085 | struct iwl_queue *q = &priv->txq[txq_id].q; | ||
1086 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | ||
1087 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | ||
1088 | |||
1089 | switch (priv->stations[sta_id].tid[tid].agg.state) { | ||
1090 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
1091 | /* We are reclaiming the last packet of the */ | ||
1092 | /* aggregated HW queue */ | ||
1093 | if ((txq_id == tid_data->agg.txq_id) && | ||
1094 | (q->read_ptr == q->write_ptr)) { | ||
1095 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1096 | int tx_fifo = get_fifo_from_tid(tid); | ||
1097 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); | ||
1098 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | ||
1099 | ssn, tx_fifo); | ||
1100 | tid_data->agg.state = IWL_AGG_OFF; | ||
1101 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1102 | } | ||
1103 | break; | ||
1104 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
1105 | /* We are reclaiming the last packet of the queue */ | ||
1106 | if (tid_data->tfds_in_queue == 0) { | ||
1107 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); | ||
1108 | tid_data->agg.state = IWL_AGG_ON; | ||
1109 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1110 | } | ||
1111 | break; | ||
1112 | } | ||
1113 | return 0; | ||
1114 | } | ||
1115 | |||
1116 | static void iwlagn_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | ||
1117 | { | ||
1118 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1119 | struct ieee80211_sta *sta; | ||
1120 | struct iwl_station_priv *sta_priv; | ||
1121 | |||
1122 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | ||
1123 | if (sta) { | ||
1124 | sta_priv = (void *)sta->drv_priv; | ||
1125 | /* avoid atomic ops if this isn't a client */ | ||
1126 | if (sta_priv->client && | ||
1127 | atomic_dec_return(&sta_priv->pending_frames) == 0) | ||
1128 | ieee80211_sta_block_awake(priv->hw, sta, false); | ||
1129 | } | ||
1130 | |||
1131 | ieee80211_tx_status_irqsafe(priv->hw, skb); | ||
1132 | } | ||
1133 | |||
1134 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | ||
1135 | { | ||
1136 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1137 | struct iwl_queue *q = &txq->q; | ||
1138 | struct iwl_tx_info *tx_info; | ||
1139 | int nfreed = 0; | ||
1140 | struct ieee80211_hdr *hdr; | ||
1141 | |||
1142 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { | ||
1143 | IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " | ||
1144 | "is out of range [0-%d] %d %d.\n", txq_id, | ||
1145 | index, q->n_bd, q->write_ptr, q->read_ptr); | ||
1146 | return 0; | ||
1147 | } | ||
1148 | |||
1149 | for (index = iwl_queue_inc_wrap(index, q->n_bd); | ||
1150 | q->read_ptr != index; | ||
1151 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
1152 | |||
1153 | tx_info = &txq->txb[txq->q.read_ptr]; | ||
1154 | iwlagn_tx_status(priv, tx_info->skb[0]); | ||
1155 | |||
1156 | hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; | ||
1157 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | ||
1158 | nfreed++; | ||
1159 | tx_info->skb[0] = NULL; | ||
1160 | |||
1161 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | ||
1162 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | ||
1163 | |||
1164 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
1165 | } | ||
1166 | return nfreed; | ||
1167 | } | ||
1168 | |||
1169 | /** | ||
1170 | * iwlagn_tx_status_reply_compressed_ba - Update tx status from block-ack | ||
1171 | * | ||
1172 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of | ||
1173 | * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. | ||
1174 | */ | ||
1175 | static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, | ||
1176 | struct iwl_ht_agg *agg, | ||
1177 | struct iwl_compressed_ba_resp *ba_resp) | ||
1178 | |||
1179 | { | ||
1180 | int i, sh, ack; | ||
1181 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | ||
1182 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1183 | u64 bitmap; | ||
1184 | int successes = 0; | ||
1185 | struct ieee80211_tx_info *info; | ||
1186 | |||
1187 | if (unlikely(!agg->wait_for_ba)) { | ||
1188 | IWL_ERR(priv, "Received BA when not expected\n"); | ||
1189 | return -EINVAL; | ||
1190 | } | ||
1191 | |||
1192 | /* Mark that the expected block-ack response arrived */ | ||
1193 | agg->wait_for_ba = 0; | ||
1194 | IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); | ||
1195 | |||
1196 | /* Calculate shift to align block-ack bits with our Tx window bits */ | ||
1197 | sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); | ||
1198 | if (sh < 0) /* tbw something is wrong with indices */ | ||
1199 | sh += 0x100; | ||
1200 | |||
1201 | /* don't use 64-bit values for now */ | ||
1202 | bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; | ||
1203 | |||
1204 | if (agg->frame_count > (64 - sh)) { | ||
1205 | IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); | ||
1206 | return -1; | ||
1207 | } | ||
1208 | |||
1209 | /* check for success or failure according to the | ||
1210 | * transmitted bitmap and block-ack bitmap */ | ||
1211 | bitmap &= agg->bitmap; | ||
1212 | |||
1213 | /* For each frame attempted in aggregation, | ||
1214 | * update driver's record of tx frame's status. */ | ||
1215 | for (i = 0; i < agg->frame_count ; i++) { | ||
1216 | ack = bitmap & (1ULL << i); | ||
1217 | successes += !!ack; | ||
1218 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", | ||
1219 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, | ||
1220 | agg->start_idx + i); | ||
1221 | } | ||
1222 | |||
1223 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | ||
1224 | memset(&info->status, 0, sizeof(info->status)); | ||
1225 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1226 | info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
1227 | info->status.ampdu_ack_map = successes; | ||
1228 | info->status.ampdu_ack_len = agg->frame_count; | ||
1229 | iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | ||
1230 | |||
1231 | IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); | ||
1232 | |||
1233 | return 0; | ||
1234 | } | ||
1235 | |||
1236 | /** | ||
1237 | * translate ucode response to mac80211 tx status control values | ||
1238 | */ | ||
1239 | void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
1240 | struct ieee80211_tx_info *info) | ||
1241 | { | ||
1242 | struct ieee80211_tx_rate *r = &info->control.rates[0]; | ||
1243 | |||
1244 | info->antenna_sel_tx = | ||
1245 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
1246 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1247 | r->flags |= IEEE80211_TX_RC_MCS; | ||
1248 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
1249 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
1250 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1251 | r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
1252 | if (rate_n_flags & RATE_MCS_DUP_MSK) | ||
1253 | r->flags |= IEEE80211_TX_RC_DUP_DATA; | ||
1254 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1255 | r->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
1256 | r->idx = iwlagn_hwrate_to_mac80211_idx(rate_n_flags, info->band); | ||
1257 | } | ||
1258 | |||
1259 | /** | ||
1260 | * iwlagn_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | ||
1261 | * | ||
1262 | * Handles block-acknowledge notification from device, which reports success | ||
1263 | * of frames sent via aggregation. | ||
1264 | */ | ||
1265 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
1266 | struct iwl_rx_mem_buffer *rxb) | ||
1267 | { | ||
1268 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1269 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | ||
1270 | struct iwl_tx_queue *txq = NULL; | ||
1271 | struct iwl_ht_agg *agg; | ||
1272 | int index; | ||
1273 | int sta_id; | ||
1274 | int tid; | ||
1275 | |||
1276 | /* "flow" corresponds to Tx queue */ | ||
1277 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1278 | |||
1279 | /* "ssn" is start of block-ack Tx window, corresponds to index | ||
1280 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | ||
1281 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | ||
1282 | |||
1283 | if (scd_flow >= priv->hw_params.max_txq_num) { | ||
1284 | IWL_ERR(priv, | ||
1285 | "BUG_ON scd_flow is bigger than number of queues\n"); | ||
1286 | return; | ||
1287 | } | ||
1288 | |||
1289 | txq = &priv->txq[scd_flow]; | ||
1290 | sta_id = ba_resp->sta_id; | ||
1291 | tid = ba_resp->tid; | ||
1292 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
1293 | |||
1294 | /* Find index just before block-ack window */ | ||
1295 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | ||
1296 | |||
1297 | /* TODO: Need to get this copy more safely - now good for debug */ | ||
1298 | |||
1299 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | ||
1300 | "sta_id = %d\n", | ||
1301 | agg->wait_for_ba, | ||
1302 | (u8 *) &ba_resp->sta_addr_lo32, | ||
1303 | ba_resp->sta_id); | ||
1304 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " | ||
1305 | "%d, scd_ssn = %d\n", | ||
1306 | ba_resp->tid, | ||
1307 | ba_resp->seq_ctl, | ||
1308 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | ||
1309 | ba_resp->scd_flow, | ||
1310 | ba_resp->scd_ssn); | ||
1311 | IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n", | ||
1312 | agg->start_idx, | ||
1313 | (unsigned long long)agg->bitmap); | ||
1314 | |||
1315 | /* Update driver's record of ACK vs. not for each frame in window */ | ||
1316 | iwlagn_tx_status_reply_compressed_ba(priv, agg, ba_resp); | ||
1317 | |||
1318 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | ||
1319 | * block-ack window (we assume that they've been successfully | ||
1320 | * transmitted ... if not, it's too late anyway). */ | ||
1321 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { | ||
1322 | /* calculate mac80211 ampdu sw queue to wake */ | ||
1323 | int freed = iwlagn_tx_queue_reclaim(priv, scd_flow, index); | ||
1324 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1325 | |||
1326 | if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
1327 | priv->mac80211_registered && | ||
1328 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) | ||
1329 | iwl_wake_queue(priv, txq->swq_id); | ||
1330 | |||
1331 | iwlagn_txq_check_empty(priv, sta_id, tid, scd_flow); | ||
1332 | } | ||
1333 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c new file mode 100644 index 000000000000..52ae157968b2 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -0,0 +1,416 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * GPL LICENSE SUMMARY | ||
4 | * | ||
5 | * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of version 2 of the GNU General Public License as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
19 | * USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called LICENSE.GPL. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/sched.h> | ||
34 | |||
35 | #include "iwl-dev.h" | ||
36 | #include "iwl-core.h" | ||
37 | #include "iwl-io.h" | ||
38 | #include "iwl-helpers.h" | ||
39 | #include "iwl-agn-hw.h" | ||
40 | #include "iwl-agn.h" | ||
41 | |||
42 | static const s8 iwlagn_default_queue_to_tx_fifo[] = { | ||
43 | IWL_TX_FIFO_VO, | ||
44 | IWL_TX_FIFO_VI, | ||
45 | IWL_TX_FIFO_BE, | ||
46 | IWL_TX_FIFO_BK, | ||
47 | IWLAGN_CMD_FIFO_NUM, | ||
48 | IWL_TX_FIFO_UNUSED, | ||
49 | IWL_TX_FIFO_UNUSED, | ||
50 | IWL_TX_FIFO_UNUSED, | ||
51 | IWL_TX_FIFO_UNUSED, | ||
52 | IWL_TX_FIFO_UNUSED, | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * ucode | ||
57 | */ | ||
58 | static int iwlagn_load_section(struct iwl_priv *priv, const char *name, | ||
59 | struct fw_desc *image, u32 dst_addr) | ||
60 | { | ||
61 | dma_addr_t phy_addr = image->p_addr; | ||
62 | u32 byte_cnt = image->len; | ||
63 | int ret; | ||
64 | |||
65 | priv->ucode_write_complete = 0; | ||
66 | |||
67 | iwl_write_direct32(priv, | ||
68 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
69 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); | ||
70 | |||
71 | iwl_write_direct32(priv, | ||
72 | FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); | ||
73 | |||
74 | iwl_write_direct32(priv, | ||
75 | FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), | ||
76 | phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); | ||
77 | |||
78 | iwl_write_direct32(priv, | ||
79 | FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), | ||
80 | (iwl_get_dma_hi_addr(phy_addr) | ||
81 | << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); | ||
82 | |||
83 | iwl_write_direct32(priv, | ||
84 | FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), | ||
85 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | | ||
86 | 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | | ||
87 | FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); | ||
88 | |||
89 | iwl_write_direct32(priv, | ||
90 | FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), | ||
91 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
92 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | | ||
93 | FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); | ||
94 | |||
95 | IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name); | ||
96 | ret = wait_event_interruptible_timeout(priv->wait_command_queue, | ||
97 | priv->ucode_write_complete, 5 * HZ); | ||
98 | if (ret == -ERESTARTSYS) { | ||
99 | IWL_ERR(priv, "Could not load the %s uCode section due " | ||
100 | "to interrupt\n", name); | ||
101 | return ret; | ||
102 | } | ||
103 | if (!ret) { | ||
104 | IWL_ERR(priv, "Could not load the %s uCode section\n", | ||
105 | name); | ||
106 | return -ETIMEDOUT; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int iwlagn_load_given_ucode(struct iwl_priv *priv, | ||
113 | struct fw_desc *inst_image, | ||
114 | struct fw_desc *data_image) | ||
115 | { | ||
116 | int ret = 0; | ||
117 | |||
118 | ret = iwlagn_load_section(priv, "INST", inst_image, | ||
119 | IWLAGN_RTC_INST_LOWER_BOUND); | ||
120 | if (ret) | ||
121 | return ret; | ||
122 | |||
123 | return iwlagn_load_section(priv, "DATA", data_image, | ||
124 | IWLAGN_RTC_DATA_LOWER_BOUND); | ||
125 | } | ||
126 | |||
127 | int iwlagn_load_ucode(struct iwl_priv *priv) | ||
128 | { | ||
129 | int ret = 0; | ||
130 | |||
131 | /* check whether init ucode should be loaded, or rather runtime ucode */ | ||
132 | if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { | ||
133 | IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); | ||
134 | ret = iwlagn_load_given_ucode(priv, | ||
135 | &priv->ucode_init, &priv->ucode_init_data); | ||
136 | if (!ret) { | ||
137 | IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); | ||
138 | priv->ucode_type = UCODE_INIT; | ||
139 | } | ||
140 | } else { | ||
141 | IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " | ||
142 | "Loading runtime ucode...\n"); | ||
143 | ret = iwlagn_load_given_ucode(priv, | ||
144 | &priv->ucode_code, &priv->ucode_data); | ||
145 | if (!ret) { | ||
146 | IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); | ||
147 | priv->ucode_type = UCODE_RT; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | #define IWL_UCODE_GET(item) \ | ||
155 | static u32 iwlagn_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | ||
156 | u32 api_ver) \ | ||
157 | { \ | ||
158 | if (api_ver <= 2) \ | ||
159 | return le32_to_cpu(ucode->u.v1.item); \ | ||
160 | return le32_to_cpu(ucode->u.v2.item); \ | ||
161 | } | ||
162 | |||
163 | static u32 iwlagn_ucode_get_header_size(u32 api_ver) | ||
164 | { | ||
165 | if (api_ver <= 2) | ||
166 | return UCODE_HEADER_SIZE(1); | ||
167 | return UCODE_HEADER_SIZE(2); | ||
168 | } | ||
169 | |||
170 | static u32 iwlagn_ucode_get_build(const struct iwl_ucode_header *ucode, | ||
171 | u32 api_ver) | ||
172 | { | ||
173 | if (api_ver <= 2) | ||
174 | return 0; | ||
175 | return le32_to_cpu(ucode->u.v2.build); | ||
176 | } | ||
177 | |||
178 | static u8 *iwlagn_ucode_get_data(const struct iwl_ucode_header *ucode, | ||
179 | u32 api_ver) | ||
180 | { | ||
181 | if (api_ver <= 2) | ||
182 | return (u8 *) ucode->u.v1.data; | ||
183 | return (u8 *) ucode->u.v2.data; | ||
184 | } | ||
185 | |||
186 | IWL_UCODE_GET(inst_size); | ||
187 | IWL_UCODE_GET(data_size); | ||
188 | IWL_UCODE_GET(init_size); | ||
189 | IWL_UCODE_GET(init_data_size); | ||
190 | IWL_UCODE_GET(boot_size); | ||
191 | |||
192 | struct iwl_ucode_ops iwlagn_ucode = { | ||
193 | .get_header_size = iwlagn_ucode_get_header_size, | ||
194 | .get_build = iwlagn_ucode_get_build, | ||
195 | .get_inst_size = iwlagn_ucode_get_inst_size, | ||
196 | .get_data_size = iwlagn_ucode_get_data_size, | ||
197 | .get_init_size = iwlagn_ucode_get_init_size, | ||
198 | .get_init_data_size = iwlagn_ucode_get_init_data_size, | ||
199 | .get_boot_size = iwlagn_ucode_get_boot_size, | ||
200 | .get_data = iwlagn_ucode_get_data, | ||
201 | }; | ||
202 | |||
203 | /* | ||
204 | * Calibration | ||
205 | */ | ||
206 | static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) | ||
207 | { | ||
208 | struct iwl_calib_xtal_freq_cmd cmd; | ||
209 | __le16 *xtal_calib = | ||
210 | (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); | ||
211 | |||
212 | cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; | ||
213 | cmd.hdr.first_group = 0; | ||
214 | cmd.hdr.groups_num = 1; | ||
215 | cmd.hdr.data_valid = 1; | ||
216 | cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); | ||
217 | cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); | ||
218 | return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], | ||
219 | (u8 *)&cmd, sizeof(cmd)); | ||
220 | } | ||
221 | |||
222 | static int iwlagn_send_calib_cfg(struct iwl_priv *priv) | ||
223 | { | ||
224 | struct iwl_calib_cfg_cmd calib_cfg_cmd; | ||
225 | struct iwl_host_cmd cmd = { | ||
226 | .id = CALIBRATION_CFG_CMD, | ||
227 | .len = sizeof(struct iwl_calib_cfg_cmd), | ||
228 | .data = &calib_cfg_cmd, | ||
229 | }; | ||
230 | |||
231 | memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); | ||
232 | calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; | ||
233 | calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; | ||
234 | calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; | ||
235 | calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; | ||
236 | |||
237 | return iwl_send_cmd(priv, &cmd); | ||
238 | } | ||
239 | |||
240 | void iwlagn_rx_calib_result(struct iwl_priv *priv, | ||
241 | struct iwl_rx_mem_buffer *rxb) | ||
242 | { | ||
243 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
244 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | ||
245 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
246 | int index; | ||
247 | |||
248 | /* reduce the size of the length field itself */ | ||
249 | len -= 4; | ||
250 | |||
251 | /* Define the order in which the results will be sent to the runtime | ||
252 | * uCode. iwl_send_calib_results sends them in a row according to | ||
253 | * their index. We sort them here | ||
254 | */ | ||
255 | switch (hdr->op_code) { | ||
256 | case IWL_PHY_CALIBRATE_DC_CMD: | ||
257 | index = IWL_CALIB_DC; | ||
258 | break; | ||
259 | case IWL_PHY_CALIBRATE_LO_CMD: | ||
260 | index = IWL_CALIB_LO; | ||
261 | break; | ||
262 | case IWL_PHY_CALIBRATE_TX_IQ_CMD: | ||
263 | index = IWL_CALIB_TX_IQ; | ||
264 | break; | ||
265 | case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: | ||
266 | index = IWL_CALIB_TX_IQ_PERD; | ||
267 | break; | ||
268 | case IWL_PHY_CALIBRATE_BASE_BAND_CMD: | ||
269 | index = IWL_CALIB_BASE_BAND; | ||
270 | break; | ||
271 | default: | ||
272 | IWL_ERR(priv, "Unknown calibration notification %d\n", | ||
273 | hdr->op_code); | ||
274 | return; | ||
275 | } | ||
276 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); | ||
277 | } | ||
278 | |||
279 | void iwlagn_rx_calib_complete(struct iwl_priv *priv, | ||
280 | struct iwl_rx_mem_buffer *rxb) | ||
281 | { | ||
282 | IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); | ||
283 | queue_work(priv->workqueue, &priv->restart); | ||
284 | } | ||
285 | |||
286 | void iwlagn_init_alive_start(struct iwl_priv *priv) | ||
287 | { | ||
288 | int ret = 0; | ||
289 | |||
290 | /* Check alive response for "valid" sign from uCode */ | ||
291 | if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { | ||
292 | /* We had an error bringing up the hardware, so take it | ||
293 | * all the way back down so we can try again */ | ||
294 | IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); | ||
295 | goto restart; | ||
296 | } | ||
297 | |||
298 | /* initialize uCode was loaded... verify inst image. | ||
299 | * This is a paranoid check, because we would not have gotten the | ||
300 | * "initialize" alive if code weren't properly loaded. */ | ||
301 | if (iwl_verify_ucode(priv)) { | ||
302 | /* Runtime instruction load was bad; | ||
303 | * take it all the way back down so we can try again */ | ||
304 | IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); | ||
305 | goto restart; | ||
306 | } | ||
307 | |||
308 | ret = priv->cfg->ops->lib->alive_notify(priv); | ||
309 | if (ret) { | ||
310 | IWL_WARN(priv, | ||
311 | "Could not complete ALIVE transition: %d\n", ret); | ||
312 | goto restart; | ||
313 | } | ||
314 | |||
315 | iwlagn_send_calib_cfg(priv); | ||
316 | return; | ||
317 | |||
318 | restart: | ||
319 | /* real restart (first load init_ucode) */ | ||
320 | queue_work(priv->workqueue, &priv->restart); | ||
321 | } | ||
322 | |||
323 | int iwlagn_alive_notify(struct iwl_priv *priv) | ||
324 | { | ||
325 | u32 a; | ||
326 | unsigned long flags; | ||
327 | int i, chan; | ||
328 | u32 reg_val; | ||
329 | |||
330 | spin_lock_irqsave(&priv->lock, flags); | ||
331 | |||
332 | priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); | ||
333 | a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; | ||
334 | for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; | ||
335 | a += 4) | ||
336 | iwl_write_targ_mem(priv, a, 0); | ||
337 | for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; | ||
338 | a += 4) | ||
339 | iwl_write_targ_mem(priv, a, 0); | ||
340 | for (; a < priv->scd_base_addr + | ||
341 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
342 | iwl_write_targ_mem(priv, a, 0); | ||
343 | |||
344 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, | ||
345 | priv->scd_bc_tbls.dma >> 10); | ||
346 | |||
347 | /* Enable DMA channel */ | ||
348 | for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) | ||
349 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
350 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
351 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
352 | |||
353 | /* Update FH chicken bits */ | ||
354 | reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); | ||
355 | iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, | ||
356 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
357 | |||
358 | iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, | ||
359 | IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); | ||
360 | iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); | ||
361 | |||
362 | /* initiate the queues */ | ||
363 | for (i = 0; i < priv->hw_params.max_txq_num; i++) { | ||
364 | iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); | ||
365 | iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); | ||
366 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
367 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); | ||
368 | iwl_write_targ_mem(priv, priv->scd_base_addr + | ||
369 | IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + | ||
370 | sizeof(u32), | ||
371 | ((SCD_WIN_SIZE << | ||
372 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & | ||
373 | IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | | ||
374 | ((SCD_FRAME_LIMIT << | ||
375 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & | ||
376 | IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); | ||
377 | } | ||
378 | |||
379 | iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, | ||
380 | IWL_MASK(0, priv->hw_params.max_txq_num)); | ||
381 | |||
382 | /* Activate all Tx DMA/FIFO channels */ | ||
383 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); | ||
384 | |||
385 | iwlagn_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | ||
386 | |||
387 | /* make sure all queue are not stopped */ | ||
388 | memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); | ||
389 | for (i = 0; i < 4; i++) | ||
390 | atomic_set(&priv->queue_stop_count[i], 0); | ||
391 | |||
392 | /* reset to 0 to enable all the queue first */ | ||
393 | priv->txq_ctx_active_msk = 0; | ||
394 | /* map qos queues to fifos one-to-one */ | ||
395 | BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); | ||
396 | |||
397 | for (i = 0; i < ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); i++) { | ||
398 | int ac = iwlagn_default_queue_to_tx_fifo[i]; | ||
399 | |||
400 | iwl_txq_ctx_activate(priv, i); | ||
401 | |||
402 | if (ac == IWL_TX_FIFO_UNUSED) | ||
403 | continue; | ||
404 | |||
405 | iwlagn_tx_queue_set_status(priv, &priv->txq[i], ac, 0); | ||
406 | } | ||
407 | |||
408 | spin_unlock_irqrestore(&priv->lock, flags); | ||
409 | |||
410 | iwl_send_wimax_coex(priv); | ||
411 | |||
412 | iwlagn_set_Xtal_calib(priv); | ||
413 | iwl_send_calib_results(priv); | ||
414 | |||
415 | return 0; | ||
416 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index fe4cec61bdec..0b497d4bc659 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -84,13 +84,6 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | |||
84 | MODULE_LICENSE("GPL"); | 84 | MODULE_LICENSE("GPL"); |
85 | MODULE_ALIAS("iwl4965"); | 85 | MODULE_ALIAS("iwl4965"); |
86 | 86 | ||
87 | /*************** STATION TABLE MANAGEMENT **** | ||
88 | * mac80211 should be examined to determine if sta_info is duplicating | ||
89 | * the functionality provided here | ||
90 | */ | ||
91 | |||
92 | /**************************************************************/ | ||
93 | |||
94 | /** | 87 | /** |
95 | * iwl_commit_rxon - commit staging_rxon to hardware | 88 | * iwl_commit_rxon - commit staging_rxon to hardware |
96 | * | 89 | * |
@@ -166,6 +159,11 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
166 | } | 159 | } |
167 | iwl_clear_ucode_stations(priv, false); | 160 | iwl_clear_ucode_stations(priv, false); |
168 | iwl_restore_stations(priv); | 161 | iwl_restore_stations(priv); |
162 | ret = iwl_restore_default_wep_keys(priv); | ||
163 | if (ret) { | ||
164 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); | ||
165 | return ret; | ||
166 | } | ||
169 | } | 167 | } |
170 | 168 | ||
171 | IWL_DEBUG_INFO(priv, "Sending RXON\n" | 169 | IWL_DEBUG_INFO(priv, "Sending RXON\n" |
@@ -189,10 +187,15 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
189 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); | 187 | IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); |
190 | return ret; | 188 | return ret; |
191 | } | 189 | } |
192 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON. \n"); | 190 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); |
193 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 191 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
194 | iwl_clear_ucode_stations(priv, false); | 192 | iwl_clear_ucode_stations(priv, false); |
195 | iwl_restore_stations(priv); | 193 | iwl_restore_stations(priv); |
194 | ret = iwl_restore_default_wep_keys(priv); | ||
195 | if (ret) { | ||
196 | IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret); | ||
197 | return ret; | ||
198 | } | ||
196 | } | 199 | } |
197 | 200 | ||
198 | priv->start_calib = 0; | 201 | priv->start_calib = 0; |
@@ -885,10 +888,10 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
885 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = | 888 | priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = |
886 | iwl_rx_missed_beacon_notif; | 889 | iwl_rx_missed_beacon_notif; |
887 | /* Rx handlers */ | 890 | /* Rx handlers */ |
888 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; | 891 | priv->rx_handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy; |
889 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; | 892 | priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx; |
890 | /* block ack */ | 893 | /* block ack */ |
891 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba; | 894 | priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba; |
892 | /* Set up hardware specific Rx handlers */ | 895 | /* Set up hardware specific Rx handlers */ |
893 | priv->cfg->ops->lib->rx_handler_setup(priv); | 896 | priv->cfg->ops->lib->rx_handler_setup(priv); |
894 | } | 897 | } |
@@ -1016,7 +1019,7 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
1016 | count++; | 1019 | count++; |
1017 | if (count >= 8) { | 1020 | if (count >= 8) { |
1018 | rxq->read = i; | 1021 | rxq->read = i; |
1019 | iwl_rx_replenish_now(priv); | 1022 | iwlagn_rx_replenish_now(priv); |
1020 | count = 0; | 1023 | count = 0; |
1021 | } | 1024 | } |
1022 | } | 1025 | } |
@@ -1025,9 +1028,9 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
1025 | /* Backtrack one entry */ | 1028 | /* Backtrack one entry */ |
1026 | rxq->read = i; | 1029 | rxq->read = i; |
1027 | if (fill_rx) | 1030 | if (fill_rx) |
1028 | iwl_rx_replenish_now(priv); | 1031 | iwlagn_rx_replenish_now(priv); |
1029 | else | 1032 | else |
1030 | iwl_rx_queue_restock(priv); | 1033 | iwlagn_rx_queue_restock(priv); |
1031 | } | 1034 | } |
1032 | 1035 | ||
1033 | /* call this function to flush any scheduled tasklet */ | 1036 | /* call this function to flush any scheduled tasklet */ |
@@ -1426,6 +1429,60 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1426 | iwl_enable_interrupts(priv); | 1429 | iwl_enable_interrupts(priv); |
1427 | } | 1430 | } |
1428 | 1431 | ||
1432 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | ||
1433 | #define ACK_CNT_RATIO (50) | ||
1434 | #define BA_TIMEOUT_CNT (5) | ||
1435 | #define BA_TIMEOUT_MAX (16) | ||
1436 | |||
1437 | /** | ||
1438 | * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. | ||
1439 | * | ||
1440 | * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding | ||
1441 | * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal | ||
1442 | * operation state. | ||
1443 | */ | ||
1444 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
1445 | struct iwl_rx_packet *pkt) | ||
1446 | { | ||
1447 | bool rc = true; | ||
1448 | int actual_ack_cnt_delta, expected_ack_cnt_delta; | ||
1449 | int ba_timeout_delta; | ||
1450 | |||
1451 | actual_ack_cnt_delta = | ||
1452 | le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - | ||
1453 | le32_to_cpu(priv->statistics.tx.actual_ack_cnt); | ||
1454 | expected_ack_cnt_delta = | ||
1455 | le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - | ||
1456 | le32_to_cpu(priv->statistics.tx.expected_ack_cnt); | ||
1457 | ba_timeout_delta = | ||
1458 | le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - | ||
1459 | le32_to_cpu(priv->statistics.tx.agg.ba_timeout); | ||
1460 | if ((priv->_agn.agg_tids_count > 0) && | ||
1461 | (expected_ack_cnt_delta > 0) && | ||
1462 | (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) | ||
1463 | < ACK_CNT_RATIO) && | ||
1464 | (ba_timeout_delta > BA_TIMEOUT_CNT)) { | ||
1465 | IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d," | ||
1466 | " expected_ack_cnt = %d\n", | ||
1467 | actual_ack_cnt_delta, expected_ack_cnt_delta); | ||
1468 | |||
1469 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1470 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | ||
1471 | priv->delta_statistics.tx.rx_detected_cnt); | ||
1472 | IWL_DEBUG_RADIO(priv, | ||
1473 | "ack_or_ba_timeout_collision delta = %d\n", | ||
1474 | priv->delta_statistics.tx. | ||
1475 | ack_or_ba_timeout_collision); | ||
1476 | #endif | ||
1477 | IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", | ||
1478 | ba_timeout_delta); | ||
1479 | if (!actual_ack_cnt_delta && | ||
1480 | (ba_timeout_delta >= BA_TIMEOUT_MAX)) | ||
1481 | rc = false; | ||
1482 | } | ||
1483 | return rc; | ||
1484 | } | ||
1485 | |||
1429 | 1486 | ||
1430 | /****************************************************************************** | 1487 | /****************************************************************************** |
1431 | * | 1488 | * |
@@ -1787,6 +1844,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1787 | u32 data2, line; | 1844 | u32 data2, line; |
1788 | u32 desc, time, count, base, data1; | 1845 | u32 desc, time, count, base, data1; |
1789 | u32 blink1, blink2, ilink1, ilink2; | 1846 | u32 blink1, blink2, ilink1, ilink2; |
1847 | u32 pc, hcmd; | ||
1790 | 1848 | ||
1791 | if (priv->ucode_type == UCODE_INIT) | 1849 | if (priv->ucode_type == UCODE_INIT) |
1792 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); | 1850 | base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); |
@@ -1809,6 +1867,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1809 | } | 1867 | } |
1810 | 1868 | ||
1811 | desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); | 1869 | desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); |
1870 | pc = iwl_read_targ_mem(priv, base + 2 * sizeof(u32)); | ||
1812 | blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); | 1871 | blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); |
1813 | blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); | 1872 | blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); |
1814 | ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); | 1873 | ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); |
@@ -1817,6 +1876,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1817 | data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); | 1876 | data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); |
1818 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); | 1877 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); |
1819 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); | 1878 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); |
1879 | hcmd = iwl_read_targ_mem(priv, base + 22 * sizeof(u32)); | ||
1820 | 1880 | ||
1821 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, | 1881 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, |
1822 | blink1, blink2, ilink1, ilink2); | 1882 | blink1, blink2, ilink1, ilink2); |
@@ -1825,10 +1885,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1825 | "data1 data2 line\n"); | 1885 | "data1 data2 line\n"); |
1826 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", | 1886 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", |
1827 | desc_lookup(desc), desc, time, data1, data2, line); | 1887 | desc_lookup(desc), desc, time, data1, data2, line); |
1828 | IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); | 1888 | IWL_ERR(priv, "pc blink1 blink2 ilink1 ilink2 hcmd\n"); |
1829 | IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, | 1889 | IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n", |
1830 | ilink1, ilink2); | 1890 | pc, blink1, blink2, ilink1, ilink2, hcmd); |
1831 | |||
1832 | } | 1891 | } |
1833 | 1892 | ||
1834 | #define EVENT_START_OFFSET (4 * sizeof(u32)) | 1893 | #define EVENT_START_OFFSET (4 * sizeof(u32)) |
@@ -1944,9 +2003,6 @@ static int iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1944 | return pos; | 2003 | return pos; |
1945 | } | 2004 | } |
1946 | 2005 | ||
1947 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | ||
1948 | #define MAX_EVENT_LOG_SIZE (512) | ||
1949 | |||
1950 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) | 2006 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) |
1951 | 2007 | ||
1952 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | 2008 | int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
@@ -1979,16 +2035,16 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
1979 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 2035 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
1980 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 2036 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
1981 | 2037 | ||
1982 | if (capacity > MAX_EVENT_LOG_SIZE) { | 2038 | if (capacity > priv->cfg->max_event_log_size) { |
1983 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | 2039 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", |
1984 | capacity, MAX_EVENT_LOG_SIZE); | 2040 | capacity, priv->cfg->max_event_log_size); |
1985 | capacity = MAX_EVENT_LOG_SIZE; | 2041 | capacity = priv->cfg->max_event_log_size; |
1986 | } | 2042 | } |
1987 | 2043 | ||
1988 | if (next_entry > MAX_EVENT_LOG_SIZE) { | 2044 | if (next_entry > priv->cfg->max_event_log_size) { |
1989 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | 2045 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", |
1990 | next_entry, MAX_EVENT_LOG_SIZE); | 2046 | next_entry, priv->cfg->max_event_log_size); |
1991 | next_entry = MAX_EVENT_LOG_SIZE; | 2047 | next_entry = priv->cfg->max_event_log_size; |
1992 | } | 2048 | } |
1993 | 2049 | ||
1994 | size = num_wraps ? capacity : next_entry; | 2050 | size = num_wraps ? capacity : next_entry; |
@@ -2204,8 +2260,8 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2204 | /* device going down, Stop using ICT table */ | 2260 | /* device going down, Stop using ICT table */ |
2205 | iwl_disable_ict(priv); | 2261 | iwl_disable_ict(priv); |
2206 | 2262 | ||
2207 | iwl_txq_ctx_stop(priv); | 2263 | iwlagn_txq_ctx_stop(priv); |
2208 | iwl_rxq_stop(priv); | 2264 | iwlagn_rxq_stop(priv); |
2209 | 2265 | ||
2210 | /* Power-down device's busmaster DMA clocks */ | 2266 | /* Power-down device's busmaster DMA clocks */ |
2211 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); | 2267 | iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); |
@@ -2265,7 +2321,7 @@ static int iwl_prepare_card_hw(struct iwl_priv *priv) | |||
2265 | { | 2321 | { |
2266 | int ret = 0; | 2322 | int ret = 0; |
2267 | 2323 | ||
2268 | IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n"); | 2324 | IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter\n"); |
2269 | 2325 | ||
2270 | ret = iwl_set_hw_ready(priv); | 2326 | ret = iwl_set_hw_ready(priv); |
2271 | if (priv->hw_ready) | 2327 | if (priv->hw_ready) |
@@ -2326,7 +2382,7 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2326 | 2382 | ||
2327 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); | 2383 | iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
2328 | 2384 | ||
2329 | ret = iwl_hw_nic_init(priv); | 2385 | ret = iwlagn_hw_nic_init(priv); |
2330 | if (ret) { | 2386 | if (ret) { |
2331 | IWL_ERR(priv, "Unable to init nic\n"); | 2387 | IWL_ERR(priv, "Unable to init nic\n"); |
2332 | return ret; | 2388 | return ret; |
@@ -2476,7 +2532,7 @@ static void iwl_bg_rx_replenish(struct work_struct *data) | |||
2476 | return; | 2532 | return; |
2477 | 2533 | ||
2478 | mutex_lock(&priv->mutex); | 2534 | mutex_lock(&priv->mutex); |
2479 | iwl_rx_replenish(priv); | 2535 | iwlagn_rx_replenish(priv); |
2480 | mutex_unlock(&priv->mutex); | 2536 | mutex_unlock(&priv->mutex); |
2481 | } | 2537 | } |
2482 | 2538 | ||
@@ -2486,7 +2542,6 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2486 | { | 2542 | { |
2487 | struct ieee80211_conf *conf = NULL; | 2543 | struct ieee80211_conf *conf = NULL; |
2488 | int ret = 0; | 2544 | int ret = 0; |
2489 | unsigned long flags; | ||
2490 | 2545 | ||
2491 | if (priv->iw_mode == NL80211_IFTYPE_AP) { | 2546 | if (priv->iw_mode == NL80211_IFTYPE_AP) { |
2492 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); | 2547 | IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); |
@@ -2567,10 +2622,6 @@ void iwl_post_associate(struct iwl_priv *priv) | |||
2567 | break; | 2622 | break; |
2568 | } | 2623 | } |
2569 | 2624 | ||
2570 | spin_lock_irqsave(&priv->lock, flags); | ||
2571 | iwl_activate_qos(priv, 0); | ||
2572 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2573 | |||
2574 | /* the chain noise calibration will enabled PM upon completion | 2625 | /* the chain noise calibration will enabled PM upon completion |
2575 | * If chain noise has already been run, then we need to enable | 2626 | * If chain noise has already been run, then we need to enable |
2576 | * power management here */ | 2627 | * power management here */ |
@@ -2737,7 +2788,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2737 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, | 2788 | IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, |
2738 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); | 2789 | ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); |
2739 | 2790 | ||
2740 | if (iwl_tx_skb(priv, skb)) | 2791 | if (iwlagn_tx_skb(priv, skb)) |
2741 | dev_kfree_skb_any(skb); | 2792 | dev_kfree_skb_any(skb); |
2742 | 2793 | ||
2743 | IWL_DEBUG_MACDUMP(priv, "leave\n"); | 2794 | IWL_DEBUG_MACDUMP(priv, "leave\n"); |
@@ -2747,7 +2798,6 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2747 | void iwl_config_ap(struct iwl_priv *priv) | 2798 | void iwl_config_ap(struct iwl_priv *priv) |
2748 | { | 2799 | { |
2749 | int ret = 0; | 2800 | int ret = 0; |
2750 | unsigned long flags; | ||
2751 | 2801 | ||
2752 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 2802 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
2753 | return; | 2803 | return; |
@@ -2799,10 +2849,6 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2799 | /* restore RXON assoc */ | 2849 | /* restore RXON assoc */ |
2800 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2850 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2801 | iwlcore_commit_rxon(priv); | 2851 | iwlcore_commit_rxon(priv); |
2802 | iwl_reset_qos(priv); | ||
2803 | spin_lock_irqsave(&priv->lock, flags); | ||
2804 | iwl_activate_qos(priv, 1); | ||
2805 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2806 | iwl_add_bcast_station(priv); | 2852 | iwl_add_bcast_station(priv); |
2807 | } | 2853 | } |
2808 | iwl_send_beacon_cmd(priv); | 2854 | iwl_send_beacon_cmd(priv); |
@@ -2858,12 +2904,13 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2858 | mutex_lock(&priv->mutex); | 2904 | mutex_lock(&priv->mutex); |
2859 | iwl_scan_cancel_timeout(priv, 100); | 2905 | iwl_scan_cancel_timeout(priv, 100); |
2860 | 2906 | ||
2861 | /* If we are getting WEP group key and we didn't receive any key mapping | 2907 | /* |
2908 | * If we are getting WEP group key and we didn't receive any key mapping | ||
2862 | * so far, we are in legacy wep mode (group key only), otherwise we are | 2909 | * so far, we are in legacy wep mode (group key only), otherwise we are |
2863 | * in 1X mode. | 2910 | * in 1X mode. |
2864 | * In legacy wep mode, we use another host command to the uCode */ | 2911 | * In legacy wep mode, we use another host command to the uCode. |
2865 | if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && | 2912 | */ |
2866 | priv->iw_mode != NL80211_IFTYPE_AP) { | 2913 | if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) { |
2867 | if (cmd == SET_KEY) | 2914 | if (cmd == SET_KEY) |
2868 | is_default_wep_key = !priv->key_mapping_key; | 2915 | is_default_wep_key = !priv->key_mapping_key; |
2869 | else | 2916 | else |
@@ -2925,7 +2972,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2925 | return ret; | 2972 | return ret; |
2926 | case IEEE80211_AMPDU_TX_START: | 2973 | case IEEE80211_AMPDU_TX_START: |
2927 | IWL_DEBUG_HT(priv, "start Tx\n"); | 2974 | IWL_DEBUG_HT(priv, "start Tx\n"); |
2928 | ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn); | 2975 | ret = iwlagn_tx_agg_start(priv, sta->addr, tid, ssn); |
2929 | if (ret == 0) { | 2976 | if (ret == 0) { |
2930 | priv->_agn.agg_tids_count++; | 2977 | priv->_agn.agg_tids_count++; |
2931 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | 2978 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", |
@@ -2934,7 +2981,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
2934 | return ret; | 2981 | return ret; |
2935 | case IEEE80211_AMPDU_TX_STOP: | 2982 | case IEEE80211_AMPDU_TX_STOP: |
2936 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 2983 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
2937 | ret = iwl_tx_agg_stop(priv, sta->addr, tid); | 2984 | ret = iwlagn_tx_agg_stop(priv, sta->addr, tid); |
2938 | if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { | 2985 | if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { |
2939 | priv->_agn.agg_tids_count--; | 2986 | priv->_agn.agg_tids_count--; |
2940 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", | 2987 | IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", |
@@ -2997,19 +3044,6 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | |||
2997 | } | 3044 | } |
2998 | } | 3045 | } |
2999 | 3046 | ||
3000 | /** | ||
3001 | * iwl_restore_wepkeys - Restore WEP keys to device | ||
3002 | */ | ||
3003 | static void iwl_restore_wepkeys(struct iwl_priv *priv) | ||
3004 | { | ||
3005 | mutex_lock(&priv->mutex); | ||
3006 | if (priv->iw_mode == NL80211_IFTYPE_STATION && | ||
3007 | priv->default_wep_key && | ||
3008 | iwl_send_static_wepkey_cmd(priv, 0)) | ||
3009 | IWL_ERR(priv, "Could not send WEP static key\n"); | ||
3010 | mutex_unlock(&priv->mutex); | ||
3011 | } | ||
3012 | |||
3013 | static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | 3047 | static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, |
3014 | struct ieee80211_vif *vif, | 3048 | struct ieee80211_vif *vif, |
3015 | struct ieee80211_sta *sta) | 3049 | struct ieee80211_sta *sta) |
@@ -3036,10 +3070,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, | |||
3036 | return ret; | 3070 | return ret; |
3037 | } | 3071 | } |
3038 | 3072 | ||
3039 | iwl_restore_wepkeys(priv); | ||
3040 | |||
3041 | /* Initialize rate scaling */ | 3073 | /* Initialize rate scaling */ |
3042 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM \n", | 3074 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", |
3043 | sta->addr); | 3075 | sta->addr); |
3044 | iwl_rs_rate_init(priv, sta, sta_id); | 3076 | iwl_rs_rate_init(priv, sta, sta_id); |
3045 | 3077 | ||
@@ -3337,15 +3369,10 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3337 | 3369 | ||
3338 | iwl_init_scan_params(priv); | 3370 | iwl_init_scan_params(priv); |
3339 | 3371 | ||
3340 | iwl_reset_qos(priv); | ||
3341 | |||
3342 | priv->qos_data.qos_active = 0; | ||
3343 | priv->qos_data.qos_cap.val = 0; | ||
3344 | |||
3345 | /* Set the tx_power_user_lmt to the lowest power level | 3372 | /* Set the tx_power_user_lmt to the lowest power level |
3346 | * this value will get overwritten by channel max power avg | 3373 | * this value will get overwritten by channel max power avg |
3347 | * from eeprom */ | 3374 | * from eeprom */ |
3348 | priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN; | 3375 | priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; |
3349 | 3376 | ||
3350 | ret = iwl_init_channel_map(priv); | 3377 | ret = iwl_init_channel_map(priv); |
3351 | if (ret) { | 3378 | if (ret) { |
@@ -3692,8 +3719,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) | |||
3692 | iwl_dealloc_ucode_pci(priv); | 3719 | iwl_dealloc_ucode_pci(priv); |
3693 | 3720 | ||
3694 | if (priv->rxq.bd) | 3721 | if (priv->rxq.bd) |
3695 | iwl_rx_queue_free(priv, &priv->rxq); | 3722 | iwlagn_rx_queue_free(priv, &priv->rxq); |
3696 | iwl_hw_txq_ctx_free(priv); | 3723 | iwlagn_hw_txq_ctx_free(priv); |
3697 | 3724 | ||
3698 | iwl_eeprom_free(priv); | 3725 | iwl_eeprom_free(priv); |
3699 | 3726 | ||
@@ -3808,6 +3835,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { | |||
3808 | {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, | 3835 | {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, |
3809 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, | 3836 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, |
3810 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, | 3837 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, |
3838 | {IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000i_g2_2agn_cfg)}, | ||
3811 | 3839 | ||
3812 | /* 6x50 WiFi/WiMax Series */ | 3840 | /* 6x50 WiFi/WiMax Series */ |
3813 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 3841 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |
@@ -3890,3 +3918,33 @@ module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); | |||
3890 | MODULE_PARM_DESC(debug, "debug output mask"); | 3918 | MODULE_PARM_DESC(debug, "debug output mask"); |
3891 | #endif | 3919 | #endif |
3892 | 3920 | ||
3921 | module_param_named(swcrypto50, iwlagn_mod_params.sw_crypto, bool, S_IRUGO); | ||
3922 | MODULE_PARM_DESC(swcrypto50, | ||
3923 | "using crypto in software (default 0 [hardware]) (deprecated)"); | ||
3924 | module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); | ||
3925 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | ||
3926 | module_param_named(queues_num50, | ||
3927 | iwlagn_mod_params.num_of_queues, int, S_IRUGO); | ||
3928 | MODULE_PARM_DESC(queues_num50, | ||
3929 | "number of hw queues in 50xx series (deprecated)"); | ||
3930 | module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO); | ||
3931 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | ||
3932 | module_param_named(11n_disable50, iwlagn_mod_params.disable_11n, int, S_IRUGO); | ||
3933 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality (deprecated)"); | ||
3934 | module_param_named(11n_disable, iwlagn_mod_params.disable_11n, int, S_IRUGO); | ||
3935 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | ||
3936 | module_param_named(amsdu_size_8K50, iwlagn_mod_params.amsdu_size_8K, | ||
3937 | int, S_IRUGO); | ||
3938 | MODULE_PARM_DESC(amsdu_size_8K50, | ||
3939 | "enable 8K amsdu size in 50XX series (deprecated)"); | ||
3940 | module_param_named(amsdu_size_8K, iwlagn_mod_params.amsdu_size_8K, | ||
3941 | int, S_IRUGO); | ||
3942 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | ||
3943 | module_param_named(fw_restart50, iwlagn_mod_params.restart_fw, int, S_IRUGO); | ||
3944 | MODULE_PARM_DESC(fw_restart50, | ||
3945 | "restart firmware in case of error (deprecated)"); | ||
3946 | module_param_named(fw_restart, iwlagn_mod_params.restart_fw, int, S_IRUGO); | ||
3947 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | ||
3948 | module_param_named( | ||
3949 | disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO); | ||
3950 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 26eeb586ee00..5d3142287e14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -65,10 +65,110 @@ | |||
65 | 65 | ||
66 | #include "iwl-dev.h" | 66 | #include "iwl-dev.h" |
67 | 67 | ||
68 | extern struct iwl_mod_params iwlagn_mod_params; | ||
69 | extern struct iwl_ucode_ops iwlagn_ucode; | ||
70 | extern struct iwl_hcmd_ops iwlagn_hcmd; | ||
71 | extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils; | ||
72 | |||
68 | int iwl_reset_ict(struct iwl_priv *priv); | 73 | int iwl_reset_ict(struct iwl_priv *priv); |
69 | void iwl_disable_ict(struct iwl_priv *priv); | 74 | void iwl_disable_ict(struct iwl_priv *priv); |
70 | int iwl_alloc_isr_ict(struct iwl_priv *priv); | 75 | int iwl_alloc_isr_ict(struct iwl_priv *priv); |
71 | void iwl_free_isr_ict(struct iwl_priv *priv); | 76 | void iwl_free_isr_ict(struct iwl_priv *priv); |
72 | irqreturn_t iwl_isr_ict(int irq, void *data); | 77 | irqreturn_t iwl_isr_ict(int irq, void *data); |
78 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
79 | struct iwl_rx_packet *pkt); | ||
80 | |||
81 | /* tx queue */ | ||
82 | void iwlagn_set_wr_ptrs(struct iwl_priv *priv, | ||
83 | int txq_id, u32 index); | ||
84 | void iwlagn_tx_queue_set_status(struct iwl_priv *priv, | ||
85 | struct iwl_tx_queue *txq, | ||
86 | int tx_fifo_id, int scd_retry); | ||
87 | void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
88 | struct iwl_tx_queue *txq, | ||
89 | u16 byte_cnt); | ||
90 | void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
91 | struct iwl_tx_queue *txq); | ||
92 | int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
93 | int tx_fifo, int sta_id, int tid, u16 ssn_idx); | ||
94 | int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
95 | u16 ssn_idx, u8 tx_fifo); | ||
96 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); | ||
97 | |||
98 | /* uCode */ | ||
99 | int iwlagn_load_ucode(struct iwl_priv *priv); | ||
100 | void iwlagn_rx_calib_result(struct iwl_priv *priv, | ||
101 | struct iwl_rx_mem_buffer *rxb); | ||
102 | void iwlagn_rx_calib_complete(struct iwl_priv *priv, | ||
103 | struct iwl_rx_mem_buffer *rxb); | ||
104 | void iwlagn_init_alive_start(struct iwl_priv *priv); | ||
105 | int iwlagn_alive_notify(struct iwl_priv *priv); | ||
106 | |||
107 | /* lib */ | ||
108 | void iwl_check_abort_status(struct iwl_priv *priv, | ||
109 | u8 frame_count, u32 status); | ||
110 | void iwlagn_rx_handler_setup(struct iwl_priv *priv); | ||
111 | void iwlagn_setup_deferred_work(struct iwl_priv *priv); | ||
112 | int iwlagn_hw_valid_rtc_data_addr(u32 addr); | ||
113 | int iwlagn_send_tx_power(struct iwl_priv *priv); | ||
114 | void iwlagn_temperature(struct iwl_priv *priv); | ||
115 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); | ||
116 | const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv, | ||
117 | size_t offset); | ||
118 | void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
119 | int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
120 | int iwlagn_hw_nic_init(struct iwl_priv *priv); | ||
121 | |||
122 | /* rx */ | ||
123 | void iwlagn_rx_queue_restock(struct iwl_priv *priv); | ||
124 | void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority); | ||
125 | void iwlagn_rx_replenish(struct iwl_priv *priv); | ||
126 | void iwlagn_rx_replenish_now(struct iwl_priv *priv); | ||
127 | void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
128 | int iwlagn_rxq_stop(struct iwl_priv *priv); | ||
129 | int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | ||
130 | void iwlagn_rx_reply_rx(struct iwl_priv *priv, | ||
131 | struct iwl_rx_mem_buffer *rxb); | ||
132 | void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, | ||
133 | struct iwl_rx_mem_buffer *rxb); | ||
134 | |||
135 | /* tx */ | ||
136 | void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
137 | struct ieee80211_tx_info *info); | ||
138 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | ||
139 | int iwlagn_tx_agg_start(struct iwl_priv *priv, | ||
140 | const u8 *ra, u16 tid, u16 *ssn); | ||
141 | int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | ||
142 | int iwlagn_txq_check_empty(struct iwl_priv *priv, | ||
143 | int sta_id, u8 tid, int txq_id); | ||
144 | void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
145 | struct iwl_rx_mem_buffer *rxb); | ||
146 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | ||
147 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); | ||
148 | int iwlagn_txq_ctx_alloc(struct iwl_priv *priv); | ||
149 | void iwlagn_txq_ctx_reset(struct iwl_priv *priv); | ||
150 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv); | ||
151 | |||
152 | static inline u32 iwl_tx_status_to_mac80211(u32 status) | ||
153 | { | ||
154 | status &= TX_STATUS_MSK; | ||
155 | |||
156 | switch (status) { | ||
157 | case TX_STATUS_SUCCESS: | ||
158 | case TX_STATUS_DIRECT_DONE: | ||
159 | return IEEE80211_TX_STAT_ACK; | ||
160 | case TX_STATUS_FAIL_DEST_PS: | ||
161 | return IEEE80211_TX_STAT_TX_FILTERED; | ||
162 | default: | ||
163 | return 0; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | static inline bool iwl_is_tx_success(u32 status) | ||
168 | { | ||
169 | status &= TX_STATUS_MSK; | ||
170 | return (status == TX_STATUS_SUCCESS) || | ||
171 | (status == TX_STATUS_DIRECT_DONE); | ||
172 | } | ||
73 | 173 | ||
74 | #endif /* __iwl_agn_h__ */ | 174 | #endif /* __iwl_agn_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index de3b3f403d1f..0471c3f8713e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -593,7 +593,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, | |||
593 | IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); | 593 | IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); |
594 | 594 | ||
595 | if (!rx_enable_time) { | 595 | if (!rx_enable_time) { |
596 | IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0! \n"); | 596 | IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n"); |
597 | return; | 597 | return; |
598 | } | 598 | } |
599 | 599 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6383d9f8c9b3..d830086ca195 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -106,7 +106,7 @@ enum { | |||
106 | REPLY_TX = 0x1c, | 106 | REPLY_TX = 0x1c, |
107 | REPLY_RATE_SCALE = 0x47, /* 3945 only */ | 107 | REPLY_RATE_SCALE = 0x47, /* 3945 only */ |
108 | REPLY_LEDS_CMD = 0x48, | 108 | REPLY_LEDS_CMD = 0x48, |
109 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ | 109 | REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */ |
110 | 110 | ||
111 | /* WiMAX coexistence */ | 111 | /* WiMAX coexistence */ |
112 | COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */ | 112 | COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */ |
@@ -512,8 +512,9 @@ struct iwl_init_alive_resp { | |||
512 | * | 512 | * |
513 | * Entries without timestamps contain only event_id and data. | 513 | * Entries without timestamps contain only event_id and data. |
514 | * | 514 | * |
515 | * | ||
515 | * 2) error_event_table_ptr indicates base of the error log. This contains | 516 | * 2) error_event_table_ptr indicates base of the error log. This contains |
516 | * information about any uCode error that occurs. For 4965, the format | 517 | * information about any uCode error that occurs. For agn, the format |
517 | * of the error log is: | 518 | * of the error log is: |
518 | * | 519 | * |
519 | * __le32 valid; (nonzero) valid, (0) log is empty | 520 | * __le32 valid; (nonzero) valid, (0) log is empty |
@@ -529,6 +530,30 @@ struct iwl_init_alive_resp { | |||
529 | * __le32 bcon_time; beacon timer | 530 | * __le32 bcon_time; beacon timer |
530 | * __le32 tsf_low; network timestamp function timer | 531 | * __le32 tsf_low; network timestamp function timer |
531 | * __le32 tsf_hi; network timestamp function timer | 532 | * __le32 tsf_hi; network timestamp function timer |
533 | * __le32 gp1; GP1 timer register | ||
534 | * __le32 gp2; GP2 timer register | ||
535 | * __le32 gp3; GP3 timer register | ||
536 | * __le32 ucode_ver; uCode version | ||
537 | * __le32 hw_ver; HW Silicon version | ||
538 | * __le32 brd_ver; HW board version | ||
539 | * __le32 log_pc; log program counter | ||
540 | * __le32 frame_ptr; frame pointer | ||
541 | * __le32 stack_ptr; stack pointer | ||
542 | * __le32 hcmd; last host command | ||
543 | * __le32 isr0; isr status register LMPM_NIC_ISR0: rxtx_flag | ||
544 | * __le32 isr1; isr status register LMPM_NIC_ISR1: host_flag | ||
545 | * __le32 isr2; isr status register LMPM_NIC_ISR2: enc_flag | ||
546 | * __le32 isr3; isr status register LMPM_NIC_ISR3: time_flag | ||
547 | * __le32 isr4; isr status register LMPM_NIC_ISR4: wico interrupt | ||
548 | * __le32 isr_pref; isr status register LMPM_NIC_PREF_STAT | ||
549 | * __le32 wait_event; wait event() caller address | ||
550 | * __le32 l2p_control; L2pControlField | ||
551 | * __le32 l2p_duration; L2pDurationField | ||
552 | * __le32 l2p_mhvalid; L2pMhValidBits | ||
553 | * __le32 l2p_addr_match; L2pAddrMatchStat | ||
554 | * __le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL) | ||
555 | * __le32 u_timestamp; indicate when the date and time of the compilation | ||
556 | * __le32 reserved; | ||
532 | * | 557 | * |
533 | * The Linux driver can print both logs to the system log when a uCode error | 558 | * The Linux driver can print both logs to the system log when a uCode error |
534 | * occurs. | 559 | * occurs. |
@@ -1637,7 +1662,7 @@ struct iwl_tx_cmd { | |||
1637 | struct ieee80211_hdr hdr[0]; | 1662 | struct ieee80211_hdr hdr[0]; |
1638 | } __attribute__ ((packed)); | 1663 | } __attribute__ ((packed)); |
1639 | 1664 | ||
1640 | /* TX command response is sent after *all* transmission attempts. | 1665 | /* TX command response is sent after *3945* transmission attempts. |
1641 | * | 1666 | * |
1642 | * NOTES: | 1667 | * NOTES: |
1643 | * | 1668 | * |
@@ -1665,24 +1690,65 @@ struct iwl_tx_cmd { | |||
1665 | * control line. Receiving is still allowed in this case. | 1690 | * control line. Receiving is still allowed in this case. |
1666 | */ | 1691 | */ |
1667 | enum { | 1692 | enum { |
1693 | TX_3945_STATUS_SUCCESS = 0x01, | ||
1694 | TX_3945_STATUS_DIRECT_DONE = 0x02, | ||
1695 | TX_3945_STATUS_FAIL_SHORT_LIMIT = 0x82, | ||
1696 | TX_3945_STATUS_FAIL_LONG_LIMIT = 0x83, | ||
1697 | TX_3945_STATUS_FAIL_FIFO_UNDERRUN = 0x84, | ||
1698 | TX_3945_STATUS_FAIL_MGMNT_ABORT = 0x85, | ||
1699 | TX_3945_STATUS_FAIL_NEXT_FRAG = 0x86, | ||
1700 | TX_3945_STATUS_FAIL_LIFE_EXPIRE = 0x87, | ||
1701 | TX_3945_STATUS_FAIL_DEST_PS = 0x88, | ||
1702 | TX_3945_STATUS_FAIL_ABORTED = 0x89, | ||
1703 | TX_3945_STATUS_FAIL_BT_RETRY = 0x8a, | ||
1704 | TX_3945_STATUS_FAIL_STA_INVALID = 0x8b, | ||
1705 | TX_3945_STATUS_FAIL_FRAG_DROPPED = 0x8c, | ||
1706 | TX_3945_STATUS_FAIL_TID_DISABLE = 0x8d, | ||
1707 | TX_3945_STATUS_FAIL_FRAME_FLUSHED = 0x8e, | ||
1708 | TX_3945_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, | ||
1709 | TX_3945_STATUS_FAIL_TX_LOCKED = 0x90, | ||
1710 | TX_3945_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, | ||
1711 | }; | ||
1712 | |||
1713 | /* | ||
1714 | * TX command response is sent after *agn* transmission attempts. | ||
1715 | * | ||
1716 | * both postpone and abort status are expected behavior from uCode. there is | ||
1717 | * no special operation required from driver; except for RFKILL_FLUSH, | ||
1718 | * which required tx flush host command to flush all the tx frames in queues | ||
1719 | */ | ||
1720 | enum { | ||
1668 | TX_STATUS_SUCCESS = 0x01, | 1721 | TX_STATUS_SUCCESS = 0x01, |
1669 | TX_STATUS_DIRECT_DONE = 0x02, | 1722 | TX_STATUS_DIRECT_DONE = 0x02, |
1723 | /* postpone TX */ | ||
1724 | TX_STATUS_POSTPONE_DELAY = 0x40, | ||
1725 | TX_STATUS_POSTPONE_FEW_BYTES = 0x41, | ||
1726 | TX_STATUS_POSTPONE_BT_PRIO = 0x42, | ||
1727 | TX_STATUS_POSTPONE_QUIET_PERIOD = 0x43, | ||
1728 | TX_STATUS_POSTPONE_CALC_TTAK = 0x44, | ||
1729 | /* abort TX */ | ||
1730 | TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY = 0x81, | ||
1670 | TX_STATUS_FAIL_SHORT_LIMIT = 0x82, | 1731 | TX_STATUS_FAIL_SHORT_LIMIT = 0x82, |
1671 | TX_STATUS_FAIL_LONG_LIMIT = 0x83, | 1732 | TX_STATUS_FAIL_LONG_LIMIT = 0x83, |
1672 | TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84, | 1733 | TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84, |
1673 | TX_STATUS_FAIL_MGMNT_ABORT = 0x85, | 1734 | TX_STATUS_FAIL_DRAIN_FLOW = 0x85, |
1674 | TX_STATUS_FAIL_NEXT_FRAG = 0x86, | 1735 | TX_STATUS_FAIL_RFKILL_FLUSH = 0x86, |
1675 | TX_STATUS_FAIL_LIFE_EXPIRE = 0x87, | 1736 | TX_STATUS_FAIL_LIFE_EXPIRE = 0x87, |
1676 | TX_STATUS_FAIL_DEST_PS = 0x88, | 1737 | TX_STATUS_FAIL_DEST_PS = 0x88, |
1677 | TX_STATUS_FAIL_ABORTED = 0x89, | 1738 | TX_STATUS_FAIL_HOST_ABORTED = 0x89, |
1678 | TX_STATUS_FAIL_BT_RETRY = 0x8a, | 1739 | TX_STATUS_FAIL_BT_RETRY = 0x8a, |
1679 | TX_STATUS_FAIL_STA_INVALID = 0x8b, | 1740 | TX_STATUS_FAIL_STA_INVALID = 0x8b, |
1680 | TX_STATUS_FAIL_FRAG_DROPPED = 0x8c, | 1741 | TX_STATUS_FAIL_FRAG_DROPPED = 0x8c, |
1681 | TX_STATUS_FAIL_TID_DISABLE = 0x8d, | 1742 | TX_STATUS_FAIL_TID_DISABLE = 0x8d, |
1682 | TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e, | 1743 | TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e, |
1683 | TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, | 1744 | TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, |
1684 | TX_STATUS_FAIL_TX_LOCKED = 0x90, | 1745 | /* uCode drop due to FW drop request */ |
1685 | TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, | 1746 | TX_STATUS_FAIL_FW_DROP = 0x90, |
1747 | /* | ||
1748 | * uCode drop due to station color mismatch | ||
1749 | * between tx command and station table | ||
1750 | */ | ||
1751 | TX_STATUS_FAIL_STA_COLOR_MISMATCH_DROP = 0x91, | ||
1686 | }; | 1752 | }; |
1687 | 1753 | ||
1688 | #define TX_PACKET_MODE_REGULAR 0x0000 | 1754 | #define TX_PACKET_MODE_REGULAR 0x0000 |
@@ -1704,30 +1770,6 @@ enum { | |||
1704 | TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ | 1770 | TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ |
1705 | }; | 1771 | }; |
1706 | 1772 | ||
1707 | static inline u32 iwl_tx_status_to_mac80211(u32 status) | ||
1708 | { | ||
1709 | status &= TX_STATUS_MSK; | ||
1710 | |||
1711 | switch (status) { | ||
1712 | case TX_STATUS_SUCCESS: | ||
1713 | case TX_STATUS_DIRECT_DONE: | ||
1714 | return IEEE80211_TX_STAT_ACK; | ||
1715 | case TX_STATUS_FAIL_DEST_PS: | ||
1716 | return IEEE80211_TX_STAT_TX_FILTERED; | ||
1717 | default: | ||
1718 | return 0; | ||
1719 | } | ||
1720 | } | ||
1721 | |||
1722 | static inline bool iwl_is_tx_success(u32 status) | ||
1723 | { | ||
1724 | status &= TX_STATUS_MSK; | ||
1725 | return (status == TX_STATUS_SUCCESS) || | ||
1726 | (status == TX_STATUS_DIRECT_DONE); | ||
1727 | } | ||
1728 | |||
1729 | |||
1730 | |||
1731 | /* ******************************* | 1773 | /* ******************************* |
1732 | * TX aggregation status | 1774 | * TX aggregation status |
1733 | ******************************* */ | 1775 | ******************************* */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 0ee8cc296e48..2a89747d3473 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -66,7 +66,7 @@ MODULE_LICENSE("GPL"); | |||
66 | */ | 66 | */ |
67 | static bool bt_coex_active = true; | 67 | static bool bt_coex_active = true; |
68 | module_param(bt_coex_active, bool, S_IRUGO); | 68 | module_param(bt_coex_active, bool, S_IRUGO); |
69 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist\n"); | 69 | MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); |
70 | 70 | ||
71 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { | 71 | static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = { |
72 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, | 72 | {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP, |
@@ -141,30 +141,6 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { | |||
141 | }; | 141 | }; |
142 | EXPORT_SYMBOL(iwl_rates); | 142 | EXPORT_SYMBOL(iwl_rates); |
143 | 143 | ||
144 | /** | ||
145 | * translate ucode response to mac80211 tx status control values | ||
146 | */ | ||
147 | void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
148 | struct ieee80211_tx_info *info) | ||
149 | { | ||
150 | struct ieee80211_tx_rate *r = &info->control.rates[0]; | ||
151 | |||
152 | info->antenna_sel_tx = | ||
153 | ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); | ||
154 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
155 | r->flags |= IEEE80211_TX_RC_MCS; | ||
156 | if (rate_n_flags & RATE_MCS_GF_MSK) | ||
157 | r->flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
158 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
159 | r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
160 | if (rate_n_flags & RATE_MCS_DUP_MSK) | ||
161 | r->flags |= IEEE80211_TX_RC_DUP_DATA; | ||
162 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
163 | r->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
164 | r->idx = iwl_hwrate_to_mac80211_idx(rate_n_flags, info->band); | ||
165 | } | ||
166 | EXPORT_SYMBOL(iwl_hwrate_to_tx_control); | ||
167 | |||
168 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | 144 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) |
169 | { | 145 | { |
170 | int idx = 0; | 146 | int idx = 0; |
@@ -196,27 +172,6 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) | |||
196 | } | 172 | } |
197 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); | 173 | EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); |
198 | 174 | ||
199 | int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) | ||
200 | { | ||
201 | int idx = 0; | ||
202 | int band_offset = 0; | ||
203 | |||
204 | /* HT rate format: mac80211 wants an MCS number, which is just LSB */ | ||
205 | if (rate_n_flags & RATE_MCS_HT_MSK) { | ||
206 | idx = (rate_n_flags & 0xff); | ||
207 | return idx; | ||
208 | /* Legacy rate format, search for match in table */ | ||
209 | } else { | ||
210 | if (band == IEEE80211_BAND_5GHZ) | ||
211 | band_offset = IWL_FIRST_OFDM_RATE; | ||
212 | for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) | ||
213 | if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) | ||
214 | return idx - band_offset; | ||
215 | } | ||
216 | |||
217 | return -1; | ||
218 | } | ||
219 | |||
220 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) | 175 | u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) |
221 | { | 176 | { |
222 | int i; | 177 | int i; |
@@ -266,74 +221,16 @@ void iwl_hw_detect(struct iwl_priv *priv) | |||
266 | } | 221 | } |
267 | EXPORT_SYMBOL(iwl_hw_detect); | 222 | EXPORT_SYMBOL(iwl_hw_detect); |
268 | 223 | ||
269 | int iwl_hw_nic_init(struct iwl_priv *priv) | ||
270 | { | ||
271 | unsigned long flags; | ||
272 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
273 | int ret; | ||
274 | |||
275 | /* nic_init */ | ||
276 | spin_lock_irqsave(&priv->lock, flags); | ||
277 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
278 | |||
279 | /* Set interrupt coalescing calibration timer to default (512 usecs) */ | ||
280 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF); | ||
281 | |||
282 | spin_unlock_irqrestore(&priv->lock, flags); | ||
283 | |||
284 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | ||
285 | |||
286 | priv->cfg->ops->lib->apm_ops.config(priv); | ||
287 | |||
288 | /* Allocate the RX queue, or reset if it is already allocated */ | ||
289 | if (!rxq->bd) { | ||
290 | ret = iwl_rx_queue_alloc(priv); | ||
291 | if (ret) { | ||
292 | IWL_ERR(priv, "Unable to initialize Rx queue\n"); | ||
293 | return -ENOMEM; | ||
294 | } | ||
295 | } else | ||
296 | iwl_rx_queue_reset(priv, rxq); | ||
297 | |||
298 | iwl_rx_replenish(priv); | ||
299 | |||
300 | iwl_rx_init(priv, rxq); | ||
301 | |||
302 | spin_lock_irqsave(&priv->lock, flags); | ||
303 | |||
304 | rxq->need_update = 1; | ||
305 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
306 | |||
307 | spin_unlock_irqrestore(&priv->lock, flags); | ||
308 | |||
309 | /* Allocate or reset and init all Tx and Command queues */ | ||
310 | if (!priv->txq) { | ||
311 | ret = iwl_txq_ctx_alloc(priv); | ||
312 | if (ret) | ||
313 | return ret; | ||
314 | } else | ||
315 | iwl_txq_ctx_reset(priv); | ||
316 | |||
317 | set_bit(STATUS_INIT, &priv->status); | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | EXPORT_SYMBOL(iwl_hw_nic_init); | ||
322 | |||
323 | /* | 224 | /* |
324 | * QoS support | 225 | * QoS support |
325 | */ | 226 | */ |
326 | void iwl_activate_qos(struct iwl_priv *priv, u8 force) | 227 | static void iwl_update_qos(struct iwl_priv *priv) |
327 | { | 228 | { |
328 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 229 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
329 | return; | 230 | return; |
330 | 231 | ||
331 | priv->qos_data.def_qos_parm.qos_flags = 0; | 232 | priv->qos_data.def_qos_parm.qos_flags = 0; |
332 | 233 | ||
333 | if (priv->qos_data.qos_cap.q_AP.queue_request && | ||
334 | !priv->qos_data.qos_cap.q_AP.txop_request) | ||
335 | priv->qos_data.def_qos_parm.qos_flags |= | ||
336 | QOS_PARAM_FLG_TXOP_TYPE_MSK; | ||
337 | if (priv->qos_data.qos_active) | 234 | if (priv->qos_data.qos_active) |
338 | priv->qos_data.def_qos_parm.qos_flags |= | 235 | priv->qos_data.def_qos_parm.qos_flags |= |
339 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; | 236 | QOS_PARAM_FLG_UPDATE_EDCA_MSK; |
@@ -341,118 +238,14 @@ void iwl_activate_qos(struct iwl_priv *priv, u8 force) | |||
341 | if (priv->current_ht_config.is_ht) | 238 | if (priv->current_ht_config.is_ht) |
342 | priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; | 239 | priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; |
343 | 240 | ||
344 | if (force || iwl_is_associated(priv)) { | 241 | IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", |
345 | IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", | 242 | priv->qos_data.qos_active, |
346 | priv->qos_data.qos_active, | 243 | priv->qos_data.def_qos_parm.qos_flags); |
347 | priv->qos_data.def_qos_parm.qos_flags); | ||
348 | |||
349 | iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, | ||
350 | sizeof(struct iwl_qosparam_cmd), | ||
351 | &priv->qos_data.def_qos_parm, NULL); | ||
352 | } | ||
353 | } | ||
354 | EXPORT_SYMBOL(iwl_activate_qos); | ||
355 | |||
356 | /* | ||
357 | * AC CWmin CW max AIFSN TXOP Limit TXOP Limit | ||
358 | * (802.11b) (802.11a/g) | ||
359 | * AC_BK 15 1023 7 0 0 | ||
360 | * AC_BE 15 1023 3 0 0 | ||
361 | * AC_VI 7 15 2 6.016ms 3.008ms | ||
362 | * AC_VO 3 7 2 3.264ms 1.504ms | ||
363 | */ | ||
364 | void iwl_reset_qos(struct iwl_priv *priv) | ||
365 | { | ||
366 | u16 cw_min = 15; | ||
367 | u16 cw_max = 1023; | ||
368 | u8 aifs = 2; | ||
369 | bool is_legacy = false; | ||
370 | unsigned long flags; | ||
371 | int i; | ||
372 | |||
373 | spin_lock_irqsave(&priv->lock, flags); | ||
374 | /* QoS always active in AP and ADHOC mode | ||
375 | * In STA mode wait for association | ||
376 | */ | ||
377 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC || | ||
378 | priv->iw_mode == NL80211_IFTYPE_AP) | ||
379 | priv->qos_data.qos_active = 1; | ||
380 | else | ||
381 | priv->qos_data.qos_active = 0; | ||
382 | |||
383 | /* check for legacy mode */ | ||
384 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC && | ||
385 | (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) || | ||
386 | (priv->iw_mode == NL80211_IFTYPE_STATION && | ||
387 | (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) { | ||
388 | cw_min = 31; | ||
389 | is_legacy = 1; | ||
390 | } | ||
391 | |||
392 | if (priv->qos_data.qos_active) | ||
393 | aifs = 3; | ||
394 | |||
395 | /* AC_BE */ | ||
396 | priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); | ||
397 | priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); | ||
398 | priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; | ||
399 | priv->qos_data.def_qos_parm.ac[0].edca_txop = 0; | ||
400 | priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; | ||
401 | |||
402 | if (priv->qos_data.qos_active) { | ||
403 | /* AC_BK */ | ||
404 | i = 1; | ||
405 | priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); | ||
406 | priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); | ||
407 | priv->qos_data.def_qos_parm.ac[i].aifsn = 7; | ||
408 | priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; | ||
409 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
410 | |||
411 | /* AC_VI */ | ||
412 | i = 2; | ||
413 | priv->qos_data.def_qos_parm.ac[i].cw_min = | ||
414 | cpu_to_le16((cw_min + 1) / 2 - 1); | ||
415 | priv->qos_data.def_qos_parm.ac[i].cw_max = | ||
416 | cpu_to_le16(cw_min); | ||
417 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; | ||
418 | if (is_legacy) | ||
419 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
420 | cpu_to_le16(6016); | ||
421 | else | ||
422 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
423 | cpu_to_le16(3008); | ||
424 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
425 | |||
426 | /* AC_VO */ | ||
427 | i = 3; | ||
428 | priv->qos_data.def_qos_parm.ac[i].cw_min = | ||
429 | cpu_to_le16((cw_min + 1) / 4 - 1); | ||
430 | priv->qos_data.def_qos_parm.ac[i].cw_max = | ||
431 | cpu_to_le16((cw_min + 1) / 2 - 1); | ||
432 | priv->qos_data.def_qos_parm.ac[i].aifsn = 2; | ||
433 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
434 | if (is_legacy) | ||
435 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
436 | cpu_to_le16(3264); | ||
437 | else | ||
438 | priv->qos_data.def_qos_parm.ac[i].edca_txop = | ||
439 | cpu_to_le16(1504); | ||
440 | } else { | ||
441 | for (i = 1; i < 4; i++) { | ||
442 | priv->qos_data.def_qos_parm.ac[i].cw_min = | ||
443 | cpu_to_le16(cw_min); | ||
444 | priv->qos_data.def_qos_parm.ac[i].cw_max = | ||
445 | cpu_to_le16(cw_max); | ||
446 | priv->qos_data.def_qos_parm.ac[i].aifsn = aifs; | ||
447 | priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; | ||
448 | priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; | ||
449 | } | ||
450 | } | ||
451 | IWL_DEBUG_QOS(priv, "set QoS to default \n"); | ||
452 | 244 | ||
453 | spin_unlock_irqrestore(&priv->lock, flags); | 245 | iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, |
246 | sizeof(struct iwl_qosparam_cmd), | ||
247 | &priv->qos_data.def_qos_parm, NULL); | ||
454 | } | 248 | } |
455 | EXPORT_SYMBOL(iwl_reset_qos); | ||
456 | 249 | ||
457 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ | 250 | #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ |
458 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ | 251 | #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ |
@@ -1092,12 +885,12 @@ void iwl_set_rxon_chain(struct iwl_priv *priv) | |||
1092 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; | 885 | rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; |
1093 | 886 | ||
1094 | /* copied from 'iwl_bg_request_scan()' */ | 887 | /* copied from 'iwl_bg_request_scan()' */ |
1095 | /* Force use of chains B and C (0x6) for Rx for 4965 | 888 | /* Force use of chains B and C (0x6) for Rx |
1096 | * Avoid A (0x1) because of its off-channel reception on A-band. | 889 | * Avoid A (0x1) for the device has off-channel reception on A-band. |
1097 | * MIMO is not used here, but value is required */ | 890 | * MIMO is not used here, but value is required */ |
1098 | if (iwl_is_monitor_mode(priv) && | 891 | if (iwl_is_monitor_mode(priv) && |
1099 | !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && | 892 | !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && |
1100 | ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) { | 893 | priv->cfg->off_channel_workaround) { |
1101 | rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; | 894 | rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; |
1102 | rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; | 895 | rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; |
1103 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; | 896 | rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; |
@@ -1584,10 +1377,11 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | |||
1584 | int ret = 0; | 1377 | int ret = 0; |
1585 | s8 prev_tx_power = priv->tx_power_user_lmt; | 1378 | s8 prev_tx_power = priv->tx_power_user_lmt; |
1586 | 1379 | ||
1587 | if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) { | 1380 | if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) { |
1588 | IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n", | 1381 | IWL_WARN(priv, |
1382 | "Requested user TXPOWER %d below lower limit %d.\n", | ||
1589 | tx_power, | 1383 | tx_power, |
1590 | IWL_TX_POWER_TARGET_POWER_MIN); | 1384 | IWLAGN_TX_POWER_TARGET_POWER_MIN); |
1591 | return -EINVAL; | 1385 | return -EINVAL; |
1592 | } | 1386 | } |
1593 | 1387 | ||
@@ -1631,10 +1425,11 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) | |||
1631 | struct iwl_priv *priv = data; | 1425 | struct iwl_priv *priv = data; |
1632 | u32 inta, inta_mask; | 1426 | u32 inta, inta_mask; |
1633 | u32 inta_fh; | 1427 | u32 inta_fh; |
1428 | unsigned long flags; | ||
1634 | if (!priv) | 1429 | if (!priv) |
1635 | return IRQ_NONE; | 1430 | return IRQ_NONE; |
1636 | 1431 | ||
1637 | spin_lock(&priv->lock); | 1432 | spin_lock_irqsave(&priv->lock, flags); |
1638 | 1433 | ||
1639 | /* Disable (but don't clear!) interrupts here to avoid | 1434 | /* Disable (but don't clear!) interrupts here to avoid |
1640 | * back-to-back ISRs and sporadic interrupts from our NIC. | 1435 | * back-to-back ISRs and sporadic interrupts from our NIC. |
@@ -1672,7 +1467,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) | |||
1672 | tasklet_schedule(&priv->irq_tasklet); | 1467 | tasklet_schedule(&priv->irq_tasklet); |
1673 | 1468 | ||
1674 | unplugged: | 1469 | unplugged: |
1675 | spin_unlock(&priv->lock); | 1470 | spin_unlock_irqrestore(&priv->lock, flags); |
1676 | return IRQ_HANDLED; | 1471 | return IRQ_HANDLED; |
1677 | 1472 | ||
1678 | none: | 1473 | none: |
@@ -1680,7 +1475,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data) | |||
1680 | /* only Re-enable if diabled by irq */ | 1475 | /* only Re-enable if diabled by irq */ |
1681 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) | 1476 | if (test_bit(STATUS_INT_ENABLED, &priv->status)) |
1682 | iwl_enable_interrupts(priv); | 1477 | iwl_enable_interrupts(priv); |
1683 | spin_unlock(&priv->lock); | 1478 | spin_unlock_irqrestore(&priv->lock, flags); |
1684 | return IRQ_NONE; | 1479 | return IRQ_NONE; |
1685 | } | 1480 | } |
1686 | EXPORT_SYMBOL(iwl_isr_legacy); | 1481 | EXPORT_SYMBOL(iwl_isr_legacy); |
@@ -1993,12 +1788,6 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1993 | cpu_to_le16((params->txop * 32)); | 1788 | cpu_to_le16((params->txop * 32)); |
1994 | 1789 | ||
1995 | priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; | 1790 | priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; |
1996 | priv->qos_data.qos_active = 1; | ||
1997 | |||
1998 | if (priv->iw_mode == NL80211_IFTYPE_AP) | ||
1999 | iwl_activate_qos(priv, 1); | ||
2000 | else if (priv->assoc_id && iwl_is_associated(priv)) | ||
2001 | iwl_activate_qos(priv, 0); | ||
2002 | 1791 | ||
2003 | spin_unlock_irqrestore(&priv->lock, flags); | 1792 | spin_unlock_irqrestore(&priv->lock, flags); |
2004 | 1793 | ||
@@ -2013,7 +1802,7 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
2013 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 1802 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2014 | struct ieee80211_sta *sta; | 1803 | struct ieee80211_sta *sta; |
2015 | 1804 | ||
2016 | IWL_DEBUG_MAC80211(priv, "enter: \n"); | 1805 | IWL_DEBUG_MAC80211(priv, "enter:\n"); |
2017 | 1806 | ||
2018 | if (!ht_conf->is_ht) | 1807 | if (!ht_conf->is_ht) |
2019 | return; | 1808 | return; |
@@ -2269,11 +2058,8 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2269 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2058 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2270 | spin_unlock_irqrestore(&priv->lock, flags); | 2059 | spin_unlock_irqrestore(&priv->lock, flags); |
2271 | 2060 | ||
2272 | iwl_reset_qos(priv); | ||
2273 | |||
2274 | priv->cfg->ops->lib->post_associate(priv); | 2061 | priv->cfg->ops->lib->post_associate(priv); |
2275 | 2062 | ||
2276 | |||
2277 | return 0; | 2063 | return 0; |
2278 | } | 2064 | } |
2279 | EXPORT_SYMBOL(iwl_mac_beacon_update); | 2065 | EXPORT_SYMBOL(iwl_mac_beacon_update); |
@@ -2495,6 +2281,15 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2495 | iwl_set_tx_power(priv, conf->power_level, false); | 2281 | iwl_set_tx_power(priv, conf->power_level, false); |
2496 | } | 2282 | } |
2497 | 2283 | ||
2284 | if (changed & IEEE80211_CONF_CHANGE_QOS) { | ||
2285 | bool qos_active = !!(conf->flags & IEEE80211_CONF_QOS); | ||
2286 | |||
2287 | spin_lock_irqsave(&priv->lock, flags); | ||
2288 | priv->qos_data.qos_active = qos_active; | ||
2289 | iwl_update_qos(priv); | ||
2290 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2291 | } | ||
2292 | |||
2498 | if (!iwl_is_ready(priv)) { | 2293 | if (!iwl_is_ready(priv)) { |
2499 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); | 2294 | IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); |
2500 | goto out; | 2295 | goto out; |
@@ -2529,8 +2324,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2529 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); | 2324 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); |
2530 | spin_unlock_irqrestore(&priv->lock, flags); | 2325 | spin_unlock_irqrestore(&priv->lock, flags); |
2531 | 2326 | ||
2532 | iwl_reset_qos(priv); | ||
2533 | |||
2534 | spin_lock_irqsave(&priv->lock, flags); | 2327 | spin_lock_irqsave(&priv->lock, flags); |
2535 | priv->assoc_id = 0; | 2328 | priv->assoc_id = 0; |
2536 | priv->assoc_capability = 0; | 2329 | priv->assoc_capability = 0; |
@@ -2574,7 +2367,7 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv) | |||
2574 | sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, | 2367 | sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues, |
2575 | GFP_KERNEL); | 2368 | GFP_KERNEL); |
2576 | if (!priv->txq) { | 2369 | if (!priv->txq) { |
2577 | IWL_ERR(priv, "Not enough memory for txq \n"); | 2370 | IWL_ERR(priv, "Not enough memory for txq\n"); |
2578 | return -ENOMEM; | 2371 | return -ENOMEM; |
2579 | } | 2372 | } |
2580 | return 0; | 2373 | return 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f3b6c72d82cd..d89755f5031a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -305,6 +305,9 @@ struct iwl_cfg { | |||
305 | s32 chain_noise_scale; | 305 | s32 chain_noise_scale; |
306 | /* timer period for monitor the driver queues */ | 306 | /* timer period for monitor the driver queues */ |
307 | u32 monitor_recover_period; | 307 | u32 monitor_recover_period; |
308 | bool temperature_kelvin; | ||
309 | bool off_channel_workaround; | ||
310 | u32 max_event_log_size; | ||
308 | }; | 311 | }; |
309 | 312 | ||
310 | /*************************** | 313 | /*************************** |
@@ -314,8 +317,7 @@ struct iwl_cfg { | |||
314 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, | 317 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, |
315 | struct ieee80211_ops *hw_ops); | 318 | struct ieee80211_ops *hw_ops); |
316 | void iwl_hw_detect(struct iwl_priv *priv); | 319 | void iwl_hw_detect(struct iwl_priv *priv); |
317 | void iwl_reset_qos(struct iwl_priv *priv); | 320 | void iwl_activate_qos(struct iwl_priv *priv); |
318 | void iwl_activate_qos(struct iwl_priv *priv, u8 force); | ||
319 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 321 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, |
320 | const struct ieee80211_tx_queue_params *params); | 322 | const struct ieee80211_tx_queue_params *params); |
321 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); | 323 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); |
@@ -336,7 +338,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv); | |||
336 | void iwl_configure_filter(struct ieee80211_hw *hw, | 338 | void iwl_configure_filter(struct ieee80211_hw *hw, |
337 | unsigned int changed_flags, | 339 | unsigned int changed_flags, |
338 | unsigned int *total_flags, u64 multicast); | 340 | unsigned int *total_flags, u64 multicast); |
339 | int iwl_hw_nic_init(struct iwl_priv *priv); | ||
340 | int iwl_set_hw_params(struct iwl_priv *priv); | 341 | int iwl_set_hw_params(struct iwl_priv *priv); |
341 | bool iwl_is_monitor_mode(struct iwl_priv *priv); | 342 | bool iwl_is_monitor_mode(struct iwl_priv *priv); |
342 | void iwl_post_associate(struct iwl_priv *priv); | 343 | void iwl_post_associate(struct iwl_priv *priv); |
@@ -420,21 +421,13 @@ void iwl_rx_reply_error(struct iwl_priv *priv, | |||
420 | /***************************************************** | 421 | /***************************************************** |
421 | * RX | 422 | * RX |
422 | ******************************************************/ | 423 | ******************************************************/ |
423 | void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
424 | void iwl_cmd_queue_free(struct iwl_priv *priv); | 424 | void iwl_cmd_queue_free(struct iwl_priv *priv); |
425 | int iwl_rx_queue_alloc(struct iwl_priv *priv); | 425 | int iwl_rx_queue_alloc(struct iwl_priv *priv); |
426 | void iwl_rx_handle(struct iwl_priv *priv); | 426 | void iwl_rx_handle(struct iwl_priv *priv); |
427 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | 427 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, |
428 | struct iwl_rx_queue *q); | 428 | struct iwl_rx_queue *q); |
429 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
430 | void iwl_rx_replenish(struct iwl_priv *priv); | ||
431 | void iwl_rx_replenish_now(struct iwl_priv *priv); | ||
432 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | ||
433 | void iwl_rx_queue_restock(struct iwl_priv *priv); | ||
434 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 429 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
435 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); | ||
436 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 430 | void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
437 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | ||
438 | /* Handlers */ | 431 | /* Handlers */ |
439 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 432 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
440 | struct iwl_rx_mem_buffer *rxb); | 433 | struct iwl_rx_mem_buffer *rxb); |
@@ -455,14 +448,10 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | |||
455 | /***************************************************** | 448 | /***************************************************** |
456 | * TX | 449 | * TX |
457 | ******************************************************/ | 450 | ******************************************************/ |
458 | int iwl_txq_ctx_alloc(struct iwl_priv *priv); | ||
459 | void iwl_txq_ctx_reset(struct iwl_priv *priv); | ||
460 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 451 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
461 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 452 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, |
462 | struct iwl_tx_queue *txq, | 453 | struct iwl_tx_queue *txq, |
463 | dma_addr_t addr, u16 len, u8 reset, u8 pad); | 454 | dma_addr_t addr, u16 len, u8 reset, u8 pad); |
464 | int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | ||
465 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv); | ||
466 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | 455 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, |
467 | struct iwl_tx_queue *txq); | 456 | struct iwl_tx_queue *txq); |
468 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | 457 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, |
@@ -473,9 +462,6 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
473 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 462 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
474 | int slots_num, u32 txq_id); | 463 | int slots_num, u32 txq_id); |
475 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 464 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
476 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | ||
477 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | ||
478 | int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); | ||
479 | /***************************************************** | 465 | /***************************************************** |
480 | * TX power | 466 | * TX power |
481 | ****************************************************/ | 467 | ****************************************************/ |
@@ -485,10 +471,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); | |||
485 | * Rate | 471 | * Rate |
486 | ******************************************************************************/ | 472 | ******************************************************************************/ |
487 | 473 | ||
488 | void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | ||
489 | struct ieee80211_tx_info *info); | ||
490 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); | 474 | int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); |
491 | int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | ||
492 | 475 | ||
493 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); | 476 | u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); |
494 | 477 | ||
@@ -688,12 +671,6 @@ extern int iwl_send_statistics_request(struct iwl_priv *priv, | |||
688 | extern int iwl_verify_ucode(struct iwl_priv *priv); | 671 | extern int iwl_verify_ucode(struct iwl_priv *priv); |
689 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, | 672 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, |
690 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); | 673 | struct iwl_link_quality_cmd *lq, u8 flags, bool init); |
691 | extern void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
692 | struct iwl_rx_mem_buffer *rxb); | ||
693 | extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
694 | struct iwl_rx_mem_buffer *rxb); | ||
695 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
696 | struct iwl_rx_mem_buffer *rxb); | ||
697 | void iwl_apm_stop(struct iwl_priv *priv); | 674 | void iwl_apm_stop(struct iwl_priv *priv); |
698 | int iwl_apm_init(struct iwl_priv *priv); | 675 | int iwl_apm_init(struct iwl_priv *priv); |
699 | 676 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e847e6197a3d..9466e909f553 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #include "iwl-debug.h" | 43 | #include "iwl-debug.h" |
44 | #include "iwl-4965-hw.h" | 44 | #include "iwl-4965-hw.h" |
45 | #include "iwl-3945-hw.h" | 45 | #include "iwl-3945-hw.h" |
46 | #include "iwl-agn-hw.h" | ||
46 | #include "iwl-led.h" | 47 | #include "iwl-led.h" |
47 | #include "iwl-power.h" | 48 | #include "iwl-power.h" |
48 | #include "iwl-agn-rs.h" | 49 | #include "iwl-agn-rs.h" |
@@ -57,6 +58,7 @@ extern struct iwl_cfg iwl5100_abg_cfg; | |||
57 | extern struct iwl_cfg iwl5150_agn_cfg; | 58 | extern struct iwl_cfg iwl5150_agn_cfg; |
58 | extern struct iwl_cfg iwl5150_abg_cfg; | 59 | extern struct iwl_cfg iwl5150_abg_cfg; |
59 | extern struct iwl_cfg iwl6000i_2agn_cfg; | 60 | extern struct iwl_cfg iwl6000i_2agn_cfg; |
61 | extern struct iwl_cfg iwl6000i_g2_2agn_cfg; | ||
60 | extern struct iwl_cfg iwl6000i_2abg_cfg; | 62 | extern struct iwl_cfg iwl6000i_2abg_cfg; |
61 | extern struct iwl_cfg iwl6000i_2bg_cfg; | 63 | extern struct iwl_cfg iwl6000i_2bg_cfg; |
62 | extern struct iwl_cfg iwl6000_3agn_cfg; | 64 | extern struct iwl_cfg iwl6000_3agn_cfg; |
@@ -67,45 +69,6 @@ extern struct iwl_cfg iwl1000_bg_cfg; | |||
67 | 69 | ||
68 | struct iwl_tx_queue; | 70 | struct iwl_tx_queue; |
69 | 71 | ||
70 | /* shared structures from iwl-5000.c */ | ||
71 | extern struct iwl_mod_params iwl50_mod_params; | ||
72 | extern struct iwl_ucode_ops iwl5000_ucode; | ||
73 | extern struct iwl_lib_ops iwl5000_lib; | ||
74 | extern struct iwl_hcmd_ops iwl5000_hcmd; | ||
75 | extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; | ||
76 | |||
77 | /* shared functions from iwl-5000.c */ | ||
78 | extern u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len); | ||
79 | extern u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, | ||
80 | u8 *data); | ||
81 | extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | ||
82 | __le32 *tx_flags); | ||
83 | extern int iwl5000_calc_rssi(struct iwl_priv *priv, | ||
84 | struct iwl_rx_phy_res *rx_resp); | ||
85 | extern void iwl5000_nic_config(struct iwl_priv *priv); | ||
86 | extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); | ||
87 | extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, | ||
88 | size_t offset); | ||
89 | extern void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
90 | struct iwl_tx_queue *txq, | ||
91 | u16 byte_cnt); | ||
92 | extern void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
93 | struct iwl_tx_queue *txq); | ||
94 | extern int iwl5000_load_ucode(struct iwl_priv *priv); | ||
95 | extern void iwl5000_init_alive_start(struct iwl_priv *priv); | ||
96 | extern int iwl5000_alive_notify(struct iwl_priv *priv); | ||
97 | extern int iwl5000_hw_set_hw_params(struct iwl_priv *priv); | ||
98 | extern int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | ||
99 | int tx_fifo, int sta_id, int tid, u16 ssn_idx); | ||
100 | extern int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, | ||
101 | u16 ssn_idx, u8 tx_fifo); | ||
102 | extern void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask); | ||
103 | extern void iwl5000_setup_deferred_work(struct iwl_priv *priv); | ||
104 | extern void iwl5000_rx_handler_setup(struct iwl_priv *priv); | ||
105 | extern int iwl5000_hw_valid_rtc_data_addr(u32 addr); | ||
106 | extern int iwl5000_send_tx_power(struct iwl_priv *priv); | ||
107 | extern void iwl5000_temperature(struct iwl_priv *priv); | ||
108 | |||
109 | /* CT-KILL constants */ | 72 | /* CT-KILL constants */ |
110 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ | 73 | #define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ |
111 | #define CT_KILL_THRESHOLD 114 /* in Celsius */ | 74 | #define CT_KILL_THRESHOLD 114 /* in Celsius */ |
@@ -363,13 +326,6 @@ enum { | |||
363 | 326 | ||
364 | #define DEF_CMD_PAYLOAD_SIZE 320 | 327 | #define DEF_CMD_PAYLOAD_SIZE 320 |
365 | 328 | ||
366 | /* | ||
367 | * IWL_LINK_HDR_MAX should include ieee80211_hdr, radiotap header, | ||
368 | * SNAP header and alignment. It should also be big enough for 802.11 | ||
369 | * control frames. | ||
370 | */ | ||
371 | #define IWL_LINK_HDR_MAX 64 | ||
372 | |||
373 | /** | 329 | /** |
374 | * struct iwl_device_cmd | 330 | * struct iwl_device_cmd |
375 | * | 331 | * |
@@ -521,30 +477,9 @@ struct iwl_ht_config { | |||
521 | u8 non_GF_STA_present; | 477 | u8 non_GF_STA_present; |
522 | }; | 478 | }; |
523 | 479 | ||
524 | union iwl_qos_capabity { | ||
525 | struct { | ||
526 | u8 edca_count:4; /* bit 0-3 */ | ||
527 | u8 q_ack:1; /* bit 4 */ | ||
528 | u8 queue_request:1; /* bit 5 */ | ||
529 | u8 txop_request:1; /* bit 6 */ | ||
530 | u8 reserved:1; /* bit 7 */ | ||
531 | } q_AP; | ||
532 | struct { | ||
533 | u8 acvo_APSD:1; /* bit 0 */ | ||
534 | u8 acvi_APSD:1; /* bit 1 */ | ||
535 | u8 ac_bk_APSD:1; /* bit 2 */ | ||
536 | u8 ac_be_APSD:1; /* bit 3 */ | ||
537 | u8 q_ack:1; /* bit 4 */ | ||
538 | u8 max_len:2; /* bit 5-6 */ | ||
539 | u8 more_data_ack:1; /* bit 7 */ | ||
540 | } q_STA; | ||
541 | u8 val; | ||
542 | }; | ||
543 | |||
544 | /* QoS structures */ | 480 | /* QoS structures */ |
545 | struct iwl_qos_info { | 481 | struct iwl_qos_info { |
546 | int qos_active; | 482 | int qos_active; |
547 | union iwl_qos_capabity qos_cap; | ||
548 | struct iwl_qosparam_cmd def_qos_parm; | 483 | struct iwl_qosparam_cmd def_qos_parm; |
549 | }; | 484 | }; |
550 | 485 | ||
@@ -1185,7 +1120,6 @@ struct iwl_priv { | |||
1185 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; | 1120 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; |
1186 | 1121 | ||
1187 | struct iwl_ht_config current_ht_config; | 1122 | struct iwl_ht_config current_ht_config; |
1188 | u8 last_phy_res[100]; | ||
1189 | 1123 | ||
1190 | /* Rate scaling data */ | 1124 | /* Rate scaling data */ |
1191 | u8 retry_rate; | 1125 | u8 retry_rate; |
@@ -1205,8 +1139,6 @@ struct iwl_priv { | |||
1205 | 1139 | ||
1206 | unsigned long status; | 1140 | unsigned long status; |
1207 | 1141 | ||
1208 | int last_rx_noise; /* From beacon statistics */ | ||
1209 | |||
1210 | /* counts mgmt, ctl, and data packets */ | 1142 | /* counts mgmt, ctl, and data packets */ |
1211 | struct traffic_stats tx_stats; | 1143 | struct traffic_stats tx_stats; |
1212 | struct traffic_stats rx_stats; | 1144 | struct traffic_stats rx_stats; |
@@ -1234,7 +1166,6 @@ struct iwl_priv { | |||
1234 | int num_stations; | 1166 | int num_stations; |
1235 | struct iwl_station_entry stations[IWL_STATION_COUNT]; | 1167 | struct iwl_station_entry stations[IWL_STATION_COUNT]; |
1236 | struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */ | 1168 | struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; /* protected by mutex */ |
1237 | u8 default_wep_key; | ||
1238 | u8 key_mapping_key; | 1169 | u8 key_mapping_key; |
1239 | unsigned long ucode_key_table; | 1170 | unsigned long ucode_key_table; |
1240 | 1171 | ||
@@ -1305,6 +1236,9 @@ struct iwl_priv { | |||
1305 | * no AGGREGATION | 1236 | * no AGGREGATION |
1306 | */ | 1237 | */ |
1307 | u8 agg_tids_count; | 1238 | u8 agg_tids_count; |
1239 | |||
1240 | struct iwl_rx_phy_res last_phy_res; | ||
1241 | bool last_phy_res_valid; | ||
1308 | } _agn; | 1242 | } _agn; |
1309 | #endif | 1243 | #endif |
1310 | }; | 1244 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 2ffc2edbf4f0..4a487639d932 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
@@ -37,6 +37,7 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8); | |||
37 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); | 37 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); |
38 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); | 38 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); |
39 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); | 39 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); |
40 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_tx); | ||
40 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); | 41 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); |
41 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); | 42 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); |
42 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); | 43 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_cont_event); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 4e1ba824dc50..cb6d50b78140 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -188,19 +188,19 @@ struct iwl_eeprom_enhanced_txpwr { | |||
188 | /* 5000 regulatory - indirect access */ | 188 | /* 5000 regulatory - indirect access */ |
189 | #define EEPROM_5000_REG_SKU_ID ((0x02)\ | 189 | #define EEPROM_5000_REG_SKU_ID ((0x02)\ |
190 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */ | 190 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */ |
191 | #define EEPROM_5000_REG_BAND_1_CHANNELS ((0x08)\ | 191 | #define EEPROM_REG_BAND_1_CHANNELS ((0x08)\ |
192 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ | 192 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ |
193 | #define EEPROM_5000_REG_BAND_2_CHANNELS ((0x26)\ | 193 | #define EEPROM_REG_BAND_2_CHANNELS ((0x26)\ |
194 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ | 194 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ |
195 | #define EEPROM_5000_REG_BAND_3_CHANNELS ((0x42)\ | 195 | #define EEPROM_REG_BAND_3_CHANNELS ((0x42)\ |
196 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ | 196 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ |
197 | #define EEPROM_5000_REG_BAND_4_CHANNELS ((0x5C)\ | 197 | #define EEPROM_REG_BAND_4_CHANNELS ((0x5C)\ |
198 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | 198 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ |
199 | #define EEPROM_5000_REG_BAND_5_CHANNELS ((0x74)\ | 199 | #define EEPROM_REG_BAND_5_CHANNELS ((0x74)\ |
200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ | 200 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ |
201 | #define EEPROM_5000_REG_BAND_24_HT40_CHANNELS ((0x82)\ | 201 | #define EEPROM_REG_BAND_24_HT40_CHANNELS ((0x82)\ |
202 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ | 202 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ |
203 | #define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\ | 203 | #define EEPROM_REG_BAND_52_HT40_CHANNELS ((0x92)\ |
204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ | 204 | | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ |
205 | 205 | ||
206 | /* 6000 and up regulatory tx power - indirect access */ | 206 | /* 6000 and up regulatory tx power - indirect access */ |
@@ -261,12 +261,15 @@ struct iwl_eeprom_enhanced_txpwr { | |||
261 | #define EEPROM_5050_EEPROM_VERSION (0x21E) | 261 | #define EEPROM_5050_EEPROM_VERSION (0x21E) |
262 | 262 | ||
263 | /* 1000 Specific */ | 263 | /* 1000 Specific */ |
264 | #define EEPROM_1000_TX_POWER_VERSION (4) | ||
264 | #define EEPROM_1000_EEPROM_VERSION (0x15C) | 265 | #define EEPROM_1000_EEPROM_VERSION (0x15C) |
265 | 266 | ||
266 | /* 6x00 Specific */ | 267 | /* 6x00 Specific */ |
268 | #define EEPROM_6000_TX_POWER_VERSION (4) | ||
267 | #define EEPROM_6000_EEPROM_VERSION (0x434) | 269 | #define EEPROM_6000_EEPROM_VERSION (0x434) |
268 | 270 | ||
269 | /* 6x50 Specific */ | 271 | /* 6x50 Specific */ |
272 | #define EEPROM_6050_TX_POWER_VERSION (4) | ||
270 | #define EEPROM_6050_EEPROM_VERSION (0x532) | 273 | #define EEPROM_6050_EEPROM_VERSION (0x532) |
271 | 274 | ||
272 | /* OTP */ | 275 | /* OTP */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 73681c4fefe7..51f89e7ba681 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -169,7 +169,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
169 | mutex_lock(&priv->sync_cmd_mutex); | 169 | mutex_lock(&priv->sync_cmd_mutex); |
170 | 170 | ||
171 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); | 171 | set_bit(STATUS_HCMD_ACTIVE, &priv->status); |
172 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n", | 172 | IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n", |
173 | get_cmd_string(cmd->id)); | 173 | get_cmd_string(cmd->id)); |
174 | 174 | ||
175 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); | 175 | cmd_idx = iwl_enqueue_hcmd(priv, cmd); |
@@ -191,7 +191,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
191 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); | 191 | jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); |
192 | 192 | ||
193 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 193 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
194 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | 194 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", |
195 | get_cmd_string(cmd->id)); | 195 | get_cmd_string(cmd->id)); |
196 | ret = -ETIMEDOUT; | 196 | ret = -ETIMEDOUT; |
197 | goto cancel; | 197 | goto cancel; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 16eb3ced9b30..0203a3bbf872 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -298,7 +298,7 @@ static inline u32 __iwl_read_direct32(const char *f, u32 l, | |||
298 | struct iwl_priv *priv, u32 reg) | 298 | struct iwl_priv *priv, u32 reg) |
299 | { | 299 | { |
300 | u32 value = _iwl_read_direct32(priv, reg); | 300 | u32 value = _iwl_read_direct32(priv, reg); |
301 | IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, | 301 | IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value, |
302 | f, l); | 302 | f, l); |
303 | return value; | 303 | return value; |
304 | } | 304 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index a6f9c918aabc..db5bfcb036ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -46,7 +46,7 @@ | |||
46 | static int led_mode; | 46 | static int led_mode; |
47 | module_param(led_mode, int, S_IRUGO); | 47 | module_param(led_mode, int, S_IRUGO); |
48 | MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " | 48 | MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " |
49 | "(default 0)\n"); | 49 | "(default 0)"); |
50 | 50 | ||
51 | 51 | ||
52 | static const struct { | 52 | static const struct { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 548dac2f6a96..581c683a8507 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -384,10 +384,10 @@ EXPORT_SYMBOL(iwl_ht_enabled); | |||
384 | 384 | ||
385 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | 385 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) |
386 | { | 386 | { |
387 | s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ | 387 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ |
388 | bool within_margin = false; | 388 | bool within_margin = false; |
389 | 389 | ||
390 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 390 | if (priv->cfg->temperature_kelvin) |
391 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 391 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
392 | 392 | ||
393 | if (!priv->thermal_throttle.advanced_tt) | 393 | if (!priv->thermal_throttle.advanced_tt) |
@@ -840,12 +840,12 @@ EXPORT_SYMBOL(iwl_tt_exit_ct_kill); | |||
840 | static void iwl_bg_tt_work(struct work_struct *work) | 840 | static void iwl_bg_tt_work(struct work_struct *work) |
841 | { | 841 | { |
842 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); | 842 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); |
843 | s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ | 843 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ |
844 | 844 | ||
845 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 845 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
846 | return; | 846 | return; |
847 | 847 | ||
848 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 848 | if (priv->cfg->temperature_kelvin) |
849 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 849 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
850 | 850 | ||
851 | if (!priv->thermal_throttle.advanced_tt) | 851 | if (!priv->thermal_throttle.advanced_tt) |
@@ -875,7 +875,7 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
875 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); | 875 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); |
876 | struct iwl_tt_trans *transaction; | 876 | struct iwl_tt_trans *transaction; |
877 | 877 | ||
878 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n"); | 878 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); |
879 | 879 | ||
880 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); | 880 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); |
881 | 881 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index d3b2fb389e58..267eb8935902 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -163,197 +163,6 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q | |||
163 | spin_unlock_irqrestore(&q->lock, flags); | 163 | spin_unlock_irqrestore(&q->lock, flags); |
164 | } | 164 | } |
165 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); | 165 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); |
166 | /** | ||
167 | * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | ||
168 | */ | ||
169 | static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, | ||
170 | dma_addr_t dma_addr) | ||
171 | { | ||
172 | return cpu_to_le32((u32)(dma_addr >> 8)); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * iwl_rx_queue_restock - refill RX queue from pre-allocated pool | ||
177 | * | ||
178 | * If there are slots in the RX queue that need to be restocked, | ||
179 | * and we have free pre-allocated buffers, fill the ranks as much | ||
180 | * as we can, pulling from rx_free. | ||
181 | * | ||
182 | * This moves the 'write' index forward to catch up with 'processed', and | ||
183 | * also updates the memory address in the firmware to reference the new | ||
184 | * target buffer. | ||
185 | */ | ||
186 | void iwl_rx_queue_restock(struct iwl_priv *priv) | ||
187 | { | ||
188 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
189 | struct list_head *element; | ||
190 | struct iwl_rx_mem_buffer *rxb; | ||
191 | unsigned long flags; | ||
192 | int write; | ||
193 | |||
194 | spin_lock_irqsave(&rxq->lock, flags); | ||
195 | write = rxq->write & ~0x7; | ||
196 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | ||
197 | /* Get next free Rx buffer, remove from free list */ | ||
198 | element = rxq->rx_free.next; | ||
199 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
200 | list_del(element); | ||
201 | |||
202 | /* Point to Rx buffer via next RBD in circular buffer */ | ||
203 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma); | ||
204 | rxq->queue[rxq->write] = rxb; | ||
205 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | ||
206 | rxq->free_count--; | ||
207 | } | ||
208 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
209 | /* If the pre-allocated buffer pool is dropping low, schedule to | ||
210 | * refill it */ | ||
211 | if (rxq->free_count <= RX_LOW_WATERMARK) | ||
212 | queue_work(priv->workqueue, &priv->rx_replenish); | ||
213 | |||
214 | |||
215 | /* If we've added more space for the firmware to place data, tell it. | ||
216 | * Increment device's write pointer in multiples of 8. */ | ||
217 | if (rxq->write_actual != (rxq->write & ~0x7)) { | ||
218 | spin_lock_irqsave(&rxq->lock, flags); | ||
219 | rxq->need_update = 1; | ||
220 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
221 | iwl_rx_queue_update_write_ptr(priv, rxq); | ||
222 | } | ||
223 | } | ||
224 | EXPORT_SYMBOL(iwl_rx_queue_restock); | ||
225 | |||
226 | |||
227 | /** | ||
228 | * iwl_rx_replenish - Move all used packet from rx_used to rx_free | ||
229 | * | ||
230 | * When moving to rx_free an SKB is allocated for the slot. | ||
231 | * | ||
232 | * Also restock the Rx queue via iwl_rx_queue_restock. | ||
233 | * This is called as a scheduled work item (except for during initialization) | ||
234 | */ | ||
235 | void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) | ||
236 | { | ||
237 | struct iwl_rx_queue *rxq = &priv->rxq; | ||
238 | struct list_head *element; | ||
239 | struct iwl_rx_mem_buffer *rxb; | ||
240 | struct page *page; | ||
241 | unsigned long flags; | ||
242 | gfp_t gfp_mask = priority; | ||
243 | |||
244 | while (1) { | ||
245 | spin_lock_irqsave(&rxq->lock, flags); | ||
246 | if (list_empty(&rxq->rx_used)) { | ||
247 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
248 | return; | ||
249 | } | ||
250 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
251 | |||
252 | if (rxq->free_count > RX_LOW_WATERMARK) | ||
253 | gfp_mask |= __GFP_NOWARN; | ||
254 | |||
255 | if (priv->hw_params.rx_page_order > 0) | ||
256 | gfp_mask |= __GFP_COMP; | ||
257 | |||
258 | /* Alloc a new receive buffer */ | ||
259 | page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order); | ||
260 | if (!page) { | ||
261 | if (net_ratelimit()) | ||
262 | IWL_DEBUG_INFO(priv, "alloc_pages failed, " | ||
263 | "order: %d\n", | ||
264 | priv->hw_params.rx_page_order); | ||
265 | |||
266 | if ((rxq->free_count <= RX_LOW_WATERMARK) && | ||
267 | net_ratelimit()) | ||
268 | IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n", | ||
269 | priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", | ||
270 | rxq->free_count); | ||
271 | /* We don't reschedule replenish work here -- we will | ||
272 | * call the restock method and if it still needs | ||
273 | * more buffers it will schedule replenish */ | ||
274 | return; | ||
275 | } | ||
276 | |||
277 | spin_lock_irqsave(&rxq->lock, flags); | ||
278 | |||
279 | if (list_empty(&rxq->rx_used)) { | ||
280 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
281 | __free_pages(page, priv->hw_params.rx_page_order); | ||
282 | return; | ||
283 | } | ||
284 | element = rxq->rx_used.next; | ||
285 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | ||
286 | list_del(element); | ||
287 | |||
288 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
289 | |||
290 | rxb->page = page; | ||
291 | /* Get physical address of the RB */ | ||
292 | rxb->page_dma = pci_map_page(priv->pci_dev, page, 0, | ||
293 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
294 | PCI_DMA_FROMDEVICE); | ||
295 | /* dma address must be no more than 36 bits */ | ||
296 | BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); | ||
297 | /* and also 256 byte aligned! */ | ||
298 | BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); | ||
299 | |||
300 | spin_lock_irqsave(&rxq->lock, flags); | ||
301 | |||
302 | list_add_tail(&rxb->list, &rxq->rx_free); | ||
303 | rxq->free_count++; | ||
304 | priv->alloc_rxb_page++; | ||
305 | |||
306 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | void iwl_rx_replenish(struct iwl_priv *priv) | ||
311 | { | ||
312 | unsigned long flags; | ||
313 | |||
314 | iwl_rx_allocate(priv, GFP_KERNEL); | ||
315 | |||
316 | spin_lock_irqsave(&priv->lock, flags); | ||
317 | iwl_rx_queue_restock(priv); | ||
318 | spin_unlock_irqrestore(&priv->lock, flags); | ||
319 | } | ||
320 | EXPORT_SYMBOL(iwl_rx_replenish); | ||
321 | |||
322 | void iwl_rx_replenish_now(struct iwl_priv *priv) | ||
323 | { | ||
324 | iwl_rx_allocate(priv, GFP_ATOMIC); | ||
325 | |||
326 | iwl_rx_queue_restock(priv); | ||
327 | } | ||
328 | EXPORT_SYMBOL(iwl_rx_replenish_now); | ||
329 | |||
330 | |||
331 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | ||
332 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL | ||
333 | * This free routine walks the list of POOL entries and if SKB is set to | ||
334 | * non NULL it is unmapped and freed | ||
335 | */ | ||
336 | void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
337 | { | ||
338 | int i; | ||
339 | for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { | ||
340 | if (rxq->pool[i].page != NULL) { | ||
341 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
342 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
343 | PCI_DMA_FROMDEVICE); | ||
344 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
345 | rxq->pool[i].page = NULL; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, | ||
350 | rxq->dma_addr); | ||
351 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), | ||
352 | rxq->rb_stts, rxq->rb_stts_dma); | ||
353 | rxq->bd = NULL; | ||
354 | rxq->rb_stts = NULL; | ||
355 | } | ||
356 | EXPORT_SYMBOL(iwl_rx_queue_free); | ||
357 | 166 | ||
358 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | 167 | int iwl_rx_queue_alloc(struct iwl_priv *priv) |
359 | { | 168 | { |
@@ -396,98 +205,6 @@ err_bd: | |||
396 | } | 205 | } |
397 | EXPORT_SYMBOL(iwl_rx_queue_alloc); | 206 | EXPORT_SYMBOL(iwl_rx_queue_alloc); |
398 | 207 | ||
399 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
400 | { | ||
401 | unsigned long flags; | ||
402 | int i; | ||
403 | spin_lock_irqsave(&rxq->lock, flags); | ||
404 | INIT_LIST_HEAD(&rxq->rx_free); | ||
405 | INIT_LIST_HEAD(&rxq->rx_used); | ||
406 | /* Fill the rx_used queue with _all_ of the Rx buffers */ | ||
407 | for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { | ||
408 | /* In the reset function, these buffers may have been allocated | ||
409 | * to an SKB, so we need to unmap and free potential storage */ | ||
410 | if (rxq->pool[i].page != NULL) { | ||
411 | pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma, | ||
412 | PAGE_SIZE << priv->hw_params.rx_page_order, | ||
413 | PCI_DMA_FROMDEVICE); | ||
414 | __iwl_free_pages(priv, rxq->pool[i].page); | ||
415 | rxq->pool[i].page = NULL; | ||
416 | } | ||
417 | list_add_tail(&rxq->pool[i].list, &rxq->rx_used); | ||
418 | } | ||
419 | |||
420 | /* Set us so that we have processed and used all buffers, but have | ||
421 | * not restocked the Rx queue with fresh buffers */ | ||
422 | rxq->read = rxq->write = 0; | ||
423 | rxq->write_actual = 0; | ||
424 | rxq->free_count = 0; | ||
425 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
426 | } | ||
427 | |||
428 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | ||
429 | { | ||
430 | u32 rb_size; | ||
431 | const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ | ||
432 | u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ | ||
433 | |||
434 | if (!priv->cfg->use_isr_legacy) | ||
435 | rb_timeout = RX_RB_TIMEOUT; | ||
436 | |||
437 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
438 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; | ||
439 | else | ||
440 | rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; | ||
441 | |||
442 | /* Stop Rx DMA */ | ||
443 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
444 | |||
445 | /* Reset driver's Rx queue write index */ | ||
446 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); | ||
447 | |||
448 | /* Tell device where to find RBD circular buffer in DRAM */ | ||
449 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, | ||
450 | (u32)(rxq->dma_addr >> 8)); | ||
451 | |||
452 | /* Tell device where in DRAM to update its Rx status */ | ||
453 | iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, | ||
454 | rxq->rb_stts_dma >> 4); | ||
455 | |||
456 | /* Enable Rx DMA | ||
457 | * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in | ||
458 | * the credit mechanism in 5000 HW RX FIFO | ||
459 | * Direct rx interrupts to hosts | ||
460 | * Rx buffer size 4 or 8k | ||
461 | * RB timeout 0x10 | ||
462 | * 256 RBDs | ||
463 | */ | ||
464 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, | ||
465 | FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | | ||
466 | FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | | ||
467 | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | | ||
468 | FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | | ||
469 | rb_size| | ||
470 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | ||
471 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | ||
472 | |||
473 | /* Set interrupt coalescing timer to default (2048 usecs) */ | ||
474 | iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF); | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | int iwl_rxq_stop(struct iwl_priv *priv) | ||
480 | { | ||
481 | |||
482 | /* stop Rx DMA */ | ||
483 | iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); | ||
484 | iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, | ||
485 | FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | EXPORT_SYMBOL(iwl_rxq_stop); | ||
490 | |||
491 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | 208 | void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, |
492 | struct iwl_rx_mem_buffer *rxb) | 209 | struct iwl_rx_mem_buffer *rxb) |
493 | 210 | ||
@@ -543,6 +260,7 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
543 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; | 260 | le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; |
544 | int bcn_silence_c = | 261 | int bcn_silence_c = |
545 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; | 262 | le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; |
263 | int last_rx_noise; | ||
546 | 264 | ||
547 | if (bcn_silence_a) { | 265 | if (bcn_silence_a) { |
548 | total_silence += bcn_silence_a; | 266 | total_silence += bcn_silence_a; |
@@ -559,13 +277,13 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) | |||
559 | 277 | ||
560 | /* Average among active antennas */ | 278 | /* Average among active antennas */ |
561 | if (num_active_rx) | 279 | if (num_active_rx) |
562 | priv->last_rx_noise = (total_silence / num_active_rx) - 107; | 280 | last_rx_noise = (total_silence / num_active_rx) - 107; |
563 | else | 281 | else |
564 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 282 | last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; |
565 | 283 | ||
566 | IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", | 284 | IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", |
567 | bcn_silence_a, bcn_silence_b, bcn_silence_c, | 285 | bcn_silence_a, bcn_silence_b, bcn_silence_c, |
568 | priv->last_rx_noise); | 286 | last_rx_noise); |
569 | } | 287 | } |
570 | 288 | ||
571 | #ifdef CONFIG_IWLWIFI_DEBUG | 289 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -617,63 +335,6 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
617 | 335 | ||
618 | #define REG_RECALIB_PERIOD (60) | 336 | #define REG_RECALIB_PERIOD (60) |
619 | 337 | ||
620 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | ||
621 | #define ACK_CNT_RATIO (50) | ||
622 | #define BA_TIMEOUT_CNT (5) | ||
623 | #define BA_TIMEOUT_MAX (16) | ||
624 | |||
625 | #if defined(CONFIG_IWLAGN) || defined(CONFIG_IWLAGN_MODULE) | ||
626 | /** | ||
627 | * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries. | ||
628 | * | ||
629 | * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding | ||
630 | * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal | ||
631 | * operation state. | ||
632 | */ | ||
633 | bool iwl_good_ack_health(struct iwl_priv *priv, | ||
634 | struct iwl_rx_packet *pkt) | ||
635 | { | ||
636 | bool rc = true; | ||
637 | int actual_ack_cnt_delta, expected_ack_cnt_delta; | ||
638 | int ba_timeout_delta; | ||
639 | |||
640 | actual_ack_cnt_delta = | ||
641 | le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - | ||
642 | le32_to_cpu(priv->statistics.tx.actual_ack_cnt); | ||
643 | expected_ack_cnt_delta = | ||
644 | le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) - | ||
645 | le32_to_cpu(priv->statistics.tx.expected_ack_cnt); | ||
646 | ba_timeout_delta = | ||
647 | le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) - | ||
648 | le32_to_cpu(priv->statistics.tx.agg.ba_timeout); | ||
649 | if ((priv->_agn.agg_tids_count > 0) && | ||
650 | (expected_ack_cnt_delta > 0) && | ||
651 | (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) | ||
652 | < ACK_CNT_RATIO) && | ||
653 | (ba_timeout_delta > BA_TIMEOUT_CNT)) { | ||
654 | IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d," | ||
655 | " expected_ack_cnt = %d\n", | ||
656 | actual_ack_cnt_delta, expected_ack_cnt_delta); | ||
657 | |||
658 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
659 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | ||
660 | priv->delta_statistics.tx.rx_detected_cnt); | ||
661 | IWL_DEBUG_RADIO(priv, | ||
662 | "ack_or_ba_timeout_collision delta = %d\n", | ||
663 | priv->delta_statistics.tx. | ||
664 | ack_or_ba_timeout_collision); | ||
665 | #endif | ||
666 | IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", | ||
667 | ba_timeout_delta); | ||
668 | if (!actual_ack_cnt_delta && | ||
669 | (ba_timeout_delta >= BA_TIMEOUT_MAX)) | ||
670 | rc = false; | ||
671 | } | ||
672 | return rc; | ||
673 | } | ||
674 | EXPORT_SYMBOL(iwl_good_ack_health); | ||
675 | #endif | ||
676 | |||
677 | /** | 338 | /** |
678 | * iwl_good_plcp_health - checks for plcp error. | 339 | * iwl_good_plcp_health - checks for plcp error. |
679 | * | 340 | * |
@@ -830,139 +491,6 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
830 | } | 491 | } |
831 | EXPORT_SYMBOL(iwl_reply_statistics); | 492 | EXPORT_SYMBOL(iwl_reply_statistics); |
832 | 493 | ||
833 | /* Calc max signal level (dBm) among 3 possible receivers */ | ||
834 | static inline int iwl_calc_rssi(struct iwl_priv *priv, | ||
835 | struct iwl_rx_phy_res *rx_resp) | ||
836 | { | ||
837 | return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); | ||
838 | } | ||
839 | |||
840 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
841 | /** | ||
842 | * iwl_dbg_report_frame - dump frame to syslog during debug sessions | ||
843 | * | ||
844 | * You may hack this function to show different aspects of received frames, | ||
845 | * including selective frame dumps. | ||
846 | * group100 parameter selects whether to show 1 out of 100 good data frames. | ||
847 | * All beacon and probe response frames are printed. | ||
848 | */ | ||
849 | static void iwl_dbg_report_frame(struct iwl_priv *priv, | ||
850 | struct iwl_rx_phy_res *phy_res, u16 length, | ||
851 | struct ieee80211_hdr *header, int group100) | ||
852 | { | ||
853 | u32 to_us; | ||
854 | u32 print_summary = 0; | ||
855 | u32 print_dump = 0; /* set to 1 to dump all frames' contents */ | ||
856 | u32 hundred = 0; | ||
857 | u32 dataframe = 0; | ||
858 | __le16 fc; | ||
859 | u16 seq_ctl; | ||
860 | u16 channel; | ||
861 | u16 phy_flags; | ||
862 | u32 rate_n_flags; | ||
863 | u32 tsf_low; | ||
864 | int rssi; | ||
865 | |||
866 | if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) | ||
867 | return; | ||
868 | |||
869 | /* MAC header */ | ||
870 | fc = header->frame_control; | ||
871 | seq_ctl = le16_to_cpu(header->seq_ctrl); | ||
872 | |||
873 | /* metadata */ | ||
874 | channel = le16_to_cpu(phy_res->channel); | ||
875 | phy_flags = le16_to_cpu(phy_res->phy_flags); | ||
876 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
877 | |||
878 | /* signal statistics */ | ||
879 | rssi = iwl_calc_rssi(priv, phy_res); | ||
880 | tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; | ||
881 | |||
882 | to_us = !compare_ether_addr(header->addr1, priv->mac_addr); | ||
883 | |||
884 | /* if data frame is to us and all is good, | ||
885 | * (optionally) print summary for only 1 out of every 100 */ | ||
886 | if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == | ||
887 | cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { | ||
888 | dataframe = 1; | ||
889 | if (!group100) | ||
890 | print_summary = 1; /* print each frame */ | ||
891 | else if (priv->framecnt_to_us < 100) { | ||
892 | priv->framecnt_to_us++; | ||
893 | print_summary = 0; | ||
894 | } else { | ||
895 | priv->framecnt_to_us = 0; | ||
896 | print_summary = 1; | ||
897 | hundred = 1; | ||
898 | } | ||
899 | } else { | ||
900 | /* print summary for all other frames */ | ||
901 | print_summary = 1; | ||
902 | } | ||
903 | |||
904 | if (print_summary) { | ||
905 | char *title; | ||
906 | int rate_idx; | ||
907 | u32 bitrate; | ||
908 | |||
909 | if (hundred) | ||
910 | title = "100Frames"; | ||
911 | else if (ieee80211_has_retry(fc)) | ||
912 | title = "Retry"; | ||
913 | else if (ieee80211_is_assoc_resp(fc)) | ||
914 | title = "AscRsp"; | ||
915 | else if (ieee80211_is_reassoc_resp(fc)) | ||
916 | title = "RasRsp"; | ||
917 | else if (ieee80211_is_probe_resp(fc)) { | ||
918 | title = "PrbRsp"; | ||
919 | print_dump = 1; /* dump frame contents */ | ||
920 | } else if (ieee80211_is_beacon(fc)) { | ||
921 | title = "Beacon"; | ||
922 | print_dump = 1; /* dump frame contents */ | ||
923 | } else if (ieee80211_is_atim(fc)) | ||
924 | title = "ATIM"; | ||
925 | else if (ieee80211_is_auth(fc)) | ||
926 | title = "Auth"; | ||
927 | else if (ieee80211_is_deauth(fc)) | ||
928 | title = "DeAuth"; | ||
929 | else if (ieee80211_is_disassoc(fc)) | ||
930 | title = "DisAssoc"; | ||
931 | else | ||
932 | title = "Frame"; | ||
933 | |||
934 | rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | ||
935 | if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { | ||
936 | bitrate = 0; | ||
937 | WARN_ON_ONCE(1); | ||
938 | } else { | ||
939 | bitrate = iwl_rates[rate_idx].ieee / 2; | ||
940 | } | ||
941 | |||
942 | /* print frame summary. | ||
943 | * MAC addresses show just the last byte (for brevity), | ||
944 | * but you can hack it to show more, if you'd like to. */ | ||
945 | if (dataframe) | ||
946 | IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " | ||
947 | "len=%u, rssi=%d, chnl=%d, rate=%u, \n", | ||
948 | title, le16_to_cpu(fc), header->addr1[5], | ||
949 | length, rssi, channel, bitrate); | ||
950 | else { | ||
951 | /* src/dst addresses assume managed mode */ | ||
952 | IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " | ||
953 | "len=%u, rssi=%d, tim=%lu usec, " | ||
954 | "phy=0x%02x, chnl=%d\n", | ||
955 | title, le16_to_cpu(fc), header->addr1[5], | ||
956 | header->addr3[5], length, rssi, | ||
957 | tsf_low - priv->scan_start_tsf, | ||
958 | phy_flags, channel); | ||
959 | } | ||
960 | } | ||
961 | if (print_dump) | ||
962 | iwl_print_hex_dump(priv, IWL_DL_RX, header, length); | ||
963 | } | ||
964 | #endif | ||
965 | |||
966 | /* | 494 | /* |
967 | * returns non-zero if packet should be dropped | 495 | * returns non-zero if packet should be dropped |
968 | */ | 496 | */ |
@@ -1010,281 +538,3 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
1010 | return 0; | 538 | return 0; |
1011 | } | 539 | } |
1012 | EXPORT_SYMBOL(iwl_set_decrypted_flag); | 540 | EXPORT_SYMBOL(iwl_set_decrypted_flag); |
1013 | |||
1014 | static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | ||
1015 | { | ||
1016 | u32 decrypt_out = 0; | ||
1017 | |||
1018 | if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == | ||
1019 | RX_RES_STATUS_STATION_FOUND) | ||
1020 | decrypt_out |= (RX_RES_STATUS_STATION_FOUND | | ||
1021 | RX_RES_STATUS_NO_STATION_INFO_MISMATCH); | ||
1022 | |||
1023 | decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); | ||
1024 | |||
1025 | /* packet was not encrypted */ | ||
1026 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
1027 | RX_RES_STATUS_SEC_TYPE_NONE) | ||
1028 | return decrypt_out; | ||
1029 | |||
1030 | /* packet was encrypted with unknown alg */ | ||
1031 | if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == | ||
1032 | RX_RES_STATUS_SEC_TYPE_ERR) | ||
1033 | return decrypt_out; | ||
1034 | |||
1035 | /* decryption was not done in HW */ | ||
1036 | if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != | ||
1037 | RX_MPDU_RES_STATUS_DEC_DONE_MSK) | ||
1038 | return decrypt_out; | ||
1039 | |||
1040 | switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { | ||
1041 | |||
1042 | case RX_RES_STATUS_SEC_TYPE_CCMP: | ||
1043 | /* alg is CCM: check MIC only */ | ||
1044 | if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) | ||
1045 | /* Bad MIC */ | ||
1046 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
1047 | else | ||
1048 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
1049 | |||
1050 | break; | ||
1051 | |||
1052 | case RX_RES_STATUS_SEC_TYPE_TKIP: | ||
1053 | if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { | ||
1054 | /* Bad TTAK */ | ||
1055 | decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; | ||
1056 | break; | ||
1057 | } | ||
1058 | /* fall through if TTAK OK */ | ||
1059 | default: | ||
1060 | if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) | ||
1061 | decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; | ||
1062 | else | ||
1063 | decrypt_out |= RX_RES_STATUS_DECRYPT_OK; | ||
1064 | break; | ||
1065 | }; | ||
1066 | |||
1067 | IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", | ||
1068 | decrypt_in, decrypt_out); | ||
1069 | |||
1070 | return decrypt_out; | ||
1071 | } | ||
1072 | |||
1073 | static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | ||
1074 | struct ieee80211_hdr *hdr, | ||
1075 | u16 len, | ||
1076 | u32 ampdu_status, | ||
1077 | struct iwl_rx_mem_buffer *rxb, | ||
1078 | struct ieee80211_rx_status *stats) | ||
1079 | { | ||
1080 | struct sk_buff *skb; | ||
1081 | int ret = 0; | ||
1082 | __le16 fc = hdr->frame_control; | ||
1083 | |||
1084 | /* We only process data packets if the interface is open */ | ||
1085 | if (unlikely(!priv->is_open)) { | ||
1086 | IWL_DEBUG_DROP_LIMIT(priv, | ||
1087 | "Dropping packet while interface is not open.\n"); | ||
1088 | return; | ||
1089 | } | ||
1090 | |||
1091 | /* In case of HW accelerated crypto and bad decryption, drop */ | ||
1092 | if (!priv->cfg->mod_params->sw_crypto && | ||
1093 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | ||
1094 | return; | ||
1095 | |||
1096 | skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC); | ||
1097 | if (!skb) { | ||
1098 | IWL_ERR(priv, "alloc_skb failed\n"); | ||
1099 | return; | ||
1100 | } | ||
1101 | |||
1102 | skb_reserve(skb, IWL_LINK_HDR_MAX); | ||
1103 | skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len); | ||
1104 | |||
1105 | /* mac80211 currently doesn't support paged SKB. Convert it to | ||
1106 | * linear SKB for management frame and data frame requires | ||
1107 | * software decryption or software defragementation. */ | ||
1108 | if (ieee80211_is_mgmt(fc) || | ||
1109 | ieee80211_has_protected(fc) || | ||
1110 | ieee80211_has_morefrags(fc) || | ||
1111 | le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG || | ||
1112 | (ieee80211_is_data_qos(fc) && | ||
1113 | *ieee80211_get_qos_ctl(hdr) & | ||
1114 | IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)) | ||
1115 | ret = skb_linearize(skb); | ||
1116 | else | ||
1117 | ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ? | ||
1118 | 0 : -ENOMEM; | ||
1119 | |||
1120 | if (ret) { | ||
1121 | kfree_skb(skb); | ||
1122 | goto out; | ||
1123 | } | ||
1124 | |||
1125 | /* | ||
1126 | * XXX: We cannot touch the page and its virtual memory (hdr) after | ||
1127 | * here. It might have already been freed by the above skb change. | ||
1128 | */ | ||
1129 | |||
1130 | iwl_update_stats(priv, false, fc, len); | ||
1131 | memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); | ||
1132 | |||
1133 | ieee80211_rx(priv->hw, skb); | ||
1134 | out: | ||
1135 | priv->alloc_rxb_page--; | ||
1136 | rxb->page = NULL; | ||
1137 | } | ||
1138 | |||
1139 | /* Called for REPLY_RX (legacy ABG frames), or | ||
1140 | * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ | ||
1141 | void iwl_rx_reply_rx(struct iwl_priv *priv, | ||
1142 | struct iwl_rx_mem_buffer *rxb) | ||
1143 | { | ||
1144 | struct ieee80211_hdr *header; | ||
1145 | struct ieee80211_rx_status rx_status; | ||
1146 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1147 | struct iwl_rx_phy_res *phy_res; | ||
1148 | __le32 rx_pkt_status; | ||
1149 | struct iwl4965_rx_mpdu_res_start *amsdu; | ||
1150 | u32 len; | ||
1151 | u32 ampdu_status; | ||
1152 | u32 rate_n_flags; | ||
1153 | |||
1154 | /** | ||
1155 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
1156 | * REPLY_RX: physical layer info is in this buffer | ||
1157 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
1158 | * command and cached in priv->last_phy_res | ||
1159 | * | ||
1160 | * Here we set up local variables depending on which command is | ||
1161 | * received. | ||
1162 | */ | ||
1163 | if (pkt->hdr.cmd == REPLY_RX) { | ||
1164 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
1165 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
1166 | + phy_res->cfg_phy_cnt); | ||
1167 | |||
1168 | len = le16_to_cpu(phy_res->byte_count); | ||
1169 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
1170 | phy_res->cfg_phy_cnt + len); | ||
1171 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
1172 | } else { | ||
1173 | if (!priv->last_phy_res[0]) { | ||
1174 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
1175 | return; | ||
1176 | } | ||
1177 | phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; | ||
1178 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1179 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
1180 | len = le16_to_cpu(amsdu->byte_count); | ||
1181 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
1182 | ampdu_status = iwl_translate_rx_status(priv, | ||
1183 | le32_to_cpu(rx_pkt_status)); | ||
1184 | } | ||
1185 | |||
1186 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
1187 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
1188 | phy_res->cfg_phy_cnt); | ||
1189 | return; | ||
1190 | } | ||
1191 | |||
1192 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1193 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1194 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1195 | le32_to_cpu(rx_pkt_status)); | ||
1196 | return; | ||
1197 | } | ||
1198 | |||
1199 | /* This will be used in several places later */ | ||
1200 | rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); | ||
1201 | |||
1202 | /* rx_status carries information about the packet to mac80211 */ | ||
1203 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
1204 | rx_status.freq = | ||
1205 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); | ||
1206 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | ||
1207 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1208 | rx_status.rate_idx = | ||
1209 | iwl_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); | ||
1210 | rx_status.flag = 0; | ||
1211 | |||
1212 | /* TSF isn't reliable. In order to allow smooth user experience, | ||
1213 | * this W/A doesn't propagate it to the mac80211 */ | ||
1214 | /*rx_status.flag |= RX_FLAG_TSFT;*/ | ||
1215 | |||
1216 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); | ||
1217 | |||
1218 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | ||
1219 | rx_status.signal = iwl_calc_rssi(priv, phy_res); | ||
1220 | |||
1221 | /* Meaningful noise values are available only from beacon statistics, | ||
1222 | * which are gathered only when associated, and indicate noise | ||
1223 | * only for the associated network channel ... | ||
1224 | * Ignore these noise values while scanning (other channels) */ | ||
1225 | if (iwl_is_associated(priv) && | ||
1226 | !test_bit(STATUS_SCANNING, &priv->status)) { | ||
1227 | rx_status.noise = priv->last_rx_noise; | ||
1228 | } else { | ||
1229 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1230 | } | ||
1231 | |||
1232 | /* Reset beacon noise level if not associated. */ | ||
1233 | if (!iwl_is_associated(priv)) | ||
1234 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | ||
1235 | |||
1236 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1237 | /* Set "1" to report good data frames in groups of 100 */ | ||
1238 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | ||
1239 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); | ||
1240 | #endif | ||
1241 | iwl_dbg_log_rx_data_frame(priv, len, header); | ||
1242 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", | ||
1243 | rx_status.signal, rx_status.noise, | ||
1244 | (unsigned long long)rx_status.mactime); | ||
1245 | |||
1246 | /* | ||
1247 | * "antenna number" | ||
1248 | * | ||
1249 | * It seems that the antenna field in the phy flags value | ||
1250 | * is actually a bit field. This is undefined by radiotap, | ||
1251 | * it wants an actual antenna number but I always get "7" | ||
1252 | * for most legacy frames I receive indicating that the | ||
1253 | * same frame was received on all three RX chains. | ||
1254 | * | ||
1255 | * I think this field should be removed in favor of a | ||
1256 | * new 802.11n radiotap field "RX chains" that is defined | ||
1257 | * as a bitmask. | ||
1258 | */ | ||
1259 | rx_status.antenna = | ||
1260 | (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) | ||
1261 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1262 | |||
1263 | /* set the preamble flag if appropriate */ | ||
1264 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | ||
1265 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
1266 | |||
1267 | /* Set up the HT phy flags */ | ||
1268 | if (rate_n_flags & RATE_MCS_HT_MSK) | ||
1269 | rx_status.flag |= RX_FLAG_HT; | ||
1270 | if (rate_n_flags & RATE_MCS_HT40_MSK) | ||
1271 | rx_status.flag |= RX_FLAG_40MHZ; | ||
1272 | if (rate_n_flags & RATE_MCS_SGI_MSK) | ||
1273 | rx_status.flag |= RX_FLAG_SHORT_GI; | ||
1274 | |||
1275 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1276 | rxb, &rx_status); | ||
1277 | } | ||
1278 | EXPORT_SYMBOL(iwl_rx_reply_rx); | ||
1279 | |||
1280 | /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). | ||
1281 | * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ | ||
1282 | void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | ||
1283 | struct iwl_rx_mem_buffer *rxb) | ||
1284 | { | ||
1285 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1286 | priv->last_phy_res[0] = 1; | ||
1287 | memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), | ||
1288 | sizeof(struct iwl_rx_phy_res)); | ||
1289 | } | ||
1290 | EXPORT_SYMBOL(iwl_rx_reply_rx_phy); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index e8e4b5493e89..ae981932ce61 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -454,7 +454,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
454 | added++; | 454 | added++; |
455 | } | 455 | } |
456 | 456 | ||
457 | IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); | 457 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); |
458 | return added; | 458 | return added; |
459 | } | 459 | } |
460 | 460 | ||
@@ -814,10 +814,11 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
814 | */ | 814 | */ |
815 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; | 815 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; |
816 | 816 | ||
817 | /* Force use of chains B and C (0x6) for scan Rx for 4965 | 817 | /* Force use of chains B and C (0x6) for scan Rx |
818 | * Avoid A (0x1) because of its off-channel reception on A-band. | 818 | * Avoid A (0x1) for the device has off-channel reception |
819 | * on A-band. | ||
819 | */ | 820 | */ |
820 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 821 | if (priv->cfg->off_channel_workaround) |
821 | rx_ant = ANT_BC; | 822 | rx_ant = ANT_BC; |
822 | } else { | 823 | } else { |
823 | IWL_WARN(priv, "Invalid scan band count\n"); | 824 | IWL_WARN(priv, "Invalid scan band count\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index d401b6f226f9..d86ecd2f9ec2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -71,7 +71,7 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) | |||
71 | (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || | 71 | (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || |
72 | ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && | 72 | ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && |
73 | (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { | 73 | (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { |
74 | IWL_ERR(priv, "Requested station info for sta %d before ready. \n", | 74 | IWL_ERR(priv, "Requested station info for sta %d before ready.\n", |
75 | ret); | 75 | ret); |
76 | ret = IWL_INVALID_STATION; | 76 | ret = IWL_INVALID_STATION; |
77 | } | 77 | } |
@@ -143,7 +143,7 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv, | |||
143 | sta_id); | 143 | sta_id); |
144 | break; | 144 | break; |
145 | case ADD_STA_MODIFY_NON_EXIST_STA: | 145 | case ADD_STA_MODIFY_NON_EXIST_STA: |
146 | IWL_ERR(priv, "Attempting to modify non-existing station %d \n", | 146 | IWL_ERR(priv, "Attempting to modify non-existing station %d\n", |
147 | sta_id); | 147 | sta_id); |
148 | break; | 148 | break; |
149 | default: | 149 | default: |
@@ -194,7 +194,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
194 | .flags = flags, | 194 | .flags = flags, |
195 | .data = data, | 195 | .data = data, |
196 | }; | 196 | }; |
197 | u8 sta_id = sta->sta.sta_id; | 197 | u8 sta_id __maybe_unused = sta->sta.sta_id; |
198 | 198 | ||
199 | IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", | 199 | IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", |
200 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); | 200 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); |
@@ -425,6 +425,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) | |||
425 | .reserved1 = 0, | 425 | .reserved1 = 0, |
426 | }; | 426 | }; |
427 | u32 rate_flags; | 427 | u32 rate_flags; |
428 | int ret = 0; | ||
428 | 429 | ||
429 | /* Set up the rate scaling to start at selected rate, fall back | 430 | /* Set up the rate scaling to start at selected rate, fall back |
430 | * all the way down to 1M in IEEE order, and then spin on 1M */ | 431 | * all the way down to 1M in IEEE order, and then spin on 1M */ |
@@ -458,8 +459,10 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) | |||
458 | /* Update the rate scaling for control frame Tx to AP */ | 459 | /* Update the rate scaling for control frame Tx to AP */ |
459 | link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; | 460 | link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; |
460 | 461 | ||
461 | iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, | 462 | ret = iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, |
462 | sizeof(link_cmd), &link_cmd); | 463 | sizeof(link_cmd), &link_cmd); |
464 | if (ret) | ||
465 | IWL_ERR(priv, "REPLY_TX_LINK_QUALITY_CMD failed (%d)\n", ret); | ||
463 | } | 466 | } |
464 | 467 | ||
465 | /* | 468 | /* |
@@ -571,7 +574,7 @@ static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) | |||
571 | 574 | ||
572 | if (!iwl_is_ready(priv)) { | 575 | if (!iwl_is_ready(priv)) { |
573 | IWL_DEBUG_INFO(priv, | 576 | IWL_DEBUG_INFO(priv, |
574 | "Unable to remove station %pM, device not ready. \n", | 577 | "Unable to remove station %pM, device not ready.\n", |
575 | sta->addr); | 578 | sta->addr); |
576 | /* | 579 | /* |
577 | * It is typical for stations to be removed when we are | 580 | * It is typical for stations to be removed when we are |
@@ -668,7 +671,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force) | |||
668 | } else { | 671 | } else { |
669 | for (i = 0; i < priv->hw_params.max_stations; i++) { | 672 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
670 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { | 673 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { |
671 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d \n", i); | 674 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); |
672 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; | 675 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; |
673 | cleared = true; | 676 | cleared = true; |
674 | } | 677 | } |
@@ -759,7 +762,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | |||
759 | } | 762 | } |
760 | EXPORT_SYMBOL(iwl_get_free_ucode_key_index); | 763 | EXPORT_SYMBOL(iwl_get_free_ucode_key_index); |
761 | 764 | ||
762 | int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | 765 | static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) |
763 | { | 766 | { |
764 | int i, not_empty = 0; | 767 | int i, not_empty = 0; |
765 | u8 buff[sizeof(struct iwl_wep_cmd) + | 768 | u8 buff[sizeof(struct iwl_wep_cmd) + |
@@ -803,7 +806,14 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) | |||
803 | else | 806 | else |
804 | return 0; | 807 | return 0; |
805 | } | 808 | } |
806 | EXPORT_SYMBOL(iwl_send_static_wepkey_cmd); | 809 | |
810 | int iwl_restore_default_wep_keys(struct iwl_priv *priv) | ||
811 | { | ||
812 | WARN_ON(!mutex_is_locked(&priv->mutex)); | ||
813 | |||
814 | return iwl_send_static_wepkey_cmd(priv, 0); | ||
815 | } | ||
816 | EXPORT_SYMBOL(iwl_restore_default_wep_keys); | ||
807 | 817 | ||
808 | int iwl_remove_default_wep_key(struct iwl_priv *priv, | 818 | int iwl_remove_default_wep_key(struct iwl_priv *priv, |
809 | struct ieee80211_key_conf *keyconf) | 819 | struct ieee80211_key_conf *keyconf) |
@@ -815,11 +825,6 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, | |||
815 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", | 825 | IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", |
816 | keyconf->keyidx); | 826 | keyconf->keyidx); |
817 | 827 | ||
818 | if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) | ||
819 | IWL_ERR(priv, "index %d not used in uCode key table.\n", | ||
820 | keyconf->keyidx); | ||
821 | |||
822 | priv->default_wep_key--; | ||
823 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); | 828 | memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); |
824 | if (iwl_is_rfkill(priv)) { | 829 | if (iwl_is_rfkill(priv)) { |
825 | IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); | 830 | IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); |
@@ -851,12 +856,6 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
851 | keyconf->hw_key_idx = HW_KEY_DEFAULT; | 856 | keyconf->hw_key_idx = HW_KEY_DEFAULT; |
852 | priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; | 857 | priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; |
853 | 858 | ||
854 | priv->default_wep_key++; | ||
855 | |||
856 | if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) | ||
857 | IWL_ERR(priv, "index %d already used in uCode key table.\n", | ||
858 | keyconf->keyidx); | ||
859 | |||
860 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; | 859 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; |
861 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, | 860 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, |
862 | keyconf->keylen); | 861 | keyconf->keylen); |
@@ -1105,7 +1104,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, | |||
1105 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1104 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1106 | 1105 | ||
1107 | if (iwl_is_rfkill(priv)) { | 1106 | if (iwl_is_rfkill(priv)) { |
1108 | IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n"); | 1107 | IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n"); |
1109 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1108 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1110 | return 0; | 1109 | return 0; |
1111 | } | 1110 | } |
@@ -1191,13 +1190,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
1191 | .data = lq, | 1190 | .data = lq, |
1192 | }; | 1191 | }; |
1193 | 1192 | ||
1194 | if ((lq->sta_id == 0xFF) && | 1193 | if (WARN_ON(lq->sta_id == IWL_INVALID_STATION)) |
1195 | (priv->iw_mode == NL80211_IFTYPE_ADHOC)) | ||
1196 | return -EINVAL; | 1194 | return -EINVAL; |
1197 | 1195 | ||
1198 | if (lq->sta_id == 0xFF) | ||
1199 | lq->sta_id = IWL_AP_ID; | ||
1200 | |||
1201 | iwl_dump_lq_cmd(priv, lq); | 1196 | iwl_dump_lq_cmd(priv, lq); |
1202 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); | 1197 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); |
1203 | 1198 | ||
@@ -1207,7 +1202,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
1207 | return ret; | 1202 | return ret; |
1208 | 1203 | ||
1209 | if (init) { | 1204 | if (init) { |
1210 | IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d \n", | 1205 | IWL_DEBUG_INFO(priv, "init LQ command complete, clearing sta addition status for sta %d\n", |
1211 | lq->sta_id); | 1206 | lq->sta_id); |
1212 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 1207 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
1213 | priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | 1208 | priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; |
@@ -1395,6 +1390,7 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) | |||
1395 | 1390 | ||
1396 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1391 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1397 | } | 1392 | } |
1393 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); | ||
1398 | 1394 | ||
1399 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, | 1395 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, |
1400 | struct ieee80211_vif *vif, | 1396 | struct ieee80211_vif *vif, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 87a34997a758..42cd2f4a01cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -44,11 +44,11 @@ | |||
44 | */ | 44 | */ |
45 | u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); | 45 | u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); |
46 | 46 | ||
47 | int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); | ||
48 | int iwl_remove_default_wep_key(struct iwl_priv *priv, | 47 | int iwl_remove_default_wep_key(struct iwl_priv *priv, |
49 | struct ieee80211_key_conf *key); | 48 | struct ieee80211_key_conf *key); |
50 | int iwl_set_default_wep_key(struct iwl_priv *priv, | 49 | int iwl_set_default_wep_key(struct iwl_priv *priv, |
51 | struct ieee80211_key_conf *key); | 50 | struct ieee80211_key_conf *key); |
51 | int iwl_restore_default_wep_keys(struct iwl_priv *priv); | ||
52 | int iwl_set_dynamic_key(struct iwl_priv *priv, | 52 | int iwl_set_dynamic_key(struct iwl_priv *priv, |
53 | struct ieee80211_key_conf *key, u8 sta_id); | 53 | struct ieee80211_key_conf *key, u8 sta_id); |
54 | int iwl_remove_dynamic_key(struct iwl_priv *priv, | 54 | int iwl_remove_dynamic_key(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index b798fbabc3b6..1ece2ea09773 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -38,84 +38,6 @@ | |||
38 | #include "iwl-io.h" | 38 | #include "iwl-io.h" |
39 | #include "iwl-helpers.h" | 39 | #include "iwl-helpers.h" |
40 | 40 | ||
41 | /* | ||
42 | * mac80211 queues, ACs, hardware queues, FIFOs. | ||
43 | * | ||
44 | * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues | ||
45 | * | ||
46 | * Mac80211 uses the following numbers, which we get as from it | ||
47 | * by way of skb_get_queue_mapping(skb): | ||
48 | * | ||
49 | * VO 0 | ||
50 | * VI 1 | ||
51 | * BE 2 | ||
52 | * BK 3 | ||
53 | * | ||
54 | * | ||
55 | * Regular (not A-MPDU) frames are put into hardware queues corresponding | ||
56 | * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their | ||
57 | * own queue per aggregation session (RA/TID combination), such queues are | ||
58 | * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In | ||
59 | * order to map frames to the right queue, we also need an AC->hw queue | ||
60 | * mapping. This is implemented here. | ||
61 | * | ||
62 | * Due to the way hw queues are set up (by the hw specific modules like | ||
63 | * iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity | ||
64 | * mapping. | ||
65 | */ | ||
66 | |||
67 | static const u8 tid_to_ac[] = { | ||
68 | /* this matches the mac80211 numbers */ | ||
69 | 2, 3, 3, 2, 1, 1, 0, 0 | ||
70 | }; | ||
71 | |||
72 | static const u8 ac_to_fifo[] = { | ||
73 | IWL_TX_FIFO_VO, | ||
74 | IWL_TX_FIFO_VI, | ||
75 | IWL_TX_FIFO_BE, | ||
76 | IWL_TX_FIFO_BK, | ||
77 | }; | ||
78 | |||
79 | static inline int get_fifo_from_ac(u8 ac) | ||
80 | { | ||
81 | return ac_to_fifo[ac]; | ||
82 | } | ||
83 | |||
84 | static inline int get_queue_from_ac(u16 ac) | ||
85 | { | ||
86 | return ac; | ||
87 | } | ||
88 | |||
89 | static inline int get_fifo_from_tid(u16 tid) | ||
90 | { | ||
91 | if (likely(tid < ARRAY_SIZE(tid_to_ac))) | ||
92 | return get_fifo_from_ac(tid_to_ac[tid]); | ||
93 | |||
94 | /* no support for TIDs 8-15 yet */ | ||
95 | return -EINVAL; | ||
96 | } | ||
97 | |||
98 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, | ||
99 | struct iwl_dma_ptr *ptr, size_t size) | ||
100 | { | ||
101 | ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, | ||
102 | GFP_KERNEL); | ||
103 | if (!ptr->addr) | ||
104 | return -ENOMEM; | ||
105 | ptr->size = size; | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static inline void iwl_free_dma_ptr(struct iwl_priv *priv, | ||
110 | struct iwl_dma_ptr *ptr) | ||
111 | { | ||
112 | if (unlikely(!ptr->addr)) | ||
113 | return; | ||
114 | |||
115 | dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); | ||
116 | memset(ptr, 0, sizeof(*ptr)); | ||
117 | } | ||
118 | |||
119 | /** | 41 | /** |
120 | * iwl_txq_update_write_ptr - Send new write index to hardware | 42 | * iwl_txq_update_write_ptr - Send new write index to hardware |
121 | */ | 43 | */ |
@@ -493,598 +415,6 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
493 | } | 415 | } |
494 | EXPORT_SYMBOL(iwl_tx_queue_reset); | 416 | EXPORT_SYMBOL(iwl_tx_queue_reset); |
495 | 417 | ||
496 | /** | ||
497 | * iwl_hw_txq_ctx_free - Free TXQ Context | ||
498 | * | ||
499 | * Destroy all TX DMA queues and structures | ||
500 | */ | ||
501 | void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | ||
502 | { | ||
503 | int txq_id; | ||
504 | |||
505 | /* Tx queues */ | ||
506 | if (priv->txq) { | ||
507 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
508 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
509 | iwl_cmd_queue_free(priv); | ||
510 | else | ||
511 | iwl_tx_queue_free(priv, txq_id); | ||
512 | } | ||
513 | iwl_free_dma_ptr(priv, &priv->kw); | ||
514 | |||
515 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
516 | |||
517 | /* free tx queue structure */ | ||
518 | iwl_free_txq_mem(priv); | ||
519 | } | ||
520 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | ||
521 | |||
522 | /** | ||
523 | * iwl_txq_ctx_alloc - allocate TX queue context | ||
524 | * Allocate all Tx DMA structures and initialize them | ||
525 | * | ||
526 | * @param priv | ||
527 | * @return error code | ||
528 | */ | ||
529 | int iwl_txq_ctx_alloc(struct iwl_priv *priv) | ||
530 | { | ||
531 | int ret; | ||
532 | int txq_id, slots_num; | ||
533 | unsigned long flags; | ||
534 | |||
535 | /* Free all tx/cmd queues and keep-warm buffer */ | ||
536 | iwl_hw_txq_ctx_free(priv); | ||
537 | |||
538 | ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
539 | priv->hw_params.scd_bc_tbls_size); | ||
540 | if (ret) { | ||
541 | IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); | ||
542 | goto error_bc_tbls; | ||
543 | } | ||
544 | /* Alloc keep-warm buffer */ | ||
545 | ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); | ||
546 | if (ret) { | ||
547 | IWL_ERR(priv, "Keep Warm allocation failed\n"); | ||
548 | goto error_kw; | ||
549 | } | ||
550 | |||
551 | /* allocate tx queue structure */ | ||
552 | ret = iwl_alloc_txq_mem(priv); | ||
553 | if (ret) | ||
554 | goto error; | ||
555 | |||
556 | spin_lock_irqsave(&priv->lock, flags); | ||
557 | |||
558 | /* Turn off all Tx DMA fifos */ | ||
559 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
560 | |||
561 | /* Tell NIC where to find the "keep warm" buffer */ | ||
562 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
563 | |||
564 | spin_unlock_irqrestore(&priv->lock, flags); | ||
565 | |||
566 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
567 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
568 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | ||
569 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
570 | ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, | ||
571 | txq_id); | ||
572 | if (ret) { | ||
573 | IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); | ||
574 | goto error; | ||
575 | } | ||
576 | } | ||
577 | |||
578 | return ret; | ||
579 | |||
580 | error: | ||
581 | iwl_hw_txq_ctx_free(priv); | ||
582 | iwl_free_dma_ptr(priv, &priv->kw); | ||
583 | error_kw: | ||
584 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
585 | error_bc_tbls: | ||
586 | return ret; | ||
587 | } | ||
588 | |||
589 | void iwl_txq_ctx_reset(struct iwl_priv *priv) | ||
590 | { | ||
591 | int txq_id, slots_num; | ||
592 | unsigned long flags; | ||
593 | |||
594 | spin_lock_irqsave(&priv->lock, flags); | ||
595 | |||
596 | /* Turn off all Tx DMA fifos */ | ||
597 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
598 | |||
599 | /* Tell NIC where to find the "keep warm" buffer */ | ||
600 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
601 | |||
602 | spin_unlock_irqrestore(&priv->lock, flags); | ||
603 | |||
604 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
605 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
606 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | ||
607 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
608 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | /** | ||
613 | * iwl_txq_ctx_stop - Stop all Tx DMA channels | ||
614 | */ | ||
615 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | ||
616 | { | ||
617 | int ch; | ||
618 | unsigned long flags; | ||
619 | |||
620 | /* Turn off all Tx DMA fifos */ | ||
621 | spin_lock_irqsave(&priv->lock, flags); | ||
622 | |||
623 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
624 | |||
625 | /* Stop each Tx DMA channel, and wait for it to be idle */ | ||
626 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | ||
627 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); | ||
628 | iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, | ||
629 | FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), | ||
630 | 1000); | ||
631 | } | ||
632 | spin_unlock_irqrestore(&priv->lock, flags); | ||
633 | } | ||
634 | EXPORT_SYMBOL(iwl_txq_ctx_stop); | ||
635 | |||
636 | /* | ||
637 | * handle build REPLY_TX command notification. | ||
638 | */ | ||
639 | static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, | ||
640 | struct iwl_tx_cmd *tx_cmd, | ||
641 | struct ieee80211_tx_info *info, | ||
642 | struct ieee80211_hdr *hdr, | ||
643 | u8 std_id) | ||
644 | { | ||
645 | __le16 fc = hdr->frame_control; | ||
646 | __le32 tx_flags = tx_cmd->tx_flags; | ||
647 | |||
648 | tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
649 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | ||
650 | tx_flags |= TX_CMD_FLG_ACK_MSK; | ||
651 | if (ieee80211_is_mgmt(fc)) | ||
652 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
653 | if (ieee80211_is_probe_resp(fc) && | ||
654 | !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) | ||
655 | tx_flags |= TX_CMD_FLG_TSF_MSK; | ||
656 | } else { | ||
657 | tx_flags &= (~TX_CMD_FLG_ACK_MSK); | ||
658 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
659 | } | ||
660 | |||
661 | if (ieee80211_is_back_req(fc)) | ||
662 | tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; | ||
663 | |||
664 | |||
665 | tx_cmd->sta_id = std_id; | ||
666 | if (ieee80211_has_morefrags(fc)) | ||
667 | tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; | ||
668 | |||
669 | if (ieee80211_is_data_qos(fc)) { | ||
670 | u8 *qc = ieee80211_get_qos_ctl(hdr); | ||
671 | tx_cmd->tid_tspec = qc[0] & 0xf; | ||
672 | tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; | ||
673 | } else { | ||
674 | tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; | ||
675 | } | ||
676 | |||
677 | priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); | ||
678 | |||
679 | if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) | ||
680 | tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; | ||
681 | |||
682 | tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); | ||
683 | if (ieee80211_is_mgmt(fc)) { | ||
684 | if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) | ||
685 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); | ||
686 | else | ||
687 | tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); | ||
688 | } else { | ||
689 | tx_cmd->timeout.pm_frame_timeout = 0; | ||
690 | } | ||
691 | |||
692 | tx_cmd->driver_txop = 0; | ||
693 | tx_cmd->tx_flags = tx_flags; | ||
694 | tx_cmd->next_frame_len = 0; | ||
695 | } | ||
696 | |||
697 | #define RTS_DFAULT_RETRY_LIMIT 60 | ||
698 | |||
699 | static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, | ||
700 | struct iwl_tx_cmd *tx_cmd, | ||
701 | struct ieee80211_tx_info *info, | ||
702 | __le16 fc) | ||
703 | { | ||
704 | u32 rate_flags; | ||
705 | int rate_idx; | ||
706 | u8 rts_retry_limit; | ||
707 | u8 data_retry_limit; | ||
708 | u8 rate_plcp; | ||
709 | |||
710 | /* Set retry limit on DATA packets and Probe Responses*/ | ||
711 | if (ieee80211_is_probe_resp(fc)) | ||
712 | data_retry_limit = 3; | ||
713 | else | ||
714 | data_retry_limit = IWL_DEFAULT_TX_RETRY; | ||
715 | tx_cmd->data_retry_limit = data_retry_limit; | ||
716 | |||
717 | /* Set retry limit on RTS packets */ | ||
718 | rts_retry_limit = RTS_DFAULT_RETRY_LIMIT; | ||
719 | if (data_retry_limit < rts_retry_limit) | ||
720 | rts_retry_limit = data_retry_limit; | ||
721 | tx_cmd->rts_retry_limit = rts_retry_limit; | ||
722 | |||
723 | /* DATA packets will use the uCode station table for rate/antenna | ||
724 | * selection */ | ||
725 | if (ieee80211_is_data(fc)) { | ||
726 | tx_cmd->initial_rate_index = 0; | ||
727 | tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; | ||
728 | return; | ||
729 | } | ||
730 | |||
731 | /** | ||
732 | * If the current TX rate stored in mac80211 has the MCS bit set, it's | ||
733 | * not really a TX rate. Thus, we use the lowest supported rate for | ||
734 | * this band. Also use the lowest supported rate if the stored rate | ||
735 | * index is invalid. | ||
736 | */ | ||
737 | rate_idx = info->control.rates[0].idx; | ||
738 | if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || | ||
739 | (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) | ||
740 | rate_idx = rate_lowest_index(&priv->bands[info->band], | ||
741 | info->control.sta); | ||
742 | /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ | ||
743 | if (info->band == IEEE80211_BAND_5GHZ) | ||
744 | rate_idx += IWL_FIRST_OFDM_RATE; | ||
745 | /* Get PLCP rate for tx_cmd->rate_n_flags */ | ||
746 | rate_plcp = iwl_rates[rate_idx].plcp; | ||
747 | /* Zero out flags for this packet */ | ||
748 | rate_flags = 0; | ||
749 | |||
750 | /* Set CCK flag as needed */ | ||
751 | if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) | ||
752 | rate_flags |= RATE_MCS_CCK_MSK; | ||
753 | |||
754 | /* Set up RTS and CTS flags for certain packets */ | ||
755 | switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { | ||
756 | case cpu_to_le16(IEEE80211_STYPE_AUTH): | ||
757 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): | ||
758 | case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): | ||
759 | case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): | ||
760 | if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { | ||
761 | tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; | ||
762 | tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; | ||
763 | } | ||
764 | break; | ||
765 | default: | ||
766 | break; | ||
767 | } | ||
768 | |||
769 | /* Set up antennas */ | ||
770 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); | ||
771 | rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
772 | |||
773 | /* Set the rate in the TX cmd */ | ||
774 | tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); | ||
775 | } | ||
776 | |||
777 | static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | ||
778 | struct ieee80211_tx_info *info, | ||
779 | struct iwl_tx_cmd *tx_cmd, | ||
780 | struct sk_buff *skb_frag, | ||
781 | int sta_id) | ||
782 | { | ||
783 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | ||
784 | |||
785 | switch (keyconf->alg) { | ||
786 | case ALG_CCMP: | ||
787 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | ||
788 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | ||
789 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
790 | tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; | ||
791 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | ||
792 | break; | ||
793 | |||
794 | case ALG_TKIP: | ||
795 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | ||
796 | ieee80211_get_tkip_key(keyconf, skb_frag, | ||
797 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); | ||
798 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | ||
799 | break; | ||
800 | |||
801 | case ALG_WEP: | ||
802 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | | ||
803 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | ||
804 | |||
805 | if (keyconf->keylen == WEP_KEY_LEN_128) | ||
806 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
807 | |||
808 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | ||
809 | |||
810 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | ||
811 | "with key %d\n", keyconf->keyidx); | ||
812 | break; | ||
813 | |||
814 | default: | ||
815 | IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); | ||
816 | break; | ||
817 | } | ||
818 | } | ||
819 | |||
820 | /* | ||
821 | * start REPLY_TX command process | ||
822 | */ | ||
823 | int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | ||
824 | { | ||
825 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
826 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
827 | struct ieee80211_sta *sta = info->control.sta; | ||
828 | struct iwl_station_priv *sta_priv = NULL; | ||
829 | struct iwl_tx_queue *txq; | ||
830 | struct iwl_queue *q; | ||
831 | struct iwl_device_cmd *out_cmd; | ||
832 | struct iwl_cmd_meta *out_meta; | ||
833 | struct iwl_tx_cmd *tx_cmd; | ||
834 | int swq_id, txq_id; | ||
835 | dma_addr_t phys_addr; | ||
836 | dma_addr_t txcmd_phys; | ||
837 | dma_addr_t scratch_phys; | ||
838 | u16 len, len_org, firstlen, secondlen; | ||
839 | u16 seq_number = 0; | ||
840 | __le16 fc; | ||
841 | u8 hdr_len; | ||
842 | u8 sta_id; | ||
843 | u8 wait_write_ptr = 0; | ||
844 | u8 tid = 0; | ||
845 | u8 *qc = NULL; | ||
846 | unsigned long flags; | ||
847 | |||
848 | spin_lock_irqsave(&priv->lock, flags); | ||
849 | if (iwl_is_rfkill(priv)) { | ||
850 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | ||
851 | goto drop_unlock; | ||
852 | } | ||
853 | |||
854 | fc = hdr->frame_control; | ||
855 | |||
856 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
857 | if (ieee80211_is_auth(fc)) | ||
858 | IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); | ||
859 | else if (ieee80211_is_assoc_req(fc)) | ||
860 | IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); | ||
861 | else if (ieee80211_is_reassoc_req(fc)) | ||
862 | IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); | ||
863 | #endif | ||
864 | |||
865 | hdr_len = ieee80211_hdrlen(fc); | ||
866 | |||
867 | /* Find (or create) index into station table for destination station */ | ||
868 | if (info->flags & IEEE80211_TX_CTL_INJECTED) | ||
869 | sta_id = priv->hw_params.bcast_sta_id; | ||
870 | else | ||
871 | sta_id = iwl_get_sta_id(priv, hdr); | ||
872 | if (sta_id == IWL_INVALID_STATION) { | ||
873 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | ||
874 | hdr->addr1); | ||
875 | goto drop_unlock; | ||
876 | } | ||
877 | |||
878 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | ||
879 | |||
880 | if (sta) | ||
881 | sta_priv = (void *)sta->drv_priv; | ||
882 | |||
883 | if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && | ||
884 | sta_priv->asleep) { | ||
885 | WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); | ||
886 | /* | ||
887 | * This sends an asynchronous command to the device, | ||
888 | * but we can rely on it being processed before the | ||
889 | * next frame is processed -- and the next frame to | ||
890 | * this station is the one that will consume this | ||
891 | * counter. | ||
892 | * For now set the counter to just 1 since we do not | ||
893 | * support uAPSD yet. | ||
894 | */ | ||
895 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | ||
896 | } | ||
897 | |||
898 | txq_id = get_queue_from_ac(skb_get_queue_mapping(skb)); | ||
899 | if (ieee80211_is_data_qos(fc)) { | ||
900 | qc = ieee80211_get_qos_ctl(hdr); | ||
901 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
902 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
903 | goto drop_unlock; | ||
904 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | ||
905 | seq_number &= IEEE80211_SCTL_SEQ; | ||
906 | hdr->seq_ctrl = hdr->seq_ctrl & | ||
907 | cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
908 | hdr->seq_ctrl |= cpu_to_le16(seq_number); | ||
909 | seq_number += 0x10; | ||
910 | /* aggregation is on for this <sta,tid> */ | ||
911 | if (info->flags & IEEE80211_TX_CTL_AMPDU && | ||
912 | priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { | ||
913 | txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; | ||
914 | } | ||
915 | } | ||
916 | |||
917 | txq = &priv->txq[txq_id]; | ||
918 | swq_id = txq->swq_id; | ||
919 | q = &txq->q; | ||
920 | |||
921 | if (unlikely(iwl_queue_space(q) < q->high_mark)) | ||
922 | goto drop_unlock; | ||
923 | |||
924 | if (ieee80211_is_data_qos(fc)) | ||
925 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
926 | |||
927 | /* Set up driver data for this TFD */ | ||
928 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | ||
929 | txq->txb[q->write_ptr].skb[0] = skb; | ||
930 | |||
931 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | ||
932 | out_cmd = txq->cmd[q->write_ptr]; | ||
933 | out_meta = &txq->meta[q->write_ptr]; | ||
934 | tx_cmd = &out_cmd->cmd.tx; | ||
935 | memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); | ||
936 | memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); | ||
937 | |||
938 | /* | ||
939 | * Set up the Tx-command (not MAC!) header. | ||
940 | * Store the chosen Tx queue and TFD index within the sequence field; | ||
941 | * after Tx, uCode's Tx response will return this value so driver can | ||
942 | * locate the frame within the tx queue and do post-tx processing. | ||
943 | */ | ||
944 | out_cmd->hdr.cmd = REPLY_TX; | ||
945 | out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | ||
946 | INDEX_TO_SEQ(q->write_ptr))); | ||
947 | |||
948 | /* Copy MAC header from skb into command buffer */ | ||
949 | memcpy(tx_cmd->hdr, hdr, hdr_len); | ||
950 | |||
951 | |||
952 | /* Total # bytes to be transmitted */ | ||
953 | len = (u16)skb->len; | ||
954 | tx_cmd->len = cpu_to_le16(len); | ||
955 | |||
956 | if (info->control.hw_key) | ||
957 | iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); | ||
958 | |||
959 | /* TODO need this for burst mode later on */ | ||
960 | iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); | ||
961 | iwl_dbg_log_tx_data_frame(priv, len, hdr); | ||
962 | |||
963 | iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc); | ||
964 | |||
965 | iwl_update_stats(priv, true, fc, len); | ||
966 | /* | ||
967 | * Use the first empty entry in this queue's command buffer array | ||
968 | * to contain the Tx command and MAC header concatenated together | ||
969 | * (payload data will be in another buffer). | ||
970 | * Size of this varies, due to varying MAC header length. | ||
971 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
972 | * of the MAC header (device reads on dword boundaries). | ||
973 | * We'll tell device about this padding later. | ||
974 | */ | ||
975 | len = sizeof(struct iwl_tx_cmd) + | ||
976 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
977 | |||
978 | len_org = len; | ||
979 | firstlen = len = (len + 3) & ~3; | ||
980 | |||
981 | if (len_org != len) | ||
982 | len_org = 1; | ||
983 | else | ||
984 | len_org = 0; | ||
985 | |||
986 | /* Tell NIC about any 2-byte padding after MAC header */ | ||
987 | if (len_org) | ||
988 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | ||
989 | |||
990 | /* Physical address of this Tx command's header (not MAC header!), | ||
991 | * within command buffer array. */ | ||
992 | txcmd_phys = pci_map_single(priv->pci_dev, | ||
993 | &out_cmd->hdr, len, | ||
994 | PCI_DMA_BIDIRECTIONAL); | ||
995 | pci_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
996 | pci_unmap_len_set(out_meta, len, len); | ||
997 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
998 | * first entry */ | ||
999 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
1000 | txcmd_phys, len, 1, 0); | ||
1001 | |||
1002 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | ||
1003 | txq->need_update = 1; | ||
1004 | if (qc) | ||
1005 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
1006 | } else { | ||
1007 | wait_write_ptr = 1; | ||
1008 | txq->need_update = 0; | ||
1009 | } | ||
1010 | |||
1011 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | ||
1012 | * if any (802.11 null frames have no payload). */ | ||
1013 | secondlen = len = skb->len - hdr_len; | ||
1014 | if (len) { | ||
1015 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | ||
1016 | len, PCI_DMA_TODEVICE); | ||
1017 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
1018 | phys_addr, len, | ||
1019 | 0, 0); | ||
1020 | } | ||
1021 | |||
1022 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
1023 | offsetof(struct iwl_tx_cmd, scratch); | ||
1024 | |||
1025 | len = sizeof(struct iwl_tx_cmd) + | ||
1026 | sizeof(struct iwl_cmd_header) + hdr_len; | ||
1027 | /* take back ownership of DMA buffer to enable update */ | ||
1028 | pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, | ||
1029 | len, PCI_DMA_BIDIRECTIONAL); | ||
1030 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1031 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
1032 | |||
1033 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | ||
1034 | le16_to_cpu(out_cmd->hdr.sequence)); | ||
1035 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); | ||
1036 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); | ||
1037 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); | ||
1038 | |||
1039 | /* Set up entry for this TFD in Tx byte-count array */ | ||
1040 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1041 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, | ||
1042 | le16_to_cpu(tx_cmd->len)); | ||
1043 | |||
1044 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, | ||
1045 | len, PCI_DMA_BIDIRECTIONAL); | ||
1046 | |||
1047 | trace_iwlwifi_dev_tx(priv, | ||
1048 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | ||
1049 | sizeof(struct iwl_tfd), | ||
1050 | &out_cmd->hdr, firstlen, | ||
1051 | skb->data + hdr_len, secondlen); | ||
1052 | |||
1053 | /* Tell device the write index *just past* this latest filled TFD */ | ||
1054 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | ||
1055 | iwl_txq_update_write_ptr(priv, txq); | ||
1056 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1057 | |||
1058 | /* | ||
1059 | * At this point the frame is "transmitted" successfully | ||
1060 | * and we will get a TX status notification eventually, | ||
1061 | * regardless of the value of ret. "ret" only indicates | ||
1062 | * whether or not we should update the write pointer. | ||
1063 | */ | ||
1064 | |||
1065 | /* avoid atomic ops if it isn't an associated client */ | ||
1066 | if (sta_priv && sta_priv->client) | ||
1067 | atomic_inc(&sta_priv->pending_frames); | ||
1068 | |||
1069 | if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { | ||
1070 | if (wait_write_ptr) { | ||
1071 | spin_lock_irqsave(&priv->lock, flags); | ||
1072 | txq->need_update = 1; | ||
1073 | iwl_txq_update_write_ptr(priv, txq); | ||
1074 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1075 | } else { | ||
1076 | iwl_stop_queue(priv, txq->swq_id); | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | return 0; | ||
1081 | |||
1082 | drop_unlock: | ||
1083 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1084 | return -1; | ||
1085 | } | ||
1086 | EXPORT_SYMBOL(iwl_tx_skb); | ||
1087 | |||
1088 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 418 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
1089 | 419 | ||
1090 | /** | 420 | /** |
@@ -1218,61 +548,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1218 | return idx; | 548 | return idx; |
1219 | } | 549 | } |
1220 | 550 | ||
1221 | static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | ||
1222 | { | ||
1223 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1224 | struct ieee80211_sta *sta; | ||
1225 | struct iwl_station_priv *sta_priv; | ||
1226 | |||
1227 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | ||
1228 | if (sta) { | ||
1229 | sta_priv = (void *)sta->drv_priv; | ||
1230 | /* avoid atomic ops if this isn't a client */ | ||
1231 | if (sta_priv->client && | ||
1232 | atomic_dec_return(&sta_priv->pending_frames) == 0) | ||
1233 | ieee80211_sta_block_awake(priv->hw, sta, false); | ||
1234 | } | ||
1235 | |||
1236 | ieee80211_tx_status_irqsafe(priv->hw, skb); | ||
1237 | } | ||
1238 | |||
1239 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | ||
1240 | { | ||
1241 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
1242 | struct iwl_queue *q = &txq->q; | ||
1243 | struct iwl_tx_info *tx_info; | ||
1244 | int nfreed = 0; | ||
1245 | struct ieee80211_hdr *hdr; | ||
1246 | |||
1247 | if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { | ||
1248 | IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " | ||
1249 | "is out of range [0-%d] %d %d.\n", txq_id, | ||
1250 | index, q->n_bd, q->write_ptr, q->read_ptr); | ||
1251 | return 0; | ||
1252 | } | ||
1253 | |||
1254 | for (index = iwl_queue_inc_wrap(index, q->n_bd); | ||
1255 | q->read_ptr != index; | ||
1256 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
1257 | |||
1258 | tx_info = &txq->txb[txq->q.read_ptr]; | ||
1259 | iwl_tx_status(priv, tx_info->skb[0]); | ||
1260 | |||
1261 | hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; | ||
1262 | if (hdr && ieee80211_is_data_qos(hdr->frame_control)) | ||
1263 | nfreed++; | ||
1264 | tx_info->skb[0] = NULL; | ||
1265 | |||
1266 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | ||
1267 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | ||
1268 | |||
1269 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
1270 | } | ||
1271 | return nfreed; | ||
1272 | } | ||
1273 | EXPORT_SYMBOL(iwl_tx_queue_reclaim); | ||
1274 | |||
1275 | |||
1276 | /** | 551 | /** |
1277 | * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd | 552 | * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd |
1278 | * | 553 | * |
@@ -1366,7 +641,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1366 | 641 | ||
1367 | if (!(meta->flags & CMD_ASYNC)) { | 642 | if (!(meta->flags & CMD_ASYNC)) { |
1368 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 643 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1369 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n", | 644 | IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n", |
1370 | get_cmd_string(cmd->hdr.cmd)); | 645 | get_cmd_string(cmd->hdr.cmd)); |
1371 | wake_up_interruptible(&priv->wait_command_queue); | 646 | wake_up_interruptible(&priv->wait_command_queue); |
1372 | } | 647 | } |
@@ -1374,353 +649,37 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | |||
1374 | } | 649 | } |
1375 | EXPORT_SYMBOL(iwl_tx_cmd_complete); | 650 | EXPORT_SYMBOL(iwl_tx_cmd_complete); |
1376 | 651 | ||
1377 | /* | ||
1378 | * Find first available (lowest unused) Tx Queue, mark it "active". | ||
1379 | * Called only when finding queue for aggregation. | ||
1380 | * Should never return anything < 7, because they should already | ||
1381 | * be in use as EDCA AC (0-3), Command (4), reserved (5, 6) | ||
1382 | */ | ||
1383 | static int iwl_txq_ctx_activate_free(struct iwl_priv *priv) | ||
1384 | { | ||
1385 | int txq_id; | ||
1386 | |||
1387 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
1388 | if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) | ||
1389 | return txq_id; | ||
1390 | return -1; | ||
1391 | } | ||
1392 | |||
1393 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) | ||
1394 | { | ||
1395 | int sta_id; | ||
1396 | int tx_fifo; | ||
1397 | int txq_id; | ||
1398 | int ret; | ||
1399 | unsigned long flags; | ||
1400 | struct iwl_tid_data *tid_data; | ||
1401 | |||
1402 | tx_fifo = get_fifo_from_tid(tid); | ||
1403 | if (unlikely(tx_fifo < 0)) | ||
1404 | return tx_fifo; | ||
1405 | |||
1406 | IWL_WARN(priv, "%s on ra = %pM tid = %d\n", | ||
1407 | __func__, ra, tid); | ||
1408 | |||
1409 | sta_id = iwl_find_station(priv, ra); | ||
1410 | if (sta_id == IWL_INVALID_STATION) { | ||
1411 | IWL_ERR(priv, "Start AGG on invalid station\n"); | ||
1412 | return -ENXIO; | ||
1413 | } | ||
1414 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1415 | return -EINVAL; | ||
1416 | |||
1417 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { | ||
1418 | IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); | ||
1419 | return -ENXIO; | ||
1420 | } | ||
1421 | |||
1422 | txq_id = iwl_txq_ctx_activate_free(priv); | ||
1423 | if (txq_id == -1) { | ||
1424 | IWL_ERR(priv, "No free aggregation queue available\n"); | ||
1425 | return -ENXIO; | ||
1426 | } | ||
1427 | |||
1428 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1429 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1430 | *ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1431 | tid_data->agg.txq_id = txq_id; | ||
1432 | priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); | ||
1433 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1434 | |||
1435 | ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, | ||
1436 | sta_id, tid, *ssn); | ||
1437 | if (ret) | ||
1438 | return ret; | ||
1439 | |||
1440 | if (tid_data->tfds_in_queue == 0) { | ||
1441 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1442 | tid_data->agg.state = IWL_AGG_ON; | ||
1443 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1444 | } else { | ||
1445 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", | ||
1446 | tid_data->tfds_in_queue); | ||
1447 | tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; | ||
1448 | } | ||
1449 | return ret; | ||
1450 | } | ||
1451 | EXPORT_SYMBOL(iwl_tx_agg_start); | ||
1452 | |||
1453 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | ||
1454 | { | ||
1455 | int tx_fifo_id, txq_id, sta_id, ssn = -1; | ||
1456 | struct iwl_tid_data *tid_data; | ||
1457 | int write_ptr, read_ptr; | ||
1458 | unsigned long flags; | ||
1459 | |||
1460 | if (!ra) { | ||
1461 | IWL_ERR(priv, "ra = NULL\n"); | ||
1462 | return -EINVAL; | ||
1463 | } | ||
1464 | |||
1465 | tx_fifo_id = get_fifo_from_tid(tid); | ||
1466 | if (unlikely(tx_fifo_id < 0)) | ||
1467 | return tx_fifo_id; | ||
1468 | |||
1469 | sta_id = iwl_find_station(priv, ra); | ||
1470 | |||
1471 | if (sta_id == IWL_INVALID_STATION) { | ||
1472 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); | ||
1473 | return -ENXIO; | ||
1474 | } | ||
1475 | |||
1476 | if (priv->stations[sta_id].tid[tid].agg.state == | ||
1477 | IWL_EMPTYING_HW_QUEUE_ADDBA) { | ||
1478 | IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); | ||
1479 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1480 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1481 | return 0; | ||
1482 | } | ||
1483 | |||
1484 | if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) | ||
1485 | IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); | ||
1486 | |||
1487 | tid_data = &priv->stations[sta_id].tid[tid]; | ||
1488 | ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; | ||
1489 | txq_id = tid_data->agg.txq_id; | ||
1490 | write_ptr = priv->txq[txq_id].q.write_ptr; | ||
1491 | read_ptr = priv->txq[txq_id].q.read_ptr; | ||
1492 | |||
1493 | /* The queue is not empty */ | ||
1494 | if (write_ptr != read_ptr) { | ||
1495 | IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); | ||
1496 | priv->stations[sta_id].tid[tid].agg.state = | ||
1497 | IWL_EMPTYING_HW_QUEUE_DELBA; | ||
1498 | return 0; | ||
1499 | } | ||
1500 | |||
1501 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | ||
1502 | priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; | ||
1503 | |||
1504 | spin_lock_irqsave(&priv->lock, flags); | ||
1505 | /* | ||
1506 | * the only reason this call can fail is queue number out of range, | ||
1507 | * which can happen if uCode is reloaded and all the station | ||
1508 | * information are lost. if it is outside the range, there is no need | ||
1509 | * to deactivate the uCode queue, just return "success" to allow | ||
1510 | * mac80211 to clean up it own data. | ||
1511 | */ | ||
1512 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, | ||
1513 | tx_fifo_id); | ||
1514 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1515 | |||
1516 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); | ||
1517 | |||
1518 | return 0; | ||
1519 | } | ||
1520 | EXPORT_SYMBOL(iwl_tx_agg_stop); | ||
1521 | |||
1522 | int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) | ||
1523 | { | ||
1524 | struct iwl_queue *q = &priv->txq[txq_id].q; | ||
1525 | u8 *addr = priv->stations[sta_id].sta.sta.addr; | ||
1526 | struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; | ||
1527 | |||
1528 | switch (priv->stations[sta_id].tid[tid].agg.state) { | ||
1529 | case IWL_EMPTYING_HW_QUEUE_DELBA: | ||
1530 | /* We are reclaiming the last packet of the */ | ||
1531 | /* aggregated HW queue */ | ||
1532 | if ((txq_id == tid_data->agg.txq_id) && | ||
1533 | (q->read_ptr == q->write_ptr)) { | ||
1534 | u16 ssn = SEQ_TO_SN(tid_data->seq_number); | ||
1535 | int tx_fifo = get_fifo_from_tid(tid); | ||
1536 | IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); | ||
1537 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | ||
1538 | ssn, tx_fifo); | ||
1539 | tid_data->agg.state = IWL_AGG_OFF; | ||
1540 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1541 | } | ||
1542 | break; | ||
1543 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | ||
1544 | /* We are reclaiming the last packet of the queue */ | ||
1545 | if (tid_data->tfds_in_queue == 0) { | ||
1546 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); | ||
1547 | tid_data->agg.state = IWL_AGG_ON; | ||
1548 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); | ||
1549 | } | ||
1550 | break; | ||
1551 | } | ||
1552 | return 0; | ||
1553 | } | ||
1554 | EXPORT_SYMBOL(iwl_txq_check_empty); | ||
1555 | |||
1556 | /** | ||
1557 | * iwl_tx_status_reply_compressed_ba - Update tx status from block-ack | ||
1558 | * | ||
1559 | * Go through block-ack's bitmap of ACK'd frames, update driver's record of | ||
1560 | * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. | ||
1561 | */ | ||
1562 | static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, | ||
1563 | struct iwl_ht_agg *agg, | ||
1564 | struct iwl_compressed_ba_resp *ba_resp) | ||
1565 | |||
1566 | { | ||
1567 | int i, sh, ack; | ||
1568 | u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); | ||
1569 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1570 | u64 bitmap; | ||
1571 | int successes = 0; | ||
1572 | struct ieee80211_tx_info *info; | ||
1573 | |||
1574 | if (unlikely(!agg->wait_for_ba)) { | ||
1575 | IWL_ERR(priv, "Received BA when not expected\n"); | ||
1576 | return -EINVAL; | ||
1577 | } | ||
1578 | |||
1579 | /* Mark that the expected block-ack response arrived */ | ||
1580 | agg->wait_for_ba = 0; | ||
1581 | IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); | ||
1582 | |||
1583 | /* Calculate shift to align block-ack bits with our Tx window bits */ | ||
1584 | sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); | ||
1585 | if (sh < 0) /* tbw something is wrong with indices */ | ||
1586 | sh += 0x100; | ||
1587 | |||
1588 | /* don't use 64-bit values for now */ | ||
1589 | bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; | ||
1590 | |||
1591 | if (agg->frame_count > (64 - sh)) { | ||
1592 | IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); | ||
1593 | return -1; | ||
1594 | } | ||
1595 | |||
1596 | /* check for success or failure according to the | ||
1597 | * transmitted bitmap and block-ack bitmap */ | ||
1598 | bitmap &= agg->bitmap; | ||
1599 | |||
1600 | /* For each frame attempted in aggregation, | ||
1601 | * update driver's record of tx frame's status. */ | ||
1602 | for (i = 0; i < agg->frame_count ; i++) { | ||
1603 | ack = bitmap & (1ULL << i); | ||
1604 | successes += !!ack; | ||
1605 | IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", | ||
1606 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, | ||
1607 | agg->start_idx + i); | ||
1608 | } | ||
1609 | |||
1610 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | ||
1611 | memset(&info->status, 0, sizeof(info->status)); | ||
1612 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1613 | info->flags |= IEEE80211_TX_STAT_AMPDU; | ||
1614 | info->status.ampdu_ack_map = successes; | ||
1615 | info->status.ampdu_ack_len = agg->frame_count; | ||
1616 | iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); | ||
1617 | |||
1618 | IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); | ||
1619 | |||
1620 | return 0; | ||
1621 | } | ||
1622 | |||
1623 | /** | ||
1624 | * iwl_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA | ||
1625 | * | ||
1626 | * Handles block-acknowledge notification from device, which reports success | ||
1627 | * of frames sent via aggregation. | ||
1628 | */ | ||
1629 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | ||
1630 | struct iwl_rx_mem_buffer *rxb) | ||
1631 | { | ||
1632 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
1633 | struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; | ||
1634 | struct iwl_tx_queue *txq = NULL; | ||
1635 | struct iwl_ht_agg *agg; | ||
1636 | int index; | ||
1637 | int sta_id; | ||
1638 | int tid; | ||
1639 | |||
1640 | /* "flow" corresponds to Tx queue */ | ||
1641 | u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); | ||
1642 | |||
1643 | /* "ssn" is start of block-ack Tx window, corresponds to index | ||
1644 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | ||
1645 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); | ||
1646 | |||
1647 | if (scd_flow >= priv->hw_params.max_txq_num) { | ||
1648 | IWL_ERR(priv, | ||
1649 | "BUG_ON scd_flow is bigger than number of queues\n"); | ||
1650 | return; | ||
1651 | } | ||
1652 | |||
1653 | txq = &priv->txq[scd_flow]; | ||
1654 | sta_id = ba_resp->sta_id; | ||
1655 | tid = ba_resp->tid; | ||
1656 | agg = &priv->stations[sta_id].tid[tid].agg; | ||
1657 | |||
1658 | /* Find index just before block-ack window */ | ||
1659 | index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); | ||
1660 | |||
1661 | /* TODO: Need to get this copy more safely - now good for debug */ | ||
1662 | |||
1663 | IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " | ||
1664 | "sta_id = %d\n", | ||
1665 | agg->wait_for_ba, | ||
1666 | (u8 *) &ba_resp->sta_addr_lo32, | ||
1667 | ba_resp->sta_id); | ||
1668 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " | ||
1669 | "%d, scd_ssn = %d\n", | ||
1670 | ba_resp->tid, | ||
1671 | ba_resp->seq_ctl, | ||
1672 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | ||
1673 | ba_resp->scd_flow, | ||
1674 | ba_resp->scd_ssn); | ||
1675 | IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx \n", | ||
1676 | agg->start_idx, | ||
1677 | (unsigned long long)agg->bitmap); | ||
1678 | |||
1679 | /* Update driver's record of ACK vs. not for each frame in window */ | ||
1680 | iwl_tx_status_reply_compressed_ba(priv, agg, ba_resp); | ||
1681 | |||
1682 | /* Release all TFDs before the SSN, i.e. all TFDs in front of | ||
1683 | * block-ack window (we assume that they've been successfully | ||
1684 | * transmitted ... if not, it's too late anyway). */ | ||
1685 | if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { | ||
1686 | /* calculate mac80211 ampdu sw queue to wake */ | ||
1687 | int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); | ||
1688 | iwl_free_tfds_in_queue(priv, sta_id, tid, freed); | ||
1689 | |||
1690 | if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && | ||
1691 | priv->mac80211_registered && | ||
1692 | (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) | ||
1693 | iwl_wake_queue(priv, txq->swq_id); | ||
1694 | |||
1695 | iwl_txq_check_empty(priv, sta_id, tid, scd_flow); | ||
1696 | } | ||
1697 | } | ||
1698 | EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); | ||
1699 | |||
1700 | #ifdef CONFIG_IWLWIFI_DEBUG | 652 | #ifdef CONFIG_IWLWIFI_DEBUG |
1701 | #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x | 653 | #define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x |
654 | #define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x | ||
1702 | 655 | ||
1703 | const char *iwl_get_tx_fail_reason(u32 status) | 656 | const char *iwl_get_tx_fail_reason(u32 status) |
1704 | { | 657 | { |
1705 | switch (status & TX_STATUS_MSK) { | 658 | switch (status & TX_STATUS_MSK) { |
1706 | case TX_STATUS_SUCCESS: | 659 | case TX_STATUS_SUCCESS: |
1707 | return "SUCCESS"; | 660 | return "SUCCESS"; |
1708 | TX_STATUS_ENTRY(SHORT_LIMIT); | 661 | TX_STATUS_POSTPONE(DELAY); |
1709 | TX_STATUS_ENTRY(LONG_LIMIT); | 662 | TX_STATUS_POSTPONE(FEW_BYTES); |
1710 | TX_STATUS_ENTRY(FIFO_UNDERRUN); | 663 | TX_STATUS_POSTPONE(BT_PRIO); |
1711 | TX_STATUS_ENTRY(MGMNT_ABORT); | 664 | TX_STATUS_POSTPONE(QUIET_PERIOD); |
1712 | TX_STATUS_ENTRY(NEXT_FRAG); | 665 | TX_STATUS_POSTPONE(CALC_TTAK); |
1713 | TX_STATUS_ENTRY(LIFE_EXPIRE); | 666 | TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); |
1714 | TX_STATUS_ENTRY(DEST_PS); | 667 | TX_STATUS_FAIL(SHORT_LIMIT); |
1715 | TX_STATUS_ENTRY(ABORTED); | 668 | TX_STATUS_FAIL(LONG_LIMIT); |
1716 | TX_STATUS_ENTRY(BT_RETRY); | 669 | TX_STATUS_FAIL(FIFO_UNDERRUN); |
1717 | TX_STATUS_ENTRY(STA_INVALID); | 670 | TX_STATUS_FAIL(DRAIN_FLOW); |
1718 | TX_STATUS_ENTRY(FRAG_DROPPED); | 671 | TX_STATUS_FAIL(RFKILL_FLUSH); |
1719 | TX_STATUS_ENTRY(TID_DISABLE); | 672 | TX_STATUS_FAIL(LIFE_EXPIRE); |
1720 | TX_STATUS_ENTRY(FRAME_FLUSHED); | 673 | TX_STATUS_FAIL(DEST_PS); |
1721 | TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); | 674 | TX_STATUS_FAIL(HOST_ABORTED); |
1722 | TX_STATUS_ENTRY(TX_LOCKED); | 675 | TX_STATUS_FAIL(BT_RETRY); |
1723 | TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); | 676 | TX_STATUS_FAIL(STA_INVALID); |
677 | TX_STATUS_FAIL(FRAG_DROPPED); | ||
678 | TX_STATUS_FAIL(TID_DISABLE); | ||
679 | TX_STATUS_FAIL(FIFO_FLUSHED); | ||
680 | TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); | ||
681 | TX_STATUS_FAIL(FW_DROP); | ||
682 | TX_STATUS_FAIL(STA_COLOR_MISMATCH_DROP); | ||
1724 | } | 683 | } |
1725 | 684 | ||
1726 | return "UNKNOWN"; | 685 | return "UNKNOWN"; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e0c05feb296c..9f362024a29c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -598,9 +598,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
598 | txq->need_update = 0; | 598 | txq->need_update = 0; |
599 | } | 599 | } |
600 | 600 | ||
601 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", | 601 | IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n", |
602 | le16_to_cpu(out_cmd->hdr.sequence)); | 602 | le16_to_cpu(out_cmd->hdr.sequence)); |
603 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); | 603 | IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags)); |
604 | iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); | 604 | iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd)); |
605 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, | 605 | iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, |
606 | ieee80211_hdrlen(fc)); | 606 | ieee80211_hdrlen(fc)); |
@@ -1604,9 +1604,6 @@ static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | |||
1604 | return pos; | 1604 | return pos; |
1605 | } | 1605 | } |
1606 | 1606 | ||
1607 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | ||
1608 | #define IWL3945_MAX_EVENT_LOG_SIZE (512) | ||
1609 | |||
1610 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) | 1607 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) |
1611 | 1608 | ||
1612 | int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | 1609 | int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, |
@@ -1633,16 +1630,16 @@ int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
1633 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); | 1630 | num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); |
1634 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); | 1631 | next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); |
1635 | 1632 | ||
1636 | if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) { | 1633 | if (capacity > priv->cfg->max_event_log_size) { |
1637 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", | 1634 | IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n", |
1638 | capacity, IWL3945_MAX_EVENT_LOG_SIZE); | 1635 | capacity, priv->cfg->max_event_log_size); |
1639 | capacity = IWL3945_MAX_EVENT_LOG_SIZE; | 1636 | capacity = priv->cfg->max_event_log_size; |
1640 | } | 1637 | } |
1641 | 1638 | ||
1642 | if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) { | 1639 | if (next_entry > priv->cfg->max_event_log_size) { |
1643 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", | 1640 | IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n", |
1644 | next_entry, IWL3945_MAX_EVENT_LOG_SIZE); | 1641 | next_entry, priv->cfg->max_event_log_size); |
1645 | next_entry = IWL3945_MAX_EVENT_LOG_SIZE; | 1642 | next_entry = priv->cfg->max_event_log_size; |
1646 | } | 1643 | } |
1647 | 1644 | ||
1648 | size = num_wraps ? capacity : next_entry; | 1645 | size = num_wraps ? capacity : next_entry; |
@@ -1938,7 +1935,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, | |||
1938 | added++; | 1935 | added++; |
1939 | } | 1936 | } |
1940 | 1937 | ||
1941 | IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); | 1938 | IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added); |
1942 | return added; | 1939 | return added; |
1943 | } | 1940 | } |
1944 | 1941 | ||
@@ -3141,8 +3138,6 @@ void iwl3945_post_associate(struct iwl_priv *priv) | |||
3141 | break; | 3138 | break; |
3142 | } | 3139 | } |
3143 | 3140 | ||
3144 | iwl_activate_qos(priv, 0); | ||
3145 | |||
3146 | /* we have just associated, don't start scan too early */ | 3141 | /* we have just associated, don't start scan too early */ |
3147 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; | 3142 | priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; |
3148 | } | 3143 | } |
@@ -3404,7 +3399,7 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, | |||
3404 | } | 3399 | } |
3405 | 3400 | ||
3406 | /* Initialize rate scaling */ | 3401 | /* Initialize rate scaling */ |
3407 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM \n", | 3402 | IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", |
3408 | sta->addr); | 3403 | sta->addr); |
3409 | iwl3945_rs_rate_init(priv, sta, sta_id); | 3404 | iwl3945_rs_rate_init(priv, sta, sta_id); |
3410 | 3405 | ||
@@ -3890,11 +3885,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv) | |||
3890 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3885 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3891 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; | 3886 | priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; |
3892 | 3887 | ||
3893 | iwl_reset_qos(priv); | ||
3894 | |||
3895 | priv->qos_data.qos_active = 0; | ||
3896 | priv->qos_data.qos_cap.val = 0; | ||
3897 | |||
3898 | priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; | 3888 | priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; |
3899 | 3889 | ||
3900 | if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { | 3890 | if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { |
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index a48ccaffb288..6f5b843c1f44 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c | |||
@@ -75,7 +75,7 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf, | |||
75 | return -ENOMEM; | 75 | return -ENOMEM; |
76 | 76 | ||
77 | pos += snprintf(buf+pos, len-pos, | 77 | pos += snprintf(buf+pos, len-pos, |
78 | "# | ch | rssi | bssid | cap | Qual | SSID \n"); | 78 | "# | ch | rssi | bssid | cap | Qual | SSID\n"); |
79 | 79 | ||
80 | mutex_lock(&priv->lock); | 80 | mutex_lock(&priv->lock); |
81 | list_for_each_entry (iter_bss, &priv->network_list, list) { | 81 | list_for_each_entry (iter_bss, &priv->network_list, list) { |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 7d1a3c6b6ce0..cd464a2589b9 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #include <linux/mmc/card.h> | 35 | #include <linux/mmc/card.h> |
36 | #include <linux/mmc/sdio_func.h> | 36 | #include <linux/mmc/sdio_func.h> |
37 | #include <linux/mmc/sdio_ids.h> | 37 | #include <linux/mmc/sdio_ids.h> |
38 | #include <linux/mmc/sdio.h> | ||
39 | #include <linux/mmc/host.h> | ||
38 | 40 | ||
39 | #include "host.h" | 41 | #include "host.h" |
40 | #include "decl.h" | 42 | #include "decl.h" |
@@ -943,6 +945,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
943 | int ret, i; | 945 | int ret, i; |
944 | unsigned int model; | 946 | unsigned int model; |
945 | struct if_sdio_packet *packet; | 947 | struct if_sdio_packet *packet; |
948 | struct mmc_host *host = func->card->host; | ||
946 | 949 | ||
947 | lbs_deb_enter(LBS_DEB_SDIO); | 950 | lbs_deb_enter(LBS_DEB_SDIO); |
948 | 951 | ||
@@ -1023,6 +1026,25 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1023 | if (ret) | 1026 | if (ret) |
1024 | goto disable; | 1027 | goto disable; |
1025 | 1028 | ||
1029 | /* For 1-bit transfers to the 8686 model, we need to enable the | ||
1030 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | ||
1031 | * bit to allow access to non-vendor registers. */ | ||
1032 | if ((card->model == IF_SDIO_MODEL_8686) && | ||
1033 | (host->caps & MMC_CAP_SDIO_IRQ) && | ||
1034 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | ||
1035 | u8 reg; | ||
1036 | |||
1037 | func->card->quirks |= MMC_QUIRK_LENIENT_FN0; | ||
1038 | reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret); | ||
1039 | if (ret) | ||
1040 | goto release_int; | ||
1041 | |||
1042 | reg |= SDIO_BUS_ECSI; | ||
1043 | sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret); | ||
1044 | if (ret) | ||
1045 | goto release_int; | ||
1046 | } | ||
1047 | |||
1026 | card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); | 1048 | card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); |
1027 | if (ret) | 1049 | if (ret) |
1028 | goto release_int; | 1050 | goto release_int; |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 7cd5f56662fc..dfff02f5c86d 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -291,7 +291,8 @@ struct mac80211_hwsim_data { | |||
291 | struct ieee80211_channel *channel; | 291 | struct ieee80211_channel *channel; |
292 | unsigned long beacon_int; /* in jiffies unit */ | 292 | unsigned long beacon_int; /* in jiffies unit */ |
293 | unsigned int rx_filter; | 293 | unsigned int rx_filter; |
294 | bool started, idle; | 294 | bool started, idle, scanning; |
295 | struct mutex mutex; | ||
295 | struct timer_list beacon_timer; | 296 | struct timer_list beacon_timer; |
296 | enum ps_mode { | 297 | enum ps_mode { |
297 | PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL | 298 | PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL |
@@ -957,9 +958,9 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, | |||
957 | hsd->hw = hw; | 958 | hsd->hw = hw; |
958 | INIT_DELAYED_WORK(&hsd->w, hw_scan_done); | 959 | INIT_DELAYED_WORK(&hsd->w, hw_scan_done); |
959 | 960 | ||
960 | printk(KERN_DEBUG "hwsim scan request\n"); | 961 | printk(KERN_DEBUG "hwsim hw_scan request\n"); |
961 | for (i = 0; i < req->n_channels; i++) | 962 | for (i = 0; i < req->n_channels; i++) |
962 | printk(KERN_DEBUG "hwsim scan freq %d\n", | 963 | printk(KERN_DEBUG "hwsim hw_scan freq %d\n", |
963 | req->channels[i]->center_freq); | 964 | req->channels[i]->center_freq); |
964 | 965 | ||
965 | ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ); | 966 | ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ); |
@@ -967,6 +968,36 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, | |||
967 | return 0; | 968 | return 0; |
968 | } | 969 | } |
969 | 970 | ||
971 | static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) | ||
972 | { | ||
973 | struct mac80211_hwsim_data *hwsim = hw->priv; | ||
974 | |||
975 | mutex_lock(&hwsim->mutex); | ||
976 | |||
977 | if (hwsim->scanning) { | ||
978 | printk(KERN_DEBUG "two hwsim sw_scans detected!\n"); | ||
979 | goto out; | ||
980 | } | ||
981 | |||
982 | printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n"); | ||
983 | hwsim->scanning = true; | ||
984 | |||
985 | out: | ||
986 | mutex_unlock(&hwsim->mutex); | ||
987 | } | ||
988 | |||
989 | static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) | ||
990 | { | ||
991 | struct mac80211_hwsim_data *hwsim = hw->priv; | ||
992 | |||
993 | mutex_lock(&hwsim->mutex); | ||
994 | |||
995 | printk(KERN_DEBUG "hwsim sw_scan_complete\n"); | ||
996 | hwsim->scanning = true; | ||
997 | |||
998 | mutex_unlock(&hwsim->mutex); | ||
999 | } | ||
1000 | |||
970 | static struct ieee80211_ops mac80211_hwsim_ops = | 1001 | static struct ieee80211_ops mac80211_hwsim_ops = |
971 | { | 1002 | { |
972 | .tx = mac80211_hwsim_tx, | 1003 | .tx = mac80211_hwsim_tx, |
@@ -984,6 +1015,8 @@ static struct ieee80211_ops mac80211_hwsim_ops = | |||
984 | .conf_tx = mac80211_hwsim_conf_tx, | 1015 | .conf_tx = mac80211_hwsim_conf_tx, |
985 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) | 1016 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) |
986 | .ampdu_action = mac80211_hwsim_ampdu_action, | 1017 | .ampdu_action = mac80211_hwsim_ampdu_action, |
1018 | .sw_scan_start = mac80211_hwsim_sw_scan, | ||
1019 | .sw_scan_complete = mac80211_hwsim_sw_scan_complete, | ||
987 | .flush = mac80211_hwsim_flush, | 1020 | .flush = mac80211_hwsim_flush, |
988 | }; | 1021 | }; |
989 | 1022 | ||
@@ -1179,8 +1212,11 @@ static int __init init_mac80211_hwsim(void) | |||
1179 | if (radios < 1 || radios > 100) | 1212 | if (radios < 1 || radios > 100) |
1180 | return -EINVAL; | 1213 | return -EINVAL; |
1181 | 1214 | ||
1182 | if (fake_hw_scan) | 1215 | if (fake_hw_scan) { |
1183 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; | 1216 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; |
1217 | mac80211_hwsim_ops.sw_scan_start = NULL; | ||
1218 | mac80211_hwsim_ops.sw_scan_complete = NULL; | ||
1219 | } | ||
1184 | 1220 | ||
1185 | spin_lock_init(&hwsim_radio_lock); | 1221 | spin_lock_init(&hwsim_radio_lock); |
1186 | INIT_LIST_HEAD(&hwsim_radios); | 1222 | INIT_LIST_HEAD(&hwsim_radios); |
@@ -1285,6 +1321,7 @@ static int __init init_mac80211_hwsim(void) | |||
1285 | } | 1321 | } |
1286 | /* By default all radios are belonging to the first group */ | 1322 | /* By default all radios are belonging to the first group */ |
1287 | data->group = 1; | 1323 | data->group = 1; |
1324 | mutex_init(&data->mutex); | ||
1288 | 1325 | ||
1289 | /* Work to be done prior to ieee80211_register_hw() */ | 1326 | /* Work to be done prior to ieee80211_register_hw() */ |
1290 | switch (regtest) { | 1327 | switch (regtest) { |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 269fda362836..86f3e9ac4c7a 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -132,7 +132,7 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev) | |||
132 | 132 | ||
133 | static void p54p_refill_rx_ring(struct ieee80211_hw *dev, | 133 | static void p54p_refill_rx_ring(struct ieee80211_hw *dev, |
134 | int ring_index, struct p54p_desc *ring, u32 ring_limit, | 134 | int ring_index, struct p54p_desc *ring, u32 ring_limit, |
135 | struct sk_buff **rx_buf) | 135 | struct sk_buff **rx_buf, u32 index) |
136 | { | 136 | { |
137 | struct p54p_priv *priv = dev->priv; | 137 | struct p54p_priv *priv = dev->priv; |
138 | struct p54p_ring_control *ring_control = priv->ring_control; | 138 | struct p54p_ring_control *ring_control = priv->ring_control; |
@@ -140,7 +140,7 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev, | |||
140 | 140 | ||
141 | idx = le32_to_cpu(ring_control->host_idx[ring_index]); | 141 | idx = le32_to_cpu(ring_control->host_idx[ring_index]); |
142 | limit = idx; | 142 | limit = idx; |
143 | limit -= le32_to_cpu(ring_control->device_idx[ring_index]); | 143 | limit -= le32_to_cpu(index); |
144 | limit = ring_limit - limit; | 144 | limit = ring_limit - limit; |
145 | 145 | ||
146 | i = idx % ring_limit; | 146 | i = idx % ring_limit; |
@@ -232,7 +232,7 @@ static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, | |||
232 | i %= ring_limit; | 232 | i %= ring_limit; |
233 | } | 233 | } |
234 | 234 | ||
235 | p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); | 235 | p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf, *index); |
236 | } | 236 | } |
237 | 237 | ||
238 | static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | 238 | static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, |
@@ -277,14 +277,6 @@ static void p54p_tasklet(unsigned long dev_id) | |||
277 | struct p54p_priv *priv = dev->priv; | 277 | struct p54p_priv *priv = dev->priv; |
278 | struct p54p_ring_control *ring_control = priv->ring_control; | 278 | struct p54p_ring_control *ring_control = priv->ring_control; |
279 | 279 | ||
280 | p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, | ||
281 | ARRAY_SIZE(ring_control->tx_mgmt), | ||
282 | priv->tx_buf_mgmt); | ||
283 | |||
284 | p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, | ||
285 | ARRAY_SIZE(ring_control->tx_data), | ||
286 | priv->tx_buf_data); | ||
287 | |||
288 | p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, | 280 | p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, |
289 | ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); | 281 | ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); |
290 | 282 | ||
@@ -293,6 +285,14 @@ static void p54p_tasklet(unsigned long dev_id) | |||
293 | 285 | ||
294 | wmb(); | 286 | wmb(); |
295 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); | 287 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); |
288 | |||
289 | p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt, | ||
290 | ARRAY_SIZE(ring_control->tx_mgmt), | ||
291 | priv->tx_buf_mgmt); | ||
292 | |||
293 | p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data, | ||
294 | ARRAY_SIZE(ring_control->tx_data), | ||
295 | priv->tx_buf_data); | ||
296 | } | 296 | } |
297 | 297 | ||
298 | static irqreturn_t p54p_interrupt(int irq, void *dev_id) | 298 | static irqreturn_t p54p_interrupt(int irq, void *dev_id) |
@@ -445,10 +445,10 @@ static int p54p_open(struct ieee80211_hw *dev) | |||
445 | priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0; | 445 | priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0; |
446 | 446 | ||
447 | p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data, | 447 | p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data, |
448 | ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data); | 448 | ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data, 0); |
449 | 449 | ||
450 | p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt, | 450 | p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt, |
451 | ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt); | 451 | ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt, 0); |
452 | 452 | ||
453 | P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); | 453 | P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); |
454 | P54P_READ(ring_control_base); | 454 | P54P_READ(ring_control_base); |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 66057999a93c..2ceff5480355 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -38,7 +38,7 @@ static void p54_dump_tx_queue(struct p54_common *priv) | |||
38 | u32 largest_hole = 0, free; | 38 | u32 largest_hole = 0, free; |
39 | 39 | ||
40 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | 40 | spin_lock_irqsave(&priv->tx_queue.lock, flags); |
41 | printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) --- \n", | 41 | printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) ---\n", |
42 | wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue)); | 42 | wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue)); |
43 | 43 | ||
44 | prev_addr = priv->rx_start; | 44 | prev_addr = priv->rx_start; |
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 689d59a13d5b..10d91afefa33 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c | |||
@@ -228,14 +228,14 @@ islpci_interrupt(int irq, void *config) | |||
228 | 228 | ||
229 | #if VERBOSE > SHOW_ERROR_MESSAGES | 229 | #if VERBOSE > SHOW_ERROR_MESSAGES |
230 | DEBUG(SHOW_FUNCTION_CALLS, | 230 | DEBUG(SHOW_FUNCTION_CALLS, |
231 | "IRQ: Identification register 0x%p 0x%x \n", device, reg); | 231 | "IRQ: Identification register 0x%p 0x%x\n", device, reg); |
232 | #endif | 232 | #endif |
233 | 233 | ||
234 | /* check for each bit in the register separately */ | 234 | /* check for each bit in the register separately */ |
235 | if (reg & ISL38XX_INT_IDENT_UPDATE) { | 235 | if (reg & ISL38XX_INT_IDENT_UPDATE) { |
236 | #if VERBOSE > SHOW_ERROR_MESSAGES | 236 | #if VERBOSE > SHOW_ERROR_MESSAGES |
237 | /* Queue has been updated */ | 237 | /* Queue has been updated */ |
238 | DEBUG(SHOW_TRACING, "IRQ: Update flag \n"); | 238 | DEBUG(SHOW_TRACING, "IRQ: Update flag\n"); |
239 | 239 | ||
240 | DEBUG(SHOW_QUEUE_INDEXES, | 240 | DEBUG(SHOW_QUEUE_INDEXES, |
241 | "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n", | 241 | "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n", |
@@ -301,7 +301,7 @@ islpci_interrupt(int irq, void *config) | |||
301 | ISL38XX_CB_RX_DATA_LQ) != 0) { | 301 | ISL38XX_CB_RX_DATA_LQ) != 0) { |
302 | #if VERBOSE > SHOW_ERROR_MESSAGES | 302 | #if VERBOSE > SHOW_ERROR_MESSAGES |
303 | DEBUG(SHOW_TRACING, | 303 | DEBUG(SHOW_TRACING, |
304 | "Received frame in Data Low Queue \n"); | 304 | "Received frame in Data Low Queue\n"); |
305 | #endif | 305 | #endif |
306 | islpci_eth_receive(priv); | 306 | islpci_eth_receive(priv); |
307 | } | 307 | } |
@@ -326,7 +326,7 @@ islpci_interrupt(int irq, void *config) | |||
326 | /* Device has been initialized */ | 326 | /* Device has been initialized */ |
327 | #if VERBOSE > SHOW_ERROR_MESSAGES | 327 | #if VERBOSE > SHOW_ERROR_MESSAGES |
328 | DEBUG(SHOW_TRACING, | 328 | DEBUG(SHOW_TRACING, |
329 | "IRQ: Init flag, device initialized \n"); | 329 | "IRQ: Init flag, device initialized\n"); |
330 | #endif | 330 | #endif |
331 | wake_up(&priv->reset_done); | 331 | wake_up(&priv->reset_done); |
332 | } | 332 | } |
@@ -334,7 +334,7 @@ islpci_interrupt(int irq, void *config) | |||
334 | if (reg & ISL38XX_INT_IDENT_SLEEP) { | 334 | if (reg & ISL38XX_INT_IDENT_SLEEP) { |
335 | /* Device intends to move to powersave state */ | 335 | /* Device intends to move to powersave state */ |
336 | #if VERBOSE > SHOW_ERROR_MESSAGES | 336 | #if VERBOSE > SHOW_ERROR_MESSAGES |
337 | DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n"); | 337 | DEBUG(SHOW_TRACING, "IRQ: Sleep flag\n"); |
338 | #endif | 338 | #endif |
339 | isl38xx_handle_sleep_request(priv->control_block, | 339 | isl38xx_handle_sleep_request(priv->control_block, |
340 | &powerstate, | 340 | &powerstate, |
@@ -344,7 +344,7 @@ islpci_interrupt(int irq, void *config) | |||
344 | if (reg & ISL38XX_INT_IDENT_WAKEUP) { | 344 | if (reg & ISL38XX_INT_IDENT_WAKEUP) { |
345 | /* Device has been woken up to active state */ | 345 | /* Device has been woken up to active state */ |
346 | #if VERBOSE > SHOW_ERROR_MESSAGES | 346 | #if VERBOSE > SHOW_ERROR_MESSAGES |
347 | DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n"); | 347 | DEBUG(SHOW_TRACING, "IRQ: Wakeup flag\n"); |
348 | #endif | 348 | #endif |
349 | 349 | ||
350 | isl38xx_handle_wakeup(priv->control_block, | 350 | isl38xx_handle_wakeup(priv->control_block, |
@@ -635,7 +635,7 @@ islpci_alloc_memory(islpci_private *priv) | |||
635 | ioremap(pci_resource_start(priv->pdev, 0), | 635 | ioremap(pci_resource_start(priv->pdev, 0), |
636 | ISL38XX_PCI_MEM_SIZE))) { | 636 | ISL38XX_PCI_MEM_SIZE))) { |
637 | /* error in remapping the PCI device memory address range */ | 637 | /* error in remapping the PCI device memory address range */ |
638 | printk(KERN_ERR "PCI memory remapping failed \n"); | 638 | printk(KERN_ERR "PCI memory remapping failed\n"); |
639 | return -1; | 639 | return -1; |
640 | } | 640 | } |
641 | 641 | ||
@@ -902,7 +902,7 @@ islpci_setup(struct pci_dev *pdev) | |||
902 | 902 | ||
903 | if (register_netdev(ndev)) { | 903 | if (register_netdev(ndev)) { |
904 | DEBUG(SHOW_ERROR_MESSAGES, | 904 | DEBUG(SHOW_ERROR_MESSAGES, |
905 | "ERROR: register_netdev() failed \n"); | 905 | "ERROR: register_netdev() failed\n"); |
906 | goto do_islpci_free_memory; | 906 | goto do_islpci_free_memory; |
907 | } | 907 | } |
908 | 908 | ||
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index ac99eaaeabce..64585da8a96c 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c | |||
@@ -90,7 +90,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) | |||
90 | u32 curr_frag; | 90 | u32 curr_frag; |
91 | 91 | ||
92 | #if VERBOSE > SHOW_ERROR_MESSAGES | 92 | #if VERBOSE > SHOW_ERROR_MESSAGES |
93 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n"); | 93 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit\n"); |
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | /* lock the driver code */ | 96 | /* lock the driver code */ |
@@ -141,7 +141,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) | |||
141 | } | 141 | } |
142 | 142 | ||
143 | #if VERBOSE > SHOW_ERROR_MESSAGES | 143 | #if VERBOSE > SHOW_ERROR_MESSAGES |
144 | DEBUG(SHOW_TRACING, "memmove %p %p %i \n", skb->data, | 144 | DEBUG(SHOW_TRACING, "memmove %p %p %i\n", skb->data, |
145 | src, skb->len); | 145 | src, skb->len); |
146 | #endif | 146 | #endif |
147 | } else { | 147 | } else { |
@@ -320,7 +320,7 @@ islpci_eth_receive(islpci_private *priv) | |||
320 | int discard = 0; | 320 | int discard = 0; |
321 | 321 | ||
322 | #if VERBOSE > SHOW_ERROR_MESSAGES | 322 | #if VERBOSE > SHOW_ERROR_MESSAGES |
323 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive \n"); | 323 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive\n"); |
324 | #endif | 324 | #endif |
325 | 325 | ||
326 | /* the device has written an Ethernet frame in the data area | 326 | /* the device has written an Ethernet frame in the data area |
@@ -432,7 +432,7 @@ islpci_eth_receive(islpci_private *priv) | |||
432 | skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); | 432 | skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); |
433 | if (unlikely(skb == NULL)) { | 433 | if (unlikely(skb == NULL)) { |
434 | /* error allocating an sk_buff structure elements */ | 434 | /* error allocating an sk_buff structure elements */ |
435 | DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n"); | 435 | DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb\n"); |
436 | break; | 436 | break; |
437 | } | 437 | } |
438 | skb_reserve(skb, (4 - (long) skb->data) & 0x03); | 438 | skb_reserve(skb, (4 - (long) skb->data) & 0x03); |
diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index adb289723a96..a5224f6160e4 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c | |||
@@ -114,7 +114,7 @@ islpci_mgmt_rx_fill(struct net_device *ndev) | |||
114 | u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); | 114 | u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); |
115 | 115 | ||
116 | #if VERBOSE > SHOW_ERROR_MESSAGES | 116 | #if VERBOSE > SHOW_ERROR_MESSAGES |
117 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill \n"); | 117 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill\n"); |
118 | #endif | 118 | #endif |
119 | 119 | ||
120 | while (curr - priv->index_mgmt_rx < ISL38XX_CB_MGMT_QSIZE) { | 120 | while (curr - priv->index_mgmt_rx < ISL38XX_CB_MGMT_QSIZE) { |
@@ -212,7 +212,7 @@ islpci_mgt_transmit(struct net_device *ndev, int operation, unsigned long oid, | |||
212 | { | 212 | { |
213 | pimfor_header_t *h = buf.mem; | 213 | pimfor_header_t *h = buf.mem; |
214 | DEBUG(SHOW_PIMFOR_FRAMES, | 214 | DEBUG(SHOW_PIMFOR_FRAMES, |
215 | "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x \n", | 215 | "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x\n", |
216 | h->operation, oid, h->device_id, h->flags, length); | 216 | h->operation, oid, h->device_id, h->flags, length); |
217 | 217 | ||
218 | /* display the buffer contents for debugging */ | 218 | /* display the buffer contents for debugging */ |
@@ -280,7 +280,7 @@ islpci_mgt_receive(struct net_device *ndev) | |||
280 | u32 curr_frag; | 280 | u32 curr_frag; |
281 | 281 | ||
282 | #if VERBOSE > SHOW_ERROR_MESSAGES | 282 | #if VERBOSE > SHOW_ERROR_MESSAGES |
283 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n"); | 283 | DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive\n"); |
284 | #endif | 284 | #endif |
285 | 285 | ||
286 | /* Only once per interrupt, determine fragment range to | 286 | /* Only once per interrupt, determine fragment range to |
@@ -339,7 +339,7 @@ islpci_mgt_receive(struct net_device *ndev) | |||
339 | 339 | ||
340 | #if VERBOSE > SHOW_ERROR_MESSAGES | 340 | #if VERBOSE > SHOW_ERROR_MESSAGES |
341 | DEBUG(SHOW_PIMFOR_FRAMES, | 341 | DEBUG(SHOW_PIMFOR_FRAMES, |
342 | "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n", | 342 | "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x\n", |
343 | header->operation, header->oid, header->device_id, | 343 | header->operation, header->oid, header->device_id, |
344 | header->flags, header->length); | 344 | header->flags, header->length); |
345 | 345 | ||
diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index d66933d70fb9..9b796cae4afe 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c | |||
@@ -820,7 +820,7 @@ mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str) | |||
820 | k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); | 820 | k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); |
821 | for (i = 0; i < list->nr; i++) | 821 | for (i = 0; i < list->nr; i++) |
822 | k += snprintf(str + k, PRIV_STR_SIZE - k, | 822 | k += snprintf(str + k, PRIV_STR_SIZE - k, |
823 | "bss[%u] : \nage=%u\nchannel=%u\n" | 823 | "bss[%u] :\nage=%u\nchannel=%u\n" |
824 | "capinfo=0x%X\nrates=0x%X\n" | 824 | "capinfo=0x%X\nrates=0x%X\n" |
825 | "basic_rates=0x%X\n", | 825 | "basic_rates=0x%X\n", |
826 | i, list->bsslist[i].age, | 826 | i, list->bsslist[i].age, |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 2940d7d3775e..d9c45bfcee61 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -555,7 +555,7 @@ static int ray_init(struct net_device *dev) | |||
555 | local->fw_ver = local->startup_res.firmware_version[0]; | 555 | local->fw_ver = local->startup_res.firmware_version[0]; |
556 | local->fw_bld = local->startup_res.firmware_version[1]; | 556 | local->fw_bld = local->startup_res.firmware_version[1]; |
557 | local->fw_var = local->startup_res.firmware_version[2]; | 557 | local->fw_var = local->startup_res.firmware_version[2]; |
558 | dev_dbg(&link->dev, "ray_init firmware version %d.%d \n", local->fw_ver, | 558 | dev_dbg(&link->dev, "ray_init firmware version %d.%d\n", local->fw_ver, |
559 | local->fw_bld); | 559 | local->fw_bld); |
560 | 560 | ||
561 | local->tib_length = 0x20; | 561 | local->tib_length = 0x20; |
@@ -2233,7 +2233,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, | |||
2233 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + | 2233 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + |
2234 | FCS_LEN)) { | 2234 | FCS_LEN)) { |
2235 | pr_debug( | 2235 | pr_debug( |
2236 | "ray_cs invalid packet length %d received \n", | 2236 | "ray_cs invalid packet length %d received\n", |
2237 | rx_len); | 2237 | rx_len); |
2238 | return; | 2238 | return; |
2239 | } | 2239 | } |
@@ -2244,7 +2244,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, | |||
2244 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + | 2244 | (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + |
2245 | FCS_LEN)) { | 2245 | FCS_LEN)) { |
2246 | pr_debug( | 2246 | pr_debug( |
2247 | "ray_cs invalid packet length %d received \n", | 2247 | "ray_cs invalid packet length %d received\n", |
2248 | rx_len); | 2248 | rx_len); |
2249 | return; | 2249 | return; |
2250 | } | 2250 | } |
@@ -2752,11 +2752,11 @@ static int ray_cs_proc_show(struct seq_file *m, void *v) | |||
2752 | seq_printf(m, "Hop dwell = %d Kus\n", | 2752 | seq_printf(m, "Hop dwell = %d Kus\n", |
2753 | pfh->dwell_time[0] + | 2753 | pfh->dwell_time[0] + |
2754 | 256 * pfh->dwell_time[1]); | 2754 | 256 * pfh->dwell_time[1]); |
2755 | seq_printf(m, "Hop set = %d \n", | 2755 | seq_printf(m, "Hop set = %d\n", |
2756 | pfh->hop_set); | 2756 | pfh->hop_set); |
2757 | seq_printf(m, "Hop pattern = %d \n", | 2757 | seq_printf(m, "Hop pattern = %d\n", |
2758 | pfh->hop_pattern); | 2758 | pfh->hop_pattern); |
2759 | seq_printf(m, "Hop index = %d \n", | 2759 | seq_printf(m, "Hop index = %d\n", |
2760 | pfh->hop_index); | 2760 | pfh->hop_index); |
2761 | p += p[1] + 2; | 2761 | p += p[1] + 2; |
2762 | } else { | 2762 | } else { |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 5f5204b82891..cdbf59108ef9 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -526,6 +526,10 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
526 | 526 | ||
527 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); | 527 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); |
528 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 528 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); |
529 | } else { | ||
530 | rt2x00pci_register_read(rt2x00dev, CSR20, ®); | ||
531 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); | ||
532 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | ||
529 | } | 533 | } |
530 | 534 | ||
531 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 535 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 2a73f593aab0..89e986f449da 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -574,6 +574,10 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, | |||
574 | 574 | ||
575 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); | 575 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); |
576 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | 576 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); |
577 | } else { | ||
578 | rt2x00pci_register_read(rt2x00dev, CSR20, ®); | ||
579 | rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); | ||
580 | rt2x00pci_register_write(rt2x00dev, CSR20, reg); | ||
577 | } | 581 | } |
578 | 582 | ||
579 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 583 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8ebb705fe106..7185cb05f257 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -649,6 +649,10 @@ static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, | |||
649 | 649 | ||
650 | rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 1); | 650 | rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 1); |
651 | rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); | 651 | rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); |
652 | } else { | ||
653 | rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); | ||
654 | rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 0); | ||
655 | rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); | ||
652 | } | 656 | } |
653 | 657 | ||
654 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 658 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
@@ -1644,11 +1648,6 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1644 | unsigned int i; | 1648 | unsigned int i; |
1645 | 1649 | ||
1646 | /* | 1650 | /* |
1647 | * Disable powersaving as default. | ||
1648 | */ | ||
1649 | rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
1650 | |||
1651 | /* | ||
1652 | * Initialize all hw fields. | 1651 | * Initialize all hw fields. |
1653 | */ | 1652 | */ |
1654 | rt2x00dev->hw->flags = | 1653 | rt2x00dev->hw->flags = |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 74c0433dba37..ec893721cc80 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -56,15 +56,20 @@ | |||
56 | #define RF3021 0x0007 | 56 | #define RF3021 0x0007 |
57 | #define RF3022 0x0008 | 57 | #define RF3022 0x0008 |
58 | #define RF3052 0x0009 | 58 | #define RF3052 0x0009 |
59 | #define RF3320 0x000b | ||
59 | 60 | ||
60 | /* | 61 | /* |
61 | * Chipset version. | 62 | * Chipset revisions. |
62 | */ | 63 | */ |
63 | #define RT2860C_VERSION 0x0100 | 64 | #define REV_RT2860C 0x0100 |
64 | #define RT2860D_VERSION 0x0101 | 65 | #define REV_RT2860D 0x0101 |
65 | #define RT2880E_VERSION 0x0200 | 66 | #define REV_RT2870D 0x0101 |
66 | #define RT2883_VERSION 0x0300 | 67 | #define REV_RT2872E 0x0200 |
67 | #define RT3070_VERSION 0x0200 | 68 | #define REV_RT3070E 0x0200 |
69 | #define REV_RT3070F 0x0201 | ||
70 | #define REV_RT3071E 0x0211 | ||
71 | #define REV_RT3090E 0x0211 | ||
72 | #define REV_RT3390E 0x0211 | ||
68 | 73 | ||
69 | /* | 74 | /* |
70 | * Signal information. | 75 | * Signal information. |
@@ -90,10 +95,16 @@ | |||
90 | #define NUM_TX_QUEUES 4 | 95 | #define NUM_TX_QUEUES 4 |
91 | 96 | ||
92 | /* | 97 | /* |
93 | * USB registers. | 98 | * Registers. |
94 | */ | 99 | */ |
95 | 100 | ||
96 | /* | 101 | /* |
102 | * OPT_14: Unknown register used by rt3xxx devices. | ||
103 | */ | ||
104 | #define OPT_14_CSR 0x0114 | ||
105 | #define OPT_14_CSR_BIT0 FIELD32(0x00000001) | ||
106 | |||
107 | /* | ||
97 | * INT_SOURCE_CSR: Interrupt source register. | 108 | * INT_SOURCE_CSR: Interrupt source register. |
98 | * Write one to clear corresponding bit. | 109 | * Write one to clear corresponding bit. |
99 | * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c | 110 | * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c |
@@ -398,6 +409,31 @@ | |||
398 | #define EFUSE_DATA3 0x059c | 409 | #define EFUSE_DATA3 0x059c |
399 | 410 | ||
400 | /* | 411 | /* |
412 | * LDO_CFG0 | ||
413 | */ | ||
414 | #define LDO_CFG0 0x05d4 | ||
415 | #define LDO_CFG0_DELAY3 FIELD32(0x000000ff) | ||
416 | #define LDO_CFG0_DELAY2 FIELD32(0x0000ff00) | ||
417 | #define LDO_CFG0_DELAY1 FIELD32(0x00ff0000) | ||
418 | #define LDO_CFG0_BGSEL FIELD32(0x03000000) | ||
419 | #define LDO_CFG0_LDO_CORE_VLEVEL FIELD32(0x1c000000) | ||
420 | #define LD0_CFG0_LDO25_LEVEL FIELD32(0x60000000) | ||
421 | #define LDO_CFG0_LDO25_LARGEA FIELD32(0x80000000) | ||
422 | |||
423 | /* | ||
424 | * GPIO_SWITCH | ||
425 | */ | ||
426 | #define GPIO_SWITCH 0x05dc | ||
427 | #define GPIO_SWITCH_0 FIELD32(0x00000001) | ||
428 | #define GPIO_SWITCH_1 FIELD32(0x00000002) | ||
429 | #define GPIO_SWITCH_2 FIELD32(0x00000004) | ||
430 | #define GPIO_SWITCH_3 FIELD32(0x00000008) | ||
431 | #define GPIO_SWITCH_4 FIELD32(0x00000010) | ||
432 | #define GPIO_SWITCH_5 FIELD32(0x00000020) | ||
433 | #define GPIO_SWITCH_6 FIELD32(0x00000040) | ||
434 | #define GPIO_SWITCH_7 FIELD32(0x00000080) | ||
435 | |||
436 | /* | ||
401 | * MAC Control/Status Registers(CSR). | 437 | * MAC Control/Status Registers(CSR). |
402 | * Some values are set in TU, whereas 1 TU == 1024 us. | 438 | * Some values are set in TU, whereas 1 TU == 1024 us. |
403 | */ | 439 | */ |
@@ -1492,14 +1528,32 @@ struct mac_iveiv_entry { | |||
1492 | #define BBP4_BANDWIDTH FIELD8(0x18) | 1528 | #define BBP4_BANDWIDTH FIELD8(0x18) |
1493 | 1529 | ||
1494 | /* | 1530 | /* |
1531 | * BBP 138: Unknown | ||
1532 | */ | ||
1533 | #define BBP138_RX_ADC1 FIELD8(0x02) | ||
1534 | #define BBP138_RX_ADC2 FIELD8(0x04) | ||
1535 | #define BBP138_TX_DAC1 FIELD8(0x20) | ||
1536 | #define BBP138_TX_DAC2 FIELD8(0x40) | ||
1537 | |||
1538 | /* | ||
1495 | * RFCSR registers | 1539 | * RFCSR registers |
1496 | * The wordsize of the RFCSR is 8 bits. | 1540 | * The wordsize of the RFCSR is 8 bits. |
1497 | */ | 1541 | */ |
1498 | 1542 | ||
1499 | /* | 1543 | /* |
1544 | * RFCSR 1: | ||
1545 | */ | ||
1546 | #define RFCSR1_RF_BLOCK_EN FIELD8(0x01) | ||
1547 | #define RFCSR1_RX0_PD FIELD8(0x04) | ||
1548 | #define RFCSR1_TX0_PD FIELD8(0x08) | ||
1549 | #define RFCSR1_RX1_PD FIELD8(0x10) | ||
1550 | #define RFCSR1_TX1_PD FIELD8(0x20) | ||
1551 | |||
1552 | /* | ||
1500 | * RFCSR 6: | 1553 | * RFCSR 6: |
1501 | */ | 1554 | */ |
1502 | #define RFCSR6_R FIELD8(0x03) | 1555 | #define RFCSR6_R1 FIELD8(0x03) |
1556 | #define RFCSR6_R2 FIELD8(0x40) | ||
1503 | 1557 | ||
1504 | /* | 1558 | /* |
1505 | * RFCSR 7: | 1559 | * RFCSR 7: |
@@ -1512,6 +1566,28 @@ struct mac_iveiv_entry { | |||
1512 | #define RFCSR12_TX_POWER FIELD8(0x1f) | 1566 | #define RFCSR12_TX_POWER FIELD8(0x1f) |
1513 | 1567 | ||
1514 | /* | 1568 | /* |
1569 | * RFCSR 15: | ||
1570 | */ | ||
1571 | #define RFCSR15_TX_LO2_EN FIELD8(0x08) | ||
1572 | |||
1573 | /* | ||
1574 | * RFCSR 17: | ||
1575 | */ | ||
1576 | #define RFCSR17_TXMIXER_GAIN FIELD8(0x07) | ||
1577 | #define RFCSR17_TX_LO1_EN FIELD8(0x08) | ||
1578 | #define RFCSR17_R FIELD8(0x20) | ||
1579 | |||
1580 | /* | ||
1581 | * RFCSR 20: | ||
1582 | */ | ||
1583 | #define RFCSR20_RX_LO1_EN FIELD8(0x08) | ||
1584 | |||
1585 | /* | ||
1586 | * RFCSR 21: | ||
1587 | */ | ||
1588 | #define RFCSR21_RX_LO2_EN FIELD8(0x08) | ||
1589 | |||
1590 | /* | ||
1515 | * RFCSR 22: | 1591 | * RFCSR 22: |
1516 | */ | 1592 | */ |
1517 | #define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01) | 1593 | #define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01) |
@@ -1522,6 +1598,14 @@ struct mac_iveiv_entry { | |||
1522 | #define RFCSR23_FREQ_OFFSET FIELD8(0x7f) | 1598 | #define RFCSR23_FREQ_OFFSET FIELD8(0x7f) |
1523 | 1599 | ||
1524 | /* | 1600 | /* |
1601 | * RFCSR 27: | ||
1602 | */ | ||
1603 | #define RFCSR27_R1 FIELD8(0x03) | ||
1604 | #define RFCSR27_R2 FIELD8(0x04) | ||
1605 | #define RFCSR27_R3 FIELD8(0x30) | ||
1606 | #define RFCSR27_R4 FIELD8(0x40) | ||
1607 | |||
1608 | /* | ||
1525 | * RFCSR 30: | 1609 | * RFCSR 30: |
1526 | */ | 1610 | */ |
1527 | #define RFCSR30_RF_CALIBRATION FIELD8(0x80) | 1611 | #define RFCSR30_RF_CALIBRATION FIELD8(0x80) |
@@ -1603,6 +1687,8 @@ struct mac_iveiv_entry { | |||
1603 | #define EEPROM_NIC_WPS_PBC FIELD16(0x0080) | 1687 | #define EEPROM_NIC_WPS_PBC FIELD16(0x0080) |
1604 | #define EEPROM_NIC_BW40M_BG FIELD16(0x0100) | 1688 | #define EEPROM_NIC_BW40M_BG FIELD16(0x0100) |
1605 | #define EEPROM_NIC_BW40M_A FIELD16(0x0200) | 1689 | #define EEPROM_NIC_BW40M_A FIELD16(0x0200) |
1690 | #define EEPROM_NIC_ANT_DIVERSITY FIELD16(0x0800) | ||
1691 | #define EEPROM_NIC_DAC_TEST FIELD16(0x8000) | ||
1606 | 1692 | ||
1607 | /* | 1693 | /* |
1608 | * EEPROM frequency | 1694 | * EEPROM frequency |
@@ -1659,6 +1745,12 @@ struct mac_iveiv_entry { | |||
1659 | #define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) | 1745 | #define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) |
1660 | 1746 | ||
1661 | /* | 1747 | /* |
1748 | * EEPROM TXMIXER GAIN BG offset (note overlaps with EEPROM RSSI BG2). | ||
1749 | */ | ||
1750 | #define EEPROM_TXMIXER_GAIN_BG 0x0024 | ||
1751 | #define EEPROM_TXMIXER_GAIN_BG_VAL FIELD16(0x0007) | ||
1752 | |||
1753 | /* | ||
1662 | * EEPROM RSSI A offset | 1754 | * EEPROM RSSI A offset |
1663 | */ | 1755 | */ |
1664 | #define EEPROM_RSSI_A 0x0025 | 1756 | #define EEPROM_RSSI_A 0x0025 |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index c015ce9fdd09..2648f315a934 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -360,11 +360,6 @@ static int rt2800_blink_set(struct led_classdev *led_cdev, | |||
360 | rt2800_register_read(led->rt2x00dev, LED_CFG, ®); | 360 | rt2800_register_read(led->rt2x00dev, LED_CFG, ®); |
361 | rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); | 361 | rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); |
362 | rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); | 362 | rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); |
363 | rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); | ||
364 | rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); | ||
365 | rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 3); | ||
366 | rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); | ||
367 | rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); | ||
368 | rt2800_register_write(led->rt2x00dev, LED_CFG, reg); | 363 | rt2800_register_write(led->rt2x00dev, LED_CFG, reg); |
369 | 364 | ||
370 | return 0; | 365 | return 0; |
@@ -610,10 +605,6 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) | |||
610 | { | 605 | { |
611 | u32 reg; | 606 | u32 reg; |
612 | 607 | ||
613 | rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); | ||
614 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); | ||
615 | rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); | ||
616 | |||
617 | rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); | 608 | rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); |
618 | rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, | 609 | rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, |
619 | !!erp->short_preamble); | 610 | !!erp->short_preamble); |
@@ -632,15 +623,12 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp) | |||
632 | 623 | ||
633 | rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); | 624 | rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); |
634 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); | 625 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); |
635 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); | ||
636 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); | 626 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); |
637 | 627 | ||
638 | rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); | 628 | rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); |
639 | rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); | 629 | rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); |
640 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); | 630 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); |
641 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); | ||
642 | rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); | 631 | rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); |
643 | rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); | ||
644 | rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); | 632 | rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); |
645 | 633 | ||
646 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); | 634 | rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); |
@@ -718,10 +706,10 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, | |||
718 | rt2x00dev->lna_gain = lna_gain; | 706 | rt2x00dev->lna_gain = lna_gain; |
719 | } | 707 | } |
720 | 708 | ||
721 | static void rt2800_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, | 709 | static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev, |
722 | struct ieee80211_conf *conf, | 710 | struct ieee80211_conf *conf, |
723 | struct rf_channel *rf, | 711 | struct rf_channel *rf, |
724 | struct channel_info *info) | 712 | struct channel_info *info) |
725 | { | 713 | { |
726 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | 714 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); |
727 | 715 | ||
@@ -787,10 +775,10 @@ static void rt2800_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, | |||
787 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); | 775 | rt2800_rf_write(rt2x00dev, 4, rf->rf4); |
788 | } | 776 | } |
789 | 777 | ||
790 | static void rt2800_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, | 778 | static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, |
791 | struct ieee80211_conf *conf, | 779 | struct ieee80211_conf *conf, |
792 | struct rf_channel *rf, | 780 | struct rf_channel *rf, |
793 | struct channel_info *info) | 781 | struct channel_info *info) |
794 | { | 782 | { |
795 | u8 rfcsr; | 783 | u8 rfcsr; |
796 | 784 | ||
@@ -798,7 +786,7 @@ static void rt2800_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, | |||
798 | rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); | 786 | rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); |
799 | 787 | ||
800 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); | 788 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); |
801 | rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); | 789 | rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); |
802 | rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); | 790 | rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); |
803 | 791 | ||
804 | rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); | 792 | rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); |
@@ -827,15 +815,13 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
827 | unsigned int tx_pin; | 815 | unsigned int tx_pin; |
828 | u8 bbp; | 816 | u8 bbp; |
829 | 817 | ||
830 | if ((rt2x00_rt(rt2x00dev, RT3070) || | 818 | if (rt2x00_rf(rt2x00dev, RF2020) || |
831 | rt2x00_rt(rt2x00dev, RT3090)) && | 819 | rt2x00_rf(rt2x00dev, RF3020) || |
832 | (rt2x00_rf(rt2x00dev, RF2020) || | 820 | rt2x00_rf(rt2x00dev, RF3021) || |
833 | rt2x00_rf(rt2x00dev, RF3020) || | 821 | rt2x00_rf(rt2x00dev, RF3022)) |
834 | rt2x00_rf(rt2x00dev, RF3021) || | 822 | rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); |
835 | rt2x00_rf(rt2x00dev, RF3022))) | ||
836 | rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); | ||
837 | else | 823 | else |
838 | rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); | 824 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); |
839 | 825 | ||
840 | /* | 826 | /* |
841 | * Change BBP settings | 827 | * Change BBP settings |
@@ -899,8 +885,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
899 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); | 885 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); |
900 | rt2800_bbp_write(rt2x00dev, 3, bbp); | 886 | rt2800_bbp_write(rt2x00dev, 3, bbp); |
901 | 887 | ||
902 | if (rt2x00_rt(rt2x00dev, RT2860) && | 888 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { |
903 | (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { | ||
904 | if (conf_is_ht40(conf)) { | 889 | if (conf_is_ht40(conf)) { |
905 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); | 890 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); |
906 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 891 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
@@ -988,10 +973,6 @@ static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
988 | libconf->conf->short_frame_max_tx_count); | 973 | libconf->conf->short_frame_max_tx_count); |
989 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, | 974 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, |
990 | libconf->conf->long_frame_max_tx_count); | 975 | libconf->conf->long_frame_max_tx_count); |
991 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); | ||
992 | rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); | ||
993 | rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); | ||
994 | rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); | ||
995 | rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg); | 976 | rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg); |
996 | } | 977 | } |
997 | 978 | ||
@@ -1015,13 +996,13 @@ static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev, | |||
1015 | 996 | ||
1016 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | 997 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); |
1017 | } else { | 998 | } else { |
1018 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
1019 | |||
1020 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); | 999 | rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); |
1021 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); | 1000 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); |
1022 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); | 1001 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); |
1023 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); | 1002 | rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); |
1024 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); | 1003 | rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); |
1004 | |||
1005 | rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); | ||
1025 | } | 1006 | } |
1026 | } | 1007 | } |
1027 | 1008 | ||
@@ -1062,9 +1043,10 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats); | |||
1062 | static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | 1043 | static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) |
1063 | { | 1044 | { |
1064 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { | 1045 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { |
1065 | if (rt2x00_is_usb(rt2x00dev) && | 1046 | if (rt2x00_rt(rt2x00dev, RT3070) || |
1066 | rt2x00_rt(rt2x00dev, RT3070) && | 1047 | rt2x00_rt(rt2x00dev, RT3071) || |
1067 | (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) | 1048 | rt2x00_rt(rt2x00dev, RT3090) || |
1049 | rt2x00_rt(rt2x00dev, RT3390)) | ||
1068 | return 0x1c + (2 * rt2x00dev->lna_gain); | 1050 | return 0x1c + (2 * rt2x00dev->lna_gain); |
1069 | else | 1051 | else |
1070 | return 0x2e + rt2x00dev->lna_gain; | 1052 | return 0x2e + rt2x00dev->lna_gain; |
@@ -1095,8 +1077,7 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); | |||
1095 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | 1077 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, |
1096 | const u32 count) | 1078 | const u32 count) |
1097 | { | 1079 | { |
1098 | if (rt2x00_rt(rt2x00dev, RT2860) && | 1080 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) |
1099 | (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) | ||
1100 | return; | 1081 | return; |
1101 | 1082 | ||
1102 | /* | 1083 | /* |
@@ -1114,8 +1095,17 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner); | |||
1114 | int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | 1095 | int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) |
1115 | { | 1096 | { |
1116 | u32 reg; | 1097 | u32 reg; |
1098 | u16 eeprom; | ||
1117 | unsigned int i; | 1099 | unsigned int i; |
1118 | 1100 | ||
1101 | rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); | ||
1102 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); | ||
1103 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); | ||
1104 | rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); | ||
1105 | rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); | ||
1106 | rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); | ||
1107 | rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); | ||
1108 | |||
1119 | if (rt2x00_is_usb(rt2x00dev)) { | 1109 | if (rt2x00_is_usb(rt2x00dev)) { |
1120 | /* | 1110 | /* |
1121 | * Wait until BBP and RF are ready. | 1111 | * Wait until BBP and RF are ready. |
@@ -1135,8 +1125,25 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1135 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); | 1125 | rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); |
1136 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, | 1126 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, |
1137 | reg & ~0x00002000); | 1127 | reg & ~0x00002000); |
1138 | } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) | 1128 | } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { |
1129 | /* | ||
1130 | * Reset DMA indexes | ||
1131 | */ | ||
1132 | rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
1133 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
1134 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
1135 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
1136 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
1137 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
1138 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
1139 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
1140 | rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
1141 | |||
1142 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
1143 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
1144 | |||
1139 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | 1145 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); |
1146 | } | ||
1140 | 1147 | ||
1141 | rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); | 1148 | rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); |
1142 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); | 1149 | rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); |
@@ -1181,12 +1188,42 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1181 | rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); | 1188 | rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); |
1182 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1189 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
1183 | 1190 | ||
1184 | if (rt2x00_is_usb(rt2x00dev) && | 1191 | rt2800_config_filter(rt2x00dev, FIF_ALLMULTI); |
1185 | rt2x00_rt(rt2x00dev, RT3070) && | 1192 | |
1186 | (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { | 1193 | rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); |
1194 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, 9); | ||
1195 | rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); | ||
1196 | rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); | ||
1197 | |||
1198 | if (rt2x00_rt(rt2x00dev, RT3071) || | ||
1199 | rt2x00_rt(rt2x00dev, RT3090) || | ||
1200 | rt2x00_rt(rt2x00dev, RT3390)) { | ||
1187 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 1201 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); |
1188 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); | 1202 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); |
1189 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 1203 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || |
1204 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | ||
1205 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { | ||
1206 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); | ||
1207 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) | ||
1208 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, | ||
1209 | 0x0000002c); | ||
1210 | else | ||
1211 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, | ||
1212 | 0x0000000f); | ||
1213 | } else { | ||
1214 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | ||
1215 | } | ||
1216 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, reg); | ||
1217 | } else if (rt2x00_rt(rt2x00dev, RT3070)) { | ||
1218 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | ||
1219 | |||
1220 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { | ||
1221 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); | ||
1222 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000002c); | ||
1223 | } else { | ||
1224 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | ||
1225 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | ||
1226 | } | ||
1190 | } else { | 1227 | } else { |
1191 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); | 1228 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); |
1192 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); | 1229 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); |
@@ -1205,19 +1242,15 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1205 | 1242 | ||
1206 | rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); | 1243 | rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); |
1207 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); | 1244 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); |
1245 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 32); | ||
1208 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); | 1246 | rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); |
1209 | rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); | 1247 | rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); |
1210 | 1248 | ||
1211 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); | 1249 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); |
1212 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); | 1250 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); |
1213 | if ((rt2x00_rt(rt2x00dev, RT2872) && | 1251 | if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) || |
1214 | (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION)) || | ||
1215 | rt2x00_rt(rt2x00dev, RT2880) || | ||
1216 | rt2x00_rt(rt2x00dev, RT2883) || | 1252 | rt2x00_rt(rt2x00dev, RT2883) || |
1217 | rt2x00_rt(rt2x00dev, RT2890) || | 1253 | rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) |
1218 | rt2x00_rt(rt2x00dev, RT3052) || | ||
1219 | (rt2x00_rt(rt2x00dev, RT3070) && | ||
1220 | (rt2x00_rev(rt2x00dev) < RT3070_VERSION))) | ||
1221 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); | 1254 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); |
1222 | else | 1255 | else |
1223 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); | 1256 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); |
@@ -1225,38 +1258,61 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1225 | rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); | 1258 | rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); |
1226 | rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg); | 1259 | rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg); |
1227 | 1260 | ||
1261 | rt2800_register_read(rt2x00dev, LED_CFG, ®); | ||
1262 | rt2x00_set_field32(®, LED_CFG_ON_PERIOD, 70); | ||
1263 | rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, 30); | ||
1264 | rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); | ||
1265 | rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); | ||
1266 | rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 3); | ||
1267 | rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); | ||
1268 | rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); | ||
1269 | rt2800_register_write(rt2x00dev, LED_CFG, reg); | ||
1270 | |||
1228 | rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); | 1271 | rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); |
1229 | 1272 | ||
1273 | rt2800_register_read(rt2x00dev, TX_RTY_CFG, ®); | ||
1274 | rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, 15); | ||
1275 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, 31); | ||
1276 | rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); | ||
1277 | rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); | ||
1278 | rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); | ||
1279 | rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); | ||
1280 | rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg); | ||
1281 | |||
1230 | rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); | 1282 | rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, ®); |
1231 | rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); | 1283 | rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); |
1284 | rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, 1); | ||
1232 | rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); | 1285 | rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); |
1233 | rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); | 1286 | rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); |
1287 | rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, 1); | ||
1234 | rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); | 1288 | rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); |
1235 | rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); | 1289 | rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); |
1236 | rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); | 1290 | rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg); |
1237 | 1291 | ||
1238 | rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®); | 1292 | rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®); |
1239 | rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 8); | 1293 | rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 3); |
1240 | rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); | 1294 | rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); |
1241 | rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); | 1295 | rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); |
1242 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); | 1296 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); |
1243 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | 1297 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); |
1244 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); | 1298 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); |
1245 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1); | 1299 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0); |
1246 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); | 1300 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); |
1247 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); | 1301 | rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 0); |
1302 | rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, 1); | ||
1248 | rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg); | 1303 | rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg); |
1249 | 1304 | ||
1250 | rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); | 1305 | rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®); |
1251 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 8); | 1306 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 3); |
1252 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); | 1307 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); |
1253 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); | 1308 | rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); |
1254 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); | 1309 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); |
1255 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | 1310 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); |
1256 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); | 1311 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); |
1257 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1); | 1312 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0); |
1258 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); | 1313 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); |
1259 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); | 1314 | rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 0); |
1315 | rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, 1); | ||
1260 | rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); | 1316 | rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg); |
1261 | 1317 | ||
1262 | rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®); | 1318 | rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®); |
@@ -1269,11 +1325,13 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1269 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); | 1325 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); |
1270 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); | 1326 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); |
1271 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); | 1327 | rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); |
1328 | rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, 0); | ||
1272 | rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg); | 1329 | rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg); |
1273 | 1330 | ||
1274 | rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); | 1331 | rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®); |
1275 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); | 1332 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); |
1276 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); | 1333 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, |
1334 | !rt2x00_is_usb(rt2x00dev)); | ||
1277 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); | 1335 | rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); |
1278 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); | 1336 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); |
1279 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); | 1337 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); |
@@ -1281,6 +1339,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1281 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); | 1339 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); |
1282 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); | 1340 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); |
1283 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); | 1341 | rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); |
1342 | rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, 0); | ||
1284 | rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg); | 1343 | rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg); |
1285 | 1344 | ||
1286 | rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®); | 1345 | rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®); |
@@ -1293,6 +1352,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1293 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); | 1352 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); |
1294 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); | 1353 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); |
1295 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); | 1354 | rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); |
1355 | rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, 0); | ||
1296 | rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg); | 1356 | rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg); |
1297 | 1357 | ||
1298 | rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®); | 1358 | rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®); |
@@ -1305,6 +1365,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1305 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); | 1365 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); |
1306 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); | 1366 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); |
1307 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); | 1367 | rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); |
1368 | rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, 0); | ||
1308 | rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); | 1369 | rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg); |
1309 | 1370 | ||
1310 | if (rt2x00_is_usb(rt2x00dev)) { | 1371 | if (rt2x00_is_usb(rt2x00dev)) { |
@@ -1334,6 +1395,15 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1334 | rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg); | 1395 | rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg); |
1335 | 1396 | ||
1336 | rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); | 1397 | rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); |
1398 | |||
1399 | rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, ®); | ||
1400 | rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, 32); | ||
1401 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, 32); | ||
1402 | rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); | ||
1403 | rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, 314); | ||
1404 | rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); | ||
1405 | rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg); | ||
1406 | |||
1337 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); | 1407 | rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); |
1338 | 1408 | ||
1339 | /* | 1409 | /* |
@@ -1483,38 +1553,67 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1483 | 1553 | ||
1484 | rt2800_bbp_write(rt2x00dev, 65, 0x2c); | 1554 | rt2800_bbp_write(rt2x00dev, 65, 0x2c); |
1485 | rt2800_bbp_write(rt2x00dev, 66, 0x38); | 1555 | rt2800_bbp_write(rt2x00dev, 66, 0x38); |
1486 | rt2800_bbp_write(rt2x00dev, 69, 0x12); | 1556 | |
1557 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) { | ||
1558 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | ||
1559 | rt2800_bbp_write(rt2x00dev, 73, 0x12); | ||
1560 | } else { | ||
1561 | rt2800_bbp_write(rt2x00dev, 69, 0x12); | ||
1562 | rt2800_bbp_write(rt2x00dev, 73, 0x10); | ||
1563 | } | ||
1564 | |||
1487 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 1565 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
1488 | rt2800_bbp_write(rt2x00dev, 73, 0x10); | 1566 | |
1489 | rt2800_bbp_write(rt2x00dev, 81, 0x37); | 1567 | if (rt2x00_rt(rt2x00dev, RT3070) || |
1568 | rt2x00_rt(rt2x00dev, RT3071) || | ||
1569 | rt2x00_rt(rt2x00dev, RT3090) || | ||
1570 | rt2x00_rt(rt2x00dev, RT3390)) { | ||
1571 | rt2800_bbp_write(rt2x00dev, 79, 0x13); | ||
1572 | rt2800_bbp_write(rt2x00dev, 80, 0x05); | ||
1573 | rt2800_bbp_write(rt2x00dev, 81, 0x33); | ||
1574 | } else { | ||
1575 | rt2800_bbp_write(rt2x00dev, 81, 0x37); | ||
1576 | } | ||
1577 | |||
1490 | rt2800_bbp_write(rt2x00dev, 82, 0x62); | 1578 | rt2800_bbp_write(rt2x00dev, 82, 0x62); |
1491 | rt2800_bbp_write(rt2x00dev, 83, 0x6a); | 1579 | rt2800_bbp_write(rt2x00dev, 83, 0x6a); |
1492 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | 1580 | |
1581 | if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D) || | ||
1582 | rt2x00_rt_rev(rt2x00dev, RT2870, REV_RT2870D)) | ||
1583 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | ||
1584 | else | ||
1585 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | ||
1586 | |||
1493 | rt2800_bbp_write(rt2x00dev, 86, 0x00); | 1587 | rt2800_bbp_write(rt2x00dev, 86, 0x00); |
1494 | rt2800_bbp_write(rt2x00dev, 91, 0x04); | 1588 | rt2800_bbp_write(rt2x00dev, 91, 0x04); |
1495 | rt2800_bbp_write(rt2x00dev, 92, 0x00); | 1589 | rt2800_bbp_write(rt2x00dev, 92, 0x00); |
1496 | rt2800_bbp_write(rt2x00dev, 103, 0x00); | 1590 | |
1591 | if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) || | ||
1592 | rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || | ||
1593 | rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || | ||
1594 | rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E)) | ||
1595 | rt2800_bbp_write(rt2x00dev, 103, 0xc0); | ||
1596 | else | ||
1597 | rt2800_bbp_write(rt2x00dev, 103, 0x00); | ||
1598 | |||
1497 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 1599 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
1600 | rt2800_bbp_write(rt2x00dev, 106, 0x35); | ||
1498 | 1601 | ||
1499 | if (rt2x00_rt(rt2x00dev, RT2860) && | 1602 | if (rt2x00_rt(rt2x00dev, RT3071) || |
1500 | (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) { | 1603 | rt2x00_rt(rt2x00dev, RT3090) || |
1501 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | 1604 | rt2x00_rt(rt2x00dev, RT3390)) { |
1502 | rt2800_bbp_write(rt2x00dev, 73, 0x12); | 1605 | rt2800_bbp_read(rt2x00dev, 138, &value); |
1503 | } | ||
1504 | 1606 | ||
1505 | if (rt2x00_rt(rt2x00dev, RT2860) && | 1607 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); |
1506 | (rt2x00_rev(rt2x00dev) > RT2860D_VERSION)) | 1608 | if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) |
1507 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | 1609 | value |= 0x20; |
1610 | if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) | ||
1611 | value &= ~0x02; | ||
1508 | 1612 | ||
1509 | if (rt2x00_is_usb(rt2x00dev) && | 1613 | rt2800_bbp_write(rt2x00dev, 138, value); |
1510 | rt2x00_rt(rt2x00dev, RT3070) && | ||
1511 | (rt2x00_rev(rt2x00dev) == RT3070_VERSION)) { | ||
1512 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | ||
1513 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | ||
1514 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | ||
1515 | } | 1614 | } |
1516 | 1615 | ||
1517 | if (rt2x00_rt(rt2x00dev, RT3052)) { | 1616 | if (rt2x00_rt(rt2x00dev, RT2872)) { |
1518 | rt2800_bbp_write(rt2x00dev, 31, 0x08); | 1617 | rt2800_bbp_write(rt2x00dev, 31, 0x08); |
1519 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); | 1618 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); |
1520 | rt2800_bbp_write(rt2x00dev, 80, 0x08); | 1619 | rt2800_bbp_write(rt2x00dev, 80, 0x08); |
@@ -1598,19 +1697,15 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1598 | { | 1697 | { |
1599 | u8 rfcsr; | 1698 | u8 rfcsr; |
1600 | u8 bbp; | 1699 | u8 bbp; |
1700 | u32 reg; | ||
1701 | u16 eeprom; | ||
1601 | 1702 | ||
1602 | if (rt2x00_is_usb(rt2x00dev) && | 1703 | if (!rt2x00_rt(rt2x00dev, RT3070) && |
1603 | rt2x00_rt(rt2x00dev, RT3070) && | 1704 | !rt2x00_rt(rt2x00dev, RT3071) && |
1604 | (rt2x00_rev(rt2x00dev) != RT3070_VERSION)) | 1705 | !rt2x00_rt(rt2x00dev, RT3090) && |
1706 | !rt2x00_rt(rt2x00dev, RT3390)) | ||
1605 | return 0; | 1707 | return 0; |
1606 | 1708 | ||
1607 | if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { | ||
1608 | if (!rt2x00_rf(rt2x00dev, RF3020) && | ||
1609 | !rt2x00_rf(rt2x00dev, RF3021) && | ||
1610 | !rt2x00_rf(rt2x00dev, RF3022)) | ||
1611 | return 0; | ||
1612 | } | ||
1613 | |||
1614 | /* | 1709 | /* |
1615 | * Init RF calibration. | 1710 | * Init RF calibration. |
1616 | */ | 1711 | */ |
@@ -1621,13 +1716,15 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1621 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); | 1716 | rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); |
1622 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); | 1717 | rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); |
1623 | 1718 | ||
1624 | if (rt2x00_is_usb(rt2x00dev)) { | 1719 | if (rt2x00_rt(rt2x00dev, RT3070) || |
1720 | rt2x00_rt(rt2x00dev, RT3071) || | ||
1721 | rt2x00_rt(rt2x00dev, RT3090)) { | ||
1625 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | 1722 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); |
1626 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); | 1723 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); |
1627 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); | 1724 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); |
1628 | rt2800_rfcsr_write(rt2x00dev, 7, 0x70); | 1725 | rt2800_rfcsr_write(rt2x00dev, 7, 0x70); |
1629 | rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); | 1726 | rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); |
1630 | rt2800_rfcsr_write(rt2x00dev, 10, 0x71); | 1727 | rt2800_rfcsr_write(rt2x00dev, 10, 0x41); |
1631 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); | 1728 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); |
1632 | rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); | 1729 | rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); |
1633 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); | 1730 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); |
@@ -1640,48 +1737,88 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1640 | rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); | 1737 | rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); |
1641 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); | 1738 | rt2800_rfcsr_write(rt2x00dev, 24, 0x16); |
1642 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | 1739 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); |
1643 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); | ||
1644 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); | 1740 | rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); |
1645 | } else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) { | 1741 | } else if (rt2x00_rt(rt2x00dev, RT3390)) { |
1646 | rt2800_rfcsr_write(rt2x00dev, 0, 0x50); | 1742 | rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); |
1647 | rt2800_rfcsr_write(rt2x00dev, 1, 0x01); | 1743 | rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); |
1648 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); | 1744 | rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); |
1649 | rt2800_rfcsr_write(rt2x00dev, 3, 0x75); | 1745 | rt2800_rfcsr_write(rt2x00dev, 3, 0x62); |
1650 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); | 1746 | rt2800_rfcsr_write(rt2x00dev, 4, 0x40); |
1651 | rt2800_rfcsr_write(rt2x00dev, 5, 0x03); | 1747 | rt2800_rfcsr_write(rt2x00dev, 5, 0x8b); |
1652 | rt2800_rfcsr_write(rt2x00dev, 6, 0x02); | 1748 | rt2800_rfcsr_write(rt2x00dev, 6, 0x42); |
1653 | rt2800_rfcsr_write(rt2x00dev, 7, 0x50); | 1749 | rt2800_rfcsr_write(rt2x00dev, 7, 0x34); |
1654 | rt2800_rfcsr_write(rt2x00dev, 8, 0x39); | 1750 | rt2800_rfcsr_write(rt2x00dev, 8, 0x00); |
1655 | rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); | 1751 | rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); |
1656 | rt2800_rfcsr_write(rt2x00dev, 10, 0x60); | 1752 | rt2800_rfcsr_write(rt2x00dev, 10, 0x61); |
1657 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); | 1753 | rt2800_rfcsr_write(rt2x00dev, 11, 0x21); |
1658 | rt2800_rfcsr_write(rt2x00dev, 12, 0x75); | 1754 | rt2800_rfcsr_write(rt2x00dev, 12, 0x3b); |
1659 | rt2800_rfcsr_write(rt2x00dev, 13, 0x75); | 1755 | rt2800_rfcsr_write(rt2x00dev, 13, 0xe0); |
1660 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); | 1756 | rt2800_rfcsr_write(rt2x00dev, 14, 0x90); |
1661 | rt2800_rfcsr_write(rt2x00dev, 15, 0x58); | 1757 | rt2800_rfcsr_write(rt2x00dev, 15, 0x53); |
1662 | rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); | 1758 | rt2800_rfcsr_write(rt2x00dev, 16, 0xe0); |
1663 | rt2800_rfcsr_write(rt2x00dev, 17, 0x92); | 1759 | rt2800_rfcsr_write(rt2x00dev, 17, 0x94); |
1664 | rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); | 1760 | rt2800_rfcsr_write(rt2x00dev, 18, 0x5c); |
1665 | rt2800_rfcsr_write(rt2x00dev, 19, 0x02); | 1761 | rt2800_rfcsr_write(rt2x00dev, 19, 0x4a); |
1666 | rt2800_rfcsr_write(rt2x00dev, 20, 0xba); | 1762 | rt2800_rfcsr_write(rt2x00dev, 20, 0xb2); |
1667 | rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); | 1763 | rt2800_rfcsr_write(rt2x00dev, 21, 0xf6); |
1668 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); | 1764 | rt2800_rfcsr_write(rt2x00dev, 22, 0x00); |
1669 | rt2800_rfcsr_write(rt2x00dev, 23, 0x31); | 1765 | rt2800_rfcsr_write(rt2x00dev, 23, 0x14); |
1670 | rt2800_rfcsr_write(rt2x00dev, 24, 0x08); | 1766 | rt2800_rfcsr_write(rt2x00dev, 24, 0x08); |
1671 | rt2800_rfcsr_write(rt2x00dev, 25, 0x01); | 1767 | rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); |
1672 | rt2800_rfcsr_write(rt2x00dev, 26, 0x25); | 1768 | rt2800_rfcsr_write(rt2x00dev, 26, 0x85); |
1673 | rt2800_rfcsr_write(rt2x00dev, 27, 0x23); | 1769 | rt2800_rfcsr_write(rt2x00dev, 27, 0x00); |
1674 | rt2800_rfcsr_write(rt2x00dev, 28, 0x13); | 1770 | rt2800_rfcsr_write(rt2x00dev, 28, 0x41); |
1675 | rt2800_rfcsr_write(rt2x00dev, 29, 0x83); | 1771 | rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); |
1772 | rt2800_rfcsr_write(rt2x00dev, 30, 0x20); | ||
1773 | rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); | ||
1774 | } | ||
1775 | |||
1776 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { | ||
1777 | rt2800_register_read(rt2x00dev, LDO_CFG0, ®); | ||
1778 | rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); | ||
1779 | rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); | ||
1780 | rt2800_register_write(rt2x00dev, LDO_CFG0, reg); | ||
1781 | } else if (rt2x00_rt(rt2x00dev, RT3071) || | ||
1782 | rt2x00_rt(rt2x00dev, RT3090)) { | ||
1783 | rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); | ||
1784 | rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); | ||
1785 | rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); | ||
1786 | |||
1787 | rt2800_rfcsr_write(rt2x00dev, 31, 0x14); | ||
1788 | |||
1789 | rt2800_register_read(rt2x00dev, LDO_CFG0, ®); | ||
1790 | rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); | ||
1791 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | ||
1792 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { | ||
1793 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); | ||
1794 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) | ||
1795 | rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); | ||
1796 | else | ||
1797 | rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); | ||
1798 | } | ||
1799 | rt2800_register_write(rt2x00dev, LDO_CFG0, reg); | ||
1800 | } else if (rt2x00_rt(rt2x00dev, RT3390)) { | ||
1801 | rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); | ||
1802 | rt2x00_set_field32(®, GPIO_SWITCH_5, 0); | ||
1803 | rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); | ||
1676 | } | 1804 | } |
1677 | 1805 | ||
1678 | /* | 1806 | /* |
1679 | * Set RX Filter calibration for 20MHz and 40MHz | 1807 | * Set RX Filter calibration for 20MHz and 40MHz |
1680 | */ | 1808 | */ |
1681 | rt2x00dev->calibration[0] = | 1809 | if (rt2x00_rt(rt2x00dev, RT3070)) { |
1682 | rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); | 1810 | rt2x00dev->calibration[0] = |
1683 | rt2x00dev->calibration[1] = | 1811 | rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); |
1684 | rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); | 1812 | rt2x00dev->calibration[1] = |
1813 | rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); | ||
1814 | } else if (rt2x00_rt(rt2x00dev, RT3071) || | ||
1815 | rt2x00_rt(rt2x00dev, RT3090) || | ||
1816 | rt2x00_rt(rt2x00dev, RT3390)) { | ||
1817 | rt2x00dev->calibration[0] = | ||
1818 | rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13); | ||
1819 | rt2x00dev->calibration[1] = | ||
1820 | rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15); | ||
1821 | } | ||
1685 | 1822 | ||
1686 | /* | 1823 | /* |
1687 | * Set back to initial state | 1824 | * Set back to initial state |
@@ -1699,6 +1836,81 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1699 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); | 1836 | rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); |
1700 | rt2800_bbp_write(rt2x00dev, 4, bbp); | 1837 | rt2800_bbp_write(rt2x00dev, 4, bbp); |
1701 | 1838 | ||
1839 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || | ||
1840 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | ||
1841 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | ||
1842 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) | ||
1843 | rt2800_rfcsr_write(rt2x00dev, 27, 0x03); | ||
1844 | |||
1845 | rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); | ||
1846 | rt2x00_set_field32(®, OPT_14_CSR_BIT0, 1); | ||
1847 | rt2800_register_write(rt2x00dev, OPT_14_CSR, reg); | ||
1848 | |||
1849 | rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); | ||
1850 | rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); | ||
1851 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || | ||
1852 | rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || | ||
1853 | rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { | ||
1854 | rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); | ||
1855 | if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) | ||
1856 | rt2x00_set_field8(&rfcsr, RFCSR17_R, 1); | ||
1857 | } | ||
1858 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); | ||
1859 | if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1) | ||
1860 | rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN, | ||
1861 | rt2x00_get_field16(eeprom, | ||
1862 | EEPROM_TXMIXER_GAIN_BG_VAL)); | ||
1863 | rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); | ||
1864 | |||
1865 | if (rt2x00_rt(rt2x00dev, RT3090)) { | ||
1866 | rt2800_bbp_read(rt2x00dev, 138, &bbp); | ||
1867 | |||
1868 | rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); | ||
1869 | if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) | ||
1870 | rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); | ||
1871 | if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) | ||
1872 | rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1); | ||
1873 | |||
1874 | rt2800_bbp_write(rt2x00dev, 138, bbp); | ||
1875 | } | ||
1876 | |||
1877 | if (rt2x00_rt(rt2x00dev, RT3071) || | ||
1878 | rt2x00_rt(rt2x00dev, RT3090) || | ||
1879 | rt2x00_rt(rt2x00dev, RT3390)) { | ||
1880 | rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); | ||
1881 | rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); | ||
1882 | rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); | ||
1883 | rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); | ||
1884 | rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); | ||
1885 | rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); | ||
1886 | rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); | ||
1887 | |||
1888 | rt2800_rfcsr_read(rt2x00dev, 15, &rfcsr); | ||
1889 | rt2x00_set_field8(&rfcsr, RFCSR15_TX_LO2_EN, 0); | ||
1890 | rt2800_rfcsr_write(rt2x00dev, 15, rfcsr); | ||
1891 | |||
1892 | rt2800_rfcsr_read(rt2x00dev, 20, &rfcsr); | ||
1893 | rt2x00_set_field8(&rfcsr, RFCSR20_RX_LO1_EN, 0); | ||
1894 | rt2800_rfcsr_write(rt2x00dev, 20, rfcsr); | ||
1895 | |||
1896 | rt2800_rfcsr_read(rt2x00dev, 21, &rfcsr); | ||
1897 | rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0); | ||
1898 | rt2800_rfcsr_write(rt2x00dev, 21, rfcsr); | ||
1899 | } | ||
1900 | |||
1901 | if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071)) { | ||
1902 | rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr); | ||
1903 | if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || | ||
1904 | rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) | ||
1905 | rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3); | ||
1906 | else | ||
1907 | rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0); | ||
1908 | rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0); | ||
1909 | rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0); | ||
1910 | rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0); | ||
1911 | rt2800_rfcsr_write(rt2x00dev, 27, rfcsr); | ||
1912 | } | ||
1913 | |||
1702 | return 0; | 1914 | return 0; |
1703 | } | 1915 | } |
1704 | EXPORT_SYMBOL_GPL(rt2800_init_rfcsr); | 1916 | EXPORT_SYMBOL_GPL(rt2800_init_rfcsr); |
@@ -1775,9 +1987,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1775 | } else if (rt2x00_rt(rt2x00dev, RT2860) || | 1987 | } else if (rt2x00_rt(rt2x00dev, RT2860) || |
1776 | rt2x00_rt(rt2x00dev, RT2870) || | 1988 | rt2x00_rt(rt2x00dev, RT2870) || |
1777 | rt2x00_rt(rt2x00dev, RT2872) || | 1989 | rt2x00_rt(rt2x00dev, RT2872) || |
1778 | rt2x00_rt(rt2x00dev, RT2880) || | 1990 | rt2x00_rt(rt2x00dev, RT2872)) { |
1779 | (rt2x00_rt(rt2x00dev, RT2883) && | ||
1780 | (rt2x00_rev(rt2x00dev) < RT2883_VERSION))) { | ||
1781 | /* | 1991 | /* |
1782 | * There is a max of 2 RX streams for RT28x0 series | 1992 | * There is a max of 2 RX streams for RT28x0 series |
1783 | */ | 1993 | */ |
@@ -1882,10 +2092,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1882 | if (!rt2x00_rt(rt2x00dev, RT2860) && | 2092 | if (!rt2x00_rt(rt2x00dev, RT2860) && |
1883 | !rt2x00_rt(rt2x00dev, RT2870) && | 2093 | !rt2x00_rt(rt2x00dev, RT2870) && |
1884 | !rt2x00_rt(rt2x00dev, RT2872) && | 2094 | !rt2x00_rt(rt2x00dev, RT2872) && |
1885 | !rt2x00_rt(rt2x00dev, RT2880) && | ||
1886 | !rt2x00_rt(rt2x00dev, RT2883) && | 2095 | !rt2x00_rt(rt2x00dev, RT2883) && |
1887 | !rt2x00_rt(rt2x00dev, RT2890) && | ||
1888 | !rt2x00_rt(rt2x00dev, RT3052) && | ||
1889 | !rt2x00_rt(rt2x00dev, RT3070) && | 2096 | !rt2x00_rt(rt2x00dev, RT3070) && |
1890 | !rt2x00_rt(rt2x00dev, RT3071) && | 2097 | !rt2x00_rt(rt2x00dev, RT3071) && |
1891 | !rt2x00_rt(rt2x00dev, RT3090) && | 2098 | !rt2x00_rt(rt2x00dev, RT3090) && |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index b1f5643f83fc..2131f8f0c502 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -60,6 +60,12 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
60 | unsigned int i; | 60 | unsigned int i; |
61 | u32 reg; | 61 | u32 reg; |
62 | 62 | ||
63 | /* | ||
64 | * SOC devices don't support MCU requests. | ||
65 | */ | ||
66 | if (rt2x00_is_soc(rt2x00dev)) | ||
67 | return; | ||
68 | |||
63 | for (i = 0; i < 200; i++) { | 69 | for (i = 0; i < 200; i++) { |
64 | rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); | 70 | rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); |
65 | 71 | ||
@@ -341,19 +347,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) | |||
341 | struct queue_entry_priv_pci *entry_priv; | 347 | struct queue_entry_priv_pci *entry_priv; |
342 | u32 reg; | 348 | u32 reg; |
343 | 349 | ||
344 | rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); | ||
345 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); | ||
346 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); | ||
347 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); | ||
348 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); | ||
349 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); | ||
350 | rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); | ||
351 | rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); | ||
352 | rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); | ||
353 | |||
354 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); | ||
355 | rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); | ||
356 | |||
357 | /* | 350 | /* |
358 | * Initialize registers. | 351 | * Initialize registers. |
359 | */ | 352 | */ |
@@ -1009,6 +1002,14 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
1009 | } | 1002 | } |
1010 | } | 1003 | } |
1011 | 1004 | ||
1005 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | ||
1006 | { | ||
1007 | struct ieee80211_conf conf = { .flags = 0 }; | ||
1008 | struct rt2x00lib_conf libconf = { .conf = &conf }; | ||
1009 | |||
1010 | rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | ||
1011 | } | ||
1012 | |||
1012 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | 1013 | static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) |
1013 | { | 1014 | { |
1014 | struct rt2x00_dev *rt2x00dev = dev_instance; | 1015 | struct rt2x00_dev *rt2x00dev = dev_instance; |
@@ -1033,6 +1034,9 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) | |||
1033 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | 1034 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) |
1034 | rt2800pci_txdone(rt2x00dev); | 1035 | rt2800pci_txdone(rt2x00dev); |
1035 | 1036 | ||
1037 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) | ||
1038 | rt2800pci_wakeup(rt2x00dev); | ||
1039 | |||
1036 | return IRQ_HANDLED; | 1040 | return IRQ_HANDLED; |
1037 | } | 1041 | } |
1038 | 1042 | ||
@@ -1212,6 +1216,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
1212 | { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1216 | { PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1213 | { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1217 | { PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1214 | { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, | 1218 | { PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, |
1219 | { PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) }, | ||
1215 | #endif | 1220 | #endif |
1216 | { 0, } | 1221 | { 0, } |
1217 | }; | 1222 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index d27d7d5d850c..6b809ab42c61 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -876,6 +876,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
876 | { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 876 | { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
877 | { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 877 | { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
878 | { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, | 878 | { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, |
879 | { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
880 | { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
879 | { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 881 | { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
880 | /* SMC */ | 882 | /* SMC */ |
881 | { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, | 883 | { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -905,8 +907,13 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
905 | { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | 907 | { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, |
906 | /* AirTies */ | 908 | /* AirTies */ |
907 | { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, | 909 | { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, |
910 | /* ASUS */ | ||
911 | { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
908 | /* AzureWave */ | 912 | /* AzureWave */ |
909 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, | 913 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, |
914 | { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
915 | { USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
916 | { USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
910 | /* Conceptronic */ | 917 | /* Conceptronic */ |
911 | { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, | 918 | { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, |
912 | /* Corega */ | 919 | /* Corega */ |
@@ -916,20 +923,46 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
916 | { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 923 | { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
917 | { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 924 | { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
918 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 925 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
926 | { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
927 | /* Draytek */ | ||
928 | { USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
919 | /* Edimax */ | 929 | /* Edimax */ |
920 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, | 930 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, |
921 | /* Encore */ | 931 | /* Encore */ |
922 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, | 932 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, |
933 | { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
923 | /* EnGenius */ | 934 | /* EnGenius */ |
924 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, | 935 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, |
925 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, | 936 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, |
926 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, | 937 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, |
938 | { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
939 | { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
940 | { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
927 | /* Gigabyte */ | 941 | /* Gigabyte */ |
928 | { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, | 942 | { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, |
929 | /* I-O DATA */ | 943 | /* I-O DATA */ |
930 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, | 944 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, |
945 | { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
946 | { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
947 | /* Logitec */ | ||
948 | { USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
931 | /* MSI */ | 949 | /* MSI */ |
932 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, | 950 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, |
951 | { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
952 | { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
953 | { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
954 | { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
955 | { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
956 | { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
957 | { USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
958 | { USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
959 | { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
960 | { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
961 | { USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
962 | { USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
963 | { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
964 | /* Para */ | ||
965 | { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
933 | /* Pegatron */ | 966 | /* Pegatron */ |
934 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 967 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
935 | { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 968 | { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -944,9 +977,15 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
944 | { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | 977 | { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, |
945 | /* Sitecom */ | 978 | /* Sitecom */ |
946 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 979 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
980 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
947 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | 981 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, |
982 | { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
983 | { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
948 | /* SMC */ | 984 | /* SMC */ |
949 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, | 985 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, |
986 | { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
987 | { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
988 | { USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
950 | /* Zinwell */ | 989 | /* Zinwell */ |
951 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, | 990 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, |
952 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, | 991 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -966,6 +1005,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
966 | { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1005 | { USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, |
967 | /* Sitecom */ | 1006 | /* Sitecom */ |
968 | { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1007 | { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1008 | { USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
969 | /* Zinwell */ | 1009 | /* Zinwell */ |
970 | { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1010 | { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, |
971 | #endif | 1011 | #endif |
@@ -985,18 +1025,14 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
985 | /* Amigo */ | 1025 | /* Amigo */ |
986 | { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1026 | { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, |
987 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1027 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, |
988 | /* Askey */ | ||
989 | { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
990 | /* ASUS */ | 1028 | /* ASUS */ |
991 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1029 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, |
992 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1030 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, |
993 | { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
994 | { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1031 | { USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, |
995 | { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1032 | { USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, |
996 | /* AzureWave */ | 1033 | /* AzureWave */ |
997 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1034 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, |
998 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1035 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, |
999 | { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1000 | /* Belkin */ | 1036 | /* Belkin */ |
1001 | { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1037 | { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1002 | /* Buffalo */ | 1038 | /* Buffalo */ |
@@ -1015,14 +1051,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1015 | { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1051 | { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1016 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1052 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1017 | { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1053 | { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1018 | { USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1019 | /* Encore */ | 1054 | /* Encore */ |
1020 | { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1055 | { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1021 | { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1022 | /* EnGenius */ | ||
1023 | { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1024 | { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1025 | { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1026 | /* Gemtek */ | 1056 | /* Gemtek */ |
1027 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1057 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1028 | /* Gigabyte */ | 1058 | /* Gigabyte */ |
@@ -1030,9 +1060,6 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1030 | /* Hawking */ | 1060 | /* Hawking */ |
1031 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1061 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1032 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1062 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1033 | /* I-O DATA */ | ||
1034 | { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1035 | { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1036 | /* LevelOne */ | 1063 | /* LevelOne */ |
1037 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1064 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1038 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1065 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -1042,20 +1069,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1042 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1069 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1043 | /* Motorola */ | 1070 | /* Motorola */ |
1044 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1071 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1045 | /* MSI */ | ||
1046 | { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1047 | { USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1048 | { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1049 | { USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1050 | { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1051 | { USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1052 | { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1053 | { USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1054 | { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1055 | /* Ovislink */ | 1072 | /* Ovislink */ |
1056 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1073 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1057 | /* Para */ | ||
1058 | { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1059 | /* Pegatron */ | 1074 | /* Pegatron */ |
1060 | { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1075 | { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1061 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1076 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -1064,19 +1079,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1064 | { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1079 | { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1065 | /* Qcom */ | 1080 | /* Qcom */ |
1066 | { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1081 | { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1067 | /* Sitecom */ | ||
1068 | { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1069 | { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1070 | { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1071 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1072 | { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1073 | { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1074 | { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1075 | { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1076 | /* SMC */ | 1082 | /* SMC */ |
1077 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1083 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1078 | { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1079 | { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
1080 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1084 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1081 | { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1085 | { USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1082 | /* Sweex */ | 1086 | /* Sweex */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index d9daa9c406fa..4de505b98331 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -177,16 +177,15 @@ struct rt2x00_chip { | |||
177 | #define RT2573 0x2573 | 177 | #define RT2573 0x2573 |
178 | #define RT2860 0x2860 /* 2.4GHz PCI/CB */ | 178 | #define RT2860 0x2860 /* 2.4GHz PCI/CB */ |
179 | #define RT2870 0x2870 | 179 | #define RT2870 0x2870 |
180 | #define RT2872 0x2872 | 180 | #define RT2872 0x2872 /* WSOC */ |
181 | #define RT2880 0x2880 /* WSOC */ | ||
182 | #define RT2883 0x2883 /* WSOC */ | 181 | #define RT2883 0x2883 /* WSOC */ |
183 | #define RT2890 0x2890 /* 2.4GHz PCIe */ | ||
184 | #define RT3052 0x3052 /* WSOC */ | ||
185 | #define RT3070 0x3070 | 182 | #define RT3070 0x3070 |
186 | #define RT3071 0x3071 | 183 | #define RT3071 0x3071 |
187 | #define RT3090 0x3090 /* 2.4GHz PCIe */ | 184 | #define RT3090 0x3090 /* 2.4GHz PCIe */ |
188 | #define RT3390 0x3390 | 185 | #define RT3390 0x3390 |
189 | #define RT3572 0x3572 | 186 | #define RT3572 0x3572 |
187 | #define RT3593 0x3593 /* PCIe */ | ||
188 | #define RT3883 0x3883 /* WSOC */ | ||
190 | 189 | ||
191 | u16 rf; | 190 | u16 rf; |
192 | u16 rev; | 191 | u16 rev; |
@@ -930,12 +929,12 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, | |||
930 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); | 929 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); |
931 | } | 930 | } |
932 | 931 | ||
933 | static inline char rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) | 932 | static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) |
934 | { | 933 | { |
935 | return (rt2x00dev->chip.rt == rt); | 934 | return (rt2x00dev->chip.rt == rt); |
936 | } | 935 | } |
937 | 936 | ||
938 | static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) | 937 | static inline bool rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) |
939 | { | 938 | { |
940 | return (rt2x00dev->chip.rf == rf); | 939 | return (rt2x00dev->chip.rf == rf); |
941 | } | 940 | } |
@@ -945,6 +944,24 @@ static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev) | |||
945 | return rt2x00dev->chip.rev; | 944 | return rt2x00dev->chip.rev; |
946 | } | 945 | } |
947 | 946 | ||
947 | static inline bool rt2x00_rt_rev(struct rt2x00_dev *rt2x00dev, | ||
948 | const u16 rt, const u16 rev) | ||
949 | { | ||
950 | return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) == rev); | ||
951 | } | ||
952 | |||
953 | static inline bool rt2x00_rt_rev_lt(struct rt2x00_dev *rt2x00dev, | ||
954 | const u16 rt, const u16 rev) | ||
955 | { | ||
956 | return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) < rev); | ||
957 | } | ||
958 | |||
959 | static inline bool rt2x00_rt_rev_gte(struct rt2x00_dev *rt2x00dev, | ||
960 | const u16 rt, const u16 rev) | ||
961 | { | ||
962 | return (rt2x00_rt(rt2x00dev, rt) && rt2x00_rev(rt2x00dev) >= rev); | ||
963 | } | ||
964 | |||
948 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, | 965 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, |
949 | enum rt2x00_chip_intf intf) | 966 | enum rt2x00_chip_intf intf) |
950 | { | 967 | { |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 432e75f960b7..b9885981f3a8 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -2118,6 +2118,14 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2118 | } | 2118 | } |
2119 | } | 2119 | } |
2120 | 2120 | ||
2121 | static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) | ||
2122 | { | ||
2123 | struct ieee80211_conf conf = { .flags = 0 }; | ||
2124 | struct rt2x00lib_conf libconf = { .conf = &conf }; | ||
2125 | |||
2126 | rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); | ||
2127 | } | ||
2128 | |||
2121 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | 2129 | static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) |
2122 | { | 2130 | { |
2123 | struct rt2x00_dev *rt2x00dev = dev_instance; | 2131 | struct rt2x00_dev *rt2x00dev = dev_instance; |
@@ -2165,6 +2173,12 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) | |||
2165 | rt2x00pci_register_write(rt2x00dev, | 2173 | rt2x00pci_register_write(rt2x00dev, |
2166 | M2H_CMD_DONE_CSR, 0xffffffff); | 2174 | M2H_CMD_DONE_CSR, 0xffffffff); |
2167 | 2175 | ||
2176 | /* | ||
2177 | * 4 - MCU Autowakeup interrupt. | ||
2178 | */ | ||
2179 | if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) | ||
2180 | rt61pci_wakeup(rt2x00dev); | ||
2181 | |||
2168 | return IRQ_HANDLED; | 2182 | return IRQ_HANDLED; |
2169 | } | 2183 | } |
2170 | 2184 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index bb58d797fb72..576ea9dd2824 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -861,15 +861,15 @@ static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev, | |||
861 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | 861 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, |
862 | USB_MODE_SLEEP, REGISTER_TIMEOUT); | 862 | USB_MODE_SLEEP, REGISTER_TIMEOUT); |
863 | } else { | 863 | } else { |
864 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | ||
865 | USB_MODE_WAKEUP, REGISTER_TIMEOUT); | ||
866 | |||
867 | rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); | 864 | rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); |
868 | rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); | 865 | rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); |
869 | rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); | 866 | rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); |
870 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); | 867 | rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); |
871 | rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); | 868 | rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); |
872 | rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); | 869 | rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); |
870 | |||
871 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | ||
872 | USB_MODE_WAKEUP, REGISTER_TIMEOUT); | ||
873 | } | 873 | } |
874 | } | 874 | } |
875 | 875 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 56b78e4b0198..4d479708158d 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -202,8 +202,8 @@ static int wl1251_chip_wakeup(struct wl1251 *wl) | |||
202 | goto out; | 202 | goto out; |
203 | } | 203 | } |
204 | 204 | ||
205 | /* No NVS from netlink, try to get it from the filesystem */ | 205 | if (wl->nvs == NULL && !wl->use_eeprom) { |
206 | if (wl->nvs == NULL) { | 206 | /* No NVS from netlink, try to get it from the filesystem */ |
207 | ret = wl1251_fetch_nvs(wl); | 207 | ret = wl1251_fetch_nvs(wl); |
208 | if (ret < 0) | 208 | if (ret < 0) |
209 | goto out; | 209 | goto out; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index 3bfb59bd4635..e81474203a23 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c | |||
@@ -310,7 +310,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi) | |||
310 | 310 | ||
311 | static struct spi_driver wl1251_spi_driver = { | 311 | static struct spi_driver wl1251_spi_driver = { |
312 | .driver = { | 312 | .driver = { |
313 | .name = "wl1251", | 313 | .name = DRIVER_NAME, |
314 | .bus = &spi_bus_type, | 314 | .bus = &spi_bus_type, |
315 | .owner = THIS_MODULE, | 315 | .owner = THIS_MODULE, |
316 | }, | 316 | }, |
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 8f11506f8310..75887e74205b 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -55,6 +55,7 @@ enum { | |||
55 | DEBUG_ACX = BIT(13), | 55 | DEBUG_ACX = BIT(13), |
56 | DEBUG_SDIO = BIT(14), | 56 | DEBUG_SDIO = BIT(14), |
57 | DEBUG_FILTERS = BIT(15), | 57 | DEBUG_FILTERS = BIT(15), |
58 | DEBUG_ADHOC = BIT(16), | ||
58 | DEBUG_ALL = ~0, | 59 | DEBUG_ALL = ~0, |
59 | }; | 60 | }; |
60 | 61 | ||
@@ -147,14 +148,7 @@ struct wl1271_nvs_file { | |||
147 | */ | 148 | */ |
148 | #undef WL1271_80211A_ENABLED | 149 | #undef WL1271_80211A_ENABLED |
149 | 150 | ||
150 | /* | 151 | #define WL1271_BUSY_WORD_CNT 1 |
151 | * FIXME: for the wl1271, a busy word count of 1 here will result in a more | ||
152 | * optimal SPI interface. There is some SPI bug however, causing RXS time outs | ||
153 | * with this mode occasionally on boot, so lets have three for now. A value of | ||
154 | * three should make sure, that the chipset will always be ready, though this | ||
155 | * will impact throughput and latencies slightly. | ||
156 | */ | ||
157 | #define WL1271_BUSY_WORD_CNT 3 | ||
158 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) | 152 | #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32)) |
159 | 153 | ||
160 | #define WL1271_ELP_HW_STATE_ASLEEP 0 | 154 | #define WL1271_ELP_HW_STATE_ASLEEP 0 |
@@ -380,6 +374,7 @@ struct wl1271 { | |||
380 | #define WL1271_FLAG_PSM_REQUESTED (8) | 374 | #define WL1271_FLAG_PSM_REQUESTED (8) |
381 | #define WL1271_FLAG_IRQ_PENDING (9) | 375 | #define WL1271_FLAG_IRQ_PENDING (9) |
382 | #define WL1271_FLAG_IRQ_RUNNING (10) | 376 | #define WL1271_FLAG_IRQ_RUNNING (10) |
377 | #define WL1271_FLAG_IDLE (11) | ||
383 | unsigned long flags; | 378 | unsigned long flags; |
384 | 379 | ||
385 | struct wl1271_partition_set part; | 380 | struct wl1271_partition_set part; |
@@ -396,6 +391,7 @@ struct wl1271 { | |||
396 | u8 bssid[ETH_ALEN]; | 391 | u8 bssid[ETH_ALEN]; |
397 | u8 mac_addr[ETH_ALEN]; | 392 | u8 mac_addr[ETH_ALEN]; |
398 | u8 bss_type; | 393 | u8 bss_type; |
394 | u8 set_bss_type; | ||
399 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; | 395 | u8 ssid[IW_ESSID_MAX_SIZE + 1]; |
400 | u8 ssid_len; | 396 | u8 ssid_len; |
401 | int channel; | 397 | int channel; |
@@ -452,11 +448,15 @@ struct wl1271 { | |||
452 | /* currently configured rate set */ | 448 | /* currently configured rate set */ |
453 | u32 sta_rate_set; | 449 | u32 sta_rate_set; |
454 | u32 basic_rate_set; | 450 | u32 basic_rate_set; |
451 | u32 basic_rate; | ||
455 | u32 rate_set; | 452 | u32 rate_set; |
456 | 453 | ||
457 | /* The current band */ | 454 | /* The current band */ |
458 | enum ieee80211_band band; | 455 | enum ieee80211_band band; |
459 | 456 | ||
457 | /* Beaconing interval (needed for ad-hoc) */ | ||
458 | u32 beacon_int; | ||
459 | |||
460 | /* Default key (for WEP) */ | 460 | /* Default key (for WEP) */ |
461 | u32 default_key; | 461 | u32 default_key; |
462 | 462 | ||
@@ -473,6 +473,9 @@ struct wl1271 { | |||
473 | /* in dBm */ | 473 | /* in dBm */ |
474 | int power_level; | 474 | int power_level; |
475 | 475 | ||
476 | int rssi_thold; | ||
477 | int last_rssi_event; | ||
478 | |||
476 | struct wl1271_stats stats; | 479 | struct wl1271_stats stats; |
477 | struct wl1271_debugfs debugfs; | 480 | struct wl1271_debugfs debugfs; |
478 | 481 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index adaa3f2485c3..2ad086efe06e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -505,12 +505,17 @@ out: | |||
505 | return ret; | 505 | return ret; |
506 | } | 506 | } |
507 | 507 | ||
508 | int wl1271_acx_conn_monit_params(struct wl1271 *wl) | 508 | #define ACX_CONN_MONIT_DISABLE_VALUE 0xffffffff |
509 | |||
510 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable) | ||
509 | { | 511 | { |
510 | struct acx_conn_monit_params *acx; | 512 | struct acx_conn_monit_params *acx; |
513 | u32 threshold = ACX_CONN_MONIT_DISABLE_VALUE; | ||
514 | u32 timeout = ACX_CONN_MONIT_DISABLE_VALUE; | ||
511 | int ret; | 515 | int ret; |
512 | 516 | ||
513 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters"); | 517 | wl1271_debug(DEBUG_ACX, "acx connection monitor parameters: %s", |
518 | enable ? "enabled" : "disabled"); | ||
514 | 519 | ||
515 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 520 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
516 | if (!acx) { | 521 | if (!acx) { |
@@ -518,8 +523,13 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl) | |||
518 | goto out; | 523 | goto out; |
519 | } | 524 | } |
520 | 525 | ||
521 | acx->synch_fail_thold = cpu_to_le32(wl->conf.conn.synch_fail_thold); | 526 | if (enable) { |
522 | acx->bss_lose_timeout = cpu_to_le32(wl->conf.conn.bss_lose_timeout); | 527 | threshold = wl->conf.conn.synch_fail_thold; |
528 | timeout = wl->conf.conn.bss_lose_timeout; | ||
529 | } | ||
530 | |||
531 | acx->synch_fail_thold = cpu_to_le32(threshold); | ||
532 | acx->bss_lose_timeout = cpu_to_le32(timeout); | ||
523 | 533 | ||
524 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, | 534 | ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, |
525 | acx, sizeof(*acx)); | 535 | acx, sizeof(*acx)); |
@@ -793,7 +803,7 @@ int wl1271_acx_rate_policies(struct wl1271 *wl) | |||
793 | 803 | ||
794 | /* configure one basic rate class */ | 804 | /* configure one basic rate class */ |
795 | idx = ACX_TX_BASIC_RATE; | 805 | idx = ACX_TX_BASIC_RATE; |
796 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); | 806 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate); |
797 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; | 807 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; |
798 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; | 808 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; |
799 | acx->rate_class[idx].aflags = c->aflags; | 809 | acx->rate_class[idx].aflags = c->aflags; |
@@ -1130,3 +1140,129 @@ out: | |||
1130 | kfree(acx); | 1140 | kfree(acx); |
1131 | return ret; | 1141 | return ret; |
1132 | } | 1142 | } |
1143 | |||
1144 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable) | ||
1145 | { | ||
1146 | struct wl1271_acx_keep_alive_mode *acx = NULL; | ||
1147 | int ret = 0; | ||
1148 | |||
1149 | wl1271_debug(DEBUG_ACX, "acx keep alive mode: %d", enable); | ||
1150 | |||
1151 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1152 | if (!acx) { | ||
1153 | ret = -ENOMEM; | ||
1154 | goto out; | ||
1155 | } | ||
1156 | |||
1157 | acx->enabled = enable; | ||
1158 | |||
1159 | ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx)); | ||
1160 | if (ret < 0) { | ||
1161 | wl1271_warning("acx keep alive mode failed: %d", ret); | ||
1162 | goto out; | ||
1163 | } | ||
1164 | |||
1165 | out: | ||
1166 | kfree(acx); | ||
1167 | return ret; | ||
1168 | } | ||
1169 | |||
1170 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid) | ||
1171 | { | ||
1172 | struct wl1271_acx_keep_alive_config *acx = NULL; | ||
1173 | int ret = 0; | ||
1174 | |||
1175 | wl1271_debug(DEBUG_ACX, "acx keep alive config"); | ||
1176 | |||
1177 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1178 | if (!acx) { | ||
1179 | ret = -ENOMEM; | ||
1180 | goto out; | ||
1181 | } | ||
1182 | |||
1183 | acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval); | ||
1184 | acx->index = index; | ||
1185 | acx->tpl_validation = tpl_valid; | ||
1186 | acx->trigger = ACX_KEEP_ALIVE_NO_TX; | ||
1187 | |||
1188 | ret = wl1271_cmd_configure(wl, ACX_SET_KEEP_ALIVE_CONFIG, | ||
1189 | acx, sizeof(*acx)); | ||
1190 | if (ret < 0) { | ||
1191 | wl1271_warning("acx keep alive config failed: %d", ret); | ||
1192 | goto out; | ||
1193 | } | ||
1194 | |||
1195 | out: | ||
1196 | kfree(acx); | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1200 | int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, | ||
1201 | s16 thold, u8 hyst) | ||
1202 | { | ||
1203 | struct wl1271_acx_rssi_snr_trigger *acx = NULL; | ||
1204 | int ret = 0; | ||
1205 | |||
1206 | wl1271_debug(DEBUG_ACX, "acx rssi snr trigger"); | ||
1207 | |||
1208 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1209 | if (!acx) { | ||
1210 | ret = -ENOMEM; | ||
1211 | goto out; | ||
1212 | } | ||
1213 | |||
1214 | wl->last_rssi_event = -1; | ||
1215 | |||
1216 | acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing); | ||
1217 | acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON; | ||
1218 | acx->type = WL1271_ACX_TRIG_TYPE_EDGE; | ||
1219 | if (enable) | ||
1220 | acx->enable = WL1271_ACX_TRIG_ENABLE; | ||
1221 | else | ||
1222 | acx->enable = WL1271_ACX_TRIG_DISABLE; | ||
1223 | |||
1224 | acx->index = WL1271_ACX_TRIG_IDX_RSSI; | ||
1225 | acx->dir = WL1271_ACX_TRIG_DIR_BIDIR; | ||
1226 | acx->threshold = cpu_to_le16(thold); | ||
1227 | acx->hysteresis = hyst; | ||
1228 | |||
1229 | ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_TRIGGER, acx, sizeof(*acx)); | ||
1230 | if (ret < 0) { | ||
1231 | wl1271_warning("acx rssi snr trigger setting failed: %d", ret); | ||
1232 | goto out; | ||
1233 | } | ||
1234 | |||
1235 | out: | ||
1236 | kfree(acx); | ||
1237 | return ret; | ||
1238 | } | ||
1239 | |||
1240 | int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl) | ||
1241 | { | ||
1242 | struct wl1271_acx_rssi_snr_avg_weights *acx = NULL; | ||
1243 | struct conf_roam_trigger_settings *c = &wl->conf.roam_trigger; | ||
1244 | int ret = 0; | ||
1245 | |||
1246 | wl1271_debug(DEBUG_ACX, "acx rssi snr avg weights"); | ||
1247 | |||
1248 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1249 | if (!acx) { | ||
1250 | ret = -ENOMEM; | ||
1251 | goto out; | ||
1252 | } | ||
1253 | |||
1254 | acx->rssi_beacon = c->avg_weight_rssi_beacon; | ||
1255 | acx->rssi_data = c->avg_weight_rssi_data; | ||
1256 | acx->snr_beacon = c->avg_weight_snr_beacon; | ||
1257 | acx->snr_data = c->avg_weight_snr_data; | ||
1258 | |||
1259 | ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_WEIGHTS, acx, sizeof(*acx)); | ||
1260 | if (ret < 0) { | ||
1261 | wl1271_warning("acx rssi snr trigger weights failed: %d", ret); | ||
1262 | goto out; | ||
1263 | } | ||
1264 | |||
1265 | out: | ||
1266 | kfree(acx); | ||
1267 | return ret; | ||
1268 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 8e5870fa9609..420e7e2fc021 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -915,6 +915,84 @@ struct wl1271_acx_pm_config { | |||
915 | u8 padding[3]; | 915 | u8 padding[3]; |
916 | } __attribute__ ((packed)); | 916 | } __attribute__ ((packed)); |
917 | 917 | ||
918 | struct wl1271_acx_keep_alive_mode { | ||
919 | struct acx_header header; | ||
920 | |||
921 | u8 enabled; | ||
922 | u8 padding[3]; | ||
923 | } __attribute__ ((packed)); | ||
924 | |||
925 | enum { | ||
926 | ACX_KEEP_ALIVE_NO_TX = 0, | ||
927 | ACX_KEEP_ALIVE_PERIOD_ONLY | ||
928 | }; | ||
929 | |||
930 | enum { | ||
931 | ACX_KEEP_ALIVE_TPL_INVALID = 0, | ||
932 | ACX_KEEP_ALIVE_TPL_VALID | ||
933 | }; | ||
934 | |||
935 | struct wl1271_acx_keep_alive_config { | ||
936 | struct acx_header header; | ||
937 | |||
938 | __le32 period; | ||
939 | u8 index; | ||
940 | u8 tpl_validation; | ||
941 | u8 trigger; | ||
942 | u8 padding; | ||
943 | } __attribute__ ((packed)); | ||
944 | |||
945 | enum { | ||
946 | WL1271_ACX_TRIG_TYPE_LEVEL = 0, | ||
947 | WL1271_ACX_TRIG_TYPE_EDGE, | ||
948 | }; | ||
949 | |||
950 | enum { | ||
951 | WL1271_ACX_TRIG_DIR_LOW = 0, | ||
952 | WL1271_ACX_TRIG_DIR_HIGH, | ||
953 | WL1271_ACX_TRIG_DIR_BIDIR, | ||
954 | }; | ||
955 | |||
956 | enum { | ||
957 | WL1271_ACX_TRIG_ENABLE = 1, | ||
958 | WL1271_ACX_TRIG_DISABLE, | ||
959 | }; | ||
960 | |||
961 | enum { | ||
962 | WL1271_ACX_TRIG_METRIC_RSSI_BEACON = 0, | ||
963 | WL1271_ACX_TRIG_METRIC_RSSI_DATA, | ||
964 | WL1271_ACX_TRIG_METRIC_SNR_BEACON, | ||
965 | WL1271_ACX_TRIG_METRIC_SNR_DATA, | ||
966 | }; | ||
967 | |||
968 | enum { | ||
969 | WL1271_ACX_TRIG_IDX_RSSI = 0, | ||
970 | WL1271_ACX_TRIG_COUNT = 8, | ||
971 | }; | ||
972 | |||
973 | struct wl1271_acx_rssi_snr_trigger { | ||
974 | struct acx_header header; | ||
975 | |||
976 | __le16 threshold; | ||
977 | __le16 pacing; /* 0 - 60000 ms */ | ||
978 | u8 metric; | ||
979 | u8 type; | ||
980 | u8 dir; | ||
981 | u8 hysteresis; | ||
982 | u8 index; | ||
983 | u8 enable; | ||
984 | u8 padding[2]; | ||
985 | }; | ||
986 | |||
987 | struct wl1271_acx_rssi_snr_avg_weights { | ||
988 | struct acx_header header; | ||
989 | |||
990 | u8 rssi_beacon; | ||
991 | u8 rssi_data; | ||
992 | u8 snr_beacon; | ||
993 | u8 snr_data; | ||
994 | }; | ||
995 | |||
918 | enum { | 996 | enum { |
919 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 997 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
920 | ACX_MEM_CFG = 0x0003, | 998 | ACX_MEM_CFG = 0x0003, |
@@ -963,8 +1041,8 @@ enum { | |||
963 | ACX_FRAG_CFG = 0x004F, | 1041 | ACX_FRAG_CFG = 0x004F, |
964 | ACX_BET_ENABLE = 0x0050, | 1042 | ACX_BET_ENABLE = 0x0050, |
965 | ACX_RSSI_SNR_TRIGGER = 0x0051, | 1043 | ACX_RSSI_SNR_TRIGGER = 0x0051, |
966 | ACX_RSSI_SNR_WEIGHTS = 0x0051, | 1044 | ACX_RSSI_SNR_WEIGHTS = 0x0052, |
967 | ACX_KEEP_ALIVE_MODE = 0x0052, | 1045 | ACX_KEEP_ALIVE_MODE = 0x0053, |
968 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, | 1046 | ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, |
969 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, | 1047 | ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, |
970 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, | 1048 | ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, |
@@ -1004,7 +1082,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | |||
1004 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | 1082 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); |
1005 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1083 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1006 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1084 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1007 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | 1085 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); |
1008 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); | 1086 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); |
1009 | int wl1271_acx_sg_cfg(struct wl1271 *wl); | 1087 | int wl1271_acx_sg_cfg(struct wl1271 *wl); |
1010 | int wl1271_acx_cca_threshold(struct wl1271 *wl); | 1088 | int wl1271_acx_cca_threshold(struct wl1271 *wl); |
@@ -1031,5 +1109,10 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | |||
1031 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1109 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, |
1032 | u8 version); | 1110 | u8 version); |
1033 | int wl1271_acx_pm_config(struct wl1271 *wl); | 1111 | int wl1271_acx_pm_config(struct wl1271 *wl); |
1112 | int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable); | ||
1113 | int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid); | ||
1114 | int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable, | ||
1115 | s16 thold, u8 hyst); | ||
1116 | int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl); | ||
1034 | 1117 | ||
1035 | #endif /* __WL1271_ACX_H__ */ | 1118 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index 1937859d74eb..8087dc17f29d 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2009 Nokia Corporation | 4 | * Copyright (C) 2008-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -411,7 +411,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
411 | /* unmask required mbox events */ | 411 | /* unmask required mbox events */ |
412 | wl->event_mask = BSS_LOSE_EVENT_ID | | 412 | wl->event_mask = BSS_LOSE_EVENT_ID | |
413 | SCAN_COMPLETE_EVENT_ID | | 413 | SCAN_COMPLETE_EVENT_ID | |
414 | PS_REPORT_EVENT_ID; | 414 | PS_REPORT_EVENT_ID | |
415 | JOIN_EVENT_COMPLETE_ID | | ||
416 | DISCONNECT_EVENT_COMPLETE_ID | | ||
417 | RSSI_SNR_TRIGGER_0_EVENT_ID; | ||
415 | 418 | ||
416 | ret = wl1271_event_unmask(wl); | 419 | ret = wl1271_event_unmask(wl); |
417 | if (ret < 0) { | 420 | if (ret < 0) { |
@@ -452,11 +455,15 @@ int wl1271_boot(struct wl1271 *wl) | |||
452 | 455 | ||
453 | if (REF_CLOCK != 0) { | 456 | if (REF_CLOCK != 0) { |
454 | u16 val; | 457 | u16 val; |
455 | /* Set clock type */ | 458 | /* Set clock type (open drain) */ |
456 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); | 459 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE); |
457 | val &= FREF_CLK_TYPE_BITS; | 460 | val &= FREF_CLK_TYPE_BITS; |
458 | val |= CLK_REQ_PRCM; | ||
459 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | 461 | wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val); |
462 | |||
463 | /* Set clock pull mode (no pull) */ | ||
464 | val = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL); | ||
465 | val |= NO_PULL; | ||
466 | wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val); | ||
460 | } else { | 467 | } else { |
461 | u16 val; | 468 | u16 val; |
462 | /* Set clock polarity */ | 469 | /* Set clock polarity */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h index 412443ee655a..95ecc5241959 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ b/drivers/net/wireless/wl12xx/wl1271_boot.h | |||
@@ -53,10 +53,13 @@ struct wl1271_static_data { | |||
53 | #define OCP_REG_POLARITY 0x0064 | 53 | #define OCP_REG_POLARITY 0x0064 |
54 | #define OCP_REG_CLK_TYPE 0x0448 | 54 | #define OCP_REG_CLK_TYPE 0x0448 |
55 | #define OCP_REG_CLK_POLARITY 0x0cb2 | 55 | #define OCP_REG_CLK_POLARITY 0x0cb2 |
56 | #define OCP_REG_CLK_PULL 0x0cb4 | ||
56 | 57 | ||
57 | #define CMD_MBOX_ADDRESS 0x407B4 | ||
58 | 58 | ||
59 | #define POLARITY_LOW BIT(1) | 59 | #define CMD_MBOX_ADDRESS 0x407B4 |
60 | |||
61 | #define POLARITY_LOW BIT(1) | ||
62 | #define NO_PULL (BIT(14) | BIT(15)) | ||
60 | 63 | ||
61 | #define FREF_CLK_TYPE_BITS 0xfffffe7f | 64 | #define FREF_CLK_TYPE_BITS 0xfffffe7f |
62 | #define CLK_REQ_PRCM 0x100 | 65 | #define CLK_REQ_PRCM 0x100 |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 92254d0d6c4c..6b5ba8ec94c9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This file is part of wl1271 | 2 | * This file is part of wl1271 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Nokia Corporation | 4 | * Copyright (C) 2009-2010 Nokia Corporation |
5 | * | 5 | * |
6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> | 6 | * Contact: Luciano Coelho <luciano.coelho@nokia.com> |
7 | * | 7 | * |
@@ -35,6 +35,9 @@ | |||
35 | #include "wl1271_acx.h" | 35 | #include "wl1271_acx.h" |
36 | #include "wl12xx_80211.h" | 36 | #include "wl12xx_80211.h" |
37 | #include "wl1271_cmd.h" | 37 | #include "wl1271_cmd.h" |
38 | #include "wl1271_event.h" | ||
39 | |||
40 | #define WL1271_CMD_POLL_COUNT 5 | ||
38 | 41 | ||
39 | /* | 42 | /* |
40 | * send command to firmware | 43 | * send command to firmware |
@@ -52,6 +55,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
52 | u32 intr; | 55 | u32 intr; |
53 | int ret = 0; | 56 | int ret = 0; |
54 | u16 status; | 57 | u16 status; |
58 | u16 poll_count = 0; | ||
55 | 59 | ||
56 | cmd = buf; | 60 | cmd = buf; |
57 | cmd->id = cpu_to_le16(id); | 61 | cmd->id = cpu_to_le16(id); |
@@ -73,7 +77,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
73 | goto out; | 77 | goto out; |
74 | } | 78 | } |
75 | 79 | ||
76 | msleep(1); | 80 | udelay(10); |
81 | poll_count++; | ||
82 | if (poll_count == WL1271_CMD_POLL_COUNT) | ||
83 | wl1271_info("cmd polling took over %d cycles", | ||
84 | poll_count); | ||
77 | 85 | ||
78 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); | 86 | intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); |
79 | } | 87 | } |
@@ -249,6 +257,35 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
249 | return ret; | 257 | return ret; |
250 | } | 258 | } |
251 | 259 | ||
260 | /* | ||
261 | * Poll the mailbox event field until any of the bits in the mask is set or a | ||
262 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | ||
263 | */ | ||
264 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | ||
265 | { | ||
266 | u32 events_vector, event; | ||
267 | unsigned long timeout; | ||
268 | |||
269 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | ||
270 | |||
271 | do { | ||
272 | if (time_after(jiffies, timeout)) | ||
273 | return -ETIMEDOUT; | ||
274 | |||
275 | msleep(1); | ||
276 | |||
277 | /* read from both event fields */ | ||
278 | wl1271_read(wl, wl->mbox_ptr[0], &events_vector, | ||
279 | sizeof(events_vector), false); | ||
280 | event = events_vector & mask; | ||
281 | wl1271_read(wl, wl->mbox_ptr[1], &events_vector, | ||
282 | sizeof(events_vector), false); | ||
283 | event |= events_vector & mask; | ||
284 | } while (!event); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
252 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | 289 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) |
253 | { | 290 | { |
254 | static bool do_cal = true; | 291 | static bool do_cal = true; |
@@ -281,20 +318,12 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | |||
281 | join->rx_config_options = cpu_to_le32(wl->rx_config); | 318 | join->rx_config_options = cpu_to_le32(wl->rx_config); |
282 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); | 319 | join->rx_filter_options = cpu_to_le32(wl->rx_filter); |
283 | join->bss_type = bss_type; | 320 | join->bss_type = bss_type; |
321 | join->basic_rate_set = wl->basic_rate_set; | ||
284 | 322 | ||
285 | if (wl->band == IEEE80211_BAND_2GHZ) | 323 | if (wl->band == IEEE80211_BAND_5GHZ) |
286 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS | | ||
287 | CONF_HW_BIT_RATE_2MBPS | | ||
288 | CONF_HW_BIT_RATE_5_5MBPS | | ||
289 | CONF_HW_BIT_RATE_11MBPS); | ||
290 | else { | ||
291 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; | 324 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; |
292 | join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS | | ||
293 | CONF_HW_BIT_RATE_12MBPS | | ||
294 | CONF_HW_BIT_RATE_24MBPS); | ||
295 | } | ||
296 | 325 | ||
297 | join->beacon_interval = cpu_to_le16(WL1271_DEFAULT_BEACON_INT); | 326 | join->beacon_interval = cpu_to_le16(wl->beacon_int); |
298 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; | 327 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; |
299 | 328 | ||
300 | join->channel = wl->channel; | 329 | join->channel = wl->channel; |
@@ -319,11 +348,9 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | |||
319 | goto out_free; | 348 | goto out_free; |
320 | } | 349 | } |
321 | 350 | ||
322 | /* | 351 | ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); |
323 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to | 352 | if (ret < 0) |
324 | * simplify locking we just sleep instead, for now | 353 | wl1271_error("cmd join event completion error"); |
325 | */ | ||
326 | msleep(10); | ||
327 | 354 | ||
328 | out_free: | 355 | out_free: |
329 | kfree(join); | 356 | kfree(join); |
@@ -455,7 +482,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) | |||
455 | if (ret < 0) { | 482 | if (ret < 0) { |
456 | wl1271_error("tx %s cmd for channel %d failed", | 483 | wl1271_error("tx %s cmd for channel %d failed", |
457 | enable ? "start" : "stop", cmd->channel); | 484 | enable ? "start" : "stop", cmd->channel); |
458 | return ret; | 485 | goto out; |
459 | } | 486 | } |
460 | 487 | ||
461 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", | 488 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
@@ -547,17 +574,21 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
547 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; | 574 | struct wl1271_cmd_trigger_scan_to *trigger = NULL; |
548 | struct wl1271_cmd_scan *params = NULL; | 575 | struct wl1271_cmd_scan *params = NULL; |
549 | struct ieee80211_channel *channels; | 576 | struct ieee80211_channel *channels; |
577 | u32 rate; | ||
550 | int i, j, n_ch, ret; | 578 | int i, j, n_ch, ret; |
551 | u16 scan_options = 0; | 579 | u16 scan_options = 0; |
552 | u8 ieee_band; | 580 | u8 ieee_band; |
553 | 581 | ||
554 | if (band == WL1271_SCAN_BAND_2_4_GHZ) | 582 | if (band == WL1271_SCAN_BAND_2_4_GHZ) { |
555 | ieee_band = IEEE80211_BAND_2GHZ; | 583 | ieee_band = IEEE80211_BAND_2GHZ; |
556 | else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) | 584 | rate = wl->conf.tx.basic_rate; |
585 | } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) { | ||
557 | ieee_band = IEEE80211_BAND_2GHZ; | 586 | ieee_band = IEEE80211_BAND_2GHZ; |
558 | else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) | 587 | rate = wl->conf.tx.basic_rate; |
588 | } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) { | ||
559 | ieee_band = IEEE80211_BAND_5GHZ; | 589 | ieee_band = IEEE80211_BAND_5GHZ; |
560 | else | 590 | rate = wl->conf.tx.basic_rate_5; |
591 | } else | ||
561 | return -EINVAL; | 592 | return -EINVAL; |
562 | 593 | ||
563 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) | 594 | if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) |
@@ -584,8 +615,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
584 | params->params.scan_options = cpu_to_le16(scan_options); | 615 | params->params.scan_options = cpu_to_le16(scan_options); |
585 | 616 | ||
586 | params->params.num_probe_requests = probe_requests; | 617 | params->params.num_probe_requests = probe_requests; |
587 | /* Let the fw autodetect suitable tx_rate for probes */ | 618 | params->params.tx_rate = rate; |
588 | params->params.tx_rate = 0; | ||
589 | params->params.tid_trigger = 0; | 619 | params->params.tid_trigger = 0; |
590 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; | 620 | params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; |
591 | 621 | ||
@@ -666,11 +696,12 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
666 | 696 | ||
667 | out: | 697 | out: |
668 | kfree(params); | 698 | kfree(params); |
699 | kfree(trigger); | ||
669 | return ret; | 700 | return ret; |
670 | } | 701 | } |
671 | 702 | ||
672 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 703 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
673 | void *buf, size_t buf_len) | 704 | void *buf, size_t buf_len, int index, u32 rates) |
674 | { | 705 | { |
675 | struct wl1271_cmd_template_set *cmd; | 706 | struct wl1271_cmd_template_set *cmd; |
676 | int ret = 0; | 707 | int ret = 0; |
@@ -688,9 +719,10 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | |||
688 | 719 | ||
689 | cmd->len = cpu_to_le16(buf_len); | 720 | cmd->len = cpu_to_le16(buf_len); |
690 | cmd->template_type = template_id; | 721 | cmd->template_type = template_id; |
691 | cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates); | 722 | cmd->enabled_rates = cpu_to_le32(rates); |
692 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; | 723 | cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit; |
693 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; | 724 | cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit; |
725 | cmd->index = index; | ||
694 | 726 | ||
695 | if (buf) | 727 | if (buf) |
696 | memcpy(cmd->template_data, buf, buf_len); | 728 | memcpy(cmd->template_data, buf, buf_len); |
@@ -727,7 +759,8 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl) | |||
727 | ptr = skb->data; | 759 | ptr = skb->data; |
728 | } | 760 | } |
729 | 761 | ||
730 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size); | 762 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, |
763 | WL1271_RATE_AUTOMATIC); | ||
731 | 764 | ||
732 | out: | 765 | out: |
733 | dev_kfree_skb(skb); | 766 | dev_kfree_skb(skb); |
@@ -738,6 +771,29 @@ out: | |||
738 | 771 | ||
739 | } | 772 | } |
740 | 773 | ||
774 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) | ||
775 | { | ||
776 | struct sk_buff *skb = NULL; | ||
777 | int ret = -ENOMEM; | ||
778 | |||
779 | skb = ieee80211_nullfunc_get(wl->hw, wl->vif); | ||
780 | if (!skb) | ||
781 | goto out; | ||
782 | |||
783 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, | ||
784 | skb->data, skb->len, | ||
785 | CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
786 | WL1271_RATE_AUTOMATIC); | ||
787 | |||
788 | out: | ||
789 | dev_kfree_skb(skb); | ||
790 | if (ret) | ||
791 | wl1271_warning("cmd build klv null data failed %d", ret); | ||
792 | |||
793 | return ret; | ||
794 | |||
795 | } | ||
796 | |||
741 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | 797 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) |
742 | { | 798 | { |
743 | struct sk_buff *skb; | 799 | struct sk_buff *skb; |
@@ -748,7 +804,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | |||
748 | goto out; | 804 | goto out; |
749 | 805 | ||
750 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, | 806 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, |
751 | skb->len); | 807 | skb->len, 0, wl->basic_rate); |
752 | 808 | ||
753 | out: | 809 | out: |
754 | dev_kfree_skb(skb); | 810 | dev_kfree_skb(skb); |
@@ -773,10 +829,12 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, | |||
773 | 829 | ||
774 | if (band == IEEE80211_BAND_2GHZ) | 830 | if (band == IEEE80211_BAND_2GHZ) |
775 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 831 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
776 | skb->data, skb->len); | 832 | skb->data, skb->len, 0, |
833 | wl->conf.tx.basic_rate); | ||
777 | else | 834 | else |
778 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 835 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
779 | skb->data, skb->len); | 836 | skb->data, skb->len, 0, |
837 | wl->conf.tx.basic_rate_5); | ||
780 | 838 | ||
781 | out: | 839 | out: |
782 | dev_kfree_skb(skb); | 840 | dev_kfree_skb(skb); |
@@ -801,7 +859,8 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) | |||
801 | template.qos_ctrl = cpu_to_le16(0); | 859 | template.qos_ctrl = cpu_to_le16(0); |
802 | 860 | ||
803 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, | 861 | return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, |
804 | sizeof(template)); | 862 | sizeof(template), 0, |
863 | WL1271_RATE_AUTOMATIC); | ||
805 | } | 864 | } |
806 | 865 | ||
807 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) | 866 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) |
@@ -914,6 +973,10 @@ int wl1271_cmd_disconnect(struct wl1271 *wl) | |||
914 | goto out_free; | 973 | goto out_free; |
915 | } | 974 | } |
916 | 975 | ||
976 | ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); | ||
977 | if (ret < 0) | ||
978 | wl1271_error("cmd disconnect event completion error"); | ||
979 | |||
917 | out_free: | 980 | out_free: |
918 | kfree(cmd); | 981 | kfree(cmd); |
919 | 982 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index 6324bbf36843..00f78b7aa384 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -45,13 +45,14 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
45 | const u8 *ie, size_t ie_len, u8 active_scan, | 45 | const u8 *ie, size_t ie_len, u8 active_scan, |
46 | u8 high_prio, u8 band, u8 probe_requests); | 46 | u8 high_prio, u8 band, u8 probe_requests); |
47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, | 47 | int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, |
48 | void *buf, size_t buf_len); | 48 | void *buf, size_t buf_len, int index, u32 rates); |
49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); | 49 | int wl1271_cmd_build_null_data(struct wl1271 *wl); |
50 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); | 50 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); |
51 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, | 51 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, |
52 | const u8 *ssid, size_t ssid_len, | 52 | const u8 *ssid, size_t ssid_len, |
53 | const u8 *ie, size_t ie_len, u8 band); | 53 | const u8 *ie, size_t ie_len, u8 band); |
54 | int wl1271_build_qos_null_data(struct wl1271 *wl); | 54 | int wl1271_build_qos_null_data(struct wl1271 *wl); |
55 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl); | ||
55 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); | 56 | int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); |
56 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 57 | int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, |
57 | u8 key_size, const u8 *key, const u8 *addr, | 58 | u8 key_size, const u8 *key, const u8 *addr, |
@@ -101,6 +102,11 @@ enum wl1271_commands { | |||
101 | 102 | ||
102 | #define MAX_CMD_PARAMS 572 | 103 | #define MAX_CMD_PARAMS 572 |
103 | 104 | ||
105 | enum { | ||
106 | CMD_TEMPL_KLV_IDX_NULL_DATA = 0, | ||
107 | CMD_TEMPL_KLV_IDX_MAX = 4 | ||
108 | }; | ||
109 | |||
104 | enum cmd_templ { | 110 | enum cmd_templ { |
105 | CMD_TEMPL_NULL_DATA = 0, | 111 | CMD_TEMPL_NULL_DATA = 0, |
106 | CMD_TEMPL_BEACON, | 112 | CMD_TEMPL_BEACON, |
@@ -123,6 +129,7 @@ enum cmd_templ { | |||
123 | /* unit ms */ | 129 | /* unit ms */ |
124 | #define WL1271_COMMAND_TIMEOUT 2000 | 130 | #define WL1271_COMMAND_TIMEOUT 2000 |
125 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 | 131 | #define WL1271_CMD_TEMPL_MAX_SIZE 252 |
132 | #define WL1271_EVENT_TIMEOUT 100 | ||
126 | 133 | ||
127 | struct wl1271_cmd_header { | 134 | struct wl1271_cmd_header { |
128 | __le16 id; | 135 | __le16 id; |
@@ -245,6 +252,8 @@ struct cmd_enabledisable_path { | |||
245 | u8 padding[3]; | 252 | u8 padding[3]; |
246 | } __attribute__ ((packed)); | 253 | } __attribute__ ((packed)); |
247 | 254 | ||
255 | #define WL1271_RATE_AUTOMATIC 0 | ||
256 | |||
248 | struct wl1271_cmd_template_set { | 257 | struct wl1271_cmd_template_set { |
249 | struct wl1271_cmd_header header; | 258 | struct wl1271_cmd_header header; |
250 | 259 | ||
@@ -511,6 +520,8 @@ enum wl1271_disconnect_type { | |||
511 | }; | 520 | }; |
512 | 521 | ||
513 | struct wl1271_cmd_disconnect { | 522 | struct wl1271_cmd_disconnect { |
523 | struct wl1271_cmd_header header; | ||
524 | |||
514 | __le32 rx_config_options; | 525 | __le32 rx_config_options; |
515 | __le32 rx_filter_options; | 526 | __le32 rx_filter_options; |
516 | 527 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 7fcfe06b1412..c44307c4bcf8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -66,6 +66,32 @@ enum { | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | enum { | 68 | enum { |
69 | CONF_HW_RXTX_RATE_MCS7 = 0, | ||
70 | CONF_HW_RXTX_RATE_MCS6, | ||
71 | CONF_HW_RXTX_RATE_MCS5, | ||
72 | CONF_HW_RXTX_RATE_MCS4, | ||
73 | CONF_HW_RXTX_RATE_MCS3, | ||
74 | CONF_HW_RXTX_RATE_MCS2, | ||
75 | CONF_HW_RXTX_RATE_MCS1, | ||
76 | CONF_HW_RXTX_RATE_MCS0, | ||
77 | CONF_HW_RXTX_RATE_54, | ||
78 | CONF_HW_RXTX_RATE_48, | ||
79 | CONF_HW_RXTX_RATE_36, | ||
80 | CONF_HW_RXTX_RATE_24, | ||
81 | CONF_HW_RXTX_RATE_22, | ||
82 | CONF_HW_RXTX_RATE_18, | ||
83 | CONF_HW_RXTX_RATE_12, | ||
84 | CONF_HW_RXTX_RATE_11, | ||
85 | CONF_HW_RXTX_RATE_9, | ||
86 | CONF_HW_RXTX_RATE_6, | ||
87 | CONF_HW_RXTX_RATE_5_5, | ||
88 | CONF_HW_RXTX_RATE_2, | ||
89 | CONF_HW_RXTX_RATE_1, | ||
90 | CONF_HW_RXTX_RATE_MAX, | ||
91 | CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff | ||
92 | }; | ||
93 | |||
94 | enum { | ||
69 | CONF_SG_DISABLE = 0, | 95 | CONF_SG_DISABLE = 0, |
70 | CONF_SG_PROTECTIVE, | 96 | CONF_SG_PROTECTIVE, |
71 | CONF_SG_OPPORTUNISTIC | 97 | CONF_SG_OPPORTUNISTIC |
@@ -648,6 +674,19 @@ struct conf_tx_settings { | |||
648 | */ | 674 | */ |
649 | u16 tx_compl_threshold; | 675 | u16 tx_compl_threshold; |
650 | 676 | ||
677 | /* | ||
678 | * The rate used for control messages and scanning on the 2.4GHz band | ||
679 | * | ||
680 | * Range: CONF_HW_BIT_RATE_* bit mask | ||
681 | */ | ||
682 | u32 basic_rate; | ||
683 | |||
684 | /* | ||
685 | * The rate used for control messages and scanning on the 5GHz band | ||
686 | * | ||
687 | * Range: CONF_HW_BIT_RATE_* bit mask | ||
688 | */ | ||
689 | u32 basic_rate_5; | ||
651 | }; | 690 | }; |
652 | 691 | ||
653 | enum { | 692 | enum { |
@@ -717,65 +756,6 @@ enum { | |||
717 | CONF_TRIG_EVENT_DIR_BIDIR | 756 | CONF_TRIG_EVENT_DIR_BIDIR |
718 | }; | 757 | }; |
719 | 758 | ||
720 | |||
721 | struct conf_sig_trigger { | ||
722 | /* | ||
723 | * The RSSI / SNR threshold value. | ||
724 | * | ||
725 | * FIXME: what is the range? | ||
726 | */ | ||
727 | s16 threshold; | ||
728 | |||
729 | /* | ||
730 | * Minimum delay between two trigger events for this trigger in ms. | ||
731 | * | ||
732 | * Range: 0 - 60000 | ||
733 | */ | ||
734 | u16 pacing; | ||
735 | |||
736 | /* | ||
737 | * The measurement data source for this trigger. | ||
738 | * | ||
739 | * Range: CONF_TRIG_METRIC_* | ||
740 | */ | ||
741 | u8 metric; | ||
742 | |||
743 | /* | ||
744 | * The trigger type of this trigger. | ||
745 | * | ||
746 | * Range: CONF_TRIG_EVENT_TYPE_* | ||
747 | */ | ||
748 | u8 type; | ||
749 | |||
750 | /* | ||
751 | * The direction of the trigger. | ||
752 | * | ||
753 | * Range: CONF_TRIG_EVENT_DIR_* | ||
754 | */ | ||
755 | u8 direction; | ||
756 | |||
757 | /* | ||
758 | * Hysteresis range of the trigger around the threshold (in dB) | ||
759 | * | ||
760 | * Range: u8 | ||
761 | */ | ||
762 | u8 hysteresis; | ||
763 | |||
764 | /* | ||
765 | * Index of the trigger rule. | ||
766 | * | ||
767 | * Range: 0 - CONF_MAX_RSSI_SNR_TRIGGERS-1 | ||
768 | */ | ||
769 | u8 index; | ||
770 | |||
771 | /* | ||
772 | * Enable / disable this rule (to use for clearing rules.) | ||
773 | * | ||
774 | * Range: 1 - Enabled, 2 - Not enabled | ||
775 | */ | ||
776 | u8 enable; | ||
777 | }; | ||
778 | |||
779 | struct conf_sig_weights { | 759 | struct conf_sig_weights { |
780 | 760 | ||
781 | /* | 761 | /* |
@@ -894,12 +874,6 @@ struct conf_conn_settings { | |||
894 | u8 ps_poll_threshold; | 874 | u8 ps_poll_threshold; |
895 | 875 | ||
896 | /* | 876 | /* |
897 | * Configuration of signal (rssi/snr) triggers. | ||
898 | */ | ||
899 | u8 sig_trigger_count; | ||
900 | struct conf_sig_trigger sig_trigger[CONF_MAX_RSSI_SNR_TRIGGERS]; | ||
901 | |||
902 | /* | ||
903 | * Configuration of signal average weights. | 877 | * Configuration of signal average weights. |
904 | */ | 878 | */ |
905 | struct conf_sig_weights sig_weights; | 879 | struct conf_sig_weights sig_weights; |
@@ -929,6 +903,22 @@ struct conf_conn_settings { | |||
929 | * Range 0 - 255 | 903 | * Range 0 - 255 |
930 | */ | 904 | */ |
931 | u8 psm_entry_retries; | 905 | u8 psm_entry_retries; |
906 | |||
907 | /* | ||
908 | * | ||
909 | * Specifies the interval of the connection keep-alive null-func | ||
910 | * frame in ms. | ||
911 | * | ||
912 | * Range: 1000 - 3600000 | ||
913 | */ | ||
914 | u32 keep_alive_interval; | ||
915 | |||
916 | /* | ||
917 | * Maximum listen interval supported by the driver in units of beacons. | ||
918 | * | ||
919 | * Range: u16 | ||
920 | */ | ||
921 | u8 max_listen_interval; | ||
932 | }; | 922 | }; |
933 | 923 | ||
934 | enum { | 924 | enum { |
@@ -990,6 +980,43 @@ struct conf_pm_config_settings { | |||
990 | bool host_fast_wakeup_support; | 980 | bool host_fast_wakeup_support; |
991 | }; | 981 | }; |
992 | 982 | ||
983 | struct conf_roam_trigger_settings { | ||
984 | /* | ||
985 | * The minimum interval between two trigger events. | ||
986 | * | ||
987 | * Range: 0 - 60000 ms | ||
988 | */ | ||
989 | u16 trigger_pacing; | ||
990 | |||
991 | /* | ||
992 | * The weight for rssi/beacon average calculation | ||
993 | * | ||
994 | * Range: 0 - 255 | ||
995 | */ | ||
996 | u8 avg_weight_rssi_beacon; | ||
997 | |||
998 | /* | ||
999 | * The weight for rssi/data frame average calculation | ||
1000 | * | ||
1001 | * Range: 0 - 255 | ||
1002 | */ | ||
1003 | u8 avg_weight_rssi_data; | ||
1004 | |||
1005 | /* | ||
1006 | * The weight for snr/beacon average calculation | ||
1007 | * | ||
1008 | * Range: 0 - 255 | ||
1009 | */ | ||
1010 | u8 avg_weight_snr_beacon; | ||
1011 | |||
1012 | /* | ||
1013 | * The weight for snr/data frame average calculation | ||
1014 | * | ||
1015 | * Range: 0 - 255 | ||
1016 | */ | ||
1017 | u8 avg_weight_snr_data; | ||
1018 | }; | ||
1019 | |||
993 | struct conf_drv_settings { | 1020 | struct conf_drv_settings { |
994 | struct conf_sg_settings sg; | 1021 | struct conf_sg_settings sg; |
995 | struct conf_rx_settings rx; | 1022 | struct conf_rx_settings rx; |
@@ -998,6 +1025,7 @@ struct conf_drv_settings { | |||
998 | struct conf_init_settings init; | 1025 | struct conf_init_settings init; |
999 | struct conf_itrim_settings itrim; | 1026 | struct conf_itrim_settings itrim; |
1000 | struct conf_pm_config_settings pm_config; | 1027 | struct conf_pm_config_settings pm_config; |
1028 | struct conf_roam_trigger_settings roam_trigger; | ||
1001 | }; | 1029 | }; |
1002 | 1030 | ||
1003 | #endif | 1031 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index 4d35af96c597..cf37aa6eb137 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -31,14 +31,11 @@ | |||
31 | static int wl1271_event_scan_complete(struct wl1271 *wl, | 31 | static int wl1271_event_scan_complete(struct wl1271 *wl, |
32 | struct event_mailbox *mbox) | 32 | struct event_mailbox *mbox) |
33 | { | 33 | { |
34 | int size = sizeof(struct wl12xx_probe_req_template); | ||
35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 34 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
36 | mbox->scheduled_scan_status); | 35 | mbox->scheduled_scan_status); |
37 | 36 | ||
38 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { | 37 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | 38 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { |
40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
41 | NULL, size); | ||
42 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend | 39 | /* 2.4 GHz band scanned, scan 5 GHz band, pretend |
43 | * to the wl1271_cmd_scan function that we are not | 40 | * to the wl1271_cmd_scan function that we are not |
44 | * scanning as it checks that. | 41 | * scanning as it checks that. |
@@ -52,15 +49,6 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
52 | WL1271_SCAN_BAND_5_GHZ, | 49 | WL1271_SCAN_BAND_5_GHZ, |
53 | wl->scan.probe_requests); | 50 | wl->scan.probe_requests); |
54 | } else { | 51 | } else { |
55 | if (wl->scan.state == WL1271_SCAN_BAND_2_4_GHZ) | ||
56 | wl1271_cmd_template_set(wl, | ||
57 | CMD_TEMPL_CFG_PROBE_REQ_2_4, | ||
58 | NULL, size); | ||
59 | else | ||
60 | wl1271_cmd_template_set(wl, | ||
61 | CMD_TEMPL_CFG_PROBE_REQ_5, | ||
62 | NULL, size); | ||
63 | |||
64 | mutex_unlock(&wl->mutex); | 52 | mutex_unlock(&wl->mutex); |
65 | ieee80211_scan_completed(wl->hw, false); | 53 | ieee80211_scan_completed(wl->hw, false); |
66 | mutex_lock(&wl->mutex); | 54 | mutex_lock(&wl->mutex); |
@@ -93,16 +81,9 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
93 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 81 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, |
94 | true); | 82 | true); |
95 | } else { | 83 | } else { |
96 | wl1271_error("PSM entry failed, giving up.\n"); | 84 | wl1271_info("No ack to nullfunc from AP."); |
97 | /* FIXME: this may need to be reconsidered. for now it | ||
98 | is not possible to indicate to the mac80211 | ||
99 | afterwards that PSM entry failed. To maximize | ||
100 | functionality (receiving data and remaining | ||
101 | associated) make sure that we are in sync with the | ||
102 | AP in regard of PSM mode. */ | ||
103 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
104 | false); | ||
105 | wl->psm_entry_retry = 0; | 85 | wl->psm_entry_retry = 0; |
86 | *beacon_loss = true; | ||
106 | } | 87 | } |
107 | break; | 88 | break; |
108 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | 89 | case EVENT_ENTER_POWER_SAVE_SUCCESS: |
@@ -144,6 +125,24 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
144 | return ret; | 125 | return ret; |
145 | } | 126 | } |
146 | 127 | ||
128 | static void wl1271_event_rssi_trigger(struct wl1271 *wl, | ||
129 | struct event_mailbox *mbox) | ||
130 | { | ||
131 | enum nl80211_cqm_rssi_threshold_event event; | ||
132 | s8 metric = mbox->rssi_snr_trigger_metric[0]; | ||
133 | |||
134 | wl1271_debug(DEBUG_EVENT, "RSSI trigger metric: %d", metric); | ||
135 | |||
136 | if (metric <= wl->rssi_thold) | ||
137 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW; | ||
138 | else | ||
139 | event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH; | ||
140 | |||
141 | if (event != wl->last_rssi_event) | ||
142 | ieee80211_cqm_rssi_notify(wl->vif, event, GFP_KERNEL); | ||
143 | wl->last_rssi_event = event; | ||
144 | } | ||
145 | |||
147 | static void wl1271_event_mbox_dump(struct event_mailbox *mbox) | 146 | static void wl1271_event_mbox_dump(struct event_mailbox *mbox) |
148 | { | 147 | { |
149 | wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); | 148 | wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); |
@@ -173,10 +172,13 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
173 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon | 172 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon |
174 | * filtering) is enabled. Without PSM, the stack will receive all | 173 | * filtering) is enabled. Without PSM, the stack will receive all |
175 | * beacons and can detect beacon loss by itself. | 174 | * beacons and can detect beacon loss by itself. |
175 | * | ||
176 | * As there's possibility that the driver disables PSM before receiving | ||
177 | * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. | ||
178 | * | ||
176 | */ | 179 | */ |
177 | if (vector & BSS_LOSE_EVENT_ID && | 180 | if (vector & BSS_LOSE_EVENT_ID) { |
178 | test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 181 | wl1271_info("Beacon loss detected."); |
179 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | ||
180 | 182 | ||
181 | /* indicate to the stack, that beacons have been lost */ | 183 | /* indicate to the stack, that beacons have been lost */ |
182 | beacon_loss = true; | 184 | beacon_loss = true; |
@@ -189,17 +191,15 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
189 | return ret; | 191 | return ret; |
190 | } | 192 | } |
191 | 193 | ||
192 | if (wl->vif && beacon_loss) { | 194 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
193 | /* Obviously, it's dangerous to release the mutex while | 195 | wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); |
194 | we are holding many of the variables in the wl struct. | 196 | if (wl->vif) |
195 | That's why it's done last in the function, and care must | 197 | wl1271_event_rssi_trigger(wl, mbox); |
196 | be taken that nothing more is done after this function | ||
197 | returns. */ | ||
198 | mutex_unlock(&wl->mutex); | ||
199 | ieee80211_beacon_loss(wl->vif); | ||
200 | mutex_lock(&wl->mutex); | ||
201 | } | 198 | } |
202 | 199 | ||
200 | if (wl->vif && beacon_loss) | ||
201 | ieee80211_connection_loss(wl->vif); | ||
202 | |||
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
205 | 205 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 278f9206aa56..58371008f270 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h | |||
@@ -38,6 +38,14 @@ | |||
38 | */ | 38 | */ |
39 | 39 | ||
40 | enum { | 40 | enum { |
41 | RSSI_SNR_TRIGGER_0_EVENT_ID = BIT(0), | ||
42 | RSSI_SNR_TRIGGER_1_EVENT_ID = BIT(1), | ||
43 | RSSI_SNR_TRIGGER_2_EVENT_ID = BIT(2), | ||
44 | RSSI_SNR_TRIGGER_3_EVENT_ID = BIT(3), | ||
45 | RSSI_SNR_TRIGGER_4_EVENT_ID = BIT(4), | ||
46 | RSSI_SNR_TRIGGER_5_EVENT_ID = BIT(5), | ||
47 | RSSI_SNR_TRIGGER_6_EVENT_ID = BIT(6), | ||
48 | RSSI_SNR_TRIGGER_7_EVENT_ID = BIT(7), | ||
41 | MEASUREMENT_START_EVENT_ID = BIT(8), | 49 | MEASUREMENT_START_EVENT_ID = BIT(8), |
42 | MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), | 50 | MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), |
43 | SCAN_COMPLETE_EVENT_ID = BIT(10), | 51 | SCAN_COMPLETE_EVENT_ID = BIT(10), |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index e3806b035d0c..4447af1557f5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -52,50 +52,65 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl) | |||
52 | 52 | ||
53 | int wl1271_init_templates_config(struct wl1271 *wl) | 53 | int wl1271_init_templates_config(struct wl1271 *wl) |
54 | { | 54 | { |
55 | int ret; | 55 | int ret, i; |
56 | 56 | ||
57 | /* send empty templates for fw memory reservation */ | 57 | /* send empty templates for fw memory reservation */ |
58 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, | 58 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, |
59 | sizeof(struct wl12xx_probe_req_template)); | 59 | sizeof(struct wl12xx_probe_req_template), |
60 | 0, WL1271_RATE_AUTOMATIC); | ||
60 | if (ret < 0) | 61 | if (ret < 0) |
61 | return ret; | 62 | return ret; |
62 | 63 | ||
63 | if (wl1271_11a_enabled()) { | 64 | if (wl1271_11a_enabled()) { |
65 | size_t size = sizeof(struct wl12xx_probe_req_template); | ||
64 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, | 66 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, |
65 | NULL, | 67 | NULL, size, 0, |
66 | sizeof(struct wl12xx_probe_req_template)); | 68 | WL1271_RATE_AUTOMATIC); |
67 | if (ret < 0) | 69 | if (ret < 0) |
68 | return ret; | 70 | return ret; |
69 | } | 71 | } |
70 | 72 | ||
71 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, | 73 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, |
72 | sizeof(struct wl12xx_null_data_template)); | 74 | sizeof(struct wl12xx_null_data_template), |
75 | 0, WL1271_RATE_AUTOMATIC); | ||
73 | if (ret < 0) | 76 | if (ret < 0) |
74 | return ret; | 77 | return ret; |
75 | 78 | ||
76 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, | 79 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, |
77 | sizeof(struct wl12xx_ps_poll_template)); | 80 | sizeof(struct wl12xx_ps_poll_template), |
81 | 0, WL1271_RATE_AUTOMATIC); | ||
78 | if (ret < 0) | 82 | if (ret < 0) |
79 | return ret; | 83 | return ret; |
80 | 84 | ||
81 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, | 85 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, |
82 | sizeof | 86 | sizeof |
83 | (struct wl12xx_qos_null_data_template)); | 87 | (struct wl12xx_qos_null_data_template), |
88 | 0, WL1271_RATE_AUTOMATIC); | ||
84 | if (ret < 0) | 89 | if (ret < 0) |
85 | return ret; | 90 | return ret; |
86 | 91 | ||
87 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, | 92 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, |
88 | sizeof | 93 | sizeof |
89 | (struct wl12xx_probe_resp_template)); | 94 | (struct wl12xx_probe_resp_template), |
95 | 0, WL1271_RATE_AUTOMATIC); | ||
90 | if (ret < 0) | 96 | if (ret < 0) |
91 | return ret; | 97 | return ret; |
92 | 98 | ||
93 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, | 99 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, |
94 | sizeof | 100 | sizeof |
95 | (struct wl12xx_beacon_template)); | 101 | (struct wl12xx_beacon_template), |
102 | 0, WL1271_RATE_AUTOMATIC); | ||
96 | if (ret < 0) | 103 | if (ret < 0) |
97 | return ret; | 104 | return ret; |
98 | 105 | ||
106 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
107 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, | ||
108 | WL1271_CMD_TEMPL_MAX_SIZE, i, | ||
109 | WL1271_RATE_AUTOMATIC); | ||
110 | if (ret < 0) | ||
111 | return ret; | ||
112 | } | ||
113 | |||
99 | return 0; | 114 | return 0; |
100 | } | 115 | } |
101 | 116 | ||
@@ -237,7 +252,7 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
237 | goto out_free_memmap; | 252 | goto out_free_memmap; |
238 | 253 | ||
239 | /* Initialize connection monitoring thresholds */ | 254 | /* Initialize connection monitoring thresholds */ |
240 | ret = wl1271_acx_conn_monit_params(wl); | 255 | ret = wl1271_acx_conn_monit_params(wl, false); |
241 | if (ret < 0) | 256 | if (ret < 0) |
242 | goto out_free_memmap; | 257 | goto out_free_memmap; |
243 | 258 | ||
@@ -325,6 +340,24 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
325 | if (ret < 0) | 340 | if (ret < 0) |
326 | goto out_free_memmap; | 341 | goto out_free_memmap; |
327 | 342 | ||
343 | /* disable all keep-alive templates */ | ||
344 | for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { | ||
345 | ret = wl1271_acx_keep_alive_config(wl, i, | ||
346 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
347 | if (ret < 0) | ||
348 | goto out_free_memmap; | ||
349 | } | ||
350 | |||
351 | /* disable the keep-alive feature */ | ||
352 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
353 | if (ret < 0) | ||
354 | goto out_free_memmap; | ||
355 | |||
356 | /* Configure rssi/snr averaging weights */ | ||
357 | ret = wl1271_acx_rssi_snr_avg_weights(wl); | ||
358 | if (ret < 0) | ||
359 | goto out_free_memmap; | ||
360 | |||
328 | return 0; | 361 | return 0; |
329 | 362 | ||
330 | out_free_memmap: | 363 | out_free_memmap: |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index aa970b759dd5..814f300c3f17 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -117,8 +117,7 @@ static struct conf_drv_settings default_conf = { | |||
117 | .tx = { | 117 | .tx = { |
118 | .tx_energy_detection = 0, | 118 | .tx_energy_detection = 0, |
119 | .rc_conf = { | 119 | .rc_conf = { |
120 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | | 120 | .enabled_rates = 0, |
121 | CONF_HW_BIT_RATE_2MBPS, | ||
122 | .short_retry_limit = 10, | 121 | .short_retry_limit = 10, |
123 | .long_retry_limit = 10, | 122 | .long_retry_limit = 10, |
124 | .aflags = 0 | 123 | .aflags = 0 |
@@ -215,11 +214,13 @@ static struct conf_drv_settings default_conf = { | |||
215 | }, | 214 | }, |
216 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 215 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
217 | .tx_compl_timeout = 700, | 216 | .tx_compl_timeout = 700, |
218 | .tx_compl_threshold = 4 | 217 | .tx_compl_threshold = 4, |
218 | .basic_rate = CONF_HW_BIT_RATE_1MBPS, | ||
219 | .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS, | ||
219 | }, | 220 | }, |
220 | .conn = { | 221 | .conn = { |
221 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 222 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
222 | .listen_interval = 0, | 223 | .listen_interval = 1, |
223 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 224 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
224 | .bcn_filt_ie_count = 1, | 225 | .bcn_filt_ie_count = 1, |
225 | .bcn_filt_ie = { | 226 | .bcn_filt_ie = { |
@@ -234,38 +235,11 @@ static struct conf_drv_settings default_conf = { | |||
234 | .broadcast_timeout = 20000, | 235 | .broadcast_timeout = 20000, |
235 | .rx_broadcast_in_ps = 1, | 236 | .rx_broadcast_in_ps = 1, |
236 | .ps_poll_threshold = 20, | 237 | .ps_poll_threshold = 20, |
237 | .sig_trigger_count = 2, | ||
238 | .sig_trigger = { | ||
239 | [0] = { | ||
240 | .threshold = -75, | ||
241 | .pacing = 500, | ||
242 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
243 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
244 | .direction = CONF_TRIG_EVENT_DIR_LOW, | ||
245 | .hysteresis = 2, | ||
246 | .index = 0, | ||
247 | .enable = 1 | ||
248 | }, | ||
249 | [1] = { | ||
250 | .threshold = -75, | ||
251 | .pacing = 500, | ||
252 | .metric = CONF_TRIG_METRIC_RSSI_BEACON, | ||
253 | .type = CONF_TRIG_EVENT_TYPE_EDGE, | ||
254 | .direction = CONF_TRIG_EVENT_DIR_HIGH, | ||
255 | .hysteresis = 2, | ||
256 | .index = 1, | ||
257 | .enable = 1 | ||
258 | } | ||
259 | }, | ||
260 | .sig_weights = { | ||
261 | .rssi_bcn_avg_weight = 10, | ||
262 | .rssi_pkt_avg_weight = 10, | ||
263 | .snr_bcn_avg_weight = 10, | ||
264 | .snr_pkt_avg_weight = 10 | ||
265 | }, | ||
266 | .bet_enable = CONF_BET_MODE_ENABLE, | 238 | .bet_enable = CONF_BET_MODE_ENABLE, |
267 | .bet_max_consecutive = 10, | 239 | .bet_max_consecutive = 10, |
268 | .psm_entry_retries = 3 | 240 | .psm_entry_retries = 3, |
241 | .keep_alive_interval = 55000, | ||
242 | .max_listen_interval = 20, | ||
269 | }, | 243 | }, |
270 | .init = { | 244 | .init = { |
271 | .radioparam = { | 245 | .radioparam = { |
@@ -279,6 +253,14 @@ static struct conf_drv_settings default_conf = { | |||
279 | .pm_config = { | 253 | .pm_config = { |
280 | .host_clk_settling_time = 5000, | 254 | .host_clk_settling_time = 5000, |
281 | .host_fast_wakeup_support = false | 255 | .host_fast_wakeup_support = false |
256 | }, | ||
257 | .roam_trigger = { | ||
258 | /* FIXME: due to firmware bug, must use value 1 for now */ | ||
259 | .trigger_pacing = 1, | ||
260 | .avg_weight_rssi_beacon = 20, | ||
261 | .avg_weight_rssi_data = 10, | ||
262 | .avg_weight_snr_beacon = 20, | ||
263 | .avg_weight_snr_data = 10 | ||
282 | } | 264 | } |
283 | }; | 265 | }; |
284 | 266 | ||
@@ -349,7 +331,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
349 | goto out_free_memmap; | 331 | goto out_free_memmap; |
350 | 332 | ||
351 | /* Initialize connection monitoring thresholds */ | 333 | /* Initialize connection monitoring thresholds */ |
352 | ret = wl1271_acx_conn_monit_params(wl); | 334 | ret = wl1271_acx_conn_monit_params(wl, false); |
353 | if (ret < 0) | 335 | if (ret < 0) |
354 | goto out_free_memmap; | 336 | goto out_free_memmap; |
355 | 337 | ||
@@ -959,9 +941,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
959 | switch (vif->type) { | 941 | switch (vif->type) { |
960 | case NL80211_IFTYPE_STATION: | 942 | case NL80211_IFTYPE_STATION: |
961 | wl->bss_type = BSS_TYPE_STA_BSS; | 943 | wl->bss_type = BSS_TYPE_STA_BSS; |
944 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
962 | break; | 945 | break; |
963 | case NL80211_IFTYPE_ADHOC: | 946 | case NL80211_IFTYPE_ADHOC: |
964 | wl->bss_type = BSS_TYPE_IBSS; | 947 | wl->bss_type = BSS_TYPE_IBSS; |
948 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
965 | break; | 949 | break; |
966 | default: | 950 | default: |
967 | ret = -EOPNOTSUPP; | 951 | ret = -EOPNOTSUPP; |
@@ -1066,6 +1050,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1066 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); | 1050 | memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); |
1067 | wl->ssid_len = 0; | 1051 | wl->ssid_len = 0; |
1068 | wl->bss_type = MAX_BSS_TYPE; | 1052 | wl->bss_type = MAX_BSS_TYPE; |
1053 | wl->set_bss_type = MAX_BSS_TYPE; | ||
1069 | wl->band = IEEE80211_BAND_2GHZ; | 1054 | wl->band = IEEE80211_BAND_2GHZ; |
1070 | 1055 | ||
1071 | wl->rx_counter = 0; | 1056 | wl->rx_counter = 0; |
@@ -1088,6 +1073,14 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1088 | wl->tx_blocks_freed[i] = 0; | 1073 | wl->tx_blocks_freed[i] = 0; |
1089 | 1074 | ||
1090 | wl1271_debugfs_reset(wl); | 1075 | wl1271_debugfs_reset(wl); |
1076 | |||
1077 | kfree(wl->fw_status); | ||
1078 | wl->fw_status = NULL; | ||
1079 | kfree(wl->tx_res_if); | ||
1080 | wl->tx_res_if = NULL; | ||
1081 | kfree(wl->target_mem_map); | ||
1082 | wl->target_mem_map = NULL; | ||
1083 | |||
1091 | mutex_unlock(&wl->mutex); | 1084 | mutex_unlock(&wl->mutex); |
1092 | } | 1085 | } |
1093 | 1086 | ||
@@ -1138,10 +1131,7 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel) | |||
1138 | /* pass through frames from all BSS */ | 1131 | /* pass through frames from all BSS */ |
1139 | wl1271_configure_filters(wl, FIF_OTHER_BSS); | 1132 | wl1271_configure_filters(wl, FIF_OTHER_BSS); |
1140 | 1133 | ||
1141 | /* the dummy join is performed always with STATION BSS type to allow | 1134 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1142 | also ad-hoc mode to listen to the surroundings without sending any | ||
1143 | beacons yet. */ | ||
1144 | ret = wl1271_cmd_join(wl, BSS_TYPE_STA_BSS); | ||
1145 | if (ret < 0) | 1135 | if (ret < 0) |
1146 | goto out; | 1136 | goto out; |
1147 | 1137 | ||
@@ -1171,6 +1161,32 @@ out: | |||
1171 | return ret; | 1161 | return ret; |
1172 | } | 1162 | } |
1173 | 1163 | ||
1164 | static void wl1271_set_band_rate(struct wl1271 *wl) | ||
1165 | { | ||
1166 | if (wl->band == IEEE80211_BAND_2GHZ) | ||
1167 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1168 | else | ||
1169 | wl->basic_rate_set = wl->conf.tx.basic_rate_5; | ||
1170 | } | ||
1171 | |||
1172 | static u32 wl1271_min_rate_get(struct wl1271 *wl) | ||
1173 | { | ||
1174 | int i; | ||
1175 | u32 rate = 0; | ||
1176 | |||
1177 | if (!wl->basic_rate_set) { | ||
1178 | WARN_ON(1); | ||
1179 | wl->basic_rate_set = wl->conf.tx.basic_rate; | ||
1180 | } | ||
1181 | |||
1182 | for (i = 0; !rate; i++) { | ||
1183 | if ((wl->basic_rate_set >> i) & 0x1) | ||
1184 | rate = 1 << i; | ||
1185 | } | ||
1186 | |||
1187 | return rate; | ||
1188 | } | ||
1189 | |||
1174 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1190 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1175 | { | 1191 | { |
1176 | struct wl1271 *wl = hw->priv; | 1192 | struct wl1271 *wl = hw->priv; |
@@ -1187,12 +1203,41 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1187 | 1203 | ||
1188 | mutex_lock(&wl->mutex); | 1204 | mutex_lock(&wl->mutex); |
1189 | 1205 | ||
1190 | wl->band = conf->channel->band; | 1206 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
1207 | goto out; | ||
1191 | 1208 | ||
1192 | ret = wl1271_ps_elp_wakeup(wl, false); | 1209 | ret = wl1271_ps_elp_wakeup(wl, false); |
1193 | if (ret < 0) | 1210 | if (ret < 0) |
1194 | goto out; | 1211 | goto out; |
1195 | 1212 | ||
1213 | /* if the channel changes while joined, join again */ | ||
1214 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
1215 | wl->band = conf->channel->band; | ||
1216 | wl->channel = channel; | ||
1217 | |||
1218 | /* | ||
1219 | * FIXME: the mac80211 should really provide a fixed rate | ||
1220 | * to use here. for now, just use the smallest possible rate | ||
1221 | * for the band as a fixed rate for association frames and | ||
1222 | * other control messages. | ||
1223 | */ | ||
1224 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | ||
1225 | wl1271_set_band_rate(wl); | ||
1226 | |||
1227 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1228 | ret = wl1271_acx_rate_policies(wl); | ||
1229 | if (ret < 0) | ||
1230 | wl1271_warning("rate policy for update channel " | ||
1231 | "failed %d", ret); | ||
1232 | |||
1233 | if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1234 | ret = wl1271_cmd_join(wl, wl->set_bss_type); | ||
1235 | if (ret < 0) | ||
1236 | wl1271_warning("cmd join to update channel " | ||
1237 | "failed %d", ret); | ||
1238 | } | ||
1239 | } | ||
1240 | |||
1196 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1241 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1197 | if (conf->flags & IEEE80211_CONF_IDLE && | 1242 | if (conf->flags & IEEE80211_CONF_IDLE && |
1198 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) | 1243 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
@@ -1201,24 +1246,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1201 | wl1271_join_channel(wl, channel); | 1246 | wl1271_join_channel(wl, channel); |
1202 | 1247 | ||
1203 | if (conf->flags & IEEE80211_CONF_IDLE) { | 1248 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1204 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 1249 | wl->rate_set = wl1271_min_rate_get(wl); |
1205 | wl->sta_rate_set = 0; | 1250 | wl->sta_rate_set = 0; |
1206 | wl1271_acx_rate_policies(wl); | 1251 | wl1271_acx_rate_policies(wl); |
1207 | } | 1252 | wl1271_acx_keep_alive_config( |
1253 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1254 | ACX_KEEP_ALIVE_TPL_INVALID); | ||
1255 | set_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1256 | } else | ||
1257 | clear_bit(WL1271_FLAG_IDLE, &wl->flags); | ||
1208 | } | 1258 | } |
1209 | 1259 | ||
1210 | /* if the channel changes while joined, join again */ | ||
1211 | if (channel != wl->channel && | ||
1212 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) { | ||
1213 | wl->channel = channel; | ||
1214 | /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */ | ||
1215 | ret = wl1271_cmd_join(wl, wl->bss_type); | ||
1216 | if (ret < 0) | ||
1217 | wl1271_warning("cmd join to update channel failed %d", | ||
1218 | ret); | ||
1219 | } else | ||
1220 | wl->channel = channel; | ||
1221 | |||
1222 | if (conf->flags & IEEE80211_CONF_PS && | 1260 | if (conf->flags & IEEE80211_CONF_PS && |
1223 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 1261 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1224 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 1262 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
@@ -1272,6 +1310,11 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, | |||
1272 | { | 1310 | { |
1273 | struct wl1271_filter_params *fp; | 1311 | struct wl1271_filter_params *fp; |
1274 | struct netdev_hw_addr *ha; | 1312 | struct netdev_hw_addr *ha; |
1313 | struct wl1271 *wl = hw->priv; | ||
1314 | int i; | ||
1315 | |||
1316 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1317 | return 0; | ||
1275 | 1318 | ||
1276 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); | 1319 | fp = kzalloc(sizeof(*fp), GFP_ATOMIC); |
1277 | if (!fp) { | 1320 | if (!fp) { |
@@ -1314,15 +1357,16 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
1314 | 1357 | ||
1315 | mutex_lock(&wl->mutex); | 1358 | mutex_lock(&wl->mutex); |
1316 | 1359 | ||
1317 | if (wl->state == WL1271_STATE_OFF) | 1360 | *total &= WL1271_SUPPORTED_FILTERS; |
1361 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1362 | |||
1363 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1318 | goto out; | 1364 | goto out; |
1319 | 1365 | ||
1320 | ret = wl1271_ps_elp_wakeup(wl, false); | 1366 | ret = wl1271_ps_elp_wakeup(wl, false); |
1321 | if (ret < 0) | 1367 | if (ret < 0) |
1322 | goto out; | 1368 | goto out; |
1323 | 1369 | ||
1324 | *total &= WL1271_SUPPORTED_FILTERS; | ||
1325 | changed &= WL1271_SUPPORTED_FILTERS; | ||
1326 | 1370 | ||
1327 | if (*total & FIF_ALLMULTI) | 1371 | if (*total & FIF_ALLMULTI) |
1328 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); | 1372 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); |
@@ -1516,10 +1560,13 @@ out: | |||
1516 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 1560 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
1517 | { | 1561 | { |
1518 | struct wl1271 *wl = hw->priv; | 1562 | struct wl1271 *wl = hw->priv; |
1519 | int ret; | 1563 | int ret = 0; |
1520 | 1564 | ||
1521 | mutex_lock(&wl->mutex); | 1565 | mutex_lock(&wl->mutex); |
1522 | 1566 | ||
1567 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
1568 | goto out; | ||
1569 | |||
1523 | ret = wl1271_ps_elp_wakeup(wl, false); | 1570 | ret = wl1271_ps_elp_wakeup(wl, false); |
1524 | if (ret < 0) | 1571 | if (ret < 0) |
1525 | goto out; | 1572 | goto out; |
@@ -1561,6 +1608,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1561 | enum wl1271_cmd_ps_mode mode; | 1608 | enum wl1271_cmd_ps_mode mode; |
1562 | struct wl1271 *wl = hw->priv; | 1609 | struct wl1271 *wl = hw->priv; |
1563 | bool do_join = false; | 1610 | bool do_join = false; |
1611 | bool do_keepalive = false; | ||
1564 | int ret; | 1612 | int ret; |
1565 | 1613 | ||
1566 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); | 1614 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); |
@@ -1571,20 +1619,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1571 | if (ret < 0) | 1619 | if (ret < 0) |
1572 | goto out; | 1620 | goto out; |
1573 | 1621 | ||
1574 | if (wl->bss_type == BSS_TYPE_IBSS) { | 1622 | if ((changed && BSS_CHANGED_BEACON_INT) && |
1575 | /* FIXME: This implements rudimentary ad-hoc support - | 1623 | (wl->bss_type == BSS_TYPE_IBSS)) { |
1576 | proper templates are on the wish list and notification | 1624 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d", |
1577 | on when they change. This patch will update the templates | 1625 | bss_conf->beacon_int); |
1578 | on every call to this function. */ | 1626 | |
1627 | wl->beacon_int = bss_conf->beacon_int; | ||
1628 | do_join = true; | ||
1629 | } | ||
1630 | |||
1631 | if ((changed && BSS_CHANGED_BEACON) && | ||
1632 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1579 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 1633 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
1580 | 1634 | ||
1635 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated"); | ||
1636 | |||
1581 | if (beacon) { | 1637 | if (beacon) { |
1582 | struct ieee80211_hdr *hdr; | 1638 | struct ieee80211_hdr *hdr; |
1583 | 1639 | ||
1584 | wl1271_ssid_set(wl, beacon); | 1640 | wl1271_ssid_set(wl, beacon); |
1585 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | 1641 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, |
1586 | beacon->data, | 1642 | beacon->data, |
1587 | beacon->len); | 1643 | beacon->len, 0, |
1644 | wl1271_min_rate_get(wl)); | ||
1588 | 1645 | ||
1589 | if (ret < 0) { | 1646 | if (ret < 0) { |
1590 | dev_kfree_skb(beacon); | 1647 | dev_kfree_skb(beacon); |
@@ -1599,7 +1656,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1599 | ret = wl1271_cmd_template_set(wl, | 1656 | ret = wl1271_cmd_template_set(wl, |
1600 | CMD_TEMPL_PROBE_RESPONSE, | 1657 | CMD_TEMPL_PROBE_RESPONSE, |
1601 | beacon->data, | 1658 | beacon->data, |
1602 | beacon->len); | 1659 | beacon->len, 0, |
1660 | wl1271_min_rate_get(wl)); | ||
1603 | dev_kfree_skb(beacon); | 1661 | dev_kfree_skb(beacon); |
1604 | if (ret < 0) | 1662 | if (ret < 0) |
1605 | goto out_sleep; | 1663 | goto out_sleep; |
@@ -1609,6 +1667,30 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1609 | } | 1667 | } |
1610 | } | 1668 | } |
1611 | 1669 | ||
1670 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | ||
1671 | (wl->bss_type == BSS_TYPE_IBSS)) { | ||
1672 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", | ||
1673 | bss_conf->enable_beacon ? "enabled" : "disabled"); | ||
1674 | |||
1675 | if (bss_conf->enable_beacon) | ||
1676 | wl->set_bss_type = BSS_TYPE_IBSS; | ||
1677 | else | ||
1678 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
1679 | do_join = true; | ||
1680 | } | ||
1681 | |||
1682 | if (changed & BSS_CHANGED_CQM) { | ||
1683 | bool enable = false; | ||
1684 | if (bss_conf->cqm_rssi_thold) | ||
1685 | enable = true; | ||
1686 | ret = wl1271_acx_rssi_snr_trigger(wl, enable, | ||
1687 | bss_conf->cqm_rssi_thold, | ||
1688 | bss_conf->cqm_rssi_hyst); | ||
1689 | if (ret < 0) | ||
1690 | goto out; | ||
1691 | wl->rssi_thold = bss_conf->cqm_rssi_thold; | ||
1692 | } | ||
1693 | |||
1612 | if ((changed & BSS_CHANGED_BSSID) && | 1694 | if ((changed & BSS_CHANGED_BSSID) && |
1613 | /* | 1695 | /* |
1614 | * Now we know the correct bssid, so we send a new join command | 1696 | * Now we know the correct bssid, so we send a new join command |
@@ -1630,10 +1712,23 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1630 | 1712 | ||
1631 | if (changed & BSS_CHANGED_ASSOC) { | 1713 | if (changed & BSS_CHANGED_ASSOC) { |
1632 | if (bss_conf->assoc) { | 1714 | if (bss_conf->assoc) { |
1715 | u32 rates; | ||
1633 | wl->aid = bss_conf->aid; | 1716 | wl->aid = bss_conf->aid; |
1634 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1717 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1635 | 1718 | ||
1636 | /* | 1719 | /* |
1720 | * use basic rates from AP, and determine lowest rate | ||
1721 | * to use with control frames. | ||
1722 | */ | ||
1723 | rates = bss_conf->basic_rates; | ||
1724 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
1725 | rates); | ||
1726 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1727 | ret = wl1271_acx_rate_policies(wl); | ||
1728 | if (ret < 0) | ||
1729 | goto out_sleep; | ||
1730 | |||
1731 | /* | ||
1637 | * with wl1271, we don't need to update the | 1732 | * with wl1271, we don't need to update the |
1638 | * beacon_int and dtim_period, because the firmware | 1733 | * beacon_int and dtim_period, because the firmware |
1639 | * updates it by itself when the first beacon is | 1734 | * updates it by itself when the first beacon is |
@@ -1643,7 +1738,30 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1643 | if (ret < 0) | 1738 | if (ret < 0) |
1644 | goto out_sleep; | 1739 | goto out_sleep; |
1645 | 1740 | ||
1646 | ret = wl1271_acx_aid(wl, wl->aid); | 1741 | /* |
1742 | * The SSID is intentionally set to NULL here - the | ||
1743 | * firmware will set the probe request with a | ||
1744 | * broadcast SSID regardless of what we set in the | ||
1745 | * template. | ||
1746 | */ | ||
1747 | ret = wl1271_cmd_build_probe_req(wl, NULL, 0, | ||
1748 | NULL, 0, wl->band); | ||
1749 | |||
1750 | /* Enable the keep-alive feature */ | ||
1751 | ret = wl1271_acx_keep_alive_mode(wl, true); | ||
1752 | if (ret < 0) | ||
1753 | goto out_sleep; | ||
1754 | |||
1755 | /* | ||
1756 | * This is awkward. The keep-alive configs must be done | ||
1757 | * *after* the join command, because otherwise it will | ||
1758 | * not work, but it must only be done *once* because | ||
1759 | * otherwise the firmware will start complaining. | ||
1760 | */ | ||
1761 | do_keepalive = true; | ||
1762 | |||
1763 | /* enable the connection monitoring feature */ | ||
1764 | ret = wl1271_acx_conn_monit_params(wl, true); | ||
1647 | if (ret < 0) | 1765 | if (ret < 0) |
1648 | goto out_sleep; | 1766 | goto out_sleep; |
1649 | 1767 | ||
@@ -1659,6 +1777,22 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1659 | /* use defaults when not associated */ | 1777 | /* use defaults when not associated */ |
1660 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 1778 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1661 | wl->aid = 0; | 1779 | wl->aid = 0; |
1780 | |||
1781 | /* revert back to minimum rates for the current band */ | ||
1782 | wl1271_set_band_rate(wl); | ||
1783 | wl->basic_rate = wl1271_min_rate_get(wl); | ||
1784 | ret = wl1271_acx_rate_policies(wl); | ||
1785 | if (ret < 0) | ||
1786 | goto out_sleep; | ||
1787 | |||
1788 | /* disable connection monitor features */ | ||
1789 | ret = wl1271_acx_conn_monit_params(wl, false); | ||
1790 | |||
1791 | /* Disable the keep-alive feature */ | ||
1792 | ret = wl1271_acx_keep_alive_mode(wl, false); | ||
1793 | |||
1794 | if (ret < 0) | ||
1795 | goto out_sleep; | ||
1662 | } | 1796 | } |
1663 | 1797 | ||
1664 | } | 1798 | } |
@@ -1693,7 +1827,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1693 | } | 1827 | } |
1694 | 1828 | ||
1695 | if (do_join) { | 1829 | if (do_join) { |
1696 | ret = wl1271_cmd_join(wl, wl->bss_type); | 1830 | ret = wl1271_cmd_join(wl, wl->set_bss_type); |
1697 | if (ret < 0) { | 1831 | if (ret < 0) { |
1698 | wl1271_warning("cmd join failed %d", ret); | 1832 | wl1271_warning("cmd join failed %d", ret); |
1699 | goto out_sleep; | 1833 | goto out_sleep; |
@@ -1701,6 +1835,29 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1701 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | 1835 | set_bit(WL1271_FLAG_JOINED, &wl->flags); |
1702 | } | 1836 | } |
1703 | 1837 | ||
1838 | /* | ||
1839 | * The JOIN operation shuts down the firmware keep-alive as a side | ||
1840 | * effect, and the ACX_AID will start the keep-alive as a side effect. | ||
1841 | * Hence, for non-IBSS, the ACX_AID must always happen *after* the | ||
1842 | * JOIN operation, and the template config after the ACX_AID. | ||
1843 | */ | ||
1844 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | ||
1845 | ret = wl1271_acx_aid(wl, wl->aid); | ||
1846 | if (ret < 0) | ||
1847 | goto out_sleep; | ||
1848 | } | ||
1849 | |||
1850 | if (do_keepalive) { | ||
1851 | ret = wl1271_cmd_build_klv_null_data(wl); | ||
1852 | if (ret < 0) | ||
1853 | goto out_sleep; | ||
1854 | ret = wl1271_acx_keep_alive_config( | ||
1855 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
1856 | ACX_KEEP_ALIVE_TPL_VALID); | ||
1857 | if (ret < 0) | ||
1858 | goto out_sleep; | ||
1859 | } | ||
1860 | |||
1704 | out_sleep: | 1861 | out_sleep: |
1705 | wl1271_ps_elp_sleep(wl); | 1862 | wl1271_ps_elp_sleep(wl); |
1706 | 1863 | ||
@@ -1812,6 +1969,36 @@ static struct ieee80211_channel wl1271_channels[] = { | |||
1812 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, | 1969 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1813 | }; | 1970 | }; |
1814 | 1971 | ||
1972 | /* mapping to indexes for wl1271_rates */ | ||
1973 | const static u8 wl1271_rate_to_idx_2ghz[] = { | ||
1974 | /* MCS rates are used only with 11n */ | ||
1975 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
1976 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
1977 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
1978 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
1979 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
1980 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
1981 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
1982 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
1983 | |||
1984 | 11, /* CONF_HW_RXTX_RATE_54 */ | ||
1985 | 10, /* CONF_HW_RXTX_RATE_48 */ | ||
1986 | 9, /* CONF_HW_RXTX_RATE_36 */ | ||
1987 | 8, /* CONF_HW_RXTX_RATE_24 */ | ||
1988 | |||
1989 | /* TI-specific rate */ | ||
1990 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
1991 | |||
1992 | 7, /* CONF_HW_RXTX_RATE_18 */ | ||
1993 | 6, /* CONF_HW_RXTX_RATE_12 */ | ||
1994 | 3, /* CONF_HW_RXTX_RATE_11 */ | ||
1995 | 5, /* CONF_HW_RXTX_RATE_9 */ | ||
1996 | 4, /* CONF_HW_RXTX_RATE_6 */ | ||
1997 | 2, /* CONF_HW_RXTX_RATE_5_5 */ | ||
1998 | 1, /* CONF_HW_RXTX_RATE_2 */ | ||
1999 | 0 /* CONF_HW_RXTX_RATE_1 */ | ||
2000 | }; | ||
2001 | |||
1815 | /* can't be const, mac80211 writes to this */ | 2002 | /* can't be const, mac80211 writes to this */ |
1816 | static struct ieee80211_supported_band wl1271_band_2ghz = { | 2003 | static struct ieee80211_supported_band wl1271_band_2ghz = { |
1817 | .channels = wl1271_channels, | 2004 | .channels = wl1271_channels, |
@@ -1894,6 +2081,35 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { | |||
1894 | { .hw_value = 165, .center_freq = 5825}, | 2081 | { .hw_value = 165, .center_freq = 5825}, |
1895 | }; | 2082 | }; |
1896 | 2083 | ||
2084 | /* mapping to indexes for wl1271_rates_5ghz */ | ||
2085 | const static u8 wl1271_rate_to_idx_5ghz[] = { | ||
2086 | /* MCS rates are used only with 11n */ | ||
2087 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS7 */ | ||
2088 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS6 */ | ||
2089 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS5 */ | ||
2090 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS4 */ | ||
2091 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS3 */ | ||
2092 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS2 */ | ||
2093 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS1 */ | ||
2094 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_MCS0 */ | ||
2095 | |||
2096 | 7, /* CONF_HW_RXTX_RATE_54 */ | ||
2097 | 6, /* CONF_HW_RXTX_RATE_48 */ | ||
2098 | 5, /* CONF_HW_RXTX_RATE_36 */ | ||
2099 | 4, /* CONF_HW_RXTX_RATE_24 */ | ||
2100 | |||
2101 | /* TI-specific rate */ | ||
2102 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22 */ | ||
2103 | |||
2104 | 3, /* CONF_HW_RXTX_RATE_18 */ | ||
2105 | 2, /* CONF_HW_RXTX_RATE_12 */ | ||
2106 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11 */ | ||
2107 | 1, /* CONF_HW_RXTX_RATE_9 */ | ||
2108 | 0, /* CONF_HW_RXTX_RATE_6 */ | ||
2109 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5 */ | ||
2110 | CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2 */ | ||
2111 | CONF_HW_RXTX_RATE_UNSUPPORTED /* CONF_HW_RXTX_RATE_1 */ | ||
2112 | }; | ||
1897 | 2113 | ||
1898 | static struct ieee80211_supported_band wl1271_band_5ghz = { | 2114 | static struct ieee80211_supported_band wl1271_band_5ghz = { |
1899 | .channels = wl1271_channels_5ghz, | 2115 | .channels = wl1271_channels_5ghz, |
@@ -1902,6 +2118,11 @@ static struct ieee80211_supported_band wl1271_band_5ghz = { | |||
1902 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), | 2118 | .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz), |
1903 | }; | 2119 | }; |
1904 | 2120 | ||
2121 | const static u8 *wl1271_band_rate_to_idx[] = { | ||
2122 | [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz, | ||
2123 | [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz | ||
2124 | }; | ||
2125 | |||
1905 | static const struct ieee80211_ops wl1271_ops = { | 2126 | static const struct ieee80211_ops wl1271_ops = { |
1906 | .start = wl1271_op_start, | 2127 | .start = wl1271_op_start, |
1907 | .stop = wl1271_op_stop, | 2128 | .stop = wl1271_op_stop, |
@@ -1919,6 +2140,27 @@ static const struct ieee80211_ops wl1271_ops = { | |||
1919 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 2140 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
1920 | }; | 2141 | }; |
1921 | 2142 | ||
2143 | |||
2144 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate) | ||
2145 | { | ||
2146 | u8 idx; | ||
2147 | |||
2148 | BUG_ON(wl->band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *)); | ||
2149 | |||
2150 | if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) { | ||
2151 | wl1271_error("Illegal RX rate from HW: %d", rate); | ||
2152 | return 0; | ||
2153 | } | ||
2154 | |||
2155 | idx = wl1271_band_rate_to_idx[wl->band][rate]; | ||
2156 | if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) { | ||
2157 | wl1271_error("Unsupported RX rate from HW: %d", rate); | ||
2158 | return 0; | ||
2159 | } | ||
2160 | |||
2161 | return idx; | ||
2162 | } | ||
2163 | |||
1922 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, | 2164 | static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev, |
1923 | struct device_attribute *attr, | 2165 | struct device_attribute *attr, |
1924 | char *buf) | 2166 | char *buf) |
@@ -2021,13 +2263,16 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2021 | /* unit us */ | 2263 | /* unit us */ |
2022 | /* FIXME: find a proper value */ | 2264 | /* FIXME: find a proper value */ |
2023 | wl->hw->channel_change_time = 10000; | 2265 | wl->hw->channel_change_time = 10000; |
2266 | wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval; | ||
2024 | 2267 | ||
2025 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 2268 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
2026 | IEEE80211_HW_NOISE_DBM | | 2269 | IEEE80211_HW_NOISE_DBM | |
2027 | IEEE80211_HW_BEACON_FILTER | | 2270 | IEEE80211_HW_BEACON_FILTER | |
2028 | IEEE80211_HW_SUPPORTS_PS | | 2271 | IEEE80211_HW_SUPPORTS_PS | |
2029 | IEEE80211_HW_SUPPORTS_UAPSD | | 2272 | IEEE80211_HW_SUPPORTS_UAPSD | |
2030 | IEEE80211_HW_HAS_RATE_CONTROL; | 2273 | IEEE80211_HW_HAS_RATE_CONTROL | |
2274 | IEEE80211_HW_CONNECTION_MONITOR | | ||
2275 | IEEE80211_HW_SUPPORTS_CQM_RSSI; | ||
2031 | 2276 | ||
2032 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 2277 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
2033 | BIT(NL80211_IFTYPE_ADHOC); | 2278 | BIT(NL80211_IFTYPE_ADHOC); |
@@ -2038,6 +2283,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
2038 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; | 2283 | wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz; |
2039 | 2284 | ||
2040 | wl->hw->queues = 4; | 2285 | wl->hw->queues = 4; |
2286 | wl->hw->max_rates = 1; | ||
2041 | 2287 | ||
2042 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); | 2288 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); |
2043 | 2289 | ||
@@ -2053,7 +2299,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2053 | struct platform_device *plat_dev = NULL; | 2299 | struct platform_device *plat_dev = NULL; |
2054 | struct wl1271 *wl; | 2300 | struct wl1271 *wl; |
2055 | int i, ret; | 2301 | int i, ret; |
2056 | static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; | ||
2057 | 2302 | ||
2058 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 2303 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
2059 | if (!hw) { | 2304 | if (!hw) { |
@@ -2083,6 +2328,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2083 | 2328 | ||
2084 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 2329 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
2085 | wl->channel = WL1271_DEFAULT_CHANNEL; | 2330 | wl->channel = WL1271_DEFAULT_CHANNEL; |
2331 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | ||
2086 | wl->default_key = 0; | 2332 | wl->default_key = 0; |
2087 | wl->rx_counter = 0; | 2333 | wl->rx_counter = 0; |
2088 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 2334 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
@@ -2090,6 +2336,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2090 | wl->psm_entry_retry = 0; | 2336 | wl->psm_entry_retry = 0; |
2091 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 2337 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
2092 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | 2338 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
2339 | wl->basic_rate = CONF_TX_RATE_MASK_BASIC; | ||
2093 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | 2340 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
2094 | wl->sta_rate_set = 0; | 2341 | wl->sta_rate_set = 0; |
2095 | wl->band = IEEE80211_BAND_2GHZ; | 2342 | wl->band = IEEE80211_BAND_2GHZ; |
@@ -2105,13 +2352,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
2105 | wl->state = WL1271_STATE_OFF; | 2352 | wl->state = WL1271_STATE_OFF; |
2106 | mutex_init(&wl->mutex); | 2353 | mutex_init(&wl->mutex); |
2107 | 2354 | ||
2108 | /* | ||
2109 | * FIXME: we should use a zero MAC address here, but for now we | ||
2110 | * generate a random Nokia address. | ||
2111 | */ | ||
2112 | memcpy(wl->mac_addr, nokia_oui, 3); | ||
2113 | get_random_bytes(wl->mac_addr + 3, 3); | ||
2114 | |||
2115 | /* Apply default driver configuration. */ | 2355 | /* Apply default driver configuration. */ |
2116 | wl1271_conf_init(wl); | 2356 | wl1271_conf_init(wl); |
2117 | 2357 | ||
@@ -2157,7 +2397,6 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
2157 | 2397 | ||
2158 | wl1271_debugfs_exit(wl); | 2398 | wl1271_debugfs_exit(wl); |
2159 | 2399 | ||
2160 | kfree(wl->target_mem_map); | ||
2161 | vfree(wl->fw); | 2400 | vfree(wl->fw); |
2162 | wl->fw = NULL; | 2401 | wl->fw = NULL; |
2163 | kfree(wl->nvs); | 2402 | kfree(wl->nvs); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 5a04482b9353..a5e60e0403e5 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -40,7 +40,8 @@ void wl1271_elp_work(struct work_struct *work) | |||
40 | mutex_lock(&wl->mutex); | 40 | mutex_lock(&wl->mutex); |
41 | 41 | ||
42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || | 42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
43 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) | 43 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && |
44 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) | ||
44 | goto out; | 45 | goto out; |
45 | 46 | ||
46 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 47 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
@@ -56,7 +57,8 @@ out: | |||
56 | /* Routines to toggle sleep mode while in ELP */ | 57 | /* Routines to toggle sleep mode while in ELP */ |
57 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 58 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
58 | { | 59 | { |
59 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 60 | if (test_bit(WL1271_FLAG_PSM, &wl->flags) || |
61 | test_bit(WL1271_FLAG_IDLE, &wl->flags)) { | ||
60 | cancel_delayed_work(&wl->elp_work); | 62 | cancel_delayed_work(&wl->elp_work); |
61 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 63 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
62 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 64 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 6f1b732ae43b..57f4bfd959c8 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -43,66 +43,6 @@ static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, | |||
43 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; | 43 | RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV; |
44 | } | 44 | } |
45 | 45 | ||
46 | /* The values of this table must match the wl1271_rates[] array */ | ||
47 | static u8 wl1271_rx_rate_to_idx[] = { | ||
48 | /* MCS rates are used only with 11n */ | ||
49 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ | ||
50 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ | ||
51 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ | ||
52 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ | ||
53 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ | ||
54 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ | ||
55 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ | ||
56 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ | ||
57 | |||
58 | 11, /* WL1271_RATE_54 */ | ||
59 | 10, /* WL1271_RATE_48 */ | ||
60 | 9, /* WL1271_RATE_36 */ | ||
61 | 8, /* WL1271_RATE_24 */ | ||
62 | |||
63 | /* TI-specific rate */ | ||
64 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ | ||
65 | |||
66 | 7, /* WL1271_RATE_18 */ | ||
67 | 6, /* WL1271_RATE_12 */ | ||
68 | 3, /* WL1271_RATE_11 */ | ||
69 | 5, /* WL1271_RATE_9 */ | ||
70 | 4, /* WL1271_RATE_6 */ | ||
71 | 2, /* WL1271_RATE_5_5 */ | ||
72 | 1, /* WL1271_RATE_2 */ | ||
73 | 0 /* WL1271_RATE_1 */ | ||
74 | }; | ||
75 | |||
76 | /* The values of this table must match the wl1271_rates[] array */ | ||
77 | static u8 wl1271_5_ghz_rx_rate_to_idx[] = { | ||
78 | /* MCS rates are used only with 11n */ | ||
79 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ | ||
80 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ | ||
81 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ | ||
82 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ | ||
83 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ | ||
84 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ | ||
85 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ | ||
86 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ | ||
87 | |||
88 | 7, /* WL1271_RATE_54 */ | ||
89 | 6, /* WL1271_RATE_48 */ | ||
90 | 5, /* WL1271_RATE_36 */ | ||
91 | 4, /* WL1271_RATE_24 */ | ||
92 | |||
93 | /* TI-specific rate */ | ||
94 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ | ||
95 | |||
96 | 3, /* WL1271_RATE_18 */ | ||
97 | 2, /* WL1271_RATE_12 */ | ||
98 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_11 */ | ||
99 | 1, /* WL1271_RATE_9 */ | ||
100 | 0, /* WL1271_RATE_6 */ | ||
101 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_5_5 */ | ||
102 | WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_2 */ | ||
103 | WL1271_RX_RATE_UNSUPPORTED /* WL1271_RATE_1 */ | ||
104 | }; | ||
105 | |||
106 | static void wl1271_rx_status(struct wl1271 *wl, | 46 | static void wl1271_rx_status(struct wl1271 *wl, |
107 | struct wl1271_rx_descriptor *desc, | 47 | struct wl1271_rx_descriptor *desc, |
108 | struct ieee80211_rx_status *status, | 48 | struct ieee80211_rx_status *status, |
@@ -110,20 +50,8 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
110 | { | 50 | { |
111 | memset(status, 0, sizeof(struct ieee80211_rx_status)); | 51 | memset(status, 0, sizeof(struct ieee80211_rx_status)); |
112 | 52 | ||
113 | if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == | 53 | status->band = wl->band; |
114 | WL1271_RX_DESC_BAND_BG) { | 54 | status->rate_idx = wl1271_rate_to_idx(wl, desc->rate); |
115 | status->band = IEEE80211_BAND_2GHZ; | ||
116 | status->rate_idx = wl1271_rx_rate_to_idx[desc->rate]; | ||
117 | } else if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == | ||
118 | WL1271_RX_DESC_BAND_A) { | ||
119 | status->band = IEEE80211_BAND_5GHZ; | ||
120 | status->rate_idx = wl1271_5_ghz_rx_rate_to_idx[desc->rate]; | ||
121 | } else | ||
122 | wl1271_warning("unsupported band 0x%x", | ||
123 | desc->flags & WL1271_RX_DESC_BAND_MASK); | ||
124 | |||
125 | if (unlikely(status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)) | ||
126 | wl1271_warning("unsupported rate"); | ||
127 | 55 | ||
128 | /* | 56 | /* |
129 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the | 57 | * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the |
@@ -133,13 +61,6 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
133 | */ | 61 | */ |
134 | status->signal = desc->rssi; | 62 | status->signal = desc->rssi; |
135 | 63 | ||
136 | /* | ||
137 | * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we | ||
138 | * need to divide by two for now, but TI has been discussing about | ||
139 | * changing it. This needs to be rechecked. | ||
140 | */ | ||
141 | status->noise = desc->rssi - (desc->snr >> 1); | ||
142 | |||
143 | status->freq = ieee80211_channel_to_frequency(desc->channel); | 64 | status->freq = ieee80211_channel_to_frequency(desc->channel); |
144 | 65 | ||
145 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { | 66 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h index 1ae6d1783ed4..b89be4758e78 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ b/drivers/net/wireless/wl12xx/wl1271_rx.h | |||
@@ -43,7 +43,6 @@ | |||
43 | #define RX_MAX_PACKET_ID 3 | 43 | #define RX_MAX_PACKET_ID 3 |
44 | 44 | ||
45 | #define NUM_RX_PKT_DESC_MOD_MASK 7 | 45 | #define NUM_RX_PKT_DESC_MOD_MASK 7 |
46 | #define WL1271_RX_RATE_UNSUPPORTED 0xFF | ||
47 | 46 | ||
48 | #define RX_DESC_VALID_FCS 0x0001 | 47 | #define RX_DESC_VALID_FCS 0x0001 |
49 | #define RX_DESC_MATCH_RXADDR1 0x0002 | 48 | #define RX_DESC_MATCH_RXADDR1 0x0002 |
@@ -117,5 +116,6 @@ struct wl1271_rx_descriptor { | |||
117 | } __attribute__ ((packed)); | 116 | } __attribute__ ((packed)); |
118 | 117 | ||
119 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); | 118 | void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); |
119 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); | ||
120 | 120 | ||
121 | #endif | 121 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 3c03de74dbfc..d3d6f302f705 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c | |||
@@ -117,7 +117,7 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
117 | else | 117 | else |
118 | ret = sdio_memcpy_fromio(func, buf, addr, len); | 118 | ret = sdio_memcpy_fromio(func, buf, addr, len); |
119 | 119 | ||
120 | wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %d bytes", | 120 | wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes", |
121 | addr, len); | 121 | addr, len); |
122 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | 122 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); |
123 | } | 123 | } |
@@ -138,7 +138,7 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, | |||
138 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", | 138 | wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x", |
139 | addr, ((u8 *)buf)[0]); | 139 | addr, ((u8 *)buf)[0]); |
140 | } else { | 140 | } else { |
141 | wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %d bytes", | 141 | wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %zu bytes", |
142 | addr, len); | 142 | addr, len); |
143 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); | 143 | wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len); |
144 | 144 | ||
@@ -255,7 +255,7 @@ static void __devexit wl1271_remove(struct sdio_func *func) | |||
255 | } | 255 | } |
256 | 256 | ||
257 | static struct sdio_driver wl1271_sdio_driver = { | 257 | static struct sdio_driver wl1271_sdio_driver = { |
258 | .name = "wl1271", | 258 | .name = "wl1271_sdio", |
259 | .id_table = wl1271_devices, | 259 | .id_table = wl1271_devices, |
260 | .probe = wl1271_probe, | 260 | .probe = wl1271_probe, |
261 | .remove = __devexit_p(wl1271_remove), | 261 | .remove = __devexit_p(wl1271_remove), |
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c index 256e84ad0baf..5189b812f939 100644 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ b/drivers/net/wireless/wl12xx/wl1271_spi.c | |||
@@ -105,6 +105,7 @@ static void wl1271_spi_reset(struct wl1271 *wl) | |||
105 | spi_message_add_tail(&t, &m); | 105 | spi_message_add_tail(&t, &m); |
106 | 106 | ||
107 | spi_sync(wl_to_spi(wl), &m); | 107 | spi_sync(wl_to_spi(wl), &m); |
108 | kfree(cmd); | ||
108 | 109 | ||
109 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); | 110 | wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); |
110 | } | 111 | } |
@@ -159,47 +160,24 @@ static void wl1271_spi_init(struct wl1271 *wl) | |||
159 | spi_message_add_tail(&t, &m); | 160 | spi_message_add_tail(&t, &m); |
160 | 161 | ||
161 | spi_sync(wl_to_spi(wl), &m); | 162 | spi_sync(wl_to_spi(wl), &m); |
163 | kfree(cmd); | ||
162 | 164 | ||
163 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); | 165 | wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); |
164 | } | 166 | } |
165 | 167 | ||
166 | #define WL1271_BUSY_WORD_TIMEOUT 1000 | 168 | #define WL1271_BUSY_WORD_TIMEOUT 1000 |
167 | 169 | ||
168 | /* FIXME: Check busy words, removed due to SPI bug */ | 170 | static int wl1271_spi_read_busy(struct wl1271 *wl) |
169 | #if 0 | ||
170 | static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | ||
171 | { | 171 | { |
172 | struct spi_transfer t[1]; | 172 | struct spi_transfer t[1]; |
173 | struct spi_message m; | 173 | struct spi_message m; |
174 | u32 *busy_buf; | 174 | u32 *busy_buf; |
175 | int num_busy_bytes = 0; | 175 | int num_busy_bytes = 0; |
176 | 176 | ||
177 | wl1271_info("spi read BUSY!"); | ||
178 | |||
179 | /* | ||
180 | * Look for the non-busy word in the read buffer, and if found, | ||
181 | * read in the remaining data into the buffer. | ||
182 | */ | ||
183 | busy_buf = (u32 *)buf; | ||
184 | for (; (u32)busy_buf < (u32)buf + len; busy_buf++) { | ||
185 | num_busy_bytes += sizeof(u32); | ||
186 | if (*busy_buf & 0x1) { | ||
187 | spi_message_init(&m); | ||
188 | memset(t, 0, sizeof(t)); | ||
189 | memmove(buf, busy_buf, len - num_busy_bytes); | ||
190 | t[0].rx_buf = buf + (len - num_busy_bytes); | ||
191 | t[0].len = num_busy_bytes; | ||
192 | spi_message_add_tail(&t[0], &m); | ||
193 | spi_sync(wl_to_spi(wl), &m); | ||
194 | return; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | /* | 177 | /* |
199 | * Read further busy words from SPI until a non-busy word is | 178 | * Read further busy words from SPI until a non-busy word is |
200 | * encountered, then read the data itself into the buffer. | 179 | * encountered, then read the data itself into the buffer. |
201 | */ | 180 | */ |
202 | wl1271_info("spi read BUSY-polling needed!"); | ||
203 | 181 | ||
204 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; | 182 | num_busy_bytes = WL1271_BUSY_WORD_TIMEOUT; |
205 | busy_buf = wl->buffer_busyword; | 183 | busy_buf = wl->buffer_busyword; |
@@ -209,28 +187,21 @@ static void wl1271_spi_read_busy(struct wl1271 *wl, void *buf, size_t len) | |||
209 | memset(t, 0, sizeof(t)); | 187 | memset(t, 0, sizeof(t)); |
210 | t[0].rx_buf = busy_buf; | 188 | t[0].rx_buf = busy_buf; |
211 | t[0].len = sizeof(u32); | 189 | t[0].len = sizeof(u32); |
190 | t[0].cs_change = true; | ||
212 | spi_message_add_tail(&t[0], &m); | 191 | spi_message_add_tail(&t[0], &m); |
213 | spi_sync(wl_to_spi(wl), &m); | 192 | spi_sync(wl_to_spi(wl), &m); |
214 | 193 | ||
215 | if (*busy_buf & 0x1) { | 194 | if (*busy_buf & 0x1) |
216 | spi_message_init(&m); | 195 | return 0; |
217 | memset(t, 0, sizeof(t)); | ||
218 | t[0].rx_buf = buf; | ||
219 | t[0].len = len; | ||
220 | spi_message_add_tail(&t[0], &m); | ||
221 | spi_sync(wl_to_spi(wl), &m); | ||
222 | return; | ||
223 | } | ||
224 | } | 196 | } |
225 | 197 | ||
226 | /* The SPI bus is unresponsive, the read failed. */ | 198 | /* The SPI bus is unresponsive, the read failed. */ |
227 | memset(buf, 0, len); | ||
228 | wl1271_error("SPI read busy-word timeout!\n"); | 199 | wl1271_error("SPI read busy-word timeout!\n"); |
200 | return -ETIMEDOUT; | ||
229 | } | 201 | } |
230 | #endif | ||
231 | 202 | ||
232 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | 203 | static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, |
233 | size_t len, bool fixed) | 204 | size_t len, bool fixed) |
234 | { | 205 | { |
235 | struct spi_transfer t[3]; | 206 | struct spi_transfer t[3]; |
236 | struct spi_message m; | 207 | struct spi_message m; |
@@ -253,22 +224,32 @@ static void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf, | |||
253 | 224 | ||
254 | t[0].tx_buf = cmd; | 225 | t[0].tx_buf = cmd; |
255 | t[0].len = 4; | 226 | t[0].len = 4; |
227 | t[0].cs_change = true; | ||
256 | spi_message_add_tail(&t[0], &m); | 228 | spi_message_add_tail(&t[0], &m); |
257 | 229 | ||
258 | /* Busy and non busy words read */ | 230 | /* Busy and non busy words read */ |
259 | t[1].rx_buf = busy_buf; | 231 | t[1].rx_buf = busy_buf; |
260 | t[1].len = WL1271_BUSY_WORD_LEN; | 232 | t[1].len = WL1271_BUSY_WORD_LEN; |
233 | t[1].cs_change = true; | ||
261 | spi_message_add_tail(&t[1], &m); | 234 | spi_message_add_tail(&t[1], &m); |
262 | 235 | ||
263 | t[2].rx_buf = buf; | ||
264 | t[2].len = len; | ||
265 | spi_message_add_tail(&t[2], &m); | ||
266 | |||
267 | spi_sync(wl_to_spi(wl), &m); | 236 | spi_sync(wl_to_spi(wl), &m); |
268 | 237 | ||
269 | /* FIXME: Check busy words, removed due to SPI bug */ | 238 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && |
270 | /* if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1)) | 239 | wl1271_spi_read_busy(wl)) { |
271 | wl1271_spi_read_busy(wl, buf, len); */ | 240 | memset(buf, 0, len); |
241 | return; | ||
242 | } | ||
243 | |||
244 | spi_message_init(&m); | ||
245 | memset(t, 0, sizeof(t)); | ||
246 | |||
247 | t[0].rx_buf = buf; | ||
248 | t[0].len = len; | ||
249 | t[0].cs_change = true; | ||
250 | spi_message_add_tail(&t[0], &m); | ||
251 | |||
252 | spi_sync(wl_to_spi(wl), &m); | ||
272 | 253 | ||
273 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); | 254 | wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); |
274 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); | 255 | wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); |
@@ -443,7 +424,7 @@ static int __devexit wl1271_remove(struct spi_device *spi) | |||
443 | 424 | ||
444 | static struct spi_driver wl1271_spi_driver = { | 425 | static struct spi_driver wl1271_spi_driver = { |
445 | .driver = { | 426 | .driver = { |
446 | .name = "wl1271", | 427 | .name = "wl1271_spi", |
447 | .bus = &spi_bus_type, | 428 | .bus = &spi_bus_type, |
448 | .owner = THIS_MODULE, | 429 | .owner = THIS_MODULE, |
449 | }, | 430 | }, |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 6d109df9a0a0..62db79508ddf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -220,7 +220,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
220 | return ret; | 220 | return ret; |
221 | } | 221 | } |
222 | 222 | ||
223 | static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | 223 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) |
224 | { | 224 | { |
225 | struct ieee80211_supported_band *band; | 225 | struct ieee80211_supported_band *band; |
226 | u32 enabled_rates = 0; | 226 | u32 enabled_rates = 0; |
@@ -304,6 +304,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
304 | struct ieee80211_tx_info *info; | 304 | struct ieee80211_tx_info *info; |
305 | struct sk_buff *skb; | 305 | struct sk_buff *skb; |
306 | int id = result->id; | 306 | int id = result->id; |
307 | int rate = -1; | ||
308 | u8 retries = 0; | ||
307 | 309 | ||
308 | /* check for id legality */ | 310 | /* check for id legality */ |
309 | if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { | 311 | if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { |
@@ -314,19 +316,22 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
314 | skb = wl->tx_frames[id]; | 316 | skb = wl->tx_frames[id]; |
315 | info = IEEE80211_SKB_CB(skb); | 317 | info = IEEE80211_SKB_CB(skb); |
316 | 318 | ||
317 | /* update packet status */ | 319 | /* update the TX status info */ |
318 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { | 320 | if (result->status == TX_SUCCESS) { |
319 | if (result->status == TX_SUCCESS) | 321 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) |
320 | info->flags |= IEEE80211_TX_STAT_ACK; | 322 | info->flags |= IEEE80211_TX_STAT_ACK; |
321 | if (result->status & TX_RETRY_EXCEEDED) { | 323 | rate = wl1271_rate_to_idx(wl, result->rate_class_index); |
322 | /* FIXME */ | 324 | retries = result->ack_failures; |
323 | /* info->status.excessive_retries = 1; */ | 325 | } else if (result->status == TX_RETRY_EXCEEDED) { |
324 | wl->stats.excessive_retries++; | 326 | wl->stats.excessive_retries++; |
325 | } | 327 | retries = result->ack_failures; |
326 | } | 328 | } |
327 | 329 | ||
328 | /* FIXME */ | 330 | info->status.rates[0].idx = rate; |
329 | /* info->status.retry_count = result->ack_failures; */ | 331 | info->status.rates[0].count = retries; |
332 | info->status.rates[0].flags = 0; | ||
333 | info->status.ack_signal = -1; | ||
334 | |||
330 | wl->stats.retry_count += result->ack_failures; | 335 | wl->stats.retry_count += result->ack_failures; |
331 | 336 | ||
332 | /* update security sequence number */ | 337 | /* update security sequence number */ |
@@ -350,8 +355,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
350 | result->id, skb, result->ack_failures, | 355 | result->id, skb, result->ack_failures, |
351 | result->rate_class_index, result->status); | 356 | result->rate_class_index, result->status); |
352 | 357 | ||
353 | /* FIXME: do we need to tell the stack about the used rate? */ | ||
354 | |||
355 | /* return the packet to the stack */ | 358 | /* return the packet to the stack */ |
356 | ieee80211_tx_status(wl->hw, skb); | 359 | ieee80211_tx_status(wl->hw, skb); |
357 | wl->tx_frames[result->id] = NULL; | 360 | wl->tx_frames[result->id] = NULL; |
@@ -413,31 +416,19 @@ void wl1271_tx_flush(struct wl1271 *wl) | |||
413 | { | 416 | { |
414 | int i; | 417 | int i; |
415 | struct sk_buff *skb; | 418 | struct sk_buff *skb; |
416 | struct ieee80211_tx_info *info; | ||
417 | 419 | ||
418 | /* TX failure */ | 420 | /* TX failure */ |
419 | /* control->flags = 0; FIXME */ | 421 | /* control->flags = 0; FIXME */ |
420 | 422 | ||
421 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 423 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
422 | info = IEEE80211_SKB_CB(skb); | ||
423 | |||
424 | wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); | 424 | wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); |
425 | |||
426 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
427 | continue; | ||
428 | |||
429 | ieee80211_tx_status(wl->hw, skb); | 425 | ieee80211_tx_status(wl->hw, skb); |
430 | } | 426 | } |
431 | 427 | ||
432 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 428 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
433 | if (wl->tx_frames[i] != NULL) { | 429 | if (wl->tx_frames[i] != NULL) { |
434 | skb = wl->tx_frames[i]; | 430 | skb = wl->tx_frames[i]; |
435 | info = IEEE80211_SKB_CB(skb); | ||
436 | |||
437 | if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) | ||
438 | continue; | ||
439 | |||
440 | ieee80211_tx_status(wl->hw, skb); | ||
441 | wl->tx_frames[i] = NULL; | 431 | wl->tx_frames[i] = NULL; |
432 | ieee80211_tx_status(wl->hw, skb); | ||
442 | } | 433 | } |
443 | } | 434 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h index 5e6c27a57415..3b8b7ac253fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ b/drivers/net/wireless/wl12xx/wl1271_tx.h | |||
@@ -159,5 +159,7 @@ static inline int wl1271_tx_ac_to_tid(int ac) | |||
159 | void wl1271_tx_work(struct work_struct *work); | 159 | void wl1271_tx_work(struct work_struct *work); |
160 | void wl1271_tx_complete(struct wl1271 *wl); | 160 | void wl1271_tx_complete(struct wl1271 *wl); |
161 | void wl1271_tx_flush(struct wl1271 *wl); | 161 | void wl1271_tx_flush(struct wl1271 *wl); |
162 | u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); | ||
163 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | ||
162 | 164 | ||
163 | #endif | 165 | #endif |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 19984958ab7b..1252ba1fbff5 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1211,6 +1211,8 @@ enum ieee80211_category { | |||
1211 | WLAN_CATEGORY_SA_QUERY = 8, | 1211 | WLAN_CATEGORY_SA_QUERY = 8, |
1212 | WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, | 1212 | WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, |
1213 | WLAN_CATEGORY_WMM = 17, | 1213 | WLAN_CATEGORY_WMM = 17, |
1214 | WLAN_CATEGORY_MESH_PLINK = 30, /* Pending ANA approval */ | ||
1215 | WLAN_CATEGORY_MESH_PATH_SEL = 32, /* Pending ANA approval */ | ||
1214 | WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, | 1216 | WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, |
1215 | WLAN_CATEGORY_VENDOR_SPECIFIC = 127, | 1217 | WLAN_CATEGORY_VENDOR_SPECIFIC = 127, |
1216 | }; | 1218 | }; |
@@ -1324,7 +1326,6 @@ enum ieee80211_back_actioncode { | |||
1324 | enum ieee80211_back_parties { | 1326 | enum ieee80211_back_parties { |
1325 | WLAN_BACK_RECIPIENT = 0, | 1327 | WLAN_BACK_RECIPIENT = 0, |
1326 | WLAN_BACK_INITIATOR = 1, | 1328 | WLAN_BACK_INITIATOR = 1, |
1327 | WLAN_BACK_TIMER = 2, | ||
1328 | }; | 1329 | }; |
1329 | 1330 | ||
1330 | /* SA Query action */ | 1331 | /* SA Query action */ |
diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h index 0ebaef577ff5..329a8faa6e37 100644 --- a/include/linux/mmc/sdio.h +++ b/include/linux/mmc/sdio.h | |||
@@ -94,6 +94,8 @@ | |||
94 | 94 | ||
95 | #define SDIO_BUS_WIDTH_1BIT 0x00 | 95 | #define SDIO_BUS_WIDTH_1BIT 0x00 |
96 | #define SDIO_BUS_WIDTH_4BIT 0x02 | 96 | #define SDIO_BUS_WIDTH_4BIT 0x02 |
97 | #define SDIO_BUS_ECSI 0x20 /* Enable continuous SPI interrupt */ | ||
98 | #define SDIO_BUS_SCSI 0x40 /* Support continuous SPI interrupt */ | ||
97 | 99 | ||
98 | #define SDIO_BUS_ASYNC_INT 0x20 | 100 | #define SDIO_BUS_ASYNC_INT 0x20 |
99 | 101 | ||
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index daf6a3432b92..2ea3edeee7aa 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -703,6 +703,12 @@ enum nl80211_commands { | |||
703 | * @NL80211_ATTR_CQM: connection quality monitor configuration in a | 703 | * @NL80211_ATTR_CQM: connection quality monitor configuration in a |
704 | * nested attribute with %NL80211_ATTR_CQM_* sub-attributes. | 704 | * nested attribute with %NL80211_ATTR_CQM_* sub-attributes. |
705 | * | 705 | * |
706 | * @NL80211_ATTR_LOCAL_STATE_CHANGE: Flag attribute to indicate that a command | ||
707 | * is requesting a local authentication/association state change without | ||
708 | * invoking actual management frame exchange. This can be used with | ||
709 | * NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE, | ||
710 | * NL80211_CMD_DISASSOCIATE. | ||
711 | * | ||
706 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 712 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
707 | * @__NL80211_ATTR_AFTER_LAST: internal use | 713 | * @__NL80211_ATTR_AFTER_LAST: internal use |
708 | */ | 714 | */ |
@@ -856,6 +862,8 @@ enum nl80211_attrs { | |||
856 | 862 | ||
857 | NL80211_ATTR_CQM, | 863 | NL80211_ATTR_CQM, |
858 | 864 | ||
865 | NL80211_ATTR_LOCAL_STATE_CHANGE, | ||
866 | |||
859 | /* add attributes here, update the policy in nl80211.c */ | 867 | /* add attributes here, update the policy in nl80211.c */ |
860 | 868 | ||
861 | __NL80211_ATTR_AFTER_LAST, | 869 | __NL80211_ATTR_AFTER_LAST, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 868cfd3b9724..37cebd3aa0f7 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -704,6 +704,10 @@ struct cfg80211_crypto_settings { | |||
704 | * @key_len: length of WEP key for shared key authentication | 704 | * @key_len: length of WEP key for shared key authentication |
705 | * @key_idx: index of WEP key for shared key authentication | 705 | * @key_idx: index of WEP key for shared key authentication |
706 | * @key: WEP key for shared key authentication | 706 | * @key: WEP key for shared key authentication |
707 | * @local_state_change: This is a request for a local state only, i.e., no | ||
708 | * Authentication frame is to be transmitted and authentication state is | ||
709 | * to be changed without having to wait for a response from the peer STA | ||
710 | * (AP). | ||
707 | */ | 711 | */ |
708 | struct cfg80211_auth_request { | 712 | struct cfg80211_auth_request { |
709 | struct cfg80211_bss *bss; | 713 | struct cfg80211_bss *bss; |
@@ -712,6 +716,7 @@ struct cfg80211_auth_request { | |||
712 | enum nl80211_auth_type auth_type; | 716 | enum nl80211_auth_type auth_type; |
713 | const u8 *key; | 717 | const u8 *key; |
714 | u8 key_len, key_idx; | 718 | u8 key_len, key_idx; |
719 | bool local_state_change; | ||
715 | }; | 720 | }; |
716 | 721 | ||
717 | /** | 722 | /** |
@@ -744,12 +749,15 @@ struct cfg80211_assoc_request { | |||
744 | * @ie: Extra IEs to add to Deauthentication frame or %NULL | 749 | * @ie: Extra IEs to add to Deauthentication frame or %NULL |
745 | * @ie_len: Length of ie buffer in octets | 750 | * @ie_len: Length of ie buffer in octets |
746 | * @reason_code: The reason code for the deauthentication | 751 | * @reason_code: The reason code for the deauthentication |
752 | * @local_state_change: This is a request for a local state only, i.e., no | ||
753 | * Deauthentication frame is to be transmitted. | ||
747 | */ | 754 | */ |
748 | struct cfg80211_deauth_request { | 755 | struct cfg80211_deauth_request { |
749 | struct cfg80211_bss *bss; | 756 | struct cfg80211_bss *bss; |
750 | const u8 *ie; | 757 | const u8 *ie; |
751 | size_t ie_len; | 758 | size_t ie_len; |
752 | u16 reason_code; | 759 | u16 reason_code; |
760 | bool local_state_change; | ||
753 | }; | 761 | }; |
754 | 762 | ||
755 | /** | 763 | /** |
@@ -762,12 +770,15 @@ struct cfg80211_deauth_request { | |||
762 | * @ie: Extra IEs to add to Disassociation frame or %NULL | 770 | * @ie: Extra IEs to add to Disassociation frame or %NULL |
763 | * @ie_len: Length of ie buffer in octets | 771 | * @ie_len: Length of ie buffer in octets |
764 | * @reason_code: The reason code for the disassociation | 772 | * @reason_code: The reason code for the disassociation |
773 | * @local_state_change: This is a request for a local state only, i.e., no | ||
774 | * Disassociation frame is to be transmitted. | ||
765 | */ | 775 | */ |
766 | struct cfg80211_disassoc_request { | 776 | struct cfg80211_disassoc_request { |
767 | struct cfg80211_bss *bss; | 777 | struct cfg80211_bss *bss; |
768 | const u8 *ie; | 778 | const u8 *ie; |
769 | size_t ie_len; | 779 | size_t ie_len; |
770 | u16 reason_code; | 780 | u16 reason_code; |
781 | bool local_state_change; | ||
771 | }; | 782 | }; |
772 | 783 | ||
773 | /** | 784 | /** |
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index b2b98f3fa265..3afdb21cc31d 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h | |||
@@ -323,7 +323,7 @@ typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info, | |||
323 | struct iw_handler_def { | 323 | struct iw_handler_def { |
324 | 324 | ||
325 | /* Array of handlers for standard ioctls | 325 | /* Array of handlers for standard ioctls |
326 | * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT] | 326 | * We will call dev->wireless_handlers->standard[ioctl - SIOCIWFIRST] |
327 | */ | 327 | */ |
328 | const iw_handler * standard; | 328 | const iw_handler * standard; |
329 | /* Number of handlers defined (more precisely, index of the | 329 | /* Number of handlers defined (more precisely, index of the |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 20823d04e03c..344e5bf72062 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -587,11 +587,15 @@ struct ieee80211_rx_status { | |||
587 | * may turn the device off as much as possible. Typically, this flag will | 587 | * may turn the device off as much as possible. Typically, this flag will |
588 | * be set when an interface is set UP but not associated or scanning, but | 588 | * be set when an interface is set UP but not associated or scanning, but |
589 | * it can also be unset in that case when monitor interfaces are active. | 589 | * it can also be unset in that case when monitor interfaces are active. |
590 | * @IEEE80211_CONF_QOS: Enable 802.11e QoS also know as WMM (Wireless | ||
591 | * Multimedia). On some drivers (iwlwifi is one of know) we have | ||
592 | * to enable/disable QoS explicitly. | ||
590 | */ | 593 | */ |
591 | enum ieee80211_conf_flags { | 594 | enum ieee80211_conf_flags { |
592 | IEEE80211_CONF_MONITOR = (1<<0), | 595 | IEEE80211_CONF_MONITOR = (1<<0), |
593 | IEEE80211_CONF_PS = (1<<1), | 596 | IEEE80211_CONF_PS = (1<<1), |
594 | IEEE80211_CONF_IDLE = (1<<2), | 597 | IEEE80211_CONF_IDLE = (1<<2), |
598 | IEEE80211_CONF_QOS = (1<<3), | ||
595 | }; | 599 | }; |
596 | 600 | ||
597 | 601 | ||
@@ -616,6 +620,7 @@ enum ieee80211_conf_changed { | |||
616 | IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), | 620 | IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), |
617 | IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), | 621 | IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), |
618 | IEEE80211_CONF_CHANGE_IDLE = BIT(8), | 622 | IEEE80211_CONF_CHANGE_IDLE = BIT(8), |
623 | IEEE80211_CONF_CHANGE_QOS = BIT(9), | ||
619 | }; | 624 | }; |
620 | 625 | ||
621 | /** | 626 | /** |
@@ -1822,7 +1827,10 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw); | |||
1822 | * ieee80211_rx - receive frame | 1827 | * ieee80211_rx - receive frame |
1823 | * | 1828 | * |
1824 | * Use this function to hand received frames to mac80211. The receive | 1829 | * Use this function to hand received frames to mac80211. The receive |
1825 | * buffer in @skb must start with an IEEE 802.11 header. | 1830 | * buffer in @skb must start with an IEEE 802.11 header. In case of a |
1831 | * paged @skb is used, the driver is recommended to put the ieee80211 | ||
1832 | * header of the frame on the linear part of the @skb to avoid memory | ||
1833 | * allocation and/or memcpy by the stack. | ||
1826 | * | 1834 | * |
1827 | * This function may not be called in IRQ context. Calls to this function | 1835 | * This function may not be called in IRQ context. Calls to this function |
1828 | * for a single hardware must be synchronized against each other. Calls to | 1836 | * for a single hardware must be synchronized against each other. Calls to |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 334c359da5e8..8a91f6c0bb18 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -221,8 +221,8 @@ config MAC80211_DRIVER_API_TRACER | |||
221 | depends on EVENT_TRACING | 221 | depends on EVENT_TRACING |
222 | help | 222 | help |
223 | Say Y here to make mac80211 register with the ftrace | 223 | Say Y here to make mac80211 register with the ftrace |
224 | framework for the driver API -- you can see which | 224 | framework for the driver API -- you can then see which |
225 | driver methods it is calling then by looking at the | 225 | driver methods it is calling and which API functions |
226 | trace. | 226 | drivers are calling by looking at the trace. |
227 | 227 | ||
228 | If unsure, say N. | 228 | If unsure, say Y. |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index f9516a27e233..9598fdb4ad01 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -23,19 +23,20 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
23 | u16 initiator, u16 reason) | 23 | u16 initiator, u16 reason) |
24 | { | 24 | { |
25 | struct ieee80211_local *local = sta->local; | 25 | struct ieee80211_local *local = sta->local; |
26 | struct tid_ampdu_rx *tid_rx; | ||
26 | int i; | 27 | int i; |
27 | 28 | ||
28 | /* check if TID is in operational state */ | ||
29 | spin_lock_bh(&sta->lock); | 29 | spin_lock_bh(&sta->lock); |
30 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) { | 30 | |
31 | /* check if TID is in operational state */ | ||
32 | if (!sta->ampdu_mlme.tid_active_rx[tid]) { | ||
31 | spin_unlock_bh(&sta->lock); | 33 | spin_unlock_bh(&sta->lock); |
32 | return; | 34 | return; |
33 | } | 35 | } |
34 | 36 | ||
35 | sta->ampdu_mlme.tid_state_rx[tid] = | 37 | sta->ampdu_mlme.tid_active_rx[tid] = false; |
36 | HT_AGG_STATE_REQ_STOP_BA_MSK | | 38 | |
37 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 39 | tid_rx = sta->ampdu_mlme.tid_rx[tid]; |
38 | spin_unlock_bh(&sta->lock); | ||
39 | 40 | ||
40 | #ifdef CONFIG_MAC80211_HT_DEBUG | 41 | #ifdef CONFIG_MAC80211_HT_DEBUG |
41 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", | 42 | printk(KERN_DEBUG "Rx BA session stop requested for %pM tid %u\n", |
@@ -47,61 +48,35 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
47 | printk(KERN_DEBUG "HW problem - can not stop rx " | 48 | printk(KERN_DEBUG "HW problem - can not stop rx " |
48 | "aggregation for tid %d\n", tid); | 49 | "aggregation for tid %d\n", tid); |
49 | 50 | ||
50 | /* shutdown timer has not expired */ | ||
51 | if (initiator != WLAN_BACK_TIMER) | ||
52 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
53 | |||
54 | /* check if this is a self generated aggregation halt */ | 51 | /* check if this is a self generated aggregation halt */ |
55 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | 52 | if (initiator == WLAN_BACK_RECIPIENT) |
56 | ieee80211_send_delba(sta->sdata, sta->sta.addr, | 53 | ieee80211_send_delba(sta->sdata, sta->sta.addr, |
57 | tid, 0, reason); | 54 | tid, 0, reason); |
58 | 55 | ||
59 | /* free the reordering buffer */ | 56 | /* free the reordering buffer */ |
60 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { | 57 | for (i = 0; i < tid_rx->buf_size; i++) { |
61 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { | 58 | if (tid_rx->reorder_buf[i]) { |
62 | /* release the reordered frames */ | 59 | /* release the reordered frames */ |
63 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); | 60 | dev_kfree_skb(tid_rx->reorder_buf[i]); |
64 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; | 61 | tid_rx->stored_mpdu_num--; |
65 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; | 62 | tid_rx->reorder_buf[i] = NULL; |
66 | } | 63 | } |
67 | } | 64 | } |
68 | 65 | ||
69 | spin_lock_bh(&sta->lock); | ||
70 | /* free resources */ | 66 | /* free resources */ |
71 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | 67 | kfree(tid_rx->reorder_buf); |
72 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_time); | 68 | kfree(tid_rx->reorder_time); |
69 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
73 | 70 | ||
74 | if (!sta->ampdu_mlme.tid_rx[tid]->shutdown) { | ||
75 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
76 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
77 | } | ||
78 | |||
79 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
80 | spin_unlock_bh(&sta->lock); | 71 | spin_unlock_bh(&sta->lock); |
81 | } | ||
82 | |||
83 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | ||
84 | u16 initiator, u16 reason) | ||
85 | { | ||
86 | struct sta_info *sta; | ||
87 | |||
88 | rcu_read_lock(); | ||
89 | |||
90 | sta = sta_info_get(sdata, ra); | ||
91 | if (!sta) { | ||
92 | rcu_read_unlock(); | ||
93 | return; | ||
94 | } | ||
95 | |||
96 | __ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); | ||
97 | 72 | ||
98 | rcu_read_unlock(); | 73 | del_timer_sync(&tid_rx->session_timer); |
74 | kfree(tid_rx); | ||
99 | } | 75 | } |
100 | 76 | ||
101 | /* | 77 | /* |
102 | * After accepting the AddBA Request we activated a timer, | 78 | * After accepting the AddBA Request we activated a timer, |
103 | * resetting it after each frame that arrives from the originator. | 79 | * resetting it after each frame that arrives from the originator. |
104 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | ||
105 | */ | 80 | */ |
106 | static void sta_rx_agg_session_timer_expired(unsigned long data) | 81 | static void sta_rx_agg_session_timer_expired(unsigned long data) |
107 | { | 82 | { |
@@ -117,9 +92,8 @@ static void sta_rx_agg_session_timer_expired(unsigned long data) | |||
117 | #ifdef CONFIG_MAC80211_HT_DEBUG | 92 | #ifdef CONFIG_MAC80211_HT_DEBUG |
118 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | 93 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); |
119 | #endif | 94 | #endif |
120 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | 95 | __ieee80211_stop_rx_ba_session(sta, *ptid, WLAN_BACK_RECIPIENT, |
121 | (u16)*ptid, WLAN_BACK_TIMER, | 96 | WLAN_REASON_QSTA_TIMEOUT); |
122 | WLAN_REASON_QSTA_TIMEOUT); | ||
123 | } | 97 | } |
124 | 98 | ||
125 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | 99 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, |
@@ -194,7 +168,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
194 | 168 | ||
195 | status = WLAN_STATUS_REQUEST_DECLINED; | 169 | status = WLAN_STATUS_REQUEST_DECLINED; |
196 | 170 | ||
197 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { | 171 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { |
198 | #ifdef CONFIG_MAC80211_HT_DEBUG | 172 | #ifdef CONFIG_MAC80211_HT_DEBUG |
199 | printk(KERN_DEBUG "Suspend in progress. " | 173 | printk(KERN_DEBUG "Suspend in progress. " |
200 | "Denying ADDBA request\n"); | 174 | "Denying ADDBA request\n"); |
@@ -232,7 +206,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
232 | /* examine state machine */ | 206 | /* examine state machine */ |
233 | spin_lock_bh(&sta->lock); | 207 | spin_lock_bh(&sta->lock); |
234 | 208 | ||
235 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | 209 | if (sta->ampdu_mlme.tid_active_rx[tid]) { |
236 | #ifdef CONFIG_MAC80211_HT_DEBUG | 210 | #ifdef CONFIG_MAC80211_HT_DEBUG |
237 | if (net_ratelimit()) | 211 | if (net_ratelimit()) |
238 | printk(KERN_DEBUG "unexpected AddBA Req from " | 212 | printk(KERN_DEBUG "unexpected AddBA Req from " |
@@ -294,7 +268,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
294 | } | 268 | } |
295 | 269 | ||
296 | /* change state and send addba resp */ | 270 | /* change state and send addba resp */ |
297 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; | 271 | sta->ampdu_mlme.tid_active_rx[tid] = true; |
298 | tid_agg_rx->dialog_token = dialog_token; | 272 | tid_agg_rx->dialog_token = dialog_token; |
299 | tid_agg_rx->ssn = start_seq_num; | 273 | tid_agg_rx->ssn = start_seq_num; |
300 | tid_agg_rx->head_seq_num = start_seq_num; | 274 | tid_agg_rx->head_seq_num = start_seq_num; |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 96d25348aa59..608063f11797 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -215,6 +215,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
215 | int ret = 0; | 215 | int ret = 0; |
216 | u16 start_seq_num; | 216 | u16 start_seq_num; |
217 | 217 | ||
218 | trace_api_start_tx_ba_session(pubsta, tid); | ||
219 | |||
218 | if (WARN_ON(!local->ops->ampdu_action)) | 220 | if (WARN_ON(!local->ops->ampdu_action)) |
219 | return -EINVAL; | 221 | return -EINVAL; |
220 | 222 | ||
@@ -246,7 +248,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
246 | return -EINVAL; | 248 | return -EINVAL; |
247 | } | 249 | } |
248 | 250 | ||
249 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { | 251 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { |
250 | #ifdef CONFIG_MAC80211_HT_DEBUG | 252 | #ifdef CONFIG_MAC80211_HT_DEBUG |
251 | printk(KERN_DEBUG "Suspend in progress. " | 253 | printk(KERN_DEBUG "Suspend in progress. " |
252 | "Denying BA session request\n"); | 254 | "Denying BA session request\n"); |
@@ -415,7 +417,7 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
415 | struct sta_info *sta, u16 tid) | 417 | struct sta_info *sta, u16 tid) |
416 | { | 418 | { |
417 | #ifdef CONFIG_MAC80211_HT_DEBUG | 419 | #ifdef CONFIG_MAC80211_HT_DEBUG |
418 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | 420 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); |
419 | #endif | 421 | #endif |
420 | 422 | ||
421 | spin_lock(&local->ampdu_lock); | 423 | spin_lock(&local->ampdu_lock); |
@@ -441,6 +443,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
441 | struct sta_info *sta; | 443 | struct sta_info *sta; |
442 | u8 *state; | 444 | u8 *state; |
443 | 445 | ||
446 | trace_api_start_tx_ba_cb(sdata, ra, tid); | ||
447 | |||
444 | if (tid >= STA_TID_NUM) { | 448 | if (tid >= STA_TID_NUM) { |
445 | #ifdef CONFIG_MAC80211_HT_DEBUG | 449 | #ifdef CONFIG_MAC80211_HT_DEBUG |
446 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | 450 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", |
@@ -542,6 +546,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
542 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 546 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
543 | struct ieee80211_local *local = sdata->local; | 547 | struct ieee80211_local *local = sdata->local; |
544 | 548 | ||
549 | trace_api_stop_tx_ba_session(pubsta, tid, initiator); | ||
550 | |||
545 | if (!local->ops->ampdu_action) | 551 | if (!local->ops->ampdu_action) |
546 | return -EINVAL; | 552 | return -EINVAL; |
547 | 553 | ||
@@ -559,6 +565,8 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
559 | struct sta_info *sta; | 565 | struct sta_info *sta; |
560 | u8 *state; | 566 | u8 *state; |
561 | 567 | ||
568 | trace_api_stop_tx_ba_cb(sdata, ra, tid); | ||
569 | |||
562 | if (tid >= STA_TID_NUM) { | 570 | if (tid >= STA_TID_NUM) { |
563 | #ifdef CONFIG_MAC80211_HT_DEBUG | 571 | #ifdef CONFIG_MAC80211_HT_DEBUG |
564 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | 572 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", |
@@ -675,7 +683,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
675 | del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 683 | del_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); |
676 | 684 | ||
677 | #ifdef CONFIG_MAC80211_HT_DEBUG | 685 | #ifdef CONFIG_MAC80211_HT_DEBUG |
678 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | 686 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); |
679 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 687 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
680 | 688 | ||
681 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 689 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index c41aaba839fa..7dd7cda75cfa 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1137,6 +1137,10 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1137 | return -EINVAL; | 1137 | return -EINVAL; |
1138 | } | 1138 | } |
1139 | 1139 | ||
1140 | /* enable WMM or activate new settings */ | ||
1141 | local->hw.conf.flags |= IEEE80211_CONF_QOS; | ||
1142 | drv_config(local, IEEE80211_CONF_CHANGE_QOS); | ||
1143 | |||
1140 | return 0; | 1144 | return 0; |
1141 | } | 1145 | } |
1142 | 1146 | ||
@@ -1412,9 +1416,6 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy, | |||
1412 | struct ieee80211_vif *vif = &sdata->vif; | 1416 | struct ieee80211_vif *vif = &sdata->vif; |
1413 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 1417 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
1414 | 1418 | ||
1415 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) | ||
1416 | return -EOPNOTSUPP; | ||
1417 | |||
1418 | if (rssi_thold == bss_conf->cqm_rssi_thold && | 1419 | if (rssi_thold == bss_conf->cqm_rssi_thold && |
1419 | rssi_hyst == bss_conf->cqm_rssi_hyst) | 1420 | rssi_hyst == bss_conf->cqm_rssi_hyst) |
1420 | return 0; | 1421 | return 0; |
@@ -1422,6 +1423,12 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy, | |||
1422 | bss_conf->cqm_rssi_thold = rssi_thold; | 1423 | bss_conf->cqm_rssi_thold = rssi_thold; |
1423 | bss_conf->cqm_rssi_hyst = rssi_hyst; | 1424 | bss_conf->cqm_rssi_hyst = rssi_hyst; |
1424 | 1425 | ||
1426 | if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | ||
1427 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
1428 | return -EOPNOTSUPP; | ||
1429 | return 0; | ||
1430 | } | ||
1431 | |||
1425 | /* tell the driver upon association, unless already associated */ | 1432 | /* tell the driver upon association, unless already associated */ |
1426 | if (sdata->u.mgd.associated) | 1433 | if (sdata->u.mgd.associated) |
1427 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM); | 1434 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM); |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 83d4289d954b..20b2998fa0ed 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -100,6 +100,14 @@ static ssize_t ieee80211_if_fmt_##name( \ | |||
100 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ | 100 | return scnprintf(buf, buflen, "%pM\n", sdata->field); \ |
101 | } | 101 | } |
102 | 102 | ||
103 | #define IEEE80211_IF_FMT_DEC_DIV_16(name, field) \ | ||
104 | static ssize_t ieee80211_if_fmt_##name( \ | ||
105 | const struct ieee80211_sub_if_data *sdata, \ | ||
106 | char *buf, int buflen) \ | ||
107 | { \ | ||
108 | return scnprintf(buf, buflen, "%d\n", sdata->field / 16); \ | ||
109 | } | ||
110 | |||
103 | #define __IEEE80211_IF_FILE(name, _write) \ | 111 | #define __IEEE80211_IF_FILE(name, _write) \ |
104 | static ssize_t ieee80211_if_read_##name(struct file *file, \ | 112 | static ssize_t ieee80211_if_read_##name(struct file *file, \ |
105 | char __user *userbuf, \ | 113 | char __user *userbuf, \ |
@@ -140,6 +148,8 @@ IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ], | |||
140 | /* STA attributes */ | 148 | /* STA attributes */ |
141 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 149 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
142 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 150 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
151 | IEEE80211_IF_FILE(last_beacon, u.mgd.last_beacon_signal, DEC); | ||
152 | IEEE80211_IF_FILE(ave_beacon, u.mgd.ave_beacon_signal, DEC_DIV_16); | ||
143 | 153 | ||
144 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | 154 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, |
145 | enum ieee80211_smps_mode smps_mode) | 155 | enum ieee80211_smps_mode smps_mode) |
@@ -276,6 +286,8 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
276 | 286 | ||
277 | DEBUGFS_ADD(bssid); | 287 | DEBUGFS_ADD(bssid); |
278 | DEBUGFS_ADD(aid); | 288 | DEBUGFS_ADD(aid); |
289 | DEBUGFS_ADD(last_beacon); | ||
290 | DEBUGFS_ADD(ave_beacon); | ||
279 | DEBUGFS_ADD_MODE(smps, 0600); | 291 | DEBUGFS_ADD_MODE(smps, 0600); |
280 | } | 292 | } |
281 | 293 | ||
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 23e720034577..6bc9b07c3eda 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -119,7 +119,7 @@ STA_OPS(last_seq_ctrl); | |||
119 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | 119 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, |
120 | size_t count, loff_t *ppos) | 120 | size_t count, loff_t *ppos) |
121 | { | 121 | { |
122 | char buf[64 + STA_TID_NUM * 40], *p = buf; | 122 | char buf[71 + STA_TID_NUM * 40], *p = buf; |
123 | int i; | 123 | int i; |
124 | struct sta_info *sta = file->private_data; | 124 | struct sta_info *sta = file->private_data; |
125 | 125 | ||
@@ -127,16 +127,16 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
127 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", | 127 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", |
128 | sta->ampdu_mlme.dialog_token_allocator + 1); | 128 | sta->ampdu_mlme.dialog_token_allocator + 1); |
129 | p += scnprintf(p, sizeof(buf) + buf - p, | 129 | p += scnprintf(p, sizeof(buf) + buf - p, |
130 | "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n"); | 130 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n"); |
131 | for (i = 0; i < STA_TID_NUM; i++) { | 131 | for (i = 0; i < STA_TID_NUM; i++) { |
132 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); | 132 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); |
133 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 133 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
134 | sta->ampdu_mlme.tid_state_rx[i]); | 134 | sta->ampdu_mlme.tid_active_rx[i]); |
135 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", | 135 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
136 | sta->ampdu_mlme.tid_state_rx[i] ? | 136 | sta->ampdu_mlme.tid_active_rx[i] ? |
137 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); | 137 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); |
138 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", | 138 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", |
139 | sta->ampdu_mlme.tid_state_rx[i] ? | 139 | sta->ampdu_mlme.tid_active_rx[i] ? |
140 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); | 140 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); |
141 | 141 | ||
142 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 142 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", |
@@ -176,7 +176,7 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | |||
176 | if (htc->ht_supported) { | 176 | if (htc->ht_supported) { |
177 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap); | 177 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.4x\n", htc->cap); |
178 | 178 | ||
179 | PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDCP"); | 179 | PRINT_HT_CAP((htc->cap & BIT(0)), "RX LDPC"); |
180 | PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40"); | 180 | PRINT_HT_CAP((htc->cap & BIT(1)), "HT20/HT40"); |
181 | PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20"); | 181 | PRINT_HT_CAP(!(htc->cap & BIT(1)), "HT20"); |
182 | 182 | ||
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 41baf730a5c7..e209cb82ff29 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -32,6 +32,10 @@ static inline void trace_ ## name(proto) {} | |||
32 | #define VIF_PR_FMT " vif:%s(%d)" | 32 | #define VIF_PR_FMT " vif:%s(%d)" |
33 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type | 33 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type |
34 | 34 | ||
35 | /* | ||
36 | * Tracing for driver callbacks. | ||
37 | */ | ||
38 | |||
35 | TRACE_EVENT(drv_start, | 39 | TRACE_EVENT(drv_start, |
36 | TP_PROTO(struct ieee80211_local *local, int ret), | 40 | TP_PROTO(struct ieee80211_local *local, int ret), |
37 | 41 | ||
@@ -766,6 +770,277 @@ TRACE_EVENT(drv_flush, | |||
766 | LOCAL_PR_ARG, __entry->drop | 770 | LOCAL_PR_ARG, __entry->drop |
767 | ) | 771 | ) |
768 | ); | 772 | ); |
773 | |||
774 | /* | ||
775 | * Tracing for API calls that drivers call. | ||
776 | */ | ||
777 | |||
778 | TRACE_EVENT(api_start_tx_ba_session, | ||
779 | TP_PROTO(struct ieee80211_sta *sta, u16 tid), | ||
780 | |||
781 | TP_ARGS(sta, tid), | ||
782 | |||
783 | TP_STRUCT__entry( | ||
784 | STA_ENTRY | ||
785 | __field(u16, tid) | ||
786 | ), | ||
787 | |||
788 | TP_fast_assign( | ||
789 | STA_ASSIGN; | ||
790 | __entry->tid = tid; | ||
791 | ), | ||
792 | |||
793 | TP_printk( | ||
794 | STA_PR_FMT " tid:%d", | ||
795 | STA_PR_ARG, __entry->tid | ||
796 | ) | ||
797 | ); | ||
798 | |||
799 | TRACE_EVENT(api_start_tx_ba_cb, | ||
800 | TP_PROTO(struct ieee80211_sub_if_data *sdata, const u8 *ra, u16 tid), | ||
801 | |||
802 | TP_ARGS(sdata, ra, tid), | ||
803 | |||
804 | TP_STRUCT__entry( | ||
805 | VIF_ENTRY | ||
806 | __array(u8, ra, ETH_ALEN) | ||
807 | __field(u16, tid) | ||
808 | ), | ||
809 | |||
810 | TP_fast_assign( | ||
811 | VIF_ASSIGN; | ||
812 | memcpy(__entry->ra, ra, ETH_ALEN); | ||
813 | __entry->tid = tid; | ||
814 | ), | ||
815 | |||
816 | TP_printk( | ||
817 | VIF_PR_FMT " ra:%pM tid:%d", | ||
818 | VIF_PR_ARG, __entry->ra, __entry->tid | ||
819 | ) | ||
820 | ); | ||
821 | |||
822 | TRACE_EVENT(api_stop_tx_ba_session, | ||
823 | TP_PROTO(struct ieee80211_sta *sta, u16 tid, u16 initiator), | ||
824 | |||
825 | TP_ARGS(sta, tid, initiator), | ||
826 | |||
827 | TP_STRUCT__entry( | ||
828 | STA_ENTRY | ||
829 | __field(u16, tid) | ||
830 | __field(u16, initiator) | ||
831 | ), | ||
832 | |||
833 | TP_fast_assign( | ||
834 | STA_ASSIGN; | ||
835 | __entry->tid = tid; | ||
836 | __entry->initiator = initiator; | ||
837 | ), | ||
838 | |||
839 | TP_printk( | ||
840 | STA_PR_FMT " tid:%d initiator:%d", | ||
841 | STA_PR_ARG, __entry->tid, __entry->initiator | ||
842 | ) | ||
843 | ); | ||
844 | |||
845 | TRACE_EVENT(api_stop_tx_ba_cb, | ||
846 | TP_PROTO(struct ieee80211_sub_if_data *sdata, const u8 *ra, u16 tid), | ||
847 | |||
848 | TP_ARGS(sdata, ra, tid), | ||
849 | |||
850 | TP_STRUCT__entry( | ||
851 | VIF_ENTRY | ||
852 | __array(u8, ra, ETH_ALEN) | ||
853 | __field(u16, tid) | ||
854 | ), | ||
855 | |||
856 | TP_fast_assign( | ||
857 | VIF_ASSIGN; | ||
858 | memcpy(__entry->ra, ra, ETH_ALEN); | ||
859 | __entry->tid = tid; | ||
860 | ), | ||
861 | |||
862 | TP_printk( | ||
863 | VIF_PR_FMT " ra:%pM tid:%d", | ||
864 | VIF_PR_ARG, __entry->ra, __entry->tid | ||
865 | ) | ||
866 | ); | ||
867 | |||
868 | TRACE_EVENT(api_restart_hw, | ||
869 | TP_PROTO(struct ieee80211_local *local), | ||
870 | |||
871 | TP_ARGS(local), | ||
872 | |||
873 | TP_STRUCT__entry( | ||
874 | LOCAL_ENTRY | ||
875 | ), | ||
876 | |||
877 | TP_fast_assign( | ||
878 | LOCAL_ASSIGN; | ||
879 | ), | ||
880 | |||
881 | TP_printk( | ||
882 | LOCAL_PR_FMT, | ||
883 | LOCAL_PR_ARG | ||
884 | ) | ||
885 | ); | ||
886 | |||
887 | TRACE_EVENT(api_beacon_loss, | ||
888 | TP_PROTO(struct ieee80211_sub_if_data *sdata), | ||
889 | |||
890 | TP_ARGS(sdata), | ||
891 | |||
892 | TP_STRUCT__entry( | ||
893 | VIF_ENTRY | ||
894 | ), | ||
895 | |||
896 | TP_fast_assign( | ||
897 | VIF_ASSIGN; | ||
898 | ), | ||
899 | |||
900 | TP_printk( | ||
901 | VIF_PR_FMT, | ||
902 | VIF_PR_ARG | ||
903 | ) | ||
904 | ); | ||
905 | |||
906 | TRACE_EVENT(api_connection_loss, | ||
907 | TP_PROTO(struct ieee80211_sub_if_data *sdata), | ||
908 | |||
909 | TP_ARGS(sdata), | ||
910 | |||
911 | TP_STRUCT__entry( | ||
912 | VIF_ENTRY | ||
913 | ), | ||
914 | |||
915 | TP_fast_assign( | ||
916 | VIF_ASSIGN; | ||
917 | ), | ||
918 | |||
919 | TP_printk( | ||
920 | VIF_PR_FMT, | ||
921 | VIF_PR_ARG | ||
922 | ) | ||
923 | ); | ||
924 | |||
925 | TRACE_EVENT(api_cqm_rssi_notify, | ||
926 | TP_PROTO(struct ieee80211_sub_if_data *sdata, | ||
927 | enum nl80211_cqm_rssi_threshold_event rssi_event), | ||
928 | |||
929 | TP_ARGS(sdata, rssi_event), | ||
930 | |||
931 | TP_STRUCT__entry( | ||
932 | VIF_ENTRY | ||
933 | __field(u32, rssi_event) | ||
934 | ), | ||
935 | |||
936 | TP_fast_assign( | ||
937 | VIF_ASSIGN; | ||
938 | __entry->rssi_event = rssi_event; | ||
939 | ), | ||
940 | |||
941 | TP_printk( | ||
942 | VIF_PR_FMT " event:%d", | ||
943 | VIF_PR_ARG, __entry->rssi_event | ||
944 | ) | ||
945 | ); | ||
946 | |||
947 | TRACE_EVENT(api_scan_completed, | ||
948 | TP_PROTO(struct ieee80211_local *local, bool aborted), | ||
949 | |||
950 | TP_ARGS(local, aborted), | ||
951 | |||
952 | TP_STRUCT__entry( | ||
953 | LOCAL_ENTRY | ||
954 | __field(bool, aborted) | ||
955 | ), | ||
956 | |||
957 | TP_fast_assign( | ||
958 | LOCAL_ASSIGN; | ||
959 | __entry->aborted = aborted; | ||
960 | ), | ||
961 | |||
962 | TP_printk( | ||
963 | LOCAL_PR_FMT " aborted:%d", | ||
964 | LOCAL_PR_ARG, __entry->aborted | ||
965 | ) | ||
966 | ); | ||
967 | |||
968 | TRACE_EVENT(api_sta_block_awake, | ||
969 | TP_PROTO(struct ieee80211_local *local, | ||
970 | struct ieee80211_sta *sta, bool block), | ||
971 | |||
972 | TP_ARGS(local, sta, block), | ||
973 | |||
974 | TP_STRUCT__entry( | ||
975 | LOCAL_ENTRY | ||
976 | STA_ENTRY | ||
977 | __field(bool, block) | ||
978 | ), | ||
979 | |||
980 | TP_fast_assign( | ||
981 | LOCAL_ASSIGN; | ||
982 | STA_ASSIGN; | ||
983 | __entry->block = block; | ||
984 | ), | ||
985 | |||
986 | TP_printk( | ||
987 | LOCAL_PR_FMT STA_PR_FMT " block:%d", | ||
988 | LOCAL_PR_ARG, STA_PR_FMT, __entry->block | ||
989 | ) | ||
990 | ); | ||
991 | |||
992 | /* | ||
993 | * Tracing for internal functions | ||
994 | * (which may also be called in response to driver calls) | ||
995 | */ | ||
996 | |||
997 | TRACE_EVENT(wake_queue, | ||
998 | TP_PROTO(struct ieee80211_local *local, u16 queue, | ||
999 | enum queue_stop_reason reason), | ||
1000 | |||
1001 | TP_ARGS(local, queue, reason), | ||
1002 | |||
1003 | TP_STRUCT__entry( | ||
1004 | LOCAL_ENTRY | ||
1005 | __field(u16, queue) | ||
1006 | __field(u32, reason) | ||
1007 | ), | ||
1008 | |||
1009 | TP_fast_assign( | ||
1010 | LOCAL_ASSIGN; | ||
1011 | __entry->queue = queue; | ||
1012 | __entry->reason = reason; | ||
1013 | ), | ||
1014 | |||
1015 | TP_printk( | ||
1016 | LOCAL_PR_FMT " queue:%d, reason:%d", | ||
1017 | LOCAL_PR_ARG, __entry->queue, __entry->reason | ||
1018 | ) | ||
1019 | ); | ||
1020 | |||
1021 | TRACE_EVENT(stop_queue, | ||
1022 | TP_PROTO(struct ieee80211_local *local, u16 queue, | ||
1023 | enum queue_stop_reason reason), | ||
1024 | |||
1025 | TP_ARGS(local, queue, reason), | ||
1026 | |||
1027 | TP_STRUCT__entry( | ||
1028 | LOCAL_ENTRY | ||
1029 | __field(u16, queue) | ||
1030 | __field(u32, reason) | ||
1031 | ), | ||
1032 | |||
1033 | TP_fast_assign( | ||
1034 | LOCAL_ASSIGN; | ||
1035 | __entry->queue = queue; | ||
1036 | __entry->reason = reason; | ||
1037 | ), | ||
1038 | |||
1039 | TP_printk( | ||
1040 | LOCAL_PR_FMT " queue:%d, reason:%d", | ||
1041 | LOCAL_PR_ARG, __entry->queue, __entry->reason | ||
1042 | ) | ||
1043 | ); | ||
769 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ | 1044 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ |
770 | 1045 | ||
771 | #undef TRACE_INCLUDE_PATH | 1046 | #undef TRACE_INCLUDE_PATH |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index bb677a73b7c9..2ab106a0a491 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -175,8 +175,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
175 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 175 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
176 | 176 | ||
177 | if (initiator == WLAN_BACK_INITIATOR) | 177 | if (initiator == WLAN_BACK_INITIATOR) |
178 | ieee80211_sta_stop_rx_ba_session(sdata, sta->sta.addr, tid, | 178 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0); |
179 | WLAN_BACK_INITIATOR, 0); | ||
180 | else { /* WLAN_BACK_RECIPIENT */ | 179 | else { /* WLAN_BACK_RECIPIENT */ |
181 | spin_lock_bh(&sta->lock); | 180 | spin_lock_bh(&sta->lock); |
182 | if (sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK) | 181 | if (sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7fdacf9408b1..c9712f35e596 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -317,6 +317,7 @@ enum ieee80211_sta_flags { | |||
317 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 317 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
318 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), | 318 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
319 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | 319 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), |
320 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), | ||
320 | }; | 321 | }; |
321 | 322 | ||
322 | struct ieee80211_if_managed { | 323 | struct ieee80211_if_managed { |
@@ -359,6 +360,24 @@ struct ieee80211_if_managed { | |||
359 | int wmm_last_param_set; | 360 | int wmm_last_param_set; |
360 | 361 | ||
361 | u8 use_4addr; | 362 | u8 use_4addr; |
363 | |||
364 | /* Signal strength from the last Beacon frame in the current BSS. */ | ||
365 | int last_beacon_signal; | ||
366 | |||
367 | /* | ||
368 | * Weighted average of the signal strength from Beacon frames in the | ||
369 | * current BSS. This is in units of 1/16 of the signal unit to maintain | ||
370 | * accuracy and to speed up calculations, i.e., the value need to be | ||
371 | * divided by 16 to get the actual value. | ||
372 | */ | ||
373 | int ave_beacon_signal; | ||
374 | |||
375 | /* | ||
376 | * Last Beacon frame signal strength average (ave_beacon_signal / 16) | ||
377 | * that triggered a cqm event. 0 indicates that no event has been | ||
378 | * generated for the current association. | ||
379 | */ | ||
380 | int last_cqm_event_signal; | ||
362 | }; | 381 | }; |
363 | 382 | ||
364 | enum ieee80211_ibss_request { | 383 | enum ieee80211_ibss_request { |
@@ -1078,8 +1097,6 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, | |||
1078 | enum ieee80211_smps_mode smps, const u8 *da, | 1097 | enum ieee80211_smps_mode smps, const u8 *da, |
1079 | const u8 *bssid); | 1098 | const u8 *bssid); |
1080 | 1099 | ||
1081 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | ||
1082 | u16 tid, u16 initiator, u16 reason); | ||
1083 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1100 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1084 | u16 initiator, u16 reason); | 1101 | u16 initiator, u16 reason); |
1085 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); | 1102 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 50c1b1ada884..011ee85bcd57 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -309,6 +309,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
309 | { | 309 | { |
310 | struct ieee80211_local *local = hw_to_local(hw); | 310 | struct ieee80211_local *local = hw_to_local(hw); |
311 | 311 | ||
312 | trace_api_restart_hw(local); | ||
313 | |||
312 | /* use this reason, __ieee80211_resume will unblock it */ | 314 | /* use this reason, __ieee80211_resume will unblock it */ |
313 | ieee80211_stop_queues_by_reason(hw, | 315 | ieee80211_stop_queues_by_reason(hw, |
314 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 316 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 859ee5f3d941..7e93524459fc 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -601,10 +601,10 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | |||
601 | struct ieee80211_rx_status *rx_status) | 601 | struct ieee80211_rx_status *rx_status) |
602 | { | 602 | { |
603 | switch (mgmt->u.action.category) { | 603 | switch (mgmt->u.action.category) { |
604 | case MESH_PLINK_CATEGORY: | 604 | case WLAN_CATEGORY_MESH_PLINK: |
605 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | 605 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); |
606 | break; | 606 | break; |
607 | case MESH_PATH_SEL_CATEGORY: | 607 | case WLAN_CATEGORY_MESH_PATH_SEL: |
608 | mesh_rx_path_sel_frame(sdata, mgmt, len); | 608 | mesh_rx_path_sel_frame(sdata, mgmt, len); |
609 | break; | 609 | break; |
610 | } | 610 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 85562c59d7d6..c88087f1cd0f 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -209,8 +209,6 @@ struct mesh_rmc { | |||
209 | #define MESH_MAX_MPATHS 1024 | 209 | #define MESH_MAX_MPATHS 1024 |
210 | 210 | ||
211 | /* Pending ANA approval */ | 211 | /* Pending ANA approval */ |
212 | #define MESH_PLINK_CATEGORY 30 | ||
213 | #define MESH_PATH_SEL_CATEGORY 32 | ||
214 | #define MESH_PATH_SEL_ACTION 0 | 212 | #define MESH_PATH_SEL_ACTION 0 |
215 | 213 | ||
216 | /* PERR reason codes */ | 214 | /* PERR reason codes */ |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index fefc45c4b4e8..d89ed7f2592b 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -132,7 +132,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
132 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 132 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
133 | /* BSSID == SA */ | 133 | /* BSSID == SA */ |
134 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 134 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
135 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 135 | mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; |
136 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 136 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; |
137 | 137 | ||
138 | switch (action) { | 138 | switch (action) { |
@@ -225,7 +225,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
225 | memcpy(mgmt->da, ra, ETH_ALEN); | 225 | memcpy(mgmt->da, ra, ETH_ALEN); |
226 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 226 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
227 | /* BSSID is left zeroed, wildcard value */ | 227 | /* BSSID is left zeroed, wildcard value */ |
228 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 228 | mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; |
229 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; | 229 | mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; |
230 | ie_len = 15; | 230 | ie_len = 15; |
231 | pos = skb_put(skb, 2 + ie_len); | 231 | pos = skb_put(skb, 2 + ie_len); |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 7b7080e2b49f..3cd5f7b5d693 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -172,7 +172,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
172 | memcpy(mgmt->da, da, ETH_ALEN); | 172 | memcpy(mgmt->da, da, ETH_ALEN); |
173 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 173 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
174 | /* BSSID is left zeroed, wildcard value */ | 174 | /* BSSID is left zeroed, wildcard value */ |
175 | mgmt->u.action.category = MESH_PLINK_CATEGORY; | 175 | mgmt->u.action.category = WLAN_CATEGORY_MESH_PLINK; |
176 | mgmt->u.action.u.plink_action.action_code = action; | 176 | mgmt->u.action.u.plink_action.action_code = action; |
177 | 177 | ||
178 | if (action == PLINK_CLOSE) | 178 | if (action == PLINK_CLOSE) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 71ff42a0465b..35d850223a75 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -47,6 +47,13 @@ | |||
47 | */ | 47 | */ |
48 | #define IEEE80211_PROBE_WAIT (HZ / 2) | 48 | #define IEEE80211_PROBE_WAIT (HZ / 2) |
49 | 49 | ||
50 | /* | ||
51 | * Weight given to the latest Beacon frame when calculating average signal | ||
52 | * strength for Beacon frames received in the current BSS. This must be | ||
53 | * between 1 and 15. | ||
54 | */ | ||
55 | #define IEEE80211_SIGNAL_AVE_WEIGHT 3 | ||
56 | |||
50 | #define TMR_RUNNING_TIMER 0 | 57 | #define TMR_RUNNING_TIMER 0 |
51 | #define TMR_RUNNING_CHANSW 1 | 58 | #define TMR_RUNNING_CHANSW 1 |
52 | 59 | ||
@@ -204,7 +211,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
204 | 211 | ||
205 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | 212 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, |
206 | const u8 *bssid, u16 stype, u16 reason, | 213 | const u8 *bssid, u16 stype, u16 reason, |
207 | void *cookie) | 214 | void *cookie, bool send_frame) |
208 | { | 215 | { |
209 | struct ieee80211_local *local = sdata->local; | 216 | struct ieee80211_local *local = sdata->local; |
210 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 217 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -241,7 +248,11 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
241 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); | 248 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); |
242 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) | 249 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) |
243 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 250 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
244 | ieee80211_tx_skb(sdata, skb); | 251 | |
252 | if (send_frame) | ||
253 | ieee80211_tx_skb(sdata, skb); | ||
254 | else | ||
255 | kfree_skb(skb); | ||
245 | } | 256 | } |
246 | 257 | ||
247 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 258 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
@@ -590,6 +601,9 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
590 | int count; | 601 | int count; |
591 | u8 *pos, uapsd_queues = 0; | 602 | u8 *pos, uapsd_queues = 0; |
592 | 603 | ||
604 | if (!local->ops->conf_tx) | ||
605 | return; | ||
606 | |||
593 | if (local->hw.queues < 4) | 607 | if (local->hw.queues < 4) |
594 | return; | 608 | return; |
595 | 609 | ||
@@ -664,11 +678,15 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
664 | params.aifs, params.cw_min, params.cw_max, params.txop, | 678 | params.aifs, params.cw_min, params.cw_max, params.txop, |
665 | params.uapsd); | 679 | params.uapsd); |
666 | #endif | 680 | #endif |
667 | if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx) | 681 | if (drv_conf_tx(local, queue, ¶ms)) |
668 | printk(KERN_DEBUG "%s: failed to set TX queue " | 682 | printk(KERN_DEBUG "%s: failed to set TX queue " |
669 | "parameters for queue %d\n", | 683 | "parameters for queue %d\n", |
670 | wiphy_name(local->hw.wiphy), queue); | 684 | wiphy_name(local->hw.wiphy), queue); |
671 | } | 685 | } |
686 | |||
687 | /* enable WMM or activate new settings */ | ||
688 | local->hw.conf.flags |= IEEE80211_CONF_QOS; | ||
689 | drv_config(local, IEEE80211_CONF_CHANGE_QOS); | ||
672 | } | 690 | } |
673 | 691 | ||
674 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | 692 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, |
@@ -729,6 +747,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
729 | sdata->u.mgd.associated = cbss; | 747 | sdata->u.mgd.associated = cbss; |
730 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); | 748 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
731 | 749 | ||
750 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; | ||
751 | |||
732 | /* just to be sure */ | 752 | /* just to be sure */ |
733 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 753 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
734 | IEEE80211_STA_BEACON_POLL); | 754 | IEEE80211_STA_BEACON_POLL); |
@@ -770,7 +790,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
770 | netif_carrier_on(sdata->dev); | 790 | netif_carrier_on(sdata->dev); |
771 | } | 791 | } |
772 | 792 | ||
773 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | 793 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
794 | bool remove_sta) | ||
774 | { | 795 | { |
775 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 796 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
776 | struct ieee80211_local *local = sdata->local; | 797 | struct ieee80211_local *local = sdata->local; |
@@ -843,7 +864,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) | |||
843 | changed |= BSS_CHANGED_BSSID; | 864 | changed |= BSS_CHANGED_BSSID; |
844 | ieee80211_bss_info_change_notify(sdata, changed); | 865 | ieee80211_bss_info_change_notify(sdata, changed); |
845 | 866 | ||
846 | sta_info_destroy_addr(sdata, bssid); | 867 | if (remove_sta) |
868 | sta_info_destroy_addr(sdata, bssid); | ||
847 | } | 869 | } |
848 | 870 | ||
849 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 871 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -956,7 +978,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
956 | 978 | ||
957 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); | 979 | printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); |
958 | 980 | ||
959 | ieee80211_set_disassoc(sdata); | 981 | ieee80211_set_disassoc(sdata, true); |
960 | ieee80211_recalc_idle(local); | 982 | ieee80211_recalc_idle(local); |
961 | mutex_unlock(&ifmgd->mtx); | 983 | mutex_unlock(&ifmgd->mtx); |
962 | /* | 984 | /* |
@@ -966,7 +988,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
966 | ieee80211_send_deauth_disassoc(sdata, bssid, | 988 | ieee80211_send_deauth_disassoc(sdata, bssid, |
967 | IEEE80211_STYPE_DEAUTH, | 989 | IEEE80211_STYPE_DEAUTH, |
968 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 990 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
969 | NULL); | 991 | NULL, true); |
970 | } | 992 | } |
971 | 993 | ||
972 | void ieee80211_beacon_connection_loss_work(struct work_struct *work) | 994 | void ieee80211_beacon_connection_loss_work(struct work_struct *work) |
@@ -986,6 +1008,8 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif) | |||
986 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1008 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
987 | struct ieee80211_hw *hw = &sdata->local->hw; | 1009 | struct ieee80211_hw *hw = &sdata->local->hw; |
988 | 1010 | ||
1011 | trace_api_beacon_loss(sdata); | ||
1012 | |||
989 | WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR); | 1013 | WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR); |
990 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); | 1014 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); |
991 | } | 1015 | } |
@@ -996,6 +1020,8 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif) | |||
996 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1020 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
997 | struct ieee80211_hw *hw = &sdata->local->hw; | 1021 | struct ieee80211_hw *hw = &sdata->local->hw; |
998 | 1022 | ||
1023 | trace_api_connection_loss(sdata); | ||
1024 | |||
999 | WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR)); | 1025 | WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR)); |
1000 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); | 1026 | ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); |
1001 | } | 1027 | } |
@@ -1022,7 +1048,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1022 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1048 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
1023 | sdata->name, bssid, reason_code); | 1049 | sdata->name, bssid, reason_code); |
1024 | 1050 | ||
1025 | ieee80211_set_disassoc(sdata); | 1051 | ieee80211_set_disassoc(sdata, true); |
1026 | ieee80211_recalc_idle(sdata->local); | 1052 | ieee80211_recalc_idle(sdata->local); |
1027 | 1053 | ||
1028 | return RX_MGMT_CFG80211_DEAUTH; | 1054 | return RX_MGMT_CFG80211_DEAUTH; |
@@ -1052,7 +1078,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1052 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1078 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
1053 | sdata->name, mgmt->sa, reason_code); | 1079 | sdata->name, mgmt->sa, reason_code); |
1054 | 1080 | ||
1055 | ieee80211_set_disassoc(sdata); | 1081 | ieee80211_set_disassoc(sdata, true); |
1056 | ieee80211_recalc_idle(sdata->local); | 1082 | ieee80211_recalc_idle(sdata->local); |
1057 | return RX_MGMT_CFG80211_DISASSOC; | 1083 | return RX_MGMT_CFG80211_DISASSOC; |
1058 | } | 1084 | } |
@@ -1344,6 +1370,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1344 | struct ieee80211_rx_status *rx_status) | 1370 | struct ieee80211_rx_status *rx_status) |
1345 | { | 1371 | { |
1346 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1372 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1373 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | ||
1347 | size_t baselen; | 1374 | size_t baselen; |
1348 | struct ieee802_11_elems elems; | 1375 | struct ieee802_11_elems elems; |
1349 | struct ieee80211_local *local = sdata->local; | 1376 | struct ieee80211_local *local = sdata->local; |
@@ -1379,6 +1406,41 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1379 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) | 1406 | if (memcmp(bssid, mgmt->bssid, ETH_ALEN) != 0) |
1380 | return; | 1407 | return; |
1381 | 1408 | ||
1409 | /* Track average RSSI from the Beacon frames of the current AP */ | ||
1410 | ifmgd->last_beacon_signal = rx_status->signal; | ||
1411 | if (ifmgd->flags & IEEE80211_STA_RESET_SIGNAL_AVE) { | ||
1412 | ifmgd->flags &= ~IEEE80211_STA_RESET_SIGNAL_AVE; | ||
1413 | ifmgd->ave_beacon_signal = rx_status->signal; | ||
1414 | ifmgd->last_cqm_event_signal = 0; | ||
1415 | } else { | ||
1416 | ifmgd->ave_beacon_signal = | ||
1417 | (IEEE80211_SIGNAL_AVE_WEIGHT * rx_status->signal * 16 + | ||
1418 | (16 - IEEE80211_SIGNAL_AVE_WEIGHT) * | ||
1419 | ifmgd->ave_beacon_signal) / 16; | ||
1420 | } | ||
1421 | if (bss_conf->cqm_rssi_thold && | ||
1422 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_CQM_RSSI)) { | ||
1423 | int sig = ifmgd->ave_beacon_signal / 16; | ||
1424 | int last_event = ifmgd->last_cqm_event_signal; | ||
1425 | int thold = bss_conf->cqm_rssi_thold; | ||
1426 | int hyst = bss_conf->cqm_rssi_hyst; | ||
1427 | if (sig < thold && | ||
1428 | (last_event == 0 || sig < last_event - hyst)) { | ||
1429 | ifmgd->last_cqm_event_signal = sig; | ||
1430 | ieee80211_cqm_rssi_notify( | ||
1431 | &sdata->vif, | ||
1432 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | ||
1433 | GFP_KERNEL); | ||
1434 | } else if (sig > thold && | ||
1435 | (last_event == 0 || sig > last_event + hyst)) { | ||
1436 | ifmgd->last_cqm_event_signal = sig; | ||
1437 | ieee80211_cqm_rssi_notify( | ||
1438 | &sdata->vif, | ||
1439 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | ||
1440 | GFP_KERNEL); | ||
1441 | } | ||
1442 | } | ||
1443 | |||
1382 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { | 1444 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { |
1383 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1445 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1384 | if (net_ratelimit()) { | 1446 | if (net_ratelimit()) { |
@@ -1664,7 +1726,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1664 | printk(KERN_DEBUG "No probe response from AP %pM" | 1726 | printk(KERN_DEBUG "No probe response from AP %pM" |
1665 | " after %dms, disconnecting.\n", | 1727 | " after %dms, disconnecting.\n", |
1666 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1728 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
1667 | ieee80211_set_disassoc(sdata); | 1729 | ieee80211_set_disassoc(sdata, true); |
1668 | ieee80211_recalc_idle(local); | 1730 | ieee80211_recalc_idle(local); |
1669 | mutex_unlock(&ifmgd->mtx); | 1731 | mutex_unlock(&ifmgd->mtx); |
1670 | /* | 1732 | /* |
@@ -1674,7 +1736,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
1674 | ieee80211_send_deauth_disassoc(sdata, bssid, | 1736 | ieee80211_send_deauth_disassoc(sdata, bssid, |
1675 | IEEE80211_STYPE_DEAUTH, | 1737 | IEEE80211_STYPE_DEAUTH, |
1676 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1738 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
1677 | NULL); | 1739 | NULL, true); |
1678 | mutex_lock(&ifmgd->mtx); | 1740 | mutex_lock(&ifmgd->mtx); |
1679 | } | 1741 | } |
1680 | } | 1742 | } |
@@ -1858,6 +1920,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
1858 | struct ieee80211_work *wk; | 1920 | struct ieee80211_work *wk; |
1859 | u16 auth_alg; | 1921 | u16 auth_alg; |
1860 | 1922 | ||
1923 | if (req->local_state_change) | ||
1924 | return 0; /* no need to update mac80211 state */ | ||
1925 | |||
1861 | switch (req->auth_type) { | 1926 | switch (req->auth_type) { |
1862 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | 1927 | case NL80211_AUTHTYPE_OPEN_SYSTEM: |
1863 | auth_alg = WLAN_AUTH_OPEN; | 1928 | auth_alg = WLAN_AUTH_OPEN; |
@@ -1966,7 +2031,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
1966 | } | 2031 | } |
1967 | 2032 | ||
1968 | /* Trying to reassociate - clear previous association state */ | 2033 | /* Trying to reassociate - clear previous association state */ |
1969 | ieee80211_set_disassoc(sdata); | 2034 | ieee80211_set_disassoc(sdata, true); |
1970 | } | 2035 | } |
1971 | mutex_unlock(&ifmgd->mtx); | 2036 | mutex_unlock(&ifmgd->mtx); |
1972 | 2037 | ||
@@ -2070,7 +2135,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2070 | 2135 | ||
2071 | if (ifmgd->associated == req->bss) { | 2136 | if (ifmgd->associated == req->bss) { |
2072 | bssid = req->bss->bssid; | 2137 | bssid = req->bss->bssid; |
2073 | ieee80211_set_disassoc(sdata); | 2138 | ieee80211_set_disassoc(sdata, true); |
2074 | mutex_unlock(&ifmgd->mtx); | 2139 | mutex_unlock(&ifmgd->mtx); |
2075 | } else { | 2140 | } else { |
2076 | bool not_auth_yet = false; | 2141 | bool not_auth_yet = false; |
@@ -2113,9 +2178,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2113 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 2178 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", |
2114 | sdata->name, bssid, req->reason_code); | 2179 | sdata->name, bssid, req->reason_code); |
2115 | 2180 | ||
2116 | ieee80211_send_deauth_disassoc(sdata, bssid, | 2181 | ieee80211_send_deauth_disassoc(sdata, bssid, IEEE80211_STYPE_DEAUTH, |
2117 | IEEE80211_STYPE_DEAUTH, req->reason_code, | 2182 | req->reason_code, cookie, |
2118 | cookie); | 2183 | !req->local_state_change); |
2119 | 2184 | ||
2120 | ieee80211_recalc_idle(sdata->local); | 2185 | ieee80211_recalc_idle(sdata->local); |
2121 | 2186 | ||
@@ -2127,6 +2192,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2127 | void *cookie) | 2192 | void *cookie) |
2128 | { | 2193 | { |
2129 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2194 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2195 | u8 bssid[ETH_ALEN]; | ||
2130 | 2196 | ||
2131 | mutex_lock(&ifmgd->mtx); | 2197 | mutex_lock(&ifmgd->mtx); |
2132 | 2198 | ||
@@ -2144,13 +2210,15 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2144 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 2210 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", |
2145 | sdata->name, req->bss->bssid, req->reason_code); | 2211 | sdata->name, req->bss->bssid, req->reason_code); |
2146 | 2212 | ||
2147 | ieee80211_set_disassoc(sdata); | 2213 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
2214 | ieee80211_set_disassoc(sdata, false); | ||
2148 | 2215 | ||
2149 | mutex_unlock(&ifmgd->mtx); | 2216 | mutex_unlock(&ifmgd->mtx); |
2150 | 2217 | ||
2151 | ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, | 2218 | ieee80211_send_deauth_disassoc(sdata, req->bss->bssid, |
2152 | IEEE80211_STYPE_DISASSOC, req->reason_code, | 2219 | IEEE80211_STYPE_DISASSOC, req->reason_code, |
2153 | cookie); | 2220 | cookie, !req->local_state_change); |
2221 | sta_info_destroy_addr(sdata, bssid); | ||
2154 | 2222 | ||
2155 | ieee80211_recalc_idle(sdata->local); | 2223 | ieee80211_recalc_idle(sdata->local); |
2156 | 2224 | ||
@@ -2198,6 +2266,8 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | |||
2198 | { | 2266 | { |
2199 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 2267 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
2200 | 2268 | ||
2269 | trace_api_cqm_rssi_notify(sdata, rssi_event); | ||
2270 | |||
2201 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | 2271 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); |
2202 | } | 2272 | } |
2203 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | 2273 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 0e64484e861c..75202b295a4e 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -46,7 +46,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
46 | 46 | ||
47 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 47 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
48 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 48 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
49 | set_sta_flags(sta, WLAN_STA_SUSPEND); | 49 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); |
50 | ieee80211_sta_tear_down_BA_sessions(sta); | 50 | ieee80211_sta_tear_down_BA_sessions(sta); |
51 | } | 51 | } |
52 | } | 52 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index e0c944fb6fc9..72efbd87c1eb 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -39,7 +39,7 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
39 | { | 39 | { |
40 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 40 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
41 | if (likely(skb->len > FCS_LEN)) | 41 | if (likely(skb->len > FCS_LEN)) |
42 | skb_trim(skb, skb->len - FCS_LEN); | 42 | __pskb_trim(skb, skb->len - FCS_LEN); |
43 | else { | 43 | else { |
44 | /* driver bug */ | 44 | /* driver bug */ |
45 | WARN_ON(1); | 45 | WARN_ON(1); |
@@ -228,6 +228,12 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
228 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 228 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
229 | present_fcs_len = FCS_LEN; | 229 | present_fcs_len = FCS_LEN; |
230 | 230 | ||
231 | /* make sure hdr->frame_control is on the linear part */ | ||
232 | if (!pskb_may_pull(origskb, 2)) { | ||
233 | dev_kfree_skb(origskb); | ||
234 | return NULL; | ||
235 | } | ||
236 | |||
231 | if (!local->monitors) { | 237 | if (!local->monitors) { |
232 | if (should_drop_frame(origskb, present_fcs_len)) { | 238 | if (should_drop_frame(origskb, present_fcs_len)) { |
233 | dev_kfree_skb(origskb); | 239 | dev_kfree_skb(origskb); |
@@ -485,7 +491,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
485 | 491 | ||
486 | if (ieee80211_is_action(hdr->frame_control)) { | 492 | if (ieee80211_is_action(hdr->frame_control)) { |
487 | mgmt = (struct ieee80211_mgmt *)hdr; | 493 | mgmt = (struct ieee80211_mgmt *)hdr; |
488 | if (mgmt->u.action.category != MESH_PLINK_CATEGORY) | 494 | if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK) |
489 | return RX_DROP_MONITOR; | 495 | return RX_DROP_MONITOR; |
490 | return RX_CONTINUE; | 496 | return RX_CONTINUE; |
491 | } | 497 | } |
@@ -715,14 +721,16 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
715 | 721 | ||
716 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 722 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
717 | 723 | ||
718 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) | 724 | spin_lock(&sta->lock); |
719 | goto dont_reorder; | 725 | |
726 | if (!sta->ampdu_mlme.tid_active_rx[tid]) | ||
727 | goto dont_reorder_unlock; | ||
720 | 728 | ||
721 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | 729 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; |
722 | 730 | ||
723 | /* qos null data frames are excluded */ | 731 | /* qos null data frames are excluded */ |
724 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) | 732 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
725 | goto dont_reorder; | 733 | goto dont_reorder_unlock; |
726 | 734 | ||
727 | /* new, potentially un-ordered, ampdu frame - process it */ | 735 | /* new, potentially un-ordered, ampdu frame - process it */ |
728 | 736 | ||
@@ -734,15 +742,20 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
734 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 742 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
735 | sc = le16_to_cpu(hdr->seq_ctrl); | 743 | sc = le16_to_cpu(hdr->seq_ctrl); |
736 | if (sc & IEEE80211_SCTL_FRAG) { | 744 | if (sc & IEEE80211_SCTL_FRAG) { |
737 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | 745 | spin_unlock(&sta->lock); |
738 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); | 746 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
747 | WLAN_REASON_QSTA_REQUIRE_SETUP); | ||
739 | dev_kfree_skb(skb); | 748 | dev_kfree_skb(skb); |
740 | return; | 749 | return; |
741 | } | 750 | } |
742 | 751 | ||
743 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) | 752 | if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames)) { |
753 | spin_unlock(&sta->lock); | ||
744 | return; | 754 | return; |
755 | } | ||
745 | 756 | ||
757 | dont_reorder_unlock: | ||
758 | spin_unlock(&sta->lock); | ||
746 | dont_reorder: | 759 | dont_reorder: |
747 | __skb_queue_tail(frames, skb); | 760 | __skb_queue_tail(frames, skb); |
748 | } | 761 | } |
@@ -889,6 +902,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
889 | rx->key = key; | 902 | rx->key = key; |
890 | return RX_CONTINUE; | 903 | return RX_CONTINUE; |
891 | } else { | 904 | } else { |
905 | u8 keyid; | ||
892 | /* | 906 | /* |
893 | * The device doesn't give us the IV so we won't be | 907 | * The device doesn't give us the IV so we won't be |
894 | * able to look up the key. That's ok though, we | 908 | * able to look up the key. That's ok though, we |
@@ -911,7 +925,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
911 | * no need to call ieee80211_wep_get_keyidx, | 925 | * no need to call ieee80211_wep_get_keyidx, |
912 | * it verifies a bunch of things we've done already | 926 | * it verifies a bunch of things we've done already |
913 | */ | 927 | */ |
914 | keyidx = rx->skb->data[hdrlen + 3] >> 6; | 928 | skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); |
929 | keyidx = keyid >> 6; | ||
915 | 930 | ||
916 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); | 931 | rx->key = rcu_dereference(rx->sdata->keys[keyidx]); |
917 | 932 | ||
@@ -932,6 +947,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
932 | return RX_DROP_MONITOR; | 947 | return RX_DROP_MONITOR; |
933 | } | 948 | } |
934 | 949 | ||
950 | if (skb_linearize(rx->skb)) | ||
951 | return RX_DROP_UNUSABLE; | ||
952 | |||
953 | hdr = (struct ieee80211_hdr *)rx->skb->data; | ||
954 | |||
935 | /* Check for weak IVs if possible */ | 955 | /* Check for weak IVs if possible */ |
936 | if (rx->sta && rx->key->conf.alg == ALG_WEP && | 956 | if (rx->sta && rx->key->conf.alg == ALG_WEP && |
937 | ieee80211_is_data(hdr->frame_control) && | 957 | ieee80211_is_data(hdr->frame_control) && |
@@ -1232,6 +1252,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1232 | } | 1252 | } |
1233 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); | 1253 | I802_DEBUG_INC(rx->local->rx_handlers_fragments); |
1234 | 1254 | ||
1255 | if (skb_linearize(rx->skb)) | ||
1256 | return RX_DROP_UNUSABLE; | ||
1257 | |||
1235 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; | 1258 | seq = (sc & IEEE80211_SCTL_SEQ) >> 4; |
1236 | 1259 | ||
1237 | if (frag == 0) { | 1260 | if (frag == 0) { |
@@ -1397,21 +1420,24 @@ static int | |||
1397 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | 1420 | ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) |
1398 | { | 1421 | { |
1399 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1422 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1423 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | ||
1400 | __le16 fc = hdr->frame_control; | 1424 | __le16 fc = hdr->frame_control; |
1401 | int res; | ||
1402 | 1425 | ||
1403 | res = ieee80211_drop_unencrypted(rx, fc); | 1426 | /* |
1404 | if (unlikely(res)) | 1427 | * Pass through unencrypted frames if the hardware has |
1405 | return res; | 1428 | * decrypted them already. |
1429 | */ | ||
1430 | if (status->flag & RX_FLAG_DECRYPTED) | ||
1431 | return 0; | ||
1406 | 1432 | ||
1407 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { | 1433 | if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) { |
1408 | if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | 1434 | if (unlikely(!ieee80211_has_protected(fc) && |
1435 | ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && | ||
1409 | rx->key)) | 1436 | rx->key)) |
1410 | return -EACCES; | 1437 | return -EACCES; |
1411 | /* BIP does not use Protected field, so need to check MMIE */ | 1438 | /* BIP does not use Protected field, so need to check MMIE */ |
1412 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && | 1439 | if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && |
1413 | ieee80211_get_mmie_keyidx(rx->skb) < 0 && | 1440 | ieee80211_get_mmie_keyidx(rx->skb) < 0)) |
1414 | rx->key)) | ||
1415 | return -EACCES; | 1441 | return -EACCES; |
1416 | /* | 1442 | /* |
1417 | * When using MFP, Action frames are not allowed prior to | 1443 | * When using MFP, Action frames are not allowed prior to |
@@ -1589,6 +1615,9 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1589 | skb->dev = dev; | 1615 | skb->dev = dev; |
1590 | __skb_queue_head_init(&frame_list); | 1616 | __skb_queue_head_init(&frame_list); |
1591 | 1617 | ||
1618 | if (skb_linearize(skb)) | ||
1619 | return RX_DROP_UNUSABLE; | ||
1620 | |||
1592 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, | 1621 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, |
1593 | rx->sdata->vif.type, | 1622 | rx->sdata->vif.type, |
1594 | rx->local->hw.extra_tx_headroom); | 1623 | rx->local->hw.extra_tx_headroom); |
@@ -1787,10 +1816,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1787 | if (ieee80211_is_back_req(bar->frame_control)) { | 1816 | if (ieee80211_is_back_req(bar->frame_control)) { |
1788 | if (!rx->sta) | 1817 | if (!rx->sta) |
1789 | return RX_DROP_MONITOR; | 1818 | return RX_DROP_MONITOR; |
1819 | spin_lock(&rx->sta->lock); | ||
1790 | tid = le16_to_cpu(bar->control) >> 12; | 1820 | tid = le16_to_cpu(bar->control) >> 12; |
1791 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] | 1821 | if (!rx->sta->ampdu_mlme.tid_active_rx[tid]) { |
1792 | != HT_AGG_STATE_OPERATIONAL) | 1822 | spin_unlock(&rx->sta->lock); |
1793 | return RX_DROP_MONITOR; | 1823 | return RX_DROP_MONITOR; |
1824 | } | ||
1794 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; | 1825 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; |
1795 | 1826 | ||
1796 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; | 1827 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; |
@@ -1804,6 +1835,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1804 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, | 1835 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, |
1805 | frames); | 1836 | frames); |
1806 | kfree_skb(skb); | 1837 | kfree_skb(skb); |
1838 | spin_unlock(&rx->sta->lock); | ||
1807 | return RX_QUEUED; | 1839 | return RX_QUEUED; |
1808 | } | 1840 | } |
1809 | 1841 | ||
@@ -1965,8 +1997,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1965 | goto handled; | 1997 | goto handled; |
1966 | } | 1998 | } |
1967 | break; | 1999 | break; |
1968 | case MESH_PLINK_CATEGORY: | 2000 | case WLAN_CATEGORY_MESH_PLINK: |
1969 | case MESH_PATH_SEL_CATEGORY: | 2001 | case WLAN_CATEGORY_MESH_PATH_SEL: |
1970 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 2002 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1971 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | 2003 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); |
1972 | break; | 2004 | break; |
@@ -2363,29 +2395,42 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2363 | struct ieee80211_local *local = hw_to_local(hw); | 2395 | struct ieee80211_local *local = hw_to_local(hw); |
2364 | struct ieee80211_sub_if_data *sdata; | 2396 | struct ieee80211_sub_if_data *sdata; |
2365 | struct ieee80211_hdr *hdr; | 2397 | struct ieee80211_hdr *hdr; |
2398 | __le16 fc; | ||
2366 | struct ieee80211_rx_data rx; | 2399 | struct ieee80211_rx_data rx; |
2367 | int prepares; | 2400 | int prepares; |
2368 | struct ieee80211_sub_if_data *prev = NULL; | 2401 | struct ieee80211_sub_if_data *prev = NULL; |
2369 | struct sk_buff *skb_new; | 2402 | struct sk_buff *skb_new; |
2370 | struct sta_info *sta, *tmp; | 2403 | struct sta_info *sta, *tmp; |
2371 | bool found_sta = false; | 2404 | bool found_sta = false; |
2405 | int err = 0; | ||
2372 | 2406 | ||
2373 | hdr = (struct ieee80211_hdr *)skb->data; | 2407 | fc = ((struct ieee80211_hdr *)skb->data)->frame_control; |
2374 | memset(&rx, 0, sizeof(rx)); | 2408 | memset(&rx, 0, sizeof(rx)); |
2375 | rx.skb = skb; | 2409 | rx.skb = skb; |
2376 | rx.local = local; | 2410 | rx.local = local; |
2377 | 2411 | ||
2378 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) | 2412 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
2379 | local->dot11ReceivedFragmentCount++; | 2413 | local->dot11ReceivedFragmentCount++; |
2380 | 2414 | ||
2381 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 2415 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
2382 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) | 2416 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) |
2383 | rx.flags |= IEEE80211_RX_IN_SCAN; | 2417 | rx.flags |= IEEE80211_RX_IN_SCAN; |
2384 | 2418 | ||
2419 | if (ieee80211_is_mgmt(fc)) | ||
2420 | err = skb_linearize(skb); | ||
2421 | else | ||
2422 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); | ||
2423 | |||
2424 | if (err) { | ||
2425 | dev_kfree_skb(skb); | ||
2426 | return; | ||
2427 | } | ||
2428 | |||
2429 | hdr = (struct ieee80211_hdr *)skb->data; | ||
2385 | ieee80211_parse_qos(&rx); | 2430 | ieee80211_parse_qos(&rx); |
2386 | ieee80211_verify_alignment(&rx); | 2431 | ieee80211_verify_alignment(&rx); |
2387 | 2432 | ||
2388 | if (ieee80211_is_data(hdr->frame_control)) { | 2433 | if (ieee80211_is_data(fc)) { |
2389 | for_each_sta_info(local, hdr->addr2, sta, tmp) { | 2434 | for_each_sta_info(local, hdr->addr2, sta, tmp) { |
2390 | rx.sta = sta; | 2435 | rx.sta = sta; |
2391 | found_sta = true; | 2436 | found_sta = true; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 1ce4ce8af80f..e1a3defdf581 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -248,6 +248,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
248 | struct ieee80211_local *local = hw_to_local(hw); | 248 | struct ieee80211_local *local = hw_to_local(hw); |
249 | bool was_hw_scan; | 249 | bool was_hw_scan; |
250 | 250 | ||
251 | trace_api_scan_completed(local, aborted); | ||
252 | |||
251 | mutex_lock(&local->scan_mtx); | 253 | mutex_lock(&local->scan_mtx); |
252 | 254 | ||
253 | /* | 255 | /* |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index fb12cec4d333..ff0eb948917b 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -250,9 +250,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
250 | * enable session_timer's data differentiation. refer to | 250 | * enable session_timer's data differentiation. refer to |
251 | * sta_rx_agg_session_timer_expired for useage */ | 251 | * sta_rx_agg_session_timer_expired for useage */ |
252 | sta->timer_to_tid[i] = i; | 252 | sta->timer_to_tid[i] = i; |
253 | /* rx */ | ||
254 | sta->ampdu_mlme.tid_state_rx[i] = HT_AGG_STATE_IDLE; | ||
255 | sta->ampdu_mlme.tid_rx[i] = NULL; | ||
256 | /* tx */ | 253 | /* tx */ |
257 | sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; | 254 | sta->ampdu_mlme.tid_state_tx[i] = HT_AGG_STATE_IDLE; |
258 | sta->ampdu_mlme.tid_tx[i] = NULL; | 255 | sta->ampdu_mlme.tid_tx[i] = NULL; |
@@ -619,7 +616,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
619 | struct ieee80211_sub_if_data *sdata; | 616 | struct ieee80211_sub_if_data *sdata; |
620 | struct sk_buff *skb; | 617 | struct sk_buff *skb; |
621 | unsigned long flags; | 618 | unsigned long flags; |
622 | int ret, i; | 619 | int ret; |
623 | 620 | ||
624 | might_sleep(); | 621 | might_sleep(); |
625 | 622 | ||
@@ -629,6 +626,15 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
629 | local = sta->local; | 626 | local = sta->local; |
630 | sdata = sta->sdata; | 627 | sdata = sta->sdata; |
631 | 628 | ||
629 | /* | ||
630 | * Before removing the station from the driver and | ||
631 | * rate control, it might still start new aggregation | ||
632 | * sessions -- block that to make sure the tear-down | ||
633 | * will be sufficient. | ||
634 | */ | ||
635 | set_sta_flags(sta, WLAN_STA_BLOCK_BA); | ||
636 | ieee80211_sta_tear_down_BA_sessions(sta); | ||
637 | |||
632 | spin_lock_irqsave(&local->sta_lock, flags); | 638 | spin_lock_irqsave(&local->sta_lock, flags); |
633 | ret = sta_info_hash_del(local, sta); | 639 | ret = sta_info_hash_del(local, sta); |
634 | /* this might still be the pending list ... which is fine */ | 640 | /* this might still be the pending list ... which is fine */ |
@@ -645,9 +651,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
645 | * may mean it is removed from hardware which requires that | 651 | * may mean it is removed from hardware which requires that |
646 | * the key->sta pointer is still valid, so flush the key todo | 652 | * the key->sta pointer is still valid, so flush the key todo |
647 | * list here. | 653 | * list here. |
648 | * | ||
649 | * ieee80211_key_todo() will synchronize_rcu() so after this | ||
650 | * nothing can reference this sta struct any more. | ||
651 | */ | 654 | */ |
652 | ieee80211_key_todo(); | 655 | ieee80211_key_todo(); |
653 | 656 | ||
@@ -679,11 +682,17 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
679 | sdata = sta->sdata; | 682 | sdata = sta->sdata; |
680 | } | 683 | } |
681 | 684 | ||
685 | /* | ||
686 | * At this point, after we wait for an RCU grace period, | ||
687 | * neither mac80211 nor the driver can reference this | ||
688 | * sta struct any more except by still existing timers | ||
689 | * associated with this station that we clean up below. | ||
690 | */ | ||
691 | synchronize_rcu(); | ||
692 | |||
682 | #ifdef CONFIG_MAC80211_MESH | 693 | #ifdef CONFIG_MAC80211_MESH |
683 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 694 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
684 | mesh_accept_plinks_update(sdata); | 695 | mesh_accept_plinks_update(sdata); |
685 | del_timer(&sta->plink_timer); | ||
686 | } | ||
687 | #endif | 696 | #endif |
688 | 697 | ||
689 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 698 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
@@ -710,50 +719,6 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
710 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) | 719 | while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) |
711 | dev_kfree_skb_any(skb); | 720 | dev_kfree_skb_any(skb); |
712 | 721 | ||
713 | for (i = 0; i < STA_TID_NUM; i++) { | ||
714 | struct tid_ampdu_rx *tid_rx; | ||
715 | struct tid_ampdu_tx *tid_tx; | ||
716 | |||
717 | spin_lock_bh(&sta->lock); | ||
718 | tid_rx = sta->ampdu_mlme.tid_rx[i]; | ||
719 | /* Make sure timer won't free the tid_rx struct, see below */ | ||
720 | if (tid_rx) | ||
721 | tid_rx->shutdown = true; | ||
722 | |||
723 | spin_unlock_bh(&sta->lock); | ||
724 | |||
725 | /* | ||
726 | * Outside spinlock - shutdown is true now so that the timer | ||
727 | * won't free tid_rx, we have to do that now. Can't let the | ||
728 | * timer do it because we have to sync the timer outside the | ||
729 | * lock that it takes itself. | ||
730 | */ | ||
731 | if (tid_rx) { | ||
732 | del_timer_sync(&tid_rx->session_timer); | ||
733 | kfree(tid_rx); | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | * No need to do such complications for TX agg sessions, the | ||
738 | * path leading to freeing the tid_tx struct goes via a call | ||
739 | * from the driver, and thus needs to look up the sta struct | ||
740 | * again, which cannot be found when we get here. Hence, we | ||
741 | * just need to delete the timer and free the aggregation | ||
742 | * info; we won't be telling the peer about it then but that | ||
743 | * doesn't matter if we're not talking to it again anyway. | ||
744 | */ | ||
745 | tid_tx = sta->ampdu_mlme.tid_tx[i]; | ||
746 | if (tid_tx) { | ||
747 | del_timer_sync(&tid_tx->addba_resp_timer); | ||
748 | /* | ||
749 | * STA removed while aggregation session being | ||
750 | * started? Bit odd, but purge frames anyway. | ||
751 | */ | ||
752 | skb_queue_purge(&tid_tx->pending); | ||
753 | kfree(tid_tx); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | __sta_info_free(local, sta); | 722 | __sta_info_free(local, sta); |
758 | 723 | ||
759 | return 0; | 724 | return 0; |
@@ -992,6 +957,8 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
992 | { | 957 | { |
993 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); | 958 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
994 | 959 | ||
960 | trace_api_sta_block_awake(sta->local, pubsta, block); | ||
961 | |||
995 | if (block) | 962 | if (block) |
996 | set_sta_flags(sta, WLAN_STA_PS_DRIVER); | 963 | set_sta_flags(sta, WLAN_STA_PS_DRIVER); |
997 | else | 964 | else |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 2b635909de5c..48a5e80957f0 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -35,8 +35,8 @@ | |||
35 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next | 35 | * IEEE80211_TX_CTL_CLEAR_PS_FILT control flag) when the next |
36 | * frame to this station is transmitted. | 36 | * frame to this station is transmitted. |
37 | * @WLAN_STA_MFP: Management frame protection is used with this STA. | 37 | * @WLAN_STA_MFP: Management frame protection is used with this STA. |
38 | * @WLAN_STA_SUSPEND: Set/cleared during a suspend/resume cycle. | 38 | * @WLAN_STA_BLOCK_BA: Used to deny ADDBA requests (both TX and RX) |
39 | * Used to deny ADDBA requests (both TX and RX). | 39 | * during suspend/resume and station removal. |
40 | * @WLAN_STA_PS_DRIVER: driver requires keeping this station in | 40 | * @WLAN_STA_PS_DRIVER: driver requires keeping this station in |
41 | * power-save mode logically to flush frames that might still | 41 | * power-save mode logically to flush frames that might still |
42 | * be in the queues | 42 | * be in the queues |
@@ -57,7 +57,7 @@ enum ieee80211_sta_info_flags { | |||
57 | WLAN_STA_WDS = 1<<7, | 57 | WLAN_STA_WDS = 1<<7, |
58 | WLAN_STA_CLEAR_PS_FILT = 1<<9, | 58 | WLAN_STA_CLEAR_PS_FILT = 1<<9, |
59 | WLAN_STA_MFP = 1<<10, | 59 | WLAN_STA_MFP = 1<<10, |
60 | WLAN_STA_SUSPEND = 1<<11, | 60 | WLAN_STA_BLOCK_BA = 1<<11, |
61 | WLAN_STA_PS_DRIVER = 1<<12, | 61 | WLAN_STA_PS_DRIVER = 1<<12, |
62 | WLAN_STA_PSPOLL = 1<<13, | 62 | WLAN_STA_PSPOLL = 1<<13, |
63 | WLAN_STA_DISASSOC = 1<<14, | 63 | WLAN_STA_DISASSOC = 1<<14, |
@@ -106,7 +106,6 @@ struct tid_ampdu_tx { | |||
106 | * @buf_size: buffer size for incoming A-MPDUs | 106 | * @buf_size: buffer size for incoming A-MPDUs |
107 | * @timeout: reset timer value (in TUs). | 107 | * @timeout: reset timer value (in TUs). |
108 | * @dialog_token: dialog token for aggregation session | 108 | * @dialog_token: dialog token for aggregation session |
109 | * @shutdown: this session is being shut down due to STA removal | ||
110 | */ | 109 | */ |
111 | struct tid_ampdu_rx { | 110 | struct tid_ampdu_rx { |
112 | struct sk_buff **reorder_buf; | 111 | struct sk_buff **reorder_buf; |
@@ -118,7 +117,6 @@ struct tid_ampdu_rx { | |||
118 | u16 buf_size; | 117 | u16 buf_size; |
119 | u16 timeout; | 118 | u16 timeout; |
120 | u8 dialog_token; | 119 | u8 dialog_token; |
121 | bool shutdown; | ||
122 | }; | 120 | }; |
123 | 121 | ||
124 | /** | 122 | /** |
@@ -156,7 +154,7 @@ enum plink_state { | |||
156 | */ | 154 | */ |
157 | struct sta_ampdu_mlme { | 155 | struct sta_ampdu_mlme { |
158 | /* rx */ | 156 | /* rx */ |
159 | u8 tid_state_rx[STA_TID_NUM]; | 157 | bool tid_active_rx[STA_TID_NUM]; |
160 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; | 158 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; |
161 | /* tx */ | 159 | /* tx */ |
162 | u8 tid_state_tx[STA_TID_NUM]; | 160 | u8 tid_state_tx[STA_TID_NUM]; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index db25fa9ef135..2cb77267f733 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -513,6 +513,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
513 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) | 513 | else if (tx->sta && (key = rcu_dereference(tx->sta->key))) |
514 | tx->key = key; | 514 | tx->key = key; |
515 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 515 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
516 | is_multicast_ether_addr(hdr->addr1) && | ||
517 | ieee80211_is_robust_mgmt_frame(hdr) && | ||
516 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | 518 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) |
517 | tx->key = key; | 519 | tx->key = key; |
518 | else if ((key = rcu_dereference(tx->sdata->default_key))) | 520 | else if ((key = rcu_dereference(tx->sdata->default_key))) |
@@ -1142,13 +1144,12 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1142 | 1144 | ||
1143 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && | 1145 | if (tx->sta && ieee80211_is_data_qos(hdr->frame_control) && |
1144 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { | 1146 | (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) { |
1145 | unsigned long flags; | ||
1146 | struct tid_ampdu_tx *tid_tx; | 1147 | struct tid_ampdu_tx *tid_tx; |
1147 | 1148 | ||
1148 | qc = ieee80211_get_qos_ctl(hdr); | 1149 | qc = ieee80211_get_qos_ctl(hdr); |
1149 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; | 1150 | tid = *qc & IEEE80211_QOS_CTL_TID_MASK; |
1150 | 1151 | ||
1151 | spin_lock_irqsave(&tx->sta->lock, flags); | 1152 | spin_lock(&tx->sta->lock); |
1152 | /* | 1153 | /* |
1153 | * XXX: This spinlock could be fairly expensive, but see the | 1154 | * XXX: This spinlock could be fairly expensive, but see the |
1154 | * comment in agg-tx.c:ieee80211_agg_tx_operational(). | 1155 | * comment in agg-tx.c:ieee80211_agg_tx_operational(). |
@@ -1173,7 +1174,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1173 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1174 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1174 | __skb_queue_tail(&tid_tx->pending, skb); | 1175 | __skb_queue_tail(&tid_tx->pending, skb); |
1175 | } | 1176 | } |
1176 | spin_unlock_irqrestore(&tx->sta->lock, flags); | 1177 | spin_unlock(&tx->sta->lock); |
1177 | 1178 | ||
1178 | if (unlikely(queued)) | 1179 | if (unlikely(queued)) |
1179 | return TX_QUEUED; | 1180 | return TX_QUEUED; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 53af57047435..2b75b4fb68f4 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -270,6 +270,8 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
270 | struct ieee80211_local *local = hw_to_local(hw); | 270 | struct ieee80211_local *local = hw_to_local(hw); |
271 | struct ieee80211_sub_if_data *sdata; | 271 | struct ieee80211_sub_if_data *sdata; |
272 | 272 | ||
273 | trace_wake_queue(local, queue, reason); | ||
274 | |||
273 | if (WARN_ON(queue >= hw->queues)) | 275 | if (WARN_ON(queue >= hw->queues)) |
274 | return; | 276 | return; |
275 | 277 | ||
@@ -312,6 +314,8 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
312 | struct ieee80211_local *local = hw_to_local(hw); | 314 | struct ieee80211_local *local = hw_to_local(hw); |
313 | struct ieee80211_sub_if_data *sdata; | 315 | struct ieee80211_sub_if_data *sdata; |
314 | 316 | ||
317 | trace_stop_queue(local, queue, reason); | ||
318 | |||
315 | if (WARN_ON(queue >= hw->queues)) | 319 | if (WARN_ON(queue >= hw->queues)) |
316 | return; | 320 | return; |
317 | 321 | ||
@@ -796,6 +800,11 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
796 | 800 | ||
797 | drv_conf_tx(local, queue, &qparam); | 801 | drv_conf_tx(local, queue, &qparam); |
798 | } | 802 | } |
803 | |||
804 | /* after reinitialize QoS TX queues setting to default, | ||
805 | * disable QoS at all */ | ||
806 | local->hw.conf.flags &= ~IEEE80211_CONF_QOS; | ||
807 | drv_config(local, IEEE80211_CONF_CHANGE_QOS); | ||
799 | } | 808 | } |
800 | 809 | ||
801 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 810 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
@@ -1135,7 +1144,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1135 | 1144 | ||
1136 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | 1145 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { |
1137 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 1146 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
1138 | clear_sta_flags(sta, WLAN_STA_SUSPEND); | 1147 | clear_sta_flags(sta, WLAN_STA_BLOCK_BA); |
1139 | } | 1148 | } |
1140 | } | 1149 | } |
1141 | 1150 | ||
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 15e1ba931b87..bdb1d05b16fc 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -920,11 +920,16 @@ static void ieee80211_work_work(struct work_struct *work) | |||
920 | run_again(local, jiffies + HZ/2); | 920 | run_again(local, jiffies + HZ/2); |
921 | } | 921 | } |
922 | 922 | ||
923 | if (list_empty(&local->work_list) && local->scan_req) | 923 | mutex_lock(&local->scan_mtx); |
924 | |||
925 | if (list_empty(&local->work_list) && local->scan_req && | ||
926 | !local->scanning) | ||
924 | ieee80211_queue_delayed_work(&local->hw, | 927 | ieee80211_queue_delayed_work(&local->hw, |
925 | &local->scan_work, | 928 | &local->scan_work, |
926 | round_jiffies_relative(0)); | 929 | round_jiffies_relative(0)); |
927 | 930 | ||
931 | mutex_unlock(&local->scan_mtx); | ||
932 | |||
928 | mutex_unlock(&local->work_mtx); | 933 | mutex_unlock(&local->work_mtx); |
929 | 934 | ||
930 | ieee80211_recalc_idle(local); | 935 | ieee80211_recalc_idle(local); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index d52da913145a..b2234b436ead 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -293,13 +293,15 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
293 | const u8 *bssid, | 293 | const u8 *bssid, |
294 | const u8 *ssid, int ssid_len, | 294 | const u8 *ssid, int ssid_len, |
295 | const u8 *ie, int ie_len, | 295 | const u8 *ie, int ie_len, |
296 | const u8 *key, int key_len, int key_idx); | 296 | const u8 *key, int key_len, int key_idx, |
297 | bool local_state_change); | ||
297 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 298 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
298 | struct net_device *dev, struct ieee80211_channel *chan, | 299 | struct net_device *dev, struct ieee80211_channel *chan, |
299 | enum nl80211_auth_type auth_type, const u8 *bssid, | 300 | enum nl80211_auth_type auth_type, const u8 *bssid, |
300 | const u8 *ssid, int ssid_len, | 301 | const u8 *ssid, int ssid_len, |
301 | const u8 *ie, int ie_len, | 302 | const u8 *ie, int ie_len, |
302 | const u8 *key, int key_len, int key_idx); | 303 | const u8 *key, int key_len, int key_idx, |
304 | bool local_state_change); | ||
303 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | 305 | int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, |
304 | struct net_device *dev, | 306 | struct net_device *dev, |
305 | struct ieee80211_channel *chan, | 307 | struct ieee80211_channel *chan, |
@@ -315,13 +317,16 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
315 | struct cfg80211_crypto_settings *crypt); | 317 | struct cfg80211_crypto_settings *crypt); |
316 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 318 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
317 | struct net_device *dev, const u8 *bssid, | 319 | struct net_device *dev, const u8 *bssid, |
318 | const u8 *ie, int ie_len, u16 reason); | 320 | const u8 *ie, int ie_len, u16 reason, |
321 | bool local_state_change); | ||
319 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 322 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
320 | struct net_device *dev, const u8 *bssid, | 323 | struct net_device *dev, const u8 *bssid, |
321 | const u8 *ie, int ie_len, u16 reason); | 324 | const u8 *ie, int ie_len, u16 reason, |
325 | bool local_state_change); | ||
322 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 326 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
323 | struct net_device *dev, const u8 *bssid, | 327 | struct net_device *dev, const u8 *bssid, |
324 | const u8 *ie, int ie_len, u16 reason); | 328 | const u8 *ie, int ie_len, u16 reason, |
329 | bool local_state_change); | ||
325 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | 330 | void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, |
326 | struct net_device *dev); | 331 | struct net_device *dev); |
327 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 332 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 4bb734a95f57..48ead6f0426d 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -378,7 +378,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
378 | const u8 *bssid, | 378 | const u8 *bssid, |
379 | const u8 *ssid, int ssid_len, | 379 | const u8 *ssid, int ssid_len, |
380 | const u8 *ie, int ie_len, | 380 | const u8 *ie, int ie_len, |
381 | const u8 *key, int key_len, int key_idx) | 381 | const u8 *key, int key_len, int key_idx, |
382 | bool local_state_change) | ||
382 | { | 383 | { |
383 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 384 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
384 | struct cfg80211_auth_request req; | 385 | struct cfg80211_auth_request req; |
@@ -408,6 +409,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
408 | 409 | ||
409 | memset(&req, 0, sizeof(req)); | 410 | memset(&req, 0, sizeof(req)); |
410 | 411 | ||
412 | req.local_state_change = local_state_change; | ||
411 | req.ie = ie; | 413 | req.ie = ie; |
412 | req.ie_len = ie_len; | 414 | req.ie_len = ie_len; |
413 | req.auth_type = auth_type; | 415 | req.auth_type = auth_type; |
@@ -434,12 +436,18 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
434 | goto out; | 436 | goto out; |
435 | } | 437 | } |
436 | 438 | ||
437 | wdev->authtry_bsses[slot] = bss; | 439 | if (local_state_change) |
440 | wdev->auth_bsses[slot] = bss; | ||
441 | else | ||
442 | wdev->authtry_bsses[slot] = bss; | ||
438 | cfg80211_hold_bss(bss); | 443 | cfg80211_hold_bss(bss); |
439 | 444 | ||
440 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); | 445 | err = rdev->ops->auth(&rdev->wiphy, dev, &req); |
441 | if (err) { | 446 | if (err) { |
442 | wdev->authtry_bsses[slot] = NULL; | 447 | if (local_state_change) |
448 | wdev->auth_bsses[slot] = NULL; | ||
449 | else | ||
450 | wdev->authtry_bsses[slot] = NULL; | ||
443 | cfg80211_unhold_bss(bss); | 451 | cfg80211_unhold_bss(bss); |
444 | } | 452 | } |
445 | 453 | ||
@@ -454,14 +462,15 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | |||
454 | enum nl80211_auth_type auth_type, const u8 *bssid, | 462 | enum nl80211_auth_type auth_type, const u8 *bssid, |
455 | const u8 *ssid, int ssid_len, | 463 | const u8 *ssid, int ssid_len, |
456 | const u8 *ie, int ie_len, | 464 | const u8 *ie, int ie_len, |
457 | const u8 *key, int key_len, int key_idx) | 465 | const u8 *key, int key_len, int key_idx, |
466 | bool local_state_change) | ||
458 | { | 467 | { |
459 | int err; | 468 | int err; |
460 | 469 | ||
461 | wdev_lock(dev->ieee80211_ptr); | 470 | wdev_lock(dev->ieee80211_ptr); |
462 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 471 | err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
463 | ssid, ssid_len, ie, ie_len, | 472 | ssid, ssid_len, ie, ie_len, |
464 | key, key_len, key_idx); | 473 | key, key_len, key_idx, local_state_change); |
465 | wdev_unlock(dev->ieee80211_ptr); | 474 | wdev_unlock(dev->ieee80211_ptr); |
466 | 475 | ||
467 | return err; | 476 | return err; |
@@ -555,7 +564,8 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
555 | 564 | ||
556 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 565 | int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
557 | struct net_device *dev, const u8 *bssid, | 566 | struct net_device *dev, const u8 *bssid, |
558 | const u8 *ie, int ie_len, u16 reason) | 567 | const u8 *ie, int ie_len, u16 reason, |
568 | bool local_state_change) | ||
559 | { | 569 | { |
560 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 570 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
561 | struct cfg80211_deauth_request req; | 571 | struct cfg80211_deauth_request req; |
@@ -565,6 +575,7 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
565 | 575 | ||
566 | memset(&req, 0, sizeof(req)); | 576 | memset(&req, 0, sizeof(req)); |
567 | req.reason_code = reason; | 577 | req.reason_code = reason; |
578 | req.local_state_change = local_state_change; | ||
568 | req.ie = ie; | 579 | req.ie = ie; |
569 | req.ie_len = ie_len; | 580 | req.ie_len = ie_len; |
570 | if (wdev->current_bss && | 581 | if (wdev->current_bss && |
@@ -591,13 +602,15 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
591 | 602 | ||
592 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | 603 | int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, |
593 | struct net_device *dev, const u8 *bssid, | 604 | struct net_device *dev, const u8 *bssid, |
594 | const u8 *ie, int ie_len, u16 reason) | 605 | const u8 *ie, int ie_len, u16 reason, |
606 | bool local_state_change) | ||
595 | { | 607 | { |
596 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 608 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
597 | int err; | 609 | int err; |
598 | 610 | ||
599 | wdev_lock(wdev); | 611 | wdev_lock(wdev); |
600 | err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason); | 612 | err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason, |
613 | local_state_change); | ||
601 | wdev_unlock(wdev); | 614 | wdev_unlock(wdev); |
602 | 615 | ||
603 | return err; | 616 | return err; |
@@ -605,7 +618,8 @@ int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
605 | 618 | ||
606 | static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 619 | static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
607 | struct net_device *dev, const u8 *bssid, | 620 | struct net_device *dev, const u8 *bssid, |
608 | const u8 *ie, int ie_len, u16 reason) | 621 | const u8 *ie, int ie_len, u16 reason, |
622 | bool local_state_change) | ||
609 | { | 623 | { |
610 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 624 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
611 | struct cfg80211_disassoc_request req; | 625 | struct cfg80211_disassoc_request req; |
@@ -620,6 +634,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
620 | 634 | ||
621 | memset(&req, 0, sizeof(req)); | 635 | memset(&req, 0, sizeof(req)); |
622 | req.reason_code = reason; | 636 | req.reason_code = reason; |
637 | req.local_state_change = local_state_change; | ||
623 | req.ie = ie; | 638 | req.ie = ie; |
624 | req.ie_len = ie_len; | 639 | req.ie_len = ie_len; |
625 | if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) | 640 | if (memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) |
@@ -632,13 +647,15 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | |||
632 | 647 | ||
633 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, | 648 | int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, |
634 | struct net_device *dev, const u8 *bssid, | 649 | struct net_device *dev, const u8 *bssid, |
635 | const u8 *ie, int ie_len, u16 reason) | 650 | const u8 *ie, int ie_len, u16 reason, |
651 | bool local_state_change) | ||
636 | { | 652 | { |
637 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 653 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
638 | int err; | 654 | int err; |
639 | 655 | ||
640 | wdev_lock(wdev); | 656 | wdev_lock(wdev); |
641 | err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason); | 657 | err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason, |
658 | local_state_change); | ||
642 | wdev_unlock(wdev); | 659 | wdev_unlock(wdev); |
643 | 660 | ||
644 | return err; | 661 | return err; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 596bf189549a..356a84a5daee 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -151,6 +151,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
151 | [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, | 151 | [NL80211_ATTR_FRAME_MATCH] = { .type = NLA_BINARY, }, |
152 | [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, | 152 | [NL80211_ATTR_PS_STATE] = { .type = NLA_U32 }, |
153 | [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, | 153 | [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, |
154 | [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, | ||
154 | }; | 155 | }; |
155 | 156 | ||
156 | /* policy for the attributes */ | 157 | /* policy for the attributes */ |
@@ -2097,7 +2098,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
2097 | goto out_rtnl; | 2098 | goto out_rtnl; |
2098 | 2099 | ||
2099 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | 2100 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && |
2100 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { | 2101 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && |
2102 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) { | ||
2101 | err = -EINVAL; | 2103 | err = -EINVAL; |
2102 | goto out; | 2104 | goto out; |
2103 | } | 2105 | } |
@@ -3393,6 +3395,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3393 | int err, ssid_len, ie_len = 0; | 3395 | int err, ssid_len, ie_len = 0; |
3394 | enum nl80211_auth_type auth_type; | 3396 | enum nl80211_auth_type auth_type; |
3395 | struct key_parse key; | 3397 | struct key_parse key; |
3398 | bool local_state_change; | ||
3396 | 3399 | ||
3397 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3400 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3398 | return -EINVAL; | 3401 | return -EINVAL; |
@@ -3471,9 +3474,12 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
3471 | goto out; | 3474 | goto out; |
3472 | } | 3475 | } |
3473 | 3476 | ||
3477 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; | ||
3478 | |||
3474 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, | 3479 | err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid, |
3475 | ssid, ssid_len, ie, ie_len, | 3480 | ssid, ssid_len, ie, ie_len, |
3476 | key.p.key, key.p.key_len, key.idx); | 3481 | key.p.key, key.p.key_len, key.idx, |
3482 | local_state_change); | ||
3477 | 3483 | ||
3478 | out: | 3484 | out: |
3479 | cfg80211_unlock_rdev(rdev); | 3485 | cfg80211_unlock_rdev(rdev); |
@@ -3650,6 +3656,7 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3650 | const u8 *ie = NULL, *bssid; | 3656 | const u8 *ie = NULL, *bssid; |
3651 | int err, ie_len = 0; | 3657 | int err, ie_len = 0; |
3652 | u16 reason_code; | 3658 | u16 reason_code; |
3659 | bool local_state_change; | ||
3653 | 3660 | ||
3654 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3661 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3655 | return -EINVAL; | 3662 | return -EINVAL; |
@@ -3695,7 +3702,10 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info) | |||
3695 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3702 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3696 | } | 3703 | } |
3697 | 3704 | ||
3698 | err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code); | 3705 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
3706 | |||
3707 | err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code, | ||
3708 | local_state_change); | ||
3699 | 3709 | ||
3700 | out: | 3710 | out: |
3701 | cfg80211_unlock_rdev(rdev); | 3711 | cfg80211_unlock_rdev(rdev); |
@@ -3712,6 +3722,7 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3712 | const u8 *ie = NULL, *bssid; | 3722 | const u8 *ie = NULL, *bssid; |
3713 | int err, ie_len = 0; | 3723 | int err, ie_len = 0; |
3714 | u16 reason_code; | 3724 | u16 reason_code; |
3725 | bool local_state_change; | ||
3715 | 3726 | ||
3716 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | 3727 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) |
3717 | return -EINVAL; | 3728 | return -EINVAL; |
@@ -3757,7 +3768,10 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info) | |||
3757 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 3768 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
3758 | } | 3769 | } |
3759 | 3770 | ||
3760 | err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code); | 3771 | local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE]; |
3772 | |||
3773 | err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code, | ||
3774 | local_state_change); | ||
3761 | 3775 | ||
3762 | out: | 3776 | out: |
3763 | cfg80211_unlock_rdev(rdev); | 3777 | cfg80211_unlock_rdev(rdev); |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 422da20d1e5b..8f0d97dd3109 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -2356,10 +2356,10 @@ static void print_regdomain(const struct ieee80211_regdomain *rd) | |||
2356 | rdev->country_ie_alpha2[1]); | 2356 | rdev->country_ie_alpha2[1]); |
2357 | } else | 2357 | } else |
2358 | printk(KERN_INFO "cfg80211: Current regulatory " | 2358 | printk(KERN_INFO "cfg80211: Current regulatory " |
2359 | "domain intersected: \n"); | 2359 | "domain intersected:\n"); |
2360 | } else | 2360 | } else |
2361 | printk(KERN_INFO "cfg80211: Current regulatory " | 2361 | printk(KERN_INFO "cfg80211: Current regulatory " |
2362 | "domain intersected: \n"); | 2362 | "domain intersected:\n"); |
2363 | } else if (is_world_regdom(rd->alpha2)) | 2363 | } else if (is_world_regdom(rd->alpha2)) |
2364 | printk(KERN_INFO "cfg80211: World regulatory " | 2364 | printk(KERN_INFO "cfg80211: World regulatory " |
2365 | "domain updated:\n"); | 2365 | "domain updated:\n"); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f4dfd5f5f2ea..c2735775ec19 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -171,7 +171,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
171 | params->ssid, params->ssid_len, | 171 | params->ssid, params->ssid_len, |
172 | NULL, 0, | 172 | NULL, 0, |
173 | params->key, params->key_len, | 173 | params->key, params->key_len, |
174 | params->key_idx); | 174 | params->key_idx, false); |
175 | case CFG80211_CONN_ASSOCIATE_NEXT: | 175 | case CFG80211_CONN_ASSOCIATE_NEXT: |
176 | BUG_ON(!rdev->ops->assoc); | 176 | BUG_ON(!rdev->ops->assoc); |
177 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; | 177 | wdev->conn->state = CFG80211_CONN_ASSOCIATING; |
@@ -186,12 +186,13 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev) | |||
186 | if (err) | 186 | if (err) |
187 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 187 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
188 | NULL, 0, | 188 | NULL, 0, |
189 | WLAN_REASON_DEAUTH_LEAVING); | 189 | WLAN_REASON_DEAUTH_LEAVING, |
190 | false); | ||
190 | return err; | 191 | return err; |
191 | case CFG80211_CONN_DEAUTH_ASSOC_FAIL: | 192 | case CFG80211_CONN_DEAUTH_ASSOC_FAIL: |
192 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, | 193 | __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, |
193 | NULL, 0, | 194 | NULL, 0, |
194 | WLAN_REASON_DEAUTH_LEAVING); | 195 | WLAN_REASON_DEAUTH_LEAVING, false); |
195 | /* return an error so that we call __cfg80211_connect_result() */ | 196 | /* return an error so that we call __cfg80211_connect_result() */ |
196 | return -EINVAL; | 197 | return -EINVAL; |
197 | default: | 198 | default: |
@@ -676,7 +677,8 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
676 | continue; | 677 | continue; |
677 | bssid = wdev->auth_bsses[i]->pub.bssid; | 678 | bssid = wdev->auth_bsses[i]->pub.bssid; |
678 | ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, | 679 | ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0, |
679 | WLAN_REASON_DEAUTH_LEAVING); | 680 | WLAN_REASON_DEAUTH_LEAVING, |
681 | false); | ||
680 | WARN(ret, "deauth failed: %d\n", ret); | 682 | WARN(ret, "deauth failed: %d\n", ret); |
681 | } | 683 | } |
682 | } | 684 | } |
@@ -935,7 +937,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
935 | /* wdev->conn->params.bssid must be set if > SCANNING */ | 937 | /* wdev->conn->params.bssid must be set if > SCANNING */ |
936 | err = __cfg80211_mlme_deauth(rdev, dev, | 938 | err = __cfg80211_mlme_deauth(rdev, dev, |
937 | wdev->conn->params.bssid, | 939 | wdev->conn->params.bssid, |
938 | NULL, 0, reason); | 940 | NULL, 0, reason, false); |
939 | if (err) | 941 | if (err) |
940 | return err; | 942 | return err; |
941 | } else { | 943 | } else { |
@@ -991,7 +993,8 @@ void cfg80211_sme_disassoc(struct net_device *dev, int idx) | |||
991 | 993 | ||
992 | memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); | 994 | memcpy(bssid, wdev->auth_bsses[idx]->pub.bssid, ETH_ALEN); |
993 | if (__cfg80211_mlme_deauth(rdev, dev, bssid, | 995 | if (__cfg80211_mlme_deauth(rdev, dev, bssid, |
994 | NULL, 0, WLAN_REASON_DEAUTH_LEAVING)) { | 996 | NULL, 0, WLAN_REASON_DEAUTH_LEAVING, |
997 | false)) { | ||
995 | /* whatever -- assume gone anyway */ | 998 | /* whatever -- assume gone anyway */ |
996 | cfg80211_unhold_bss(wdev->auth_bsses[idx]); | 999 | cfg80211_unhold_bss(wdev->auth_bsses[idx]); |
997 | cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); | 1000 | cfg80211_put_bss(&wdev->auth_bsses[idx]->pub); |
diff --git a/net/wireless/util.c b/net/wireless/util.c index d3574a4eb3ba..3416373a9c0c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -331,11 +331,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
331 | if (iftype == NL80211_IFTYPE_MESH_POINT) { | 331 | if (iftype == NL80211_IFTYPE_MESH_POINT) { |
332 | struct ieee80211s_hdr *meshdr = | 332 | struct ieee80211s_hdr *meshdr = |
333 | (struct ieee80211s_hdr *) (skb->data + hdrlen); | 333 | (struct ieee80211s_hdr *) (skb->data + hdrlen); |
334 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | 334 | /* make sure meshdr->flags is on the linear part */ |
335 | if (!pskb_may_pull(skb, hdrlen + 1)) | ||
336 | return -1; | ||
335 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | 337 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { |
336 | memcpy(dst, meshdr->eaddr1, ETH_ALEN); | 338 | skb_copy_bits(skb, hdrlen + |
337 | memcpy(src, meshdr->eaddr2, ETH_ALEN); | 339 | offsetof(struct ieee80211s_hdr, eaddr1), |
340 | dst, ETH_ALEN); | ||
341 | skb_copy_bits(skb, hdrlen + | ||
342 | offsetof(struct ieee80211s_hdr, eaddr2), | ||
343 | src, ETH_ALEN); | ||
338 | } | 344 | } |
345 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
339 | } | 346 | } |
340 | break; | 347 | break; |
341 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): | 348 | case cpu_to_le16(IEEE80211_FCTL_FROMDS): |
@@ -347,9 +354,14 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
347 | if (iftype == NL80211_IFTYPE_MESH_POINT) { | 354 | if (iftype == NL80211_IFTYPE_MESH_POINT) { |
348 | struct ieee80211s_hdr *meshdr = | 355 | struct ieee80211s_hdr *meshdr = |
349 | (struct ieee80211s_hdr *) (skb->data + hdrlen); | 356 | (struct ieee80211s_hdr *) (skb->data + hdrlen); |
350 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | 357 | /* make sure meshdr->flags is on the linear part */ |
358 | if (!pskb_may_pull(skb, hdrlen + 1)) | ||
359 | return -1; | ||
351 | if (meshdr->flags & MESH_FLAGS_AE_A4) | 360 | if (meshdr->flags & MESH_FLAGS_AE_A4) |
352 | memcpy(src, meshdr->eaddr1, ETH_ALEN); | 361 | skb_copy_bits(skb, hdrlen + |
362 | offsetof(struct ieee80211s_hdr, eaddr1), | ||
363 | src, ETH_ALEN); | ||
364 | hdrlen += ieee80211_get_mesh_hdrlen(meshdr); | ||
353 | } | 365 | } |
354 | break; | 366 | break; |
355 | case cpu_to_le16(0): | 367 | case cpu_to_le16(0): |
@@ -358,7 +370,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
358 | break; | 370 | break; |
359 | } | 371 | } |
360 | 372 | ||
361 | if (unlikely(skb->len - hdrlen < 8)) | 373 | if (!pskb_may_pull(skb, hdrlen + 8)) |
362 | return -1; | 374 | return -1; |
363 | 375 | ||
364 | payload = skb->data + hdrlen; | 376 | payload = skb->data + hdrlen; |