diff options
author | David S. Miller <davem@davemloft.net> | 2009-10-09 17:40:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-09 17:40:09 -0400 |
commit | 8aa0f64ac3835a6daf84d0b0e07c4c01d7d8eddc (patch) | |
tree | e5e6cc8637a44354997624f26d4d55834c9915b4 | |
parent | cd7e1f0b056c071860db65c847a854b3093d6606 (diff) | |
parent | eab2ec83dbf0e32e28f3108f302ffdaa225d4cce (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
141 files changed, 6262 insertions, 4538 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index d7a764a2fc1a..85f8bf4112c1 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -5,6 +5,7 @@ | |||
5 | menuconfig WLAN | 5 | menuconfig WLAN |
6 | bool "Wireless LAN" | 6 | bool "Wireless LAN" |
7 | depends on !S390 | 7 | depends on !S390 |
8 | select WIRELESS | ||
8 | default y | 9 | default y |
9 | ---help--- | 10 | ---help--- |
10 | This section contains all the pre 802.11 and 802.11 wireless | 11 | This section contains all the pre 802.11 and 802.11 wireless |
@@ -67,6 +68,8 @@ config WAVELAN | |||
67 | tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support" | 68 | tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support" |
68 | depends on ISA && WLAN_PRE80211 | 69 | depends on ISA && WLAN_PRE80211 |
69 | select WIRELESS_EXT | 70 | select WIRELESS_EXT |
71 | select WEXT_SPY | ||
72 | select WEXT_PRIV | ||
70 | ---help--- | 73 | ---help--- |
71 | The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is | 74 | The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is |
72 | a Radio LAN (wireless Ethernet-like Local Area Network) using the | 75 | a Radio LAN (wireless Ethernet-like Local Area Network) using the |
@@ -90,6 +93,8 @@ config PCMCIA_WAVELAN | |||
90 | tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support" | 93 | tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support" |
91 | depends on PCMCIA && WLAN_PRE80211 | 94 | depends on PCMCIA && WLAN_PRE80211 |
92 | select WIRELESS_EXT | 95 | select WIRELESS_EXT |
96 | select WEXT_SPY | ||
97 | select WEXT_PRIV | ||
93 | help | 98 | help |
94 | Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA | 99 | Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA |
95 | (PC-card) wireless Ethernet networking card to your computer. This | 100 | (PC-card) wireless Ethernet networking card to your computer. This |
@@ -102,6 +107,7 @@ config PCMCIA_NETWAVE | |||
102 | tristate "Xircom Netwave AirSurfer Pcmcia wireless support" | 107 | tristate "Xircom Netwave AirSurfer Pcmcia wireless support" |
103 | depends on PCMCIA && WLAN_PRE80211 | 108 | depends on PCMCIA && WLAN_PRE80211 |
104 | select WIRELESS_EXT | 109 | select WIRELESS_EXT |
110 | select WEXT_PRIV | ||
105 | help | 111 | help |
106 | Say Y here if you intend to attach this type of PCMCIA (PC-card) | 112 | Say Y here if you intend to attach this type of PCMCIA (PC-card) |
107 | wireless Ethernet networking card to your computer. | 113 | wireless Ethernet networking card to your computer. |
@@ -123,6 +129,8 @@ config PCMCIA_RAYCS | |||
123 | tristate "Aviator/Raytheon 2.4GHz wireless support" | 129 | tristate "Aviator/Raytheon 2.4GHz wireless support" |
124 | depends on PCMCIA && WLAN_80211 | 130 | depends on PCMCIA && WLAN_80211 |
125 | select WIRELESS_EXT | 131 | select WIRELESS_EXT |
132 | select WEXT_SPY | ||
133 | select WEXT_PRIV | ||
126 | ---help--- | 134 | ---help--- |
127 | Say Y here if you intend to attach an Aviator/Raytheon PCMCIA | 135 | Say Y here if you intend to attach an Aviator/Raytheon PCMCIA |
128 | (PC-card) wireless Ethernet networking card to your computer. | 136 | (PC-card) wireless Ethernet networking card to your computer. |
@@ -132,46 +140,6 @@ config PCMCIA_RAYCS | |||
132 | To compile this driver as a module, choose M here: the module will be | 140 | To compile this driver as a module, choose M here: the module will be |
133 | called ray_cs. If unsure, say N. | 141 | called ray_cs. If unsure, say N. |
134 | 142 | ||
135 | config LIBERTAS | ||
136 | tristate "Marvell 8xxx Libertas WLAN driver support" | ||
137 | depends on WLAN_80211 | ||
138 | select WIRELESS_EXT | ||
139 | select LIB80211 | ||
140 | select FW_LOADER | ||
141 | ---help--- | ||
142 | A library for Marvell Libertas 8xxx devices. | ||
143 | |||
144 | config LIBERTAS_USB | ||
145 | tristate "Marvell Libertas 8388 USB 802.11b/g cards" | ||
146 | depends on LIBERTAS && USB | ||
147 | ---help--- | ||
148 | A driver for Marvell Libertas 8388 USB devices. | ||
149 | |||
150 | config LIBERTAS_CS | ||
151 | tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards" | ||
152 | depends on LIBERTAS && PCMCIA | ||
153 | select FW_LOADER | ||
154 | ---help--- | ||
155 | A driver for Marvell Libertas 8385 CompactFlash devices. | ||
156 | |||
157 | config LIBERTAS_SDIO | ||
158 | tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards" | ||
159 | depends on LIBERTAS && MMC | ||
160 | ---help--- | ||
161 | A driver for Marvell Libertas 8385/8686/8688 SDIO devices. | ||
162 | |||
163 | config LIBERTAS_SPI | ||
164 | tristate "Marvell Libertas 8686 SPI 802.11b/g cards" | ||
165 | depends on LIBERTAS && SPI | ||
166 | ---help--- | ||
167 | A driver for Marvell Libertas 8686 SPI devices. | ||
168 | |||
169 | config LIBERTAS_DEBUG | ||
170 | bool "Enable full debugging output in the Libertas module." | ||
171 | depends on LIBERTAS | ||
172 | ---help--- | ||
173 | Debugging support. | ||
174 | |||
175 | config LIBERTAS_THINFIRM | 143 | config LIBERTAS_THINFIRM |
176 | tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware" | 144 | tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware" |
177 | depends on WLAN_80211 && MAC80211 | 145 | depends on WLAN_80211 && MAC80211 |
@@ -190,6 +158,8 @@ config AIRO | |||
190 | depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN) | 158 | depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN) |
191 | select WIRELESS_EXT | 159 | select WIRELESS_EXT |
192 | select CRYPTO | 160 | select CRYPTO |
161 | select WEXT_SPY | ||
162 | select WEXT_PRIV | ||
193 | ---help--- | 163 | ---help--- |
194 | This is the standard Linux driver to support Cisco/Aironet ISA and | 164 | This is the standard Linux driver to support Cisco/Aironet ISA and |
195 | PCI 802.11 wireless cards. | 165 | PCI 802.11 wireless cards. |
@@ -207,6 +177,7 @@ config ATMEL | |||
207 | tristate "Atmel at76c50x chipset 802.11b support" | 177 | tristate "Atmel at76c50x chipset 802.11b support" |
208 | depends on (PCI || PCMCIA) && WLAN_80211 | 178 | depends on (PCI || PCMCIA) && WLAN_80211 |
209 | select WIRELESS_EXT | 179 | select WIRELESS_EXT |
180 | select WEXT_PRIV | ||
210 | select FW_LOADER | 181 | select FW_LOADER |
211 | select CRC32 | 182 | select CRC32 |
212 | ---help--- | 183 | ---help--- |
@@ -266,18 +237,21 @@ config AIRO_CS | |||
266 | Cisco Linux utilities can be used to configure the card. | 237 | Cisco Linux utilities can be used to configure the card. |
267 | 238 | ||
268 | config PCMCIA_WL3501 | 239 | config PCMCIA_WL3501 |
269 | tristate "Planet WL3501 PCMCIA cards" | 240 | tristate "Planet WL3501 PCMCIA cards" |
270 | depends on EXPERIMENTAL && PCMCIA && WLAN_80211 | 241 | depends on EXPERIMENTAL && PCMCIA && WLAN_80211 |
271 | select WIRELESS_EXT | 242 | select WIRELESS_EXT |
272 | ---help--- | 243 | select WEXT_SPY |
273 | A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet. | 244 | help |
274 | It has basic support for Linux wireless extensions and initial | 245 | A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet. |
275 | micro support for ethtool. | 246 | It has basic support for Linux wireless extensions and initial |
247 | micro support for ethtool. | ||
276 | 248 | ||
277 | config PRISM54 | 249 | config PRISM54 |
278 | tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)' | 250 | tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)' |
279 | depends on PCI && EXPERIMENTAL && WLAN_80211 | 251 | depends on PCI && EXPERIMENTAL && WLAN_80211 |
280 | select WIRELESS_EXT | 252 | select WIRELESS_EXT |
253 | select WEXT_SPY | ||
254 | select WEXT_PRIV | ||
281 | select FW_LOADER | 255 | select FW_LOADER |
282 | ---help--- | 256 | ---help--- |
283 | This enables support for FullMAC PCI/Cardbus prism54 devices. This | 257 | This enables support for FullMAC PCI/Cardbus prism54 devices. This |
@@ -300,6 +274,7 @@ config USB_ZD1201 | |||
300 | tristate "USB ZD1201 based Wireless device support" | 274 | tristate "USB ZD1201 based Wireless device support" |
301 | depends on USB && WLAN_80211 | 275 | depends on USB && WLAN_80211 |
302 | select WIRELESS_EXT | 276 | select WIRELESS_EXT |
277 | select WEXT_PRIV | ||
303 | select FW_LOADER | 278 | select FW_LOADER |
304 | ---help--- | 279 | ---help--- |
305 | Say Y if you want to use wireless LAN adapters based on the ZyDAS | 280 | Say Y if you want to use wireless LAN adapters based on the ZyDAS |
@@ -476,17 +451,18 @@ config MWL8K | |||
476 | To compile this driver as a module, choose M here: the module | 451 | To compile this driver as a module, choose M here: the module |
477 | will be called mwl8k. If unsure, say N. | 452 | will be called mwl8k. If unsure, say N. |
478 | 453 | ||
479 | source "drivers/net/wireless/p54/Kconfig" | ||
480 | source "drivers/net/wireless/ath/Kconfig" | 454 | source "drivers/net/wireless/ath/Kconfig" |
481 | source "drivers/net/wireless/ipw2x00/Kconfig" | ||
482 | source "drivers/net/wireless/iwlwifi/Kconfig" | ||
483 | source "drivers/net/wireless/hostap/Kconfig" | ||
484 | source "drivers/net/wireless/b43/Kconfig" | 455 | source "drivers/net/wireless/b43/Kconfig" |
485 | source "drivers/net/wireless/b43legacy/Kconfig" | 456 | source "drivers/net/wireless/b43legacy/Kconfig" |
486 | source "drivers/net/wireless/zd1211rw/Kconfig" | 457 | source "drivers/net/wireless/hostap/Kconfig" |
487 | source "drivers/net/wireless/rt2x00/Kconfig" | 458 | source "drivers/net/wireless/ipw2x00/Kconfig" |
459 | source "drivers/net/wireless/iwlwifi/Kconfig" | ||
460 | source "drivers/net/wireless/iwmc3200wifi/Kconfig" | ||
461 | source "drivers/net/wireless/libertas/Kconfig" | ||
488 | source "drivers/net/wireless/orinoco/Kconfig" | 462 | source "drivers/net/wireless/orinoco/Kconfig" |
463 | source "drivers/net/wireless/p54/Kconfig" | ||
464 | source "drivers/net/wireless/rt2x00/Kconfig" | ||
489 | source "drivers/net/wireless/wl12xx/Kconfig" | 465 | source "drivers/net/wireless/wl12xx/Kconfig" |
490 | source "drivers/net/wireless/iwmc3200wifi/Kconfig" | 466 | source "drivers/net/wireless/zd1211rw/Kconfig" |
491 | 467 | ||
492 | endif # WLAN | 468 | endif # WLAN |
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 8e1a55dec351..e559dc960552 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -2217,6 +2217,8 @@ static struct ieee80211_supported_band at76_supported_band = { | |||
2217 | static int at76_init_new_device(struct at76_priv *priv, | 2217 | static int at76_init_new_device(struct at76_priv *priv, |
2218 | struct usb_interface *interface) | 2218 | struct usb_interface *interface) |
2219 | { | 2219 | { |
2220 | struct wiphy *wiphy; | ||
2221 | size_t len; | ||
2220 | int ret; | 2222 | int ret; |
2221 | 2223 | ||
2222 | /* set up the endpoint information */ | 2224 | /* set up the endpoint information */ |
@@ -2254,6 +2256,7 @@ static int at76_init_new_device(struct at76_priv *priv, | |||
2254 | priv->device_unplugged = 0; | 2256 | priv->device_unplugged = 0; |
2255 | 2257 | ||
2256 | /* mac80211 initialisation */ | 2258 | /* mac80211 initialisation */ |
2259 | wiphy = priv->hw->wiphy; | ||
2257 | priv->hw->wiphy->max_scan_ssids = 1; | 2260 | priv->hw->wiphy->max_scan_ssids = 1; |
2258 | priv->hw->wiphy->max_scan_ie_len = 0; | 2261 | priv->hw->wiphy->max_scan_ie_len = 0; |
2259 | priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 2262 | priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); |
@@ -2265,6 +2268,13 @@ static int at76_init_new_device(struct at76_priv *priv, | |||
2265 | SET_IEEE80211_DEV(priv->hw, &interface->dev); | 2268 | SET_IEEE80211_DEV(priv->hw, &interface->dev); |
2266 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); | 2269 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); |
2267 | 2270 | ||
2271 | len = sizeof(wiphy->fw_version); | ||
2272 | snprintf(wiphy->fw_version, len, "%d.%d.%d-%d", | ||
2273 | priv->fw_version.major, priv->fw_version.minor, | ||
2274 | priv->fw_version.patch, priv->fw_version.build); | ||
2275 | |||
2276 | wiphy->hw_version = priv->board_type; | ||
2277 | |||
2268 | ret = ieee80211_register_hw(priv->hw); | 2278 | ret = ieee80211_register_hw(priv->hw); |
2269 | if (ret) { | 2279 | if (ret) { |
2270 | printk(KERN_ERR "cannot register mac80211 hw (status %d)!\n", | 2280 | printk(KERN_ERR "cannot register mac80211 hw (status %d)!\n", |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 11ded150b932..6ce86cb37654 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -16,7 +16,15 @@ menuconfig ATH_COMMON | |||
16 | http://wireless.kernel.org/en/users/Drivers/Atheros | 16 | http://wireless.kernel.org/en/users/Drivers/Atheros |
17 | 17 | ||
18 | if ATH_COMMON | 18 | if ATH_COMMON |
19 | |||
20 | config ATH_DEBUG | ||
21 | bool "Atheros wireless debugging" | ||
22 | ---help--- | ||
23 | Say Y, if you want to debug atheros wireless drivers. | ||
24 | Right now only ath9k makes use of this. | ||
25 | |||
19 | source "drivers/net/wireless/ath/ath5k/Kconfig" | 26 | source "drivers/net/wireless/ath/ath5k/Kconfig" |
20 | source "drivers/net/wireless/ath/ath9k/Kconfig" | 27 | source "drivers/net/wireless/ath/ath9k/Kconfig" |
21 | source "drivers/net/wireless/ath/ar9170/Kconfig" | 28 | source "drivers/net/wireless/ath/ar9170/Kconfig" |
29 | |||
22 | endif | 30 | endif |
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 4bb0132ada37..8113a5042afa 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile | |||
@@ -1,6 +1,11 @@ | |||
1 | obj-$(CONFIG_ATH5K) += ath5k/ | 1 | obj-$(CONFIG_ATH5K) += ath5k/ |
2 | obj-$(CONFIG_ATH9K) += ath9k/ | 2 | obj-$(CONFIG_ATH9K_HW) += ath9k/ |
3 | obj-$(CONFIG_AR9170_USB) += ar9170/ | 3 | obj-$(CONFIG_AR9170_USB) += ar9170/ |
4 | 4 | ||
5 | obj-$(CONFIG_ATH_COMMON) += ath.o | 5 | obj-$(CONFIG_ATH_COMMON) += ath.o |
6 | ath-objs := main.o regd.o | 6 | |
7 | ath-objs := main.o \ | ||
8 | regd.o \ | ||
9 | hw.o | ||
10 | |||
11 | ath-$(CONFIG_ATH_DEBUG) += debug.o | ||
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 914e4718a9a8..ec034af26980 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -172,8 +172,6 @@ struct ar9170 { | |||
172 | 172 | ||
173 | /* interface mode settings */ | 173 | /* interface mode settings */ |
174 | struct ieee80211_vif *vif; | 174 | struct ieee80211_vif *vif; |
175 | u8 mac_addr[ETH_ALEN]; | ||
176 | u8 bssid[ETH_ALEN]; | ||
177 | 175 | ||
178 | /* beaconing */ | 176 | /* beaconing */ |
179 | struct sk_buff *beacon; | 177 | struct sk_buff *beacon; |
@@ -204,6 +202,8 @@ struct ar9170 { | |||
204 | u8 power_2G_ht20[8]; | 202 | u8 power_2G_ht20[8]; |
205 | u8 power_2G_ht40[8]; | 203 | u8 power_2G_ht40[8]; |
206 | 204 | ||
205 | u8 phy_heavy_clip; | ||
206 | |||
207 | #ifdef CONFIG_AR9170_LEDS | 207 | #ifdef CONFIG_AR9170_LEDS |
208 | struct delayed_work led_work; | 208 | struct delayed_work led_work; |
209 | struct ar9170_led leds[AR9170_NUM_LEDS]; | 209 | struct ar9170_led leds[AR9170_NUM_LEDS]; |
diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c index f57a6200167b..cf6f5c4174a6 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.c +++ b/drivers/net/wireless/ath/ar9170/cmd.c | |||
@@ -72,8 +72,7 @@ int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) | |||
72 | return err; | 72 | return err; |
73 | } | 73 | } |
74 | 74 | ||
75 | static int ar9170_read_mreg(struct ar9170 *ar, int nregs, | 75 | int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out) |
76 | const u32 *regs, u32 *out) | ||
77 | { | 76 | { |
78 | int i, err; | 77 | int i, err; |
79 | __le32 *offs, *res; | 78 | __le32 *offs, *res; |
diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h index a4f0e50e52b4..826c45e6b274 100644 --- a/drivers/net/wireless/ath/ar9170/cmd.h +++ b/drivers/net/wireless/ath/ar9170/cmd.h | |||
@@ -44,6 +44,7 @@ | |||
44 | int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); | 44 | int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); |
45 | int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); | 45 | int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); |
46 | int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); | 46 | int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); |
47 | int ar9170_read_mreg(struct ar9170 *ar, int nregs, const u32 *regs, u32 *out); | ||
47 | int ar9170_echo_test(struct ar9170 *ar, u32 v); | 48 | int ar9170_echo_test(struct ar9170 *ar, u32 v); |
48 | 49 | ||
49 | /* | 50 | /* |
diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h index 6cbfb2f83391..88113148331c 100644 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ b/drivers/net/wireless/ath/ar9170/hw.h | |||
@@ -311,6 +311,8 @@ struct ar9170_tx_control { | |||
311 | 311 | ||
312 | #define AR9170_TX_PHY_SHORT_GI 0x80000000 | 312 | #define AR9170_TX_PHY_SHORT_GI 0x80000000 |
313 | 313 | ||
314 | #define AR5416_MAX_RATE_POWER 63 | ||
315 | |||
314 | struct ar9170_rx_head { | 316 | struct ar9170_rx_head { |
315 | u8 plcp[12]; | 317 | u8 plcp[12]; |
316 | } __packed; | 318 | } __packed; |
diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index 614e3218a2bc..ddc8c09dc79e 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c | |||
@@ -35,6 +35,9 @@ | |||
35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | 35 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 36 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
37 | */ | 37 | */ |
38 | |||
39 | #include <asm/unaligned.h> | ||
40 | |||
38 | #include "ar9170.h" | 41 | #include "ar9170.h" |
39 | #include "cmd.h" | 42 | #include "cmd.h" |
40 | 43 | ||
@@ -227,11 +230,8 @@ static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) | |||
227 | 230 | ||
228 | ar9170_regwrite_begin(ar); | 231 | ar9170_regwrite_begin(ar); |
229 | 232 | ||
230 | ar9170_regwrite(reg, | 233 | ar9170_regwrite(reg, get_unaligned_le32(mac)); |
231 | (mac[3] << 24) | (mac[2] << 16) | | 234 | ar9170_regwrite(reg + 4, get_unaligned_le16(mac + 4)); |
232 | (mac[1] << 8) | mac[0]); | ||
233 | |||
234 | ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]); | ||
235 | 235 | ||
236 | ar9170_regwrite_finish(); | 236 | ar9170_regwrite_finish(); |
237 | 237 | ||
@@ -311,13 +311,14 @@ static int ar9170_set_promiscouous(struct ar9170 *ar) | |||
311 | 311 | ||
312 | int ar9170_set_operating_mode(struct ar9170 *ar) | 312 | int ar9170_set_operating_mode(struct ar9170 *ar) |
313 | { | 313 | { |
314 | struct ath_common *common = &ar->common; | ||
314 | u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; | 315 | u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; |
315 | u8 *mac_addr, *bssid; | 316 | u8 *mac_addr, *bssid; |
316 | int err; | 317 | int err; |
317 | 318 | ||
318 | if (ar->vif) { | 319 | if (ar->vif) { |
319 | mac_addr = ar->mac_addr; | 320 | mac_addr = common->macaddr; |
320 | bssid = ar->bssid; | 321 | bssid = common->curbssid; |
321 | 322 | ||
322 | switch (ar->vif->type) { | 323 | switch (ar->vif->type) { |
323 | case NL80211_IFTYPE_MESH_POINT: | 324 | case NL80211_IFTYPE_MESH_POINT: |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index c1f8c69db165..de0ba2bf7691 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -1952,6 +1952,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, | |||
1952 | struct ieee80211_if_init_conf *conf) | 1952 | struct ieee80211_if_init_conf *conf) |
1953 | { | 1953 | { |
1954 | struct ar9170 *ar = hw->priv; | 1954 | struct ar9170 *ar = hw->priv; |
1955 | struct ath_common *common = &ar->common; | ||
1955 | int err = 0; | 1956 | int err = 0; |
1956 | 1957 | ||
1957 | mutex_lock(&ar->mutex); | 1958 | mutex_lock(&ar->mutex); |
@@ -1962,7 +1963,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, | |||
1962 | } | 1963 | } |
1963 | 1964 | ||
1964 | ar->vif = conf->vif; | 1965 | ar->vif = conf->vif; |
1965 | memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN); | 1966 | memcpy(common->macaddr, conf->mac_addr, ETH_ALEN); |
1966 | 1967 | ||
1967 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { | 1968 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { |
1968 | ar->rx_software_decryption = true; | 1969 | ar->rx_software_decryption = true; |
@@ -2131,12 +2132,13 @@ static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2131 | u32 changed) | 2132 | u32 changed) |
2132 | { | 2133 | { |
2133 | struct ar9170 *ar = hw->priv; | 2134 | struct ar9170 *ar = hw->priv; |
2135 | struct ath_common *common = &ar->common; | ||
2134 | int err = 0; | 2136 | int err = 0; |
2135 | 2137 | ||
2136 | mutex_lock(&ar->mutex); | 2138 | mutex_lock(&ar->mutex); |
2137 | 2139 | ||
2138 | if (changed & BSS_CHANGED_BSSID) { | 2140 | if (changed & BSS_CHANGED_BSSID) { |
2139 | memcpy(ar->bssid, bss_conf->bssid, ETH_ALEN); | 2141 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
2140 | err = ar9170_set_operating_mode(ar); | 2142 | err = ar9170_set_operating_mode(ar); |
2141 | if (err) | 2143 | if (err) |
2142 | goto out; | 2144 | goto out; |
@@ -2190,22 +2192,30 @@ static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) | |||
2190 | { | 2192 | { |
2191 | struct ar9170 *ar = hw->priv; | 2193 | struct ar9170 *ar = hw->priv; |
2192 | int err; | 2194 | int err; |
2193 | u32 tsf_low; | ||
2194 | u32 tsf_high; | ||
2195 | u64 tsf; | 2195 | u64 tsf; |
2196 | #define NR 3 | ||
2197 | static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H, | ||
2198 | AR9170_MAC_REG_TSF_L, | ||
2199 | AR9170_MAC_REG_TSF_H }; | ||
2200 | u32 val[NR]; | ||
2201 | int loops = 0; | ||
2196 | 2202 | ||
2197 | mutex_lock(&ar->mutex); | 2203 | mutex_lock(&ar->mutex); |
2198 | err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low); | 2204 | |
2199 | if (!err) | 2205 | while (loops++ < 10) { |
2200 | err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high); | 2206 | err = ar9170_read_mreg(ar, NR, addr, val); |
2207 | if (err || val[0] == val[2]) | ||
2208 | break; | ||
2209 | } | ||
2210 | |||
2201 | mutex_unlock(&ar->mutex); | 2211 | mutex_unlock(&ar->mutex); |
2202 | 2212 | ||
2203 | if (WARN_ON(err)) | 2213 | if (WARN_ON(err)) |
2204 | return 0; | 2214 | return 0; |
2205 | 2215 | tsf = val[0]; | |
2206 | tsf = tsf_high; | 2216 | tsf = (tsf << 32) | val[1]; |
2207 | tsf = (tsf << 32) | tsf_low; | ||
2208 | return tsf; | 2217 | return tsf; |
2218 | #undef NR | ||
2209 | } | 2219 | } |
2210 | 2220 | ||
2211 | static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 2221 | static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c index dbd488da18b1..45a415ea809a 100644 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ b/drivers/net/wireless/ath/ar9170/phy.c | |||
@@ -1239,9 +1239,6 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar, | |||
1239 | struct ar9170_calctl_edges edges[], | 1239 | struct ar9170_calctl_edges edges[], |
1240 | u32 freq) | 1240 | u32 freq) |
1241 | { | 1241 | { |
1242 | /* TODO: move somewhere else */ | ||
1243 | #define AR5416_MAX_RATE_POWER 63 | ||
1244 | |||
1245 | int i; | 1242 | int i; |
1246 | u8 rc = AR5416_MAX_RATE_POWER; | 1243 | u8 rc = AR5416_MAX_RATE_POWER; |
1247 | u8 f; | 1244 | u8 f; |
@@ -1259,10 +1256,11 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar, | |||
1259 | break; | 1256 | break; |
1260 | } | 1257 | } |
1261 | if (i > 0 && f < edges[i].channel) { | 1258 | if (i > 0 && f < edges[i].channel) { |
1262 | if (f > edges[i-1].channel && | 1259 | if (f > edges[i - 1].channel && |
1263 | edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { | 1260 | edges[i - 1].power_flags & |
1261 | AR9170_CALCTL_EDGE_FLAGS) { | ||
1264 | /* lower channel has the inband flag set */ | 1262 | /* lower channel has the inband flag set */ |
1265 | rc = edges[i-1].power_flags & | 1263 | rc = edges[i - 1].power_flags & |
1266 | ~AR9170_CALCTL_EDGE_FLAGS; | 1264 | ~AR9170_CALCTL_EDGE_FLAGS; |
1267 | } | 1265 | } |
1268 | break; | 1266 | break; |
@@ -1270,18 +1268,48 @@ static u8 ar9170_get_max_edge_power(struct ar9170 *ar, | |||
1270 | } | 1268 | } |
1271 | 1269 | ||
1272 | if (i == AR5416_NUM_BAND_EDGES) { | 1270 | if (i == AR5416_NUM_BAND_EDGES) { |
1273 | if (f > edges[i-1].channel && | 1271 | if (f > edges[i - 1].channel && |
1274 | edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { | 1272 | edges[i - 1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { |
1275 | /* lower channel has the inband flag set */ | 1273 | /* lower channel has the inband flag set */ |
1276 | rc = edges[i-1].power_flags & | 1274 | rc = edges[i - 1].power_flags & |
1277 | ~AR9170_CALCTL_EDGE_FLAGS; | 1275 | ~AR9170_CALCTL_EDGE_FLAGS; |
1278 | } | 1276 | } |
1279 | } | 1277 | } |
1280 | return rc; | 1278 | return rc; |
1281 | } | 1279 | } |
1282 | 1280 | ||
1283 | /* calculate the conformance test limits and apply them to ar->power* | 1281 | static u8 ar9170_get_heavy_clip(struct ar9170 *ar, |
1284 | * (derived from otus hal/hpmain.c, line 3706 ff.) | 1282 | struct ar9170_calctl_edges edges[], |
1283 | u32 freq, enum ar9170_bw bw) | ||
1284 | { | ||
1285 | u8 f; | ||
1286 | int i; | ||
1287 | u8 rc = 0; | ||
1288 | |||
1289 | if (freq < 3000) | ||
1290 | f = freq - 2300; | ||
1291 | else | ||
1292 | f = (freq - 4800) / 5; | ||
1293 | |||
1294 | if (bw == AR9170_BW_40_BELOW || bw == AR9170_BW_40_ABOVE) | ||
1295 | rc |= 0xf0; | ||
1296 | |||
1297 | for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { | ||
1298 | if (edges[i].channel == 0xff) | ||
1299 | break; | ||
1300 | if (f == edges[i].channel) { | ||
1301 | if (!(edges[i].power_flags & AR9170_CALCTL_EDGE_FLAGS)) | ||
1302 | rc |= 0x0f; | ||
1303 | break; | ||
1304 | } | ||
1305 | } | ||
1306 | |||
1307 | return rc; | ||
1308 | } | ||
1309 | |||
1310 | /* | ||
1311 | * calculate the conformance test limits and the heavy clip parameter | ||
1312 | * and apply them to ar->power* (derived from otus hal/hpmain.c, line 3706) | ||
1285 | */ | 1313 | */ |
1286 | static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | 1314 | static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) |
1287 | { | 1315 | { |
@@ -1295,7 +1323,8 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1295 | int pwr_cal_len; | 1323 | int pwr_cal_len; |
1296 | } *modes; | 1324 | } *modes; |
1297 | 1325 | ||
1298 | /* order is relevant in the mode_list_*: we fall back to the | 1326 | /* |
1327 | * order is relevant in the mode_list_*: we fall back to the | ||
1299 | * lower indices if any mode is missed in the EEPROM. | 1328 | * lower indices if any mode is missed in the EEPROM. |
1300 | */ | 1329 | */ |
1301 | struct ctl_modes mode_list_2ghz[] = { | 1330 | struct ctl_modes mode_list_2ghz[] = { |
@@ -1313,7 +1342,10 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1313 | 1342 | ||
1314 | #define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) | 1343 | #define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) |
1315 | 1344 | ||
1316 | /* TODO: investigate the differences between OTUS' | 1345 | ar->phy_heavy_clip = 0; |
1346 | |||
1347 | /* | ||
1348 | * TODO: investigate the differences between OTUS' | ||
1317 | * hpreg.c::zfHpGetRegulatoryDomain() and | 1349 | * hpreg.c::zfHpGetRegulatoryDomain() and |
1318 | * ath/regd.c::ath_regd_get_band_ctl() - | 1350 | * ath/regd.c::ath_regd_get_band_ctl() - |
1319 | * e.g. for FCC3_WORLD the OTUS procedure | 1351 | * e.g. for FCC3_WORLD the OTUS procedure |
@@ -1347,6 +1379,15 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1347 | if (ctl_idx < AR5416_NUM_CTLS) { | 1379 | if (ctl_idx < AR5416_NUM_CTLS) { |
1348 | int f_off = 0; | 1380 | int f_off = 0; |
1349 | 1381 | ||
1382 | /* determine heav clip parameter from | ||
1383 | the 11G edges array */ | ||
1384 | if (modes[i].ctl_mode == CTL_11G) { | ||
1385 | ar->phy_heavy_clip = | ||
1386 | ar9170_get_heavy_clip(ar, | ||
1387 | EDGES(ctl_idx, 1), | ||
1388 | freq, bw); | ||
1389 | } | ||
1390 | |||
1350 | /* adjust freq for 40MHz */ | 1391 | /* adjust freq for 40MHz */ |
1351 | if (modes[i].ctl_mode == CTL_2GHT40 || | 1392 | if (modes[i].ctl_mode == CTL_2GHT40 || |
1352 | modes[i].ctl_mode == CTL_5GHT40) { | 1393 | modes[i].ctl_mode == CTL_5GHT40) { |
@@ -1360,13 +1401,15 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1360 | ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1), | 1401 | ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1), |
1361 | freq+f_off); | 1402 | freq+f_off); |
1362 | 1403 | ||
1363 | /* TODO: check if the regulatory max. power is | 1404 | /* |
1405 | * TODO: check if the regulatory max. power is | ||
1364 | * controlled by cfg80211 for DFS | 1406 | * controlled by cfg80211 for DFS |
1365 | * (hpmain applies it to max_power itself for DFS freq) | 1407 | * (hpmain applies it to max_power itself for DFS freq) |
1366 | */ | 1408 | */ |
1367 | 1409 | ||
1368 | } else { | 1410 | } else { |
1369 | /* Workaround in otus driver, hpmain.c, line 3906: | 1411 | /* |
1412 | * Workaround in otus driver, hpmain.c, line 3906: | ||
1370 | * if no data for 5GHT20 are found, take the | 1413 | * if no data for 5GHT20 are found, take the |
1371 | * legacy 5G value. | 1414 | * legacy 5G value. |
1372 | * We extend this here to fallback from any other *HT or | 1415 | * We extend this here to fallback from any other *HT or |
@@ -1390,6 +1433,19 @@ static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1390 | modes[i].max_power); | 1433 | modes[i].max_power); |
1391 | } | 1434 | } |
1392 | } | 1435 | } |
1436 | |||
1437 | if (ar->phy_heavy_clip & 0xf0) { | ||
1438 | ar->power_2G_ht40[0]--; | ||
1439 | ar->power_2G_ht40[1]--; | ||
1440 | ar->power_2G_ht40[2]--; | ||
1441 | } | ||
1442 | if (ar->phy_heavy_clip & 0xf) { | ||
1443 | ar->power_2G_ht20[0]++; | ||
1444 | ar->power_2G_ht20[1]++; | ||
1445 | ar->power_2G_ht20[2]++; | ||
1446 | } | ||
1447 | |||
1448 | |||
1393 | #undef EDGES | 1449 | #undef EDGES |
1394 | } | 1450 | } |
1395 | 1451 | ||
@@ -1499,8 +1555,6 @@ static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) | |||
1499 | /* calc. conformance test limits and apply to ar->power*[] */ | 1555 | /* calc. conformance test limits and apply to ar->power*[] */ |
1500 | ar9170_calc_ctl(ar, freq, bw); | 1556 | ar9170_calc_ctl(ar, freq, bw); |
1501 | 1557 | ||
1502 | /* TODO: (heavy clip) regulatory domain power level fine-tuning. */ | ||
1503 | |||
1504 | /* set ACK/CTS TX power */ | 1558 | /* set ACK/CTS TX power */ |
1505 | ar9170_regwrite_begin(ar); | 1559 | ar9170_regwrite_begin(ar); |
1506 | 1560 | ||
@@ -1643,6 +1697,17 @@ int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, | |||
1643 | if (err) | 1697 | if (err) |
1644 | return err; | 1698 | return err; |
1645 | 1699 | ||
1700 | if (ar->phy_heavy_clip) { | ||
1701 | err = ar9170_write_reg(ar, 0x1c59e0, | ||
1702 | 0x200 | ar->phy_heavy_clip); | ||
1703 | if (err) { | ||
1704 | if (ar9170_nag_limiter(ar)) | ||
1705 | printk(KERN_ERR "%s: failed to set " | ||
1706 | "heavy clip\n", | ||
1707 | wiphy_name(ar->hw->wiphy)); | ||
1708 | } | ||
1709 | } | ||
1710 | |||
1646 | for (i = 0; i < 2; i++) { | 1711 | for (i = 0; i < 2; i++) { |
1647 | ar->noise[i] = ar9170_calc_noise_dbm( | 1712 | ar->noise[i] = ar9170_calc_noise_dbm( |
1648 | (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); | 1713 | (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index a63e90cbf9e5..5e19a7330d39 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -18,6 +18,15 @@ | |||
18 | #define ATH_H | 18 | #define ATH_H |
19 | 19 | ||
20 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
21 | #include <linux/if_ether.h> | ||
22 | #include <net/mac80211.h> | ||
23 | |||
24 | static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
25 | |||
26 | enum ath_device_state { | ||
27 | ATH_HW_UNAVAILABLE, | ||
28 | ATH_HW_INITIALIZED, | ||
29 | }; | ||
21 | 30 | ||
22 | struct reg_dmn_pair_mapping { | 31 | struct reg_dmn_pair_mapping { |
23 | u16 regDmnEnum; | 32 | u16 regDmnEnum; |
@@ -36,13 +45,45 @@ struct ath_regulatory { | |||
36 | struct reg_dmn_pair_mapping *regpair; | 45 | struct reg_dmn_pair_mapping *regpair; |
37 | }; | 46 | }; |
38 | 47 | ||
48 | struct ath_ops { | ||
49 | unsigned int (*read)(void *, u32 reg_offset); | ||
50 | void (*write)(void *, u32 val, u32 reg_offset); | ||
51 | }; | ||
52 | |||
53 | struct ath_common; | ||
54 | |||
55 | struct ath_bus_ops { | ||
56 | void (*read_cachesize)(struct ath_common *common, int *csz); | ||
57 | void (*cleanup)(struct ath_common *common); | ||
58 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); | ||
59 | void (*bt_coex_prep)(struct ath_common *common); | ||
60 | }; | ||
61 | |||
39 | struct ath_common { | 62 | struct ath_common { |
63 | void *ah; | ||
64 | void *priv; | ||
65 | struct ieee80211_hw *hw; | ||
66 | int debug_mask; | ||
67 | enum ath_device_state state; | ||
68 | |||
40 | u16 cachelsz; | 69 | u16 cachelsz; |
70 | u16 curaid; | ||
71 | u8 macaddr[ETH_ALEN]; | ||
72 | u8 curbssid[ETH_ALEN]; | ||
73 | u8 bssidmask[ETH_ALEN]; | ||
74 | |||
75 | u8 tx_chainmask; | ||
76 | u8 rx_chainmask; | ||
77 | |||
41 | struct ath_regulatory regulatory; | 78 | struct ath_regulatory regulatory; |
79 | const struct ath_ops *ops; | ||
80 | const struct ath_bus_ops *bus_ops; | ||
42 | }; | 81 | }; |
43 | 82 | ||
44 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, | 83 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, |
45 | u32 len, | 84 | u32 len, |
46 | gfp_t gfp_mask); | 85 | gfp_t gfp_mask); |
47 | 86 | ||
87 | void ath_hw_setbssidmask(struct ath_common *common); | ||
88 | |||
48 | #endif /* ATH_H */ | 89 | #endif /* ATH_H */ |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 6cd5efcec417..647d826bf5fb 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -35,6 +35,7 @@ | |||
35 | * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities) | 35 | * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities) |
36 | * and clean up common bits, then introduce set/get functions in eeprom.c */ | 36 | * and clean up common bits, then introduce set/get functions in eeprom.c */ |
37 | #include "eeprom.h" | 37 | #include "eeprom.h" |
38 | #include "../ath.h" | ||
38 | 39 | ||
39 | /* PCI IDs */ | 40 | /* PCI IDs */ |
40 | #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ | 41 | #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ |
@@ -165,13 +166,6 @@ | |||
165 | #define AR5K_INI_VAL_XR 0 | 166 | #define AR5K_INI_VAL_XR 0 |
166 | #define AR5K_INI_VAL_MAX 5 | 167 | #define AR5K_INI_VAL_MAX 5 |
167 | 168 | ||
168 | /* Used for BSSID etc manipulation */ | ||
169 | #define AR5K_LOW_ID(_a)( \ | ||
170 | (_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \ | ||
171 | ) | ||
172 | |||
173 | #define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8) | ||
174 | |||
175 | /* | 169 | /* |
176 | * Some tuneable values (these should be changeable by the user) | 170 | * Some tuneable values (these should be changeable by the user) |
177 | * TODO: Make use of them and add more options OR use debug/configfs | 171 | * TODO: Make use of them and add more options OR use debug/configfs |
@@ -1027,6 +1021,7 @@ struct ath5k_capabilities { | |||
1027 | /* TODO: Clean up and merge with ath5k_softc */ | 1021 | /* TODO: Clean up and merge with ath5k_softc */ |
1028 | struct ath5k_hw { | 1022 | struct ath5k_hw { |
1029 | u32 ah_magic; | 1023 | u32 ah_magic; |
1024 | struct ath_common common; | ||
1030 | 1025 | ||
1031 | struct ath5k_softc *ah_sc; | 1026 | struct ath5k_softc *ah_sc; |
1032 | void __iomem *ah_iobase; | 1027 | void __iomem *ah_iobase; |
@@ -1067,14 +1062,6 @@ struct ath5k_hw { | |||
1067 | u8 ah_def_ant; | 1062 | u8 ah_def_ant; |
1068 | bool ah_software_retry; | 1063 | bool ah_software_retry; |
1069 | 1064 | ||
1070 | u8 ah_sta_id[ETH_ALEN]; | ||
1071 | |||
1072 | /* Current BSSID we are trying to assoc to / create. | ||
1073 | * This is passed by mac80211 on config_interface() and cached here for | ||
1074 | * use in resets */ | ||
1075 | u8 ah_bssid[ETH_ALEN]; | ||
1076 | u8 ah_bssid_mask[ETH_ALEN]; | ||
1077 | |||
1078 | int ah_gpio_npins; | 1065 | int ah_gpio_npins; |
1079 | 1066 | ||
1080 | struct ath5k_capabilities ah_capabilities; | 1067 | struct ath5k_capabilities ah_capabilities; |
@@ -1160,7 +1147,7 @@ struct ath5k_hw { | |||
1160 | */ | 1147 | */ |
1161 | 1148 | ||
1162 | /* Attach/Detach Functions */ | 1149 | /* Attach/Detach Functions */ |
1163 | extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc); | 1150 | extern int ath5k_hw_attach(struct ath5k_softc *sc); |
1164 | extern void ath5k_hw_detach(struct ath5k_hw *ah); | 1151 | extern void ath5k_hw_detach(struct ath5k_hw *ah); |
1165 | 1152 | ||
1166 | /* LED functions */ | 1153 | /* LED functions */ |
@@ -1203,10 +1190,9 @@ extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); | |||
1203 | /* Protocol Control Unit Functions */ | 1190 | /* Protocol Control Unit Functions */ |
1204 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); | 1191 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); |
1205 | /* BSSID Functions */ | 1192 | /* BSSID Functions */ |
1206 | extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac); | ||
1207 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1193 | extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1208 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id); | 1194 | extern void ath5k_hw_set_associd(struct ath5k_hw *ah); |
1209 | extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | 1195 | extern void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
1210 | /* Receive start/stop functions */ | 1196 | /* Receive start/stop functions */ |
1211 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | 1197 | extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); |
1212 | extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | 1198 | extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); |
@@ -1329,17 +1315,21 @@ static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) | |||
1329 | return turbo ? (clock / 80) : (clock / 40); | 1315 | return turbo ? (clock / 80) : (clock / 40); |
1330 | } | 1316 | } |
1331 | 1317 | ||
1332 | /* | 1318 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) |
1333 | * Read from a register | 1319 | { |
1334 | */ | 1320 | return &ah->common; |
1321 | } | ||
1322 | |||
1323 | static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) | ||
1324 | { | ||
1325 | return &(ath5k_hw_common(ah)->regulatory); | ||
1326 | } | ||
1327 | |||
1335 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) | 1328 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) |
1336 | { | 1329 | { |
1337 | return ioread32(ah->ah_iobase + reg); | 1330 | return ioread32(ah->ah_iobase + reg); |
1338 | } | 1331 | } |
1339 | 1332 | ||
1340 | /* | ||
1341 | * Write to a register | ||
1342 | */ | ||
1343 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) | 1333 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) |
1344 | { | 1334 | { |
1345 | iowrite32(val, ah->ah_iobase + reg); | 1335 | iowrite32(val, ah->ah_iobase + reg); |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 71a1bd254517..92995adeb5cd 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -101,25 +101,15 @@ static int ath5k_hw_post(struct ath5k_hw *ah) | |||
101 | * -ENODEV if the device is not supported or prints an error msg if something | 101 | * -ENODEV if the device is not supported or prints an error msg if something |
102 | * else went wrong. | 102 | * else went wrong. |
103 | */ | 103 | */ |
104 | struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | 104 | int ath5k_hw_attach(struct ath5k_softc *sc) |
105 | { | 105 | { |
106 | struct ath5k_hw *ah; | 106 | struct ath5k_hw *ah = sc->ah; |
107 | struct ath_common *common = ath5k_hw_common(ah); | ||
107 | struct pci_dev *pdev = sc->pdev; | 108 | struct pci_dev *pdev = sc->pdev; |
108 | struct ath5k_eeprom_info *ee; | 109 | struct ath5k_eeprom_info *ee; |
109 | int ret; | 110 | int ret; |
110 | u32 srev; | 111 | u32 srev; |
111 | 112 | ||
112 | /*If we passed the test malloc a ath5k_hw struct*/ | ||
113 | ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | ||
114 | if (ah == NULL) { | ||
115 | ret = -ENOMEM; | ||
116 | ATH5K_ERR(sc, "out of memory\n"); | ||
117 | goto err; | ||
118 | } | ||
119 | |||
120 | ah->ah_sc = sc; | ||
121 | ah->ah_iobase = sc->iobase; | ||
122 | |||
123 | /* | 113 | /* |
124 | * HW information | 114 | * HW information |
125 | */ | 115 | */ |
@@ -278,12 +268,12 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
278 | goto err_free; | 268 | goto err_free; |
279 | } | 269 | } |
280 | 270 | ||
271 | ee = &ah->ah_capabilities.cap_eeprom; | ||
272 | |||
281 | /* | 273 | /* |
282 | * Write PCI-E power save settings | 274 | * Write PCI-E power save settings |
283 | */ | 275 | */ |
284 | if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { | 276 | if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { |
285 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
286 | |||
287 | ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); | 277 | ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); |
288 | ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); | 278 | ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); |
289 | 279 | ||
@@ -321,7 +311,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
321 | } | 311 | } |
322 | 312 | ||
323 | /* Crypto settings */ | 313 | /* Crypto settings */ |
324 | ee = &ah->ah_capabilities.cap_eeprom; | ||
325 | ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && | 314 | ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && |
326 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && | 315 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && |
327 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); | 316 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); |
@@ -336,8 +325,8 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
336 | ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); | 325 | ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); |
337 | 326 | ||
338 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 327 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
339 | memset(ah->ah_bssid, 0xff, ETH_ALEN); | 328 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); |
340 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | 329 | ath5k_hw_set_associd(ah); |
341 | ath5k_hw_set_opmode(ah); | 330 | ath5k_hw_set_opmode(ah); |
342 | 331 | ||
343 | ath5k_hw_rfgain_opt_init(ah); | 332 | ath5k_hw_rfgain_opt_init(ah); |
@@ -345,11 +334,10 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) | |||
345 | /* turn on HW LEDs */ | 334 | /* turn on HW LEDs */ |
346 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); | 335 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); |
347 | 336 | ||
348 | return ah; | 337 | return 0; |
349 | err_free: | 338 | err_free: |
350 | kfree(ah); | 339 | kfree(ah); |
351 | err: | 340 | return ret; |
352 | return ERR_PTR(ret); | ||
353 | } | 341 | } |
354 | 342 | ||
355 | /** | 343 | /** |
@@ -369,5 +357,4 @@ void ath5k_hw_detach(struct ath5k_hw *ah) | |||
369 | ath5k_eeprom_detach(ah); | 357 | ath5k_eeprom_detach(ah); |
370 | 358 | ||
371 | /* assume interrupts are down */ | 359 | /* assume interrupts are down */ |
372 | kfree(ah); | ||
373 | } | 360 | } |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 9c6ab5378f6e..07c1e52b5a0c 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -195,12 +195,13 @@ static int __devinit ath5k_pci_probe(struct pci_dev *pdev, | |||
195 | const struct pci_device_id *id); | 195 | const struct pci_device_id *id); |
196 | static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | 196 | static void __devexit ath5k_pci_remove(struct pci_dev *pdev); |
197 | #ifdef CONFIG_PM | 197 | #ifdef CONFIG_PM |
198 | static int ath5k_pci_suspend(struct pci_dev *pdev, | 198 | static int ath5k_pci_suspend(struct device *dev); |
199 | pm_message_t state); | 199 | static int ath5k_pci_resume(struct device *dev); |
200 | static int ath5k_pci_resume(struct pci_dev *pdev); | 200 | |
201 | SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | ||
202 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | ||
201 | #else | 203 | #else |
202 | #define ath5k_pci_suspend NULL | 204 | #define ATH5K_PM_OPS NULL |
203 | #define ath5k_pci_resume NULL | ||
204 | #endif /* CONFIG_PM */ | 205 | #endif /* CONFIG_PM */ |
205 | 206 | ||
206 | static struct pci_driver ath5k_pci_driver = { | 207 | static struct pci_driver ath5k_pci_driver = { |
@@ -208,8 +209,7 @@ static struct pci_driver ath5k_pci_driver = { | |||
208 | .id_table = ath5k_pci_id_table, | 209 | .id_table = ath5k_pci_id_table, |
209 | .probe = ath5k_pci_probe, | 210 | .probe = ath5k_pci_probe, |
210 | .remove = __devexit_p(ath5k_pci_remove), | 211 | .remove = __devexit_p(ath5k_pci_remove), |
211 | .suspend = ath5k_pci_suspend, | 212 | .driver.pm = ATH5K_PM_OPS, |
212 | .resume = ath5k_pci_resume, | ||
213 | }; | 213 | }; |
214 | 214 | ||
215 | 215 | ||
@@ -437,6 +437,22 @@ ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) | |||
437 | 437 | ||
438 | return name; | 438 | return name; |
439 | } | 439 | } |
440 | static unsigned int ath5k_ioread32(void *hw_priv, u32 reg_offset) | ||
441 | { | ||
442 | struct ath5k_hw *ah = (struct ath5k_hw *) hw_priv; | ||
443 | return ath5k_hw_reg_read(ah, reg_offset); | ||
444 | } | ||
445 | |||
446 | static void ath5k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) | ||
447 | { | ||
448 | struct ath5k_hw *ah = (struct ath5k_hw *) hw_priv; | ||
449 | ath5k_hw_reg_write(ah, val, reg_offset); | ||
450 | } | ||
451 | |||
452 | static const struct ath_ops ath5k_common_ops = { | ||
453 | .read = ath5k_ioread32, | ||
454 | .write = ath5k_iowrite32, | ||
455 | }; | ||
440 | 456 | ||
441 | static int __devinit | 457 | static int __devinit |
442 | ath5k_pci_probe(struct pci_dev *pdev, | 458 | ath5k_pci_probe(struct pci_dev *pdev, |
@@ -444,6 +460,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
444 | { | 460 | { |
445 | void __iomem *mem; | 461 | void __iomem *mem; |
446 | struct ath5k_softc *sc; | 462 | struct ath5k_softc *sc; |
463 | struct ath_common *common; | ||
447 | struct ieee80211_hw *hw; | 464 | struct ieee80211_hw *hw; |
448 | int ret; | 465 | int ret; |
449 | u8 csz; | 466 | u8 csz; |
@@ -547,7 +564,6 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
547 | __set_bit(ATH_STAT_INVALID, sc->status); | 564 | __set_bit(ATH_STAT_INVALID, sc->status); |
548 | 565 | ||
549 | sc->iobase = mem; /* So we can unmap it on detach */ | 566 | sc->iobase = mem; /* So we can unmap it on detach */ |
550 | sc->common.cachelsz = csz << 2; /* convert to bytes */ | ||
551 | sc->opmode = NL80211_IFTYPE_STATION; | 567 | sc->opmode = NL80211_IFTYPE_STATION; |
552 | sc->bintval = 1000; | 568 | sc->bintval = 1000; |
553 | mutex_init(&sc->lock); | 569 | mutex_init(&sc->lock); |
@@ -565,13 +581,28 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
565 | goto err_free; | 581 | goto err_free; |
566 | } | 582 | } |
567 | 583 | ||
568 | /* Initialize device */ | 584 | /*If we passed the test malloc a ath5k_hw struct*/ |
569 | sc->ah = ath5k_hw_attach(sc); | 585 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); |
570 | if (IS_ERR(sc->ah)) { | 586 | if (!sc->ah) { |
571 | ret = PTR_ERR(sc->ah); | 587 | ret = -ENOMEM; |
588 | ATH5K_ERR(sc, "out of memory\n"); | ||
572 | goto err_irq; | 589 | goto err_irq; |
573 | } | 590 | } |
574 | 591 | ||
592 | sc->ah->ah_sc = sc; | ||
593 | sc->ah->ah_iobase = sc->iobase; | ||
594 | common = ath5k_hw_common(sc->ah); | ||
595 | common->ops = &ath5k_common_ops; | ||
596 | common->ah = sc->ah; | ||
597 | common->hw = hw; | ||
598 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
599 | |||
600 | /* Initialize device */ | ||
601 | ret = ath5k_hw_attach(sc); | ||
602 | if (ret) { | ||
603 | goto err_free_ah; | ||
604 | } | ||
605 | |||
575 | /* set up multi-rate retry capabilities */ | 606 | /* set up multi-rate retry capabilities */ |
576 | if (sc->ah->ah_version == AR5K_AR5212) { | 607 | if (sc->ah->ah_version == AR5K_AR5212) { |
577 | hw->max_rates = 4; | 608 | hw->max_rates = 4; |
@@ -640,6 +671,8 @@ err_ah: | |||
640 | ath5k_hw_detach(sc->ah); | 671 | ath5k_hw_detach(sc->ah); |
641 | err_irq: | 672 | err_irq: |
642 | free_irq(pdev->irq, sc); | 673 | free_irq(pdev->irq, sc); |
674 | err_free_ah: | ||
675 | kfree(sc->ah); | ||
643 | err_free: | 676 | err_free: |
644 | ieee80211_free_hw(hw); | 677 | ieee80211_free_hw(hw); |
645 | err_map: | 678 | err_map: |
@@ -661,6 +694,7 @@ ath5k_pci_remove(struct pci_dev *pdev) | |||
661 | ath5k_debug_finish_device(sc); | 694 | ath5k_debug_finish_device(sc); |
662 | ath5k_detach(pdev, hw); | 695 | ath5k_detach(pdev, hw); |
663 | ath5k_hw_detach(sc->ah); | 696 | ath5k_hw_detach(sc->ah); |
697 | kfree(sc->ah); | ||
664 | free_irq(pdev->irq, sc); | 698 | free_irq(pdev->irq, sc); |
665 | pci_iounmap(pdev, sc->iobase); | 699 | pci_iounmap(pdev, sc->iobase); |
666 | pci_release_region(pdev, 0); | 700 | pci_release_region(pdev, 0); |
@@ -669,33 +703,20 @@ ath5k_pci_remove(struct pci_dev *pdev) | |||
669 | } | 703 | } |
670 | 704 | ||
671 | #ifdef CONFIG_PM | 705 | #ifdef CONFIG_PM |
672 | static int | 706 | static int ath5k_pci_suspend(struct device *dev) |
673 | ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
674 | { | 707 | { |
675 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 708 | struct ieee80211_hw *hw = pci_get_drvdata(to_pci_dev(dev)); |
676 | struct ath5k_softc *sc = hw->priv; | 709 | struct ath5k_softc *sc = hw->priv; |
677 | 710 | ||
678 | ath5k_led_off(sc); | 711 | ath5k_led_off(sc); |
679 | |||
680 | pci_save_state(pdev); | ||
681 | pci_disable_device(pdev); | ||
682 | pci_set_power_state(pdev, PCI_D3hot); | ||
683 | |||
684 | return 0; | 712 | return 0; |
685 | } | 713 | } |
686 | 714 | ||
687 | static int | 715 | static int ath5k_pci_resume(struct device *dev) |
688 | ath5k_pci_resume(struct pci_dev *pdev) | ||
689 | { | 716 | { |
717 | struct pci_dev *pdev = to_pci_dev(dev); | ||
690 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 718 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
691 | struct ath5k_softc *sc = hw->priv; | 719 | struct ath5k_softc *sc = hw->priv; |
692 | int err; | ||
693 | |||
694 | pci_restore_state(pdev); | ||
695 | |||
696 | err = pci_enable_device(pdev); | ||
697 | if (err) | ||
698 | return err; | ||
699 | 720 | ||
700 | /* | 721 | /* |
701 | * Suspend/Resume resets the PCI configuration space, so we have to | 722 | * Suspend/Resume resets the PCI configuration space, so we have to |
@@ -718,7 +739,7 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re | |||
718 | { | 739 | { |
719 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 740 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
720 | struct ath5k_softc *sc = hw->priv; | 741 | struct ath5k_softc *sc = hw->priv; |
721 | struct ath_regulatory *regulatory = &sc->common.regulatory; | 742 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(sc->ah); |
722 | 743 | ||
723 | return ath_reg_notifier_apply(wiphy, request, regulatory); | 744 | return ath_reg_notifier_apply(wiphy, request, regulatory); |
724 | } | 745 | } |
@@ -728,7 +749,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
728 | { | 749 | { |
729 | struct ath5k_softc *sc = hw->priv; | 750 | struct ath5k_softc *sc = hw->priv; |
730 | struct ath5k_hw *ah = sc->ah; | 751 | struct ath5k_hw *ah = sc->ah; |
731 | struct ath_regulatory *regulatory = &sc->common.regulatory; | 752 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); |
732 | u8 mac[ETH_ALEN] = {}; | 753 | u8 mac[ETH_ALEN] = {}; |
733 | int ret; | 754 | int ret; |
734 | 755 | ||
@@ -815,7 +836,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
815 | 836 | ||
816 | SET_IEEE80211_PERM_ADDR(hw, mac); | 837 | SET_IEEE80211_PERM_ADDR(hw, mac); |
817 | /* All MAC address bits matter for ACKs */ | 838 | /* All MAC address bits matter for ACKs */ |
818 | memset(sc->bssidmask, 0xff, ETH_ALEN); | 839 | memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); |
819 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | 840 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); |
820 | 841 | ||
821 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; | 842 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; |
@@ -1153,19 +1174,20 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) | |||
1153 | static | 1174 | static |
1154 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) | 1175 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) |
1155 | { | 1176 | { |
1177 | struct ath_common *common = ath5k_hw_common(sc->ah); | ||
1156 | struct sk_buff *skb; | 1178 | struct sk_buff *skb; |
1157 | 1179 | ||
1158 | /* | 1180 | /* |
1159 | * Allocate buffer with headroom_needed space for the | 1181 | * Allocate buffer with headroom_needed space for the |
1160 | * fake physical layer header at the start. | 1182 | * fake physical layer header at the start. |
1161 | */ | 1183 | */ |
1162 | skb = ath_rxbuf_alloc(&sc->common, | 1184 | skb = ath_rxbuf_alloc(common, |
1163 | sc->rxbufsize + sc->common.cachelsz - 1, | 1185 | sc->rxbufsize + common->cachelsz - 1, |
1164 | GFP_ATOMIC); | 1186 | GFP_ATOMIC); |
1165 | 1187 | ||
1166 | if (!skb) { | 1188 | if (!skb) { |
1167 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", | 1189 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", |
1168 | sc->rxbufsize + sc->common.cachelsz - 1); | 1190 | sc->rxbufsize + common->cachelsz - 1); |
1169 | return NULL; | 1191 | return NULL; |
1170 | } | 1192 | } |
1171 | 1193 | ||
@@ -1606,13 +1628,14 @@ static int | |||
1606 | ath5k_rx_start(struct ath5k_softc *sc) | 1628 | ath5k_rx_start(struct ath5k_softc *sc) |
1607 | { | 1629 | { |
1608 | struct ath5k_hw *ah = sc->ah; | 1630 | struct ath5k_hw *ah = sc->ah; |
1631 | struct ath_common *common = ath5k_hw_common(ah); | ||
1609 | struct ath5k_buf *bf; | 1632 | struct ath5k_buf *bf; |
1610 | int ret; | 1633 | int ret; |
1611 | 1634 | ||
1612 | sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz); | 1635 | sc->rxbufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz); |
1613 | 1636 | ||
1614 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", | 1637 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", |
1615 | sc->common.cachelsz, sc->rxbufsize); | 1638 | common->cachelsz, sc->rxbufsize); |
1616 | 1639 | ||
1617 | spin_lock_bh(&sc->rxbuflock); | 1640 | spin_lock_bh(&sc->rxbuflock); |
1618 | sc->rxlink = NULL; | 1641 | sc->rxlink = NULL; |
@@ -1685,13 +1708,14 @@ static void | |||
1685 | ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | 1708 | ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, |
1686 | struct ieee80211_rx_status *rxs) | 1709 | struct ieee80211_rx_status *rxs) |
1687 | { | 1710 | { |
1711 | struct ath_common *common = ath5k_hw_common(sc->ah); | ||
1688 | u64 tsf, bc_tstamp; | 1712 | u64 tsf, bc_tstamp; |
1689 | u32 hw_tu; | 1713 | u32 hw_tu; |
1690 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; | 1714 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; |
1691 | 1715 | ||
1692 | if (ieee80211_is_beacon(mgmt->frame_control) && | 1716 | if (ieee80211_is_beacon(mgmt->frame_control) && |
1693 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && | 1717 | le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && |
1694 | memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { | 1718 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) == 0) { |
1695 | /* | 1719 | /* |
1696 | * Received an IBSS beacon with the same BSSID. Hardware *must* | 1720 | * Received an IBSS beacon with the same BSSID. Hardware *must* |
1697 | * have updated the local TSF. We have to work around various | 1721 | * have updated the local TSF. We have to work around various |
@@ -3177,6 +3201,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3177 | { | 3201 | { |
3178 | struct ath5k_softc *sc = hw->priv; | 3202 | struct ath5k_softc *sc = hw->priv; |
3179 | struct ath5k_hw *ah = sc->ah; | 3203 | struct ath5k_hw *ah = sc->ah; |
3204 | struct ath_common *common = ath5k_hw_common(ah); | ||
3180 | unsigned long flags; | 3205 | unsigned long flags; |
3181 | 3206 | ||
3182 | mutex_lock(&sc->lock); | 3207 | mutex_lock(&sc->lock); |
@@ -3185,10 +3210,9 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3185 | 3210 | ||
3186 | if (changes & BSS_CHANGED_BSSID) { | 3211 | if (changes & BSS_CHANGED_BSSID) { |
3187 | /* Cache for later use during resets */ | 3212 | /* Cache for later use during resets */ |
3188 | memcpy(ah->ah_bssid, bss_conf->bssid, ETH_ALEN); | 3213 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
3189 | /* XXX: assoc id is set to 0 for now, mac80211 doesn't have | 3214 | common->curaid = 0; |
3190 | * a clean way of letting us retrieve this yet. */ | 3215 | ath5k_hw_set_associd(ah); |
3191 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
3192 | mmiowb(); | 3216 | mmiowb(); |
3193 | } | 3217 | } |
3194 | 3218 | ||
@@ -3201,6 +3225,14 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3201 | set_beacon_filter(hw, sc->assoc); | 3225 | set_beacon_filter(hw, sc->assoc); |
3202 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | 3226 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? |
3203 | AR5K_LED_ASSOC : AR5K_LED_INIT); | 3227 | AR5K_LED_ASSOC : AR5K_LED_INIT); |
3228 | if (bss_conf->assoc) { | ||
3229 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, | ||
3230 | "Bss Info ASSOC %d, bssid: %pM\n", | ||
3231 | bss_conf->aid, common->curbssid); | ||
3232 | common->curaid = bss_conf->aid; | ||
3233 | ath5k_hw_set_associd(ah); | ||
3234 | /* Once ANI is available you would start it here */ | ||
3235 | } | ||
3204 | } | 3236 | } |
3205 | 3237 | ||
3206 | if (changes & BSS_CHANGED_BEACON) { | 3238 | if (changes & BSS_CHANGED_BEACON) { |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index a28c42f32c9d..b14ba07e9157 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -115,7 +115,6 @@ struct ath5k_rfkill { | |||
115 | * associated with an instance of a device */ | 115 | * associated with an instance of a device */ |
116 | struct ath5k_softc { | 116 | struct ath5k_softc { |
117 | struct pci_dev *pdev; /* for dma mapping */ | 117 | struct pci_dev *pdev; /* for dma mapping */ |
118 | struct ath_common common; | ||
119 | void __iomem *iobase; /* address of the device */ | 118 | void __iomem *iobase; /* address of the device */ |
120 | struct mutex lock; /* dev-level lock */ | 119 | struct mutex lock; /* dev-level lock */ |
121 | struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; | 120 | struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; |
@@ -202,15 +201,4 @@ struct ath5k_softc { | |||
202 | #define ath5k_hw_hasveol(_ah) \ | 201 | #define ath5k_hw_hasveol(_ah) \ |
203 | (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) | 202 | (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) |
204 | 203 | ||
205 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) | ||
206 | { | ||
207 | return &ah->ah_sc->common; | ||
208 | } | ||
209 | |||
210 | static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) | ||
211 | { | ||
212 | return &(ath5k_hw_common(ah)->regulatory); | ||
213 | |||
214 | } | ||
215 | |||
216 | #endif | 204 | #endif |
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 18eb5190ce4b..8fa439308828 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c | |||
@@ -560,8 +560,8 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { | |||
560 | { AR5K_SLEEP0, 0x0002aaaa }, | 560 | { AR5K_SLEEP0, 0x0002aaaa }, |
561 | { AR5K_SLEEP1, 0x02005555 }, | 561 | { AR5K_SLEEP1, 0x02005555 }, |
562 | { AR5K_SLEEP2, 0x00000000 }, | 562 | { AR5K_SLEEP2, 0x00000000 }, |
563 | { AR5K_BSS_IDM0, 0xffffffff }, | 563 | { AR_BSSMSKL, 0xffffffff }, |
564 | { AR5K_BSS_IDM1, 0x0000ffff }, | 564 | { AR_BSSMSKU, 0x0000ffff }, |
565 | { AR5K_TXPC, 0x00000000 }, | 565 | { AR5K_TXPC, 0x00000000 }, |
566 | { AR5K_PROFCNT_TX, 0x00000000 }, | 566 | { AR5K_PROFCNT_TX, 0x00000000 }, |
567 | { AR5K_PROFCNT_RX, 0x00000000 }, | 567 | { AR5K_PROFCNT_RX, 0x00000000 }, |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 2942f13c9c4a..64fc1eb9b6d9 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -24,6 +24,8 @@ | |||
24 | * Protocol Control Unit Functions * | 24 | * Protocol Control Unit Functions * |
25 | \*********************************/ | 25 | \*********************************/ |
26 | 26 | ||
27 | #include <asm/unaligned.h> | ||
28 | |||
27 | #include "ath5k.h" | 29 | #include "ath5k.h" |
28 | #include "reg.h" | 30 | #include "reg.h" |
29 | #include "debug.h" | 31 | #include "debug.h" |
@@ -44,6 +46,7 @@ | |||
44 | */ | 46 | */ |
45 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) | 47 | int ath5k_hw_set_opmode(struct ath5k_hw *ah) |
46 | { | 48 | { |
49 | struct ath_common *common = ath5k_hw_common(ah); | ||
47 | u32 pcu_reg, beacon_reg, low_id, high_id; | 50 | u32 pcu_reg, beacon_reg, low_id, high_id; |
48 | 51 | ||
49 | 52 | ||
@@ -95,8 +98,8 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah) | |||
95 | /* | 98 | /* |
96 | * Set PCU registers | 99 | * Set PCU registers |
97 | */ | 100 | */ |
98 | low_id = AR5K_LOW_ID(ah->ah_sta_id); | 101 | low_id = get_unaligned_le32(common->macaddr); |
99 | high_id = AR5K_HIGH_ID(ah->ah_sta_id); | 102 | high_id = get_unaligned_le16(common->macaddr + 4); |
100 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | 103 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); |
101 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | 104 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); |
102 | 105 | ||
@@ -238,28 +241,6 @@ int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
238 | return 0; | 241 | return 0; |
239 | } | 242 | } |
240 | 243 | ||
241 | |||
242 | /****************\ | ||
243 | * BSSID handling * | ||
244 | \****************/ | ||
245 | |||
246 | /** | ||
247 | * ath5k_hw_get_lladdr - Get station id | ||
248 | * | ||
249 | * @ah: The &struct ath5k_hw | ||
250 | * @mac: The card's mac address | ||
251 | * | ||
252 | * Initialize ah->ah_sta_id using the mac address provided | ||
253 | * (just a memcpy). | ||
254 | * | ||
255 | * TODO: Remove it once we merge ath5k_softc and ath5k_hw | ||
256 | */ | ||
257 | void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | ||
258 | { | ||
259 | ATH5K_TRACE(ah->ah_sc); | ||
260 | memcpy(mac, ah->ah_sta_id, ETH_ALEN); | ||
261 | } | ||
262 | |||
263 | /** | 244 | /** |
264 | * ath5k_hw_set_lladdr - Set station id | 245 | * ath5k_hw_set_lladdr - Set station id |
265 | * | 246 | * |
@@ -270,17 +251,18 @@ void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) | |||
270 | */ | 251 | */ |
271 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | 252 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) |
272 | { | 253 | { |
254 | struct ath_common *common = ath5k_hw_common(ah); | ||
273 | u32 low_id, high_id; | 255 | u32 low_id, high_id; |
274 | u32 pcu_reg; | 256 | u32 pcu_reg; |
275 | 257 | ||
276 | ATH5K_TRACE(ah->ah_sc); | 258 | ATH5K_TRACE(ah->ah_sc); |
277 | /* Set new station ID */ | 259 | /* Set new station ID */ |
278 | memcpy(ah->ah_sta_id, mac, ETH_ALEN); | 260 | memcpy(common->macaddr, mac, ETH_ALEN); |
279 | 261 | ||
280 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | 262 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; |
281 | 263 | ||
282 | low_id = AR5K_LOW_ID(mac); | 264 | low_id = get_unaligned_le32(mac); |
283 | high_id = AR5K_HIGH_ID(mac); | 265 | high_id = get_unaligned_le16(mac + 4); |
284 | 266 | ||
285 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | 267 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); |
286 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | 268 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); |
@@ -297,159 +279,51 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | |||
297 | * | 279 | * |
298 | * Sets the BSSID which trigers the "SME Join" operation | 280 | * Sets the BSSID which trigers the "SME Join" operation |
299 | */ | 281 | */ |
300 | void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) | 282 | void ath5k_hw_set_associd(struct ath5k_hw *ah) |
301 | { | 283 | { |
302 | u32 low_id, high_id; | 284 | struct ath_common *common = ath5k_hw_common(ah); |
303 | u16 tim_offset = 0; | 285 | u16 tim_offset = 0; |
304 | 286 | ||
305 | /* | 287 | /* |
306 | * Set simple BSSID mask on 5212 | 288 | * Set simple BSSID mask on 5212 |
307 | */ | 289 | */ |
308 | if (ah->ah_version == AR5K_AR5212) { | 290 | if (ah->ah_version == AR5K_AR5212) |
309 | ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask), | 291 | ath_hw_setbssidmask(common); |
310 | AR5K_BSS_IDM0); | ||
311 | ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask), | ||
312 | AR5K_BSS_IDM1); | ||
313 | } | ||
314 | 292 | ||
315 | /* | 293 | /* |
316 | * Set BSSID which triggers the "SME Join" operation | 294 | * Set BSSID which triggers the "SME Join" operation |
317 | */ | 295 | */ |
318 | low_id = AR5K_LOW_ID(bssid); | 296 | ath5k_hw_reg_write(ah, |
319 | high_id = AR5K_HIGH_ID(bssid); | 297 | get_unaligned_le32(common->curbssid), |
320 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); | 298 | AR5K_BSS_ID0); |
321 | ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << | 299 | ath5k_hw_reg_write(ah, |
322 | AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); | 300 | get_unaligned_le16(common->curbssid + 4) | |
323 | 301 | ((common->curaid & 0x3fff) << AR5K_BSS_ID1_AID_S), | |
324 | if (assoc_id == 0) { | 302 | AR5K_BSS_ID1); |
303 | |||
304 | if (common->curaid == 0) { | ||
325 | ath5k_hw_disable_pspoll(ah); | 305 | ath5k_hw_disable_pspoll(ah); |
326 | return; | 306 | return; |
327 | } | 307 | } |
328 | 308 | ||
329 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, | 309 | AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, |
330 | tim_offset ? tim_offset + 4 : 0); | 310 | tim_offset ? tim_offset + 4 : 0); |
331 | 311 | ||
332 | ath5k_hw_enable_pspoll(ah, NULL, 0); | 312 | ath5k_hw_enable_pspoll(ah, NULL, 0); |
333 | } | 313 | } |
334 | 314 | ||
335 | /** | 315 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) |
336 | * ath5k_hw_set_bssid_mask - filter out bssids we listen | ||
337 | * | ||
338 | * @ah: the &struct ath5k_hw | ||
339 | * @mask: the bssid_mask, a u8 array of size ETH_ALEN | ||
340 | * | ||
341 | * BSSID masking is a method used by AR5212 and newer hardware to inform PCU | ||
342 | * which bits of the interface's MAC address should be looked at when trying | ||
343 | * to decide which packets to ACK. In station mode and AP mode with a single | ||
344 | * BSS every bit matters since we lock to only one BSS. In AP mode with | ||
345 | * multiple BSSes (virtual interfaces) not every bit matters because hw must | ||
346 | * accept frames for all BSSes and so we tweak some bits of our mac address | ||
347 | * in order to have multiple BSSes. | ||
348 | * | ||
349 | * NOTE: This is a simple filter and does *not* filter out all | ||
350 | * relevant frames. Some frames that are not for us might get ACKed from us | ||
351 | * by PCU because they just match the mask. | ||
352 | * | ||
353 | * When handling multiple BSSes you can get the BSSID mask by computing the | ||
354 | * set of ~ ( MAC XOR BSSID ) for all bssids we handle. | ||
355 | * | ||
356 | * When you do this you are essentially computing the common bits of all your | ||
357 | * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with | ||
358 | * the MAC address to obtain the relevant bits and compare the result with | ||
359 | * (frame's BSSID & mask) to see if they match. | ||
360 | */ | ||
361 | /* | ||
362 | * Simple example: on your card you have have two BSSes you have created with | ||
363 | * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. | ||
364 | * There is another BSSID-03 but you are not part of it. For simplicity's sake, | ||
365 | * assuming only 4 bits for a mac address and for BSSIDs you can then have: | ||
366 | * | ||
367 | * \ | ||
368 | * MAC: 0001 | | ||
369 | * BSSID-01: 0100 | --> Belongs to us | ||
370 | * BSSID-02: 1001 | | ||
371 | * / | ||
372 | * ------------------- | ||
373 | * BSSID-03: 0110 | --> External | ||
374 | * ------------------- | ||
375 | * | ||
376 | * Our bssid_mask would then be: | ||
377 | * | ||
378 | * On loop iteration for BSSID-01: | ||
379 | * ~(0001 ^ 0100) -> ~(0101) | ||
380 | * -> 1010 | ||
381 | * bssid_mask = 1010 | ||
382 | * | ||
383 | * On loop iteration for BSSID-02: | ||
384 | * bssid_mask &= ~(0001 ^ 1001) | ||
385 | * bssid_mask = (1010) & ~(0001 ^ 1001) | ||
386 | * bssid_mask = (1010) & ~(1001) | ||
387 | * bssid_mask = (1010) & (0110) | ||
388 | * bssid_mask = 0010 | ||
389 | * | ||
390 | * A bssid_mask of 0010 means "only pay attention to the second least | ||
391 | * significant bit". This is because its the only bit common | ||
392 | * amongst the MAC and all BSSIDs we support. To findout what the real | ||
393 | * common bit is we can simply "&" the bssid_mask now with any BSSID we have | ||
394 | * or our MAC address (we assume the hardware uses the MAC address). | ||
395 | * | ||
396 | * Now, suppose there's an incoming frame for BSSID-03: | ||
397 | * | ||
398 | * IFRAME-01: 0110 | ||
399 | * | ||
400 | * An easy eye-inspeciton of this already should tell you that this frame | ||
401 | * will not pass our check. This is beacuse the bssid_mask tells the | ||
402 | * hardware to only look at the second least significant bit and the | ||
403 | * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB | ||
404 | * as 1, which does not match 0. | ||
405 | * | ||
406 | * So with IFRAME-01 we *assume* the hardware will do: | ||
407 | * | ||
408 | * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
409 | * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; | ||
410 | * --> allow = (0010) == 0000 ? 1 : 0; | ||
411 | * --> allow = 0 | ||
412 | * | ||
413 | * Lets now test a frame that should work: | ||
414 | * | ||
415 | * IFRAME-02: 0001 (we should allow) | ||
416 | * | ||
417 | * allow = (0001 & 1010) == 1010 | ||
418 | * | ||
419 | * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
420 | * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; | ||
421 | * --> allow = (0010) == (0010) | ||
422 | * --> allow = 1 | ||
423 | * | ||
424 | * Other examples: | ||
425 | * | ||
426 | * IFRAME-03: 0100 --> allowed | ||
427 | * IFRAME-04: 1001 --> allowed | ||
428 | * IFRAME-05: 1101 --> allowed but its not for us!!! | ||
429 | * | ||
430 | */ | ||
431 | int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | ||
432 | { | 316 | { |
433 | u32 low_id, high_id; | 317 | struct ath_common *common = ath5k_hw_common(ah); |
434 | ATH5K_TRACE(ah->ah_sc); | 318 | ATH5K_TRACE(ah->ah_sc); |
435 | 319 | ||
436 | /* Cache bssid mask so that we can restore it | 320 | /* Cache bssid mask so that we can restore it |
437 | * on reset */ | 321 | * on reset */ |
438 | memcpy(ah->ah_bssid_mask, mask, ETH_ALEN); | 322 | memcpy(common->bssidmask, mask, ETH_ALEN); |
439 | if (ah->ah_version == AR5K_AR5212) { | 323 | if (ah->ah_version == AR5K_AR5212) |
440 | low_id = AR5K_LOW_ID(mask); | 324 | ath_hw_setbssidmask(common); |
441 | high_id = AR5K_HIGH_ID(mask); | ||
442 | |||
443 | ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); | ||
444 | ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | return -EIO; | ||
450 | } | 325 | } |
451 | 326 | ||
452 | |||
453 | /************\ | 327 | /************\ |
454 | * RX Control * | 328 | * RX Control * |
455 | \************/ | 329 | \************/ |
@@ -1157,14 +1031,17 @@ int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | |||
1157 | /* Invalid entry (key table overflow) */ | 1031 | /* Invalid entry (key table overflow) */ |
1158 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 1032 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); |
1159 | 1033 | ||
1160 | /* MAC may be NULL if it's a broadcast key. In this case no need to | 1034 | /* |
1161 | * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ | 1035 | * MAC may be NULL if it's a broadcast key. In this case no need to |
1036 | * to compute get_unaligned_le32 and get_unaligned_le16 as we | ||
1037 | * already know it. | ||
1038 | */ | ||
1162 | if (!mac) { | 1039 | if (!mac) { |
1163 | low_id = 0xffffffff; | 1040 | low_id = 0xffffffff; |
1164 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | 1041 | high_id = 0xffff | AR5K_KEYTABLE_VALID; |
1165 | } else { | 1042 | } else { |
1166 | low_id = AR5K_LOW_ID(mac); | 1043 | low_id = get_unaligned_le32(mac); |
1167 | high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; | 1044 | high_id = get_unaligned_le16(mac + 4) | AR5K_KEYTABLE_VALID; |
1168 | } | 1045 | } |
1169 | 1046 | ||
1170 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); | 1047 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index c63ea6afd96f..64227abe3c20 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -35,7 +35,7 @@ | |||
35 | * released by Atheros and on various debug messages found on the net. | 35 | * released by Atheros and on various debug messages found on the net. |
36 | */ | 36 | */ |
37 | 37 | ||
38 | 38 | #include "../reg.h" | |
39 | 39 | ||
40 | /*====MAC DMA REGISTERS====*/ | 40 | /*====MAC DMA REGISTERS====*/ |
41 | 41 | ||
@@ -1650,12 +1650,6 @@ | |||
1650 | #define AR5K_SLEEP2_DTIM_PER_S 16 | 1650 | #define AR5K_SLEEP2_DTIM_PER_S 16 |
1651 | 1651 | ||
1652 | /* | 1652 | /* |
1653 | * BSSID mask registers | ||
1654 | */ | ||
1655 | #define AR5K_BSS_IDM0 0x80e0 /* Upper bits */ | ||
1656 | #define AR5K_BSS_IDM1 0x80e4 /* Lower bits */ | ||
1657 | |||
1658 | /* | ||
1659 | * TX power control (TPC) register | 1653 | * TX power control (TPC) register |
1660 | * | 1654 | * |
1661 | * XXX: PCDAC steps (0.5dbm) or DBM ? | 1655 | * XXX: PCDAC steps (0.5dbm) or DBM ? |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 34e13c700849..3dab3d856d7b 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -25,6 +25,8 @@ | |||
25 | Reset functions and helpers | 25 | Reset functions and helpers |
26 | \*****************************/ | 26 | \*****************************/ |
27 | 27 | ||
28 | #include <asm/unaligned.h> | ||
29 | |||
28 | #include <linux/pci.h> /* To determine if a card is pci-e */ | 30 | #include <linux/pci.h> /* To determine if a card is pci-e */ |
29 | #include <linux/log2.h> | 31 | #include <linux/log2.h> |
30 | #include "ath5k.h" | 32 | #include "ath5k.h" |
@@ -870,6 +872,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
870 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 872 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
871 | struct ieee80211_channel *channel, bool change_channel) | 873 | struct ieee80211_channel *channel, bool change_channel) |
872 | { | 874 | { |
875 | struct ath_common *common = ath5k_hw_common(ah); | ||
873 | u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; | 876 | u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; |
874 | u32 phy_tst1; | 877 | u32 phy_tst1; |
875 | u8 mode, freq, ee_mode, ant[2]; | 878 | u8 mode, freq, ee_mode, ant[2]; |
@@ -1171,10 +1174,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1171 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); | 1174 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); |
1172 | 1175 | ||
1173 | /* Restore sta_id flags and preserve our mac address*/ | 1176 | /* Restore sta_id flags and preserve our mac address*/ |
1174 | ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id), | 1177 | ath5k_hw_reg_write(ah, |
1175 | AR5K_STA_ID0); | 1178 | get_unaligned_le32(common->macaddr), |
1176 | ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id), | 1179 | AR5K_STA_ID0); |
1177 | AR5K_STA_ID1); | 1180 | ath5k_hw_reg_write(ah, |
1181 | staid1_flags | get_unaligned_le16(common->macaddr + 4), | ||
1182 | AR5K_STA_ID1); | ||
1178 | 1183 | ||
1179 | 1184 | ||
1180 | /* | 1185 | /* |
@@ -1182,8 +1187,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1182 | */ | 1187 | */ |
1183 | 1188 | ||
1184 | /* Restore bssid and bssid mask */ | 1189 | /* Restore bssid and bssid mask */ |
1185 | /* XXX: add ah->aid once mac80211 gives this to us */ | 1190 | ath5k_hw_set_associd(ah); |
1186 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | ||
1187 | 1191 | ||
1188 | /* Set PCU config */ | 1192 | /* Set PCU config */ |
1189 | ath5k_hw_set_opmode(ah); | 1193 | ath5k_hw_set_opmode(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index ef5f59c4dd80..99ce066392a7 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -1,6 +1,10 @@ | |||
1 | config ATH9K_HW | ||
2 | tristate | ||
3 | |||
1 | config ATH9K | 4 | config ATH9K |
2 | tristate "Atheros 802.11n wireless cards support" | 5 | tristate "Atheros 802.11n wireless cards support" |
3 | depends on PCI && MAC80211 && WLAN_80211 | 6 | depends on PCI && MAC80211 && WLAN_80211 |
7 | select ATH9K_HW | ||
4 | select MAC80211_LEDS | 8 | select MAC80211_LEDS |
5 | select LEDS_CLASS | 9 | select LEDS_CLASS |
6 | select NEW_LEDS | 10 | select NEW_LEDS |
@@ -16,6 +20,8 @@ config ATH9K | |||
16 | 20 | ||
17 | If you choose to build a module, it'll be called ath9k. | 21 | If you choose to build a module, it'll be called ath9k. |
18 | 22 | ||
23 | if ATH_DEBUG | ||
24 | |||
19 | config ATH9K_DEBUG | 25 | config ATH9K_DEBUG |
20 | bool "Atheros ath9k debugging" | 26 | bool "Atheros ath9k debugging" |
21 | depends on ATH9K | 27 | depends on ATH9K |
@@ -26,3 +32,5 @@ config ATH9K_DEBUG | |||
26 | modprobe ath9k debug=0x00000200 | 32 | modprobe ath9k debug=0x00000200 |
27 | 33 | ||
28 | Look in ath9k/debug.h for possible debug masks | 34 | Look in ath9k/debug.h for possible debug masks |
35 | |||
36 | endif # ATH_DEBUG | ||
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index ff2c9a26c10c..8caf2a8f8953 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -1,22 +1,25 @@ | |||
1 | ath9k-y += hw.o \ | 1 | ath9k-y += beacon.o \ |
2 | eeprom.o \ | ||
3 | eeprom_def.o \ | ||
4 | eeprom_4k.o \ | ||
5 | eeprom_9287.o \ | ||
6 | mac.o \ | ||
7 | calib.o \ | ||
8 | ani.o \ | ||
9 | phy.o \ | ||
10 | beacon.o \ | ||
11 | main.o \ | 2 | main.o \ |
12 | recv.o \ | 3 | recv.o \ |
13 | xmit.o \ | 4 | xmit.o \ |
14 | virtual.o \ | 5 | virtual.o \ |
15 | rc.o \ | 6 | rc.o |
16 | btcoex.o | ||
17 | 7 | ||
18 | ath9k-$(CONFIG_PCI) += pci.o | 8 | ath9k-$(CONFIG_PCI) += pci.o |
19 | ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o | 9 | ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o |
20 | ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o | 10 | ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o |
21 | 11 | ||
22 | obj-$(CONFIG_ATH9K) += ath9k.o | 12 | obj-$(CONFIG_ATH9K) += ath9k.o |
13 | |||
14 | ath9k_hw-y:= hw.o \ | ||
15 | eeprom.o \ | ||
16 | eeprom_def.o \ | ||
17 | eeprom_4k.o \ | ||
18 | eeprom_9287.o \ | ||
19 | calib.o \ | ||
20 | ani.o \ | ||
21 | phy.o \ | ||
22 | btcoex.o \ | ||
23 | mac.o \ | ||
24 | |||
25 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | ||
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 2ad7d0280f7a..33c9e8167185 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -22,27 +22,31 @@ | |||
22 | #include "ath9k.h" | 22 | #include "ath9k.h" |
23 | 23 | ||
24 | /* return bus cachesize in 4B word units */ | 24 | /* return bus cachesize in 4B word units */ |
25 | static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz) | 25 | static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) |
26 | { | 26 | { |
27 | *csz = L1_CACHE_BYTES >> 2; | 27 | *csz = L1_CACHE_BYTES >> 2; |
28 | } | 28 | } |
29 | 29 | ||
30 | static void ath_ahb_cleanup(struct ath_softc *sc) | 30 | static void ath_ahb_cleanup(struct ath_common *common) |
31 | { | 31 | { |
32 | struct ath_hw *ah = (struct ath_hw *) common->ah; | ||
33 | struct ath_softc *sc = ah->ah_sc; | ||
32 | iounmap(sc->mem); | 34 | iounmap(sc->mem); |
33 | } | 35 | } |
34 | 36 | ||
35 | static bool ath_ahb_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) | 37 | static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) |
36 | { | 38 | { |
39 | struct ath_hw *ah = (struct ath_hw *) common->ah; | ||
37 | struct ath_softc *sc = ah->ah_sc; | 40 | struct ath_softc *sc = ah->ah_sc; |
38 | struct platform_device *pdev = to_platform_device(sc->dev); | 41 | struct platform_device *pdev = to_platform_device(sc->dev); |
39 | struct ath9k_platform_data *pdata; | 42 | struct ath9k_platform_data *pdata; |
40 | 43 | ||
41 | pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; | 44 | pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; |
42 | if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { | 45 | if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { |
43 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 46 | ath_print(common, ATH_DBG_FATAL, |
44 | "%s: flash read failed, offset %08x is out of range\n", | 47 | "%s: flash read failed, offset %08x " |
45 | __func__, off); | 48 | "is out of range\n", |
49 | __func__, off); | ||
46 | return false; | 50 | return false; |
47 | } | 51 | } |
48 | 52 | ||
@@ -116,10 +120,9 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
116 | sc->hw = hw; | 120 | sc->hw = hw; |
117 | sc->dev = &pdev->dev; | 121 | sc->dev = &pdev->dev; |
118 | sc->mem = mem; | 122 | sc->mem = mem; |
119 | sc->bus_ops = &ath_ahb_bus_ops; | ||
120 | sc->irq = irq; | 123 | sc->irq = irq; |
121 | 124 | ||
122 | ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0); | 125 | ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); |
123 | if (ret) { | 126 | if (ret) { |
124 | dev_err(&pdev->dev, "failed to initialize device\n"); | 127 | dev_err(&pdev->dev, "failed to initialize device\n"); |
125 | goto err_free_hw; | 128 | goto err_free_hw; |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 2b493742ef10..2a0cd64c2bfb 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | 19 | static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, |
20 | struct ath9k_channel *chan) | 20 | struct ath9k_channel *chan) |
@@ -31,8 +31,8 @@ static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | |||
31 | } | 31 | } |
32 | } | 32 | } |
33 | 33 | ||
34 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 34 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, |
35 | "No more channel states left. Using channel 0\n"); | 35 | "No more channel states left. Using channel 0\n"); |
36 | 36 | ||
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
@@ -41,16 +41,17 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah, | |||
41 | enum ath9k_ani_cmd cmd, int param) | 41 | enum ath9k_ani_cmd cmd, int param) |
42 | { | 42 | { |
43 | struct ar5416AniState *aniState = ah->curani; | 43 | struct ar5416AniState *aniState = ah->curani; |
44 | struct ath_common *common = ath9k_hw_common(ah); | ||
44 | 45 | ||
45 | switch (cmd & ah->ani_function) { | 46 | switch (cmd & ah->ani_function) { |
46 | case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ | 47 | case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ |
47 | u32 level = param; | 48 | u32 level = param; |
48 | 49 | ||
49 | if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { | 50 | if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { |
50 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 51 | ath_print(common, ATH_DBG_ANI, |
51 | "level out of range (%u > %u)\n", | 52 | "level out of range (%u > %u)\n", |
52 | level, | 53 | level, |
53 | (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); | 54 | (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); |
54 | return false; | 55 | return false; |
55 | } | 56 | } |
56 | 57 | ||
@@ -152,10 +153,10 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah, | |||
152 | u32 level = param; | 153 | u32 level = param; |
153 | 154 | ||
154 | if (level >= ARRAY_SIZE(firstep)) { | 155 | if (level >= ARRAY_SIZE(firstep)) { |
155 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 156 | ath_print(common, ATH_DBG_ANI, |
156 | "level out of range (%u > %u)\n", | 157 | "level out of range (%u > %u)\n", |
157 | level, | 158 | level, |
158 | (unsigned) ARRAY_SIZE(firstep)); | 159 | (unsigned) ARRAY_SIZE(firstep)); |
159 | return false; | 160 | return false; |
160 | } | 161 | } |
161 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | 162 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, |
@@ -174,11 +175,10 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah, | |||
174 | u32 level = param; | 175 | u32 level = param; |
175 | 176 | ||
176 | if (level >= ARRAY_SIZE(cycpwrThr1)) { | 177 | if (level >= ARRAY_SIZE(cycpwrThr1)) { |
177 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 178 | ath_print(common, ATH_DBG_ANI, |
178 | "level out of range (%u > %u)\n", | 179 | "level out of range (%u > %u)\n", |
179 | level, | 180 | level, |
180 | (unsigned) | 181 | (unsigned) ARRAY_SIZE(cycpwrThr1)); |
181 | ARRAY_SIZE(cycpwrThr1)); | ||
182 | return false; | 182 | return false; |
183 | } | 183 | } |
184 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | 184 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, |
@@ -194,25 +194,28 @@ static bool ath9k_hw_ani_control(struct ath_hw *ah, | |||
194 | case ATH9K_ANI_PRESENT: | 194 | case ATH9K_ANI_PRESENT: |
195 | break; | 195 | break; |
196 | default: | 196 | default: |
197 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 197 | ath_print(common, ATH_DBG_ANI, |
198 | "invalid cmd %u\n", cmd); | 198 | "invalid cmd %u\n", cmd); |
199 | return false; | 199 | return false; |
200 | } | 200 | } |
201 | 201 | ||
202 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "ANI parameters:\n"); | 202 | ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); |
203 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 203 | ath_print(common, ATH_DBG_ANI, |
204 | "noiseImmunityLevel=%d, spurImmunityLevel=%d, " | 204 | "noiseImmunityLevel=%d, spurImmunityLevel=%d, " |
205 | "ofdmWeakSigDetectOff=%d\n", | 205 | "ofdmWeakSigDetectOff=%d\n", |
206 | aniState->noiseImmunityLevel, aniState->spurImmunityLevel, | 206 | aniState->noiseImmunityLevel, |
207 | !aniState->ofdmWeakSigDetectOff); | 207 | aniState->spurImmunityLevel, |
208 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 208 | !aniState->ofdmWeakSigDetectOff); |
209 | "cckWeakSigThreshold=%d, " | 209 | ath_print(common, ATH_DBG_ANI, |
210 | "firstepLevel=%d, listenTime=%d\n", | 210 | "cckWeakSigThreshold=%d, " |
211 | aniState->cckWeakSigThreshold, aniState->firstepLevel, | 211 | "firstepLevel=%d, listenTime=%d\n", |
212 | aniState->listenTime); | 212 | aniState->cckWeakSigThreshold, |
213 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 213 | aniState->firstepLevel, |
214 | aniState->listenTime); | ||
215 | ath_print(common, ATH_DBG_ANI, | ||
214 | "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", | 216 | "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", |
215 | aniState->cycleCount, aniState->ofdmPhyErrCount, | 217 | aniState->cycleCount, |
218 | aniState->ofdmPhyErrCount, | ||
216 | aniState->cckPhyErrCount); | 219 | aniState->cckPhyErrCount); |
217 | 220 | ||
218 | return true; | 221 | return true; |
@@ -231,6 +234,7 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, | |||
231 | static void ath9k_ani_restart(struct ath_hw *ah) | 234 | static void ath9k_ani_restart(struct ath_hw *ah) |
232 | { | 235 | { |
233 | struct ar5416AniState *aniState; | 236 | struct ar5416AniState *aniState; |
237 | struct ath_common *common = ath9k_hw_common(ah); | ||
234 | 238 | ||
235 | if (!DO_ANI(ah)) | 239 | if (!DO_ANI(ah)) |
236 | return; | 240 | return; |
@@ -240,24 +244,24 @@ static void ath9k_ani_restart(struct ath_hw *ah) | |||
240 | 244 | ||
241 | if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { | 245 | if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { |
242 | aniState->ofdmPhyErrBase = 0; | 246 | aniState->ofdmPhyErrBase = 0; |
243 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 247 | ath_print(common, ATH_DBG_ANI, |
244 | "OFDM Trigger is too high for hw counters\n"); | 248 | "OFDM Trigger is too high for hw counters\n"); |
245 | } else { | 249 | } else { |
246 | aniState->ofdmPhyErrBase = | 250 | aniState->ofdmPhyErrBase = |
247 | AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; | 251 | AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; |
248 | } | 252 | } |
249 | if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { | 253 | if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { |
250 | aniState->cckPhyErrBase = 0; | 254 | aniState->cckPhyErrBase = 0; |
251 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 255 | ath_print(common, ATH_DBG_ANI, |
252 | "CCK Trigger is too high for hw counters\n"); | 256 | "CCK Trigger is too high for hw counters\n"); |
253 | } else { | 257 | } else { |
254 | aniState->cckPhyErrBase = | 258 | aniState->cckPhyErrBase = |
255 | AR_PHY_COUNTMAX - aniState->cckTrigHigh; | 259 | AR_PHY_COUNTMAX - aniState->cckTrigHigh; |
256 | } | 260 | } |
257 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 261 | ath_print(common, ATH_DBG_ANI, |
258 | "Writing ofdmbase=%u cckbase=%u\n", | 262 | "Writing ofdmbase=%u cckbase=%u\n", |
259 | aniState->ofdmPhyErrBase, | 263 | aniState->ofdmPhyErrBase, |
260 | aniState->cckPhyErrBase); | 264 | aniState->cckPhyErrBase); |
261 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | 265 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); |
262 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | 266 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); |
263 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | 267 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); |
@@ -271,7 +275,7 @@ static void ath9k_ani_restart(struct ath_hw *ah) | |||
271 | 275 | ||
272 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) | 276 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) |
273 | { | 277 | { |
274 | struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; | 278 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
275 | struct ar5416AniState *aniState; | 279 | struct ar5416AniState *aniState; |
276 | int32_t rssi; | 280 | int32_t rssi; |
277 | 281 | ||
@@ -343,7 +347,7 @@ static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) | |||
343 | 347 | ||
344 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) | 348 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) |
345 | { | 349 | { |
346 | struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; | 350 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
347 | struct ar5416AniState *aniState; | 351 | struct ar5416AniState *aniState; |
348 | int32_t rssi; | 352 | int32_t rssi; |
349 | 353 | ||
@@ -464,6 +468,7 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
464 | { | 468 | { |
465 | struct ar5416AniState *aniState; | 469 | struct ar5416AniState *aniState; |
466 | struct ath9k_channel *chan = ah->curchan; | 470 | struct ath9k_channel *chan = ah->curchan; |
471 | struct ath_common *common = ath9k_hw_common(ah); | ||
467 | int index; | 472 | int index; |
468 | 473 | ||
469 | if (!DO_ANI(ah)) | 474 | if (!DO_ANI(ah)) |
@@ -475,8 +480,8 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
475 | 480 | ||
476 | if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION | 481 | if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION |
477 | && ah->opmode != NL80211_IFTYPE_ADHOC) { | 482 | && ah->opmode != NL80211_IFTYPE_ADHOC) { |
478 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 483 | ath_print(common, ATH_DBG_ANI, |
479 | "Reset ANI state opmode %u\n", ah->opmode); | 484 | "Reset ANI state opmode %u\n", ah->opmode); |
480 | ah->stats.ast_ani_reset++; | 485 | ah->stats.ast_ani_reset++; |
481 | 486 | ||
482 | if (ah->opmode == NL80211_IFTYPE_AP) { | 487 | if (ah->opmode == NL80211_IFTYPE_AP) { |
@@ -543,6 +548,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
543 | struct ath9k_channel *chan) | 548 | struct ath9k_channel *chan) |
544 | { | 549 | { |
545 | struct ar5416AniState *aniState; | 550 | struct ar5416AniState *aniState; |
551 | struct ath_common *common = ath9k_hw_common(ah); | ||
546 | int32_t listenTime; | 552 | int32_t listenTime; |
547 | u32 phyCnt1, phyCnt2; | 553 | u32 phyCnt1, phyCnt2; |
548 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | 554 | u32 ofdmPhyErrCnt, cckPhyErrCnt; |
@@ -569,20 +575,22 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
569 | if (phyCnt1 < aniState->ofdmPhyErrBase || | 575 | if (phyCnt1 < aniState->ofdmPhyErrBase || |
570 | phyCnt2 < aniState->cckPhyErrBase) { | 576 | phyCnt2 < aniState->cckPhyErrBase) { |
571 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | 577 | if (phyCnt1 < aniState->ofdmPhyErrBase) { |
572 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 578 | ath_print(common, ATH_DBG_ANI, |
573 | "phyCnt1 0x%x, resetting " | 579 | "phyCnt1 0x%x, resetting " |
574 | "counter value to 0x%x\n", | 580 | "counter value to 0x%x\n", |
575 | phyCnt1, aniState->ofdmPhyErrBase); | 581 | phyCnt1, |
582 | aniState->ofdmPhyErrBase); | ||
576 | REG_WRITE(ah, AR_PHY_ERR_1, | 583 | REG_WRITE(ah, AR_PHY_ERR_1, |
577 | aniState->ofdmPhyErrBase); | 584 | aniState->ofdmPhyErrBase); |
578 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | 585 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, |
579 | AR_PHY_ERR_OFDM_TIMING); | 586 | AR_PHY_ERR_OFDM_TIMING); |
580 | } | 587 | } |
581 | if (phyCnt2 < aniState->cckPhyErrBase) { | 588 | if (phyCnt2 < aniState->cckPhyErrBase) { |
582 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 589 | ath_print(common, ATH_DBG_ANI, |
583 | "phyCnt2 0x%x, resetting " | 590 | "phyCnt2 0x%x, resetting " |
584 | "counter value to 0x%x\n", | 591 | "counter value to 0x%x\n", |
585 | phyCnt2, aniState->cckPhyErrBase); | 592 | phyCnt2, |
593 | aniState->cckPhyErrBase); | ||
586 | REG_WRITE(ah, AR_PHY_ERR_2, | 594 | REG_WRITE(ah, AR_PHY_ERR_2, |
587 | aniState->cckPhyErrBase); | 595 | aniState->cckPhyErrBase); |
588 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | 596 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, |
@@ -621,10 +629,13 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
621 | } | 629 | } |
622 | } | 630 | } |
623 | } | 631 | } |
632 | EXPORT_SYMBOL(ath9k_hw_ani_monitor); | ||
624 | 633 | ||
625 | void ath9k_enable_mib_counters(struct ath_hw *ah) | 634 | void ath9k_enable_mib_counters(struct ath_hw *ah) |
626 | { | 635 | { |
627 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n"); | 636 | struct ath_common *common = ath9k_hw_common(ah); |
637 | |||
638 | ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n"); | ||
628 | 639 | ||
629 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 640 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
630 | 641 | ||
@@ -640,7 +651,10 @@ void ath9k_enable_mib_counters(struct ath_hw *ah) | |||
640 | /* Freeze the MIB counters, get the stats and then clear them */ | 651 | /* Freeze the MIB counters, get the stats and then clear them */ |
641 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah) | 652 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah) |
642 | { | 653 | { |
643 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n"); | 654 | struct ath_common *common = ath9k_hw_common(ah); |
655 | |||
656 | ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n"); | ||
657 | |||
644 | REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); | 658 | REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); |
645 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 659 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
646 | REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC); | 660 | REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC); |
@@ -653,6 +667,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, | |||
653 | u32 *rxf_pcnt, | 667 | u32 *rxf_pcnt, |
654 | u32 *txf_pcnt) | 668 | u32 *txf_pcnt) |
655 | { | 669 | { |
670 | struct ath_common *common = ath9k_hw_common(ah); | ||
656 | static u32 cycles, rx_clear, rx_frame, tx_frame; | 671 | static u32 cycles, rx_clear, rx_frame, tx_frame; |
657 | u32 good = 1; | 672 | u32 good = 1; |
658 | 673 | ||
@@ -662,8 +677,8 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, | |||
662 | u32 cc = REG_READ(ah, AR_CCCNT); | 677 | u32 cc = REG_READ(ah, AR_CCCNT); |
663 | 678 | ||
664 | if (cycles == 0 || cycles > cc) { | 679 | if (cycles == 0 || cycles > cc) { |
665 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 680 | ath_print(common, ATH_DBG_ANI, |
666 | "cycle counter wrap. ExtBusy = 0\n"); | 681 | "cycle counter wrap. ExtBusy = 0\n"); |
667 | good = 0; | 682 | good = 0; |
668 | } else { | 683 | } else { |
669 | u32 cc_d = cc - cycles; | 684 | u32 cc_d = cc - cycles; |
@@ -742,6 +757,7 @@ void ath9k_hw_procmibevent(struct ath_hw *ah) | |||
742 | ath9k_ani_restart(ah); | 757 | ath9k_ani_restart(ah); |
743 | } | 758 | } |
744 | } | 759 | } |
760 | EXPORT_SYMBOL(ath9k_hw_procmibevent); | ||
745 | 761 | ||
746 | void ath9k_hw_ani_setup(struct ath_hw *ah) | 762 | void ath9k_hw_ani_setup(struct ath_hw *ah) |
747 | { | 763 | { |
@@ -762,9 +778,10 @@ void ath9k_hw_ani_setup(struct ath_hw *ah) | |||
762 | 778 | ||
763 | void ath9k_hw_ani_init(struct ath_hw *ah) | 779 | void ath9k_hw_ani_init(struct ath_hw *ah) |
764 | { | 780 | { |
781 | struct ath_common *common = ath9k_hw_common(ah); | ||
765 | int i; | 782 | int i; |
766 | 783 | ||
767 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Initialize ANI\n"); | 784 | ath_print(common, ATH_DBG_ANI, "Initialize ANI\n"); |
768 | 785 | ||
769 | memset(ah->ani, 0, sizeof(ah->ani)); | 786 | memset(ah->ani, 0, sizeof(ah->ani)); |
770 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | 787 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { |
@@ -786,11 +803,11 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
786 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; | 803 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; |
787 | } | 804 | } |
788 | 805 | ||
789 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 806 | ath_print(common, ATH_DBG_ANI, |
790 | "Setting OfdmErrBase = 0x%08x\n", | 807 | "Setting OfdmErrBase = 0x%08x\n", |
791 | ah->ani[0].ofdmPhyErrBase); | 808 | ah->ani[0].ofdmPhyErrBase); |
792 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", | 809 | ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", |
793 | ah->ani[0].cckPhyErrBase); | 810 | ah->ani[0].cckPhyErrBase); |
794 | 811 | ||
795 | REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); | 812 | REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); |
796 | REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); | 813 | REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); |
@@ -803,7 +820,7 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
803 | 820 | ||
804 | void ath9k_hw_ani_disable(struct ath_hw *ah) | 821 | void ath9k_hw_ani_disable(struct ath_hw *ah) |
805 | { | 822 | { |
806 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n"); | 823 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, "Disabling ANI\n"); |
807 | 824 | ||
808 | ath9k_hw_disable_mib_counters(ah); | 825 | ath9k_hw_disable_mib_counters(ah); |
809 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | 826 | REG_WRITE(ah, AR_PHY_ERR_1, 0); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 1d59f10f68da..13dd0202d6b5 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #include "rc.h" | 26 | #include "rc.h" |
27 | #include "debug.h" | 27 | #include "debug.h" |
28 | #include "../ath.h" | 28 | #include "../ath.h" |
29 | #include "btcoex.h" | 29 | #include "../debug.h" |
30 | 30 | ||
31 | struct ath_node; | 31 | struct ath_node; |
32 | 32 | ||
@@ -54,15 +54,11 @@ struct ath_node; | |||
54 | 54 | ||
55 | #define A_MAX(a, b) ((a) > (b) ? (a) : (b)) | 55 | #define A_MAX(a, b) ((a) > (b) ? (a) : (b)) |
56 | 56 | ||
57 | #define ASSERT(exp) BUG_ON(!(exp)) | ||
58 | |||
59 | #define TSF_TO_TU(_h,_l) \ | 57 | #define TSF_TO_TU(_h,_l) \ |
60 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | 58 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) |
61 | 59 | ||
62 | #define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i)) | 60 | #define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i)) |
63 | 61 | ||
64 | static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
65 | |||
66 | struct ath_config { | 62 | struct ath_config { |
67 | u32 ath_aggr_prot; | 63 | u32 ath_aggr_prot; |
68 | u16 txpowlimit; | 64 | u16 txpowlimit; |
@@ -191,7 +187,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
191 | /* minimum h/w qdepth to be sustained to maximize aggregation */ | 187 | /* minimum h/w qdepth to be sustained to maximize aggregation */ |
192 | #define ATH_AGGR_MIN_QDEPTH 2 | 188 | #define ATH_AGGR_MIN_QDEPTH 2 |
193 | #define ATH_AMPDU_SUBFRAME_DEFAULT 32 | 189 | #define ATH_AMPDU_SUBFRAME_DEFAULT 32 |
194 | #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) | ||
195 | 190 | ||
196 | #define IEEE80211_SEQ_SEQ_SHIFT 4 | 191 | #define IEEE80211_SEQ_SEQ_SHIFT 4 |
197 | #define IEEE80211_SEQ_MAX 4096 | 192 | #define IEEE80211_SEQ_MAX 4096 |
@@ -293,7 +288,6 @@ struct ath_tx_control { | |||
293 | 288 | ||
294 | #define ATH_RSSI_LPF_LEN 10 | 289 | #define ATH_RSSI_LPF_LEN 10 |
295 | #define RSSI_LPF_THRESHOLD -20 | 290 | #define RSSI_LPF_THRESHOLD -20 |
296 | #define ATH9K_RSSI_BAD 0x80 | ||
297 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) | 291 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) |
298 | #define ATH_EP_MUL(x, mul) ((x) * (mul)) | 292 | #define ATH_EP_MUL(x, mul) ((x) * (mul)) |
299 | #define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) | 293 | #define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) |
@@ -427,7 +421,6 @@ struct ath_beacon { | |||
427 | 421 | ||
428 | void ath_beacon_tasklet(unsigned long data); | 422 | void ath_beacon_tasklet(unsigned long data); |
429 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); | 423 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); |
430 | int ath_beaconq_setup(struct ath_hw *ah); | ||
431 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif); | 424 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif); |
432 | void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); | 425 | void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); |
433 | 426 | ||
@@ -451,6 +444,26 @@ struct ath_ani { | |||
451 | struct timer_list timer; | 444 | struct timer_list timer; |
452 | }; | 445 | }; |
453 | 446 | ||
447 | /* Defines the BT AR_BT_COEX_WGHT used */ | ||
448 | enum ath_stomp_type { | ||
449 | ATH_BTCOEX_NO_STOMP, | ||
450 | ATH_BTCOEX_STOMP_ALL, | ||
451 | ATH_BTCOEX_STOMP_LOW, | ||
452 | ATH_BTCOEX_STOMP_NONE | ||
453 | }; | ||
454 | |||
455 | struct ath_btcoex { | ||
456 | bool hw_timer_enabled; | ||
457 | spinlock_t btcoex_lock; | ||
458 | struct timer_list period_timer; /* Timer for BT period */ | ||
459 | u32 bt_priority_cnt; | ||
460 | unsigned long bt_priority_time; | ||
461 | int bt_stomp_type; /* Types of BT stomping */ | ||
462 | u32 btcoex_no_stomp; /* in usec */ | ||
463 | u32 btcoex_period; /* in usec */ | ||
464 | struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ | ||
465 | }; | ||
466 | |||
454 | /********************/ | 467 | /********************/ |
455 | /* LED Control */ | 468 | /* LED Control */ |
456 | /********************/ | 469 | /********************/ |
@@ -484,7 +497,6 @@ struct ath_led { | |||
484 | * Used when PCI device not fully initialized by bootrom/BIOS | 497 | * Used when PCI device not fully initialized by bootrom/BIOS |
485 | */ | 498 | */ |
486 | #define DEFAULT_CACHELINE 32 | 499 | #define DEFAULT_CACHELINE 32 |
487 | #define ATH_DEFAULT_NOISE_FLOOR -95 | ||
488 | #define ATH_REGCLASSIDS_MAX 10 | 500 | #define ATH_REGCLASSIDS_MAX 10 |
489 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | 501 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ |
490 | #define ATH_MAX_SW_RETRIES 10 | 502 | #define ATH_MAX_SW_RETRIES 10 |
@@ -522,23 +534,14 @@ struct ath_led { | |||
522 | #define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17) | 534 | #define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17) |
523 | #define SC_OP_WAIT_FOR_TX_ACK BIT(18) | 535 | #define SC_OP_WAIT_FOR_TX_ACK BIT(18) |
524 | #define SC_OP_BEACON_SYNC BIT(19) | 536 | #define SC_OP_BEACON_SYNC BIT(19) |
525 | #define SC_OP_BTCOEX_ENABLED BIT(20) | ||
526 | #define SC_OP_BT_PRIORITY_DETECTED BIT(21) | 537 | #define SC_OP_BT_PRIORITY_DETECTED BIT(21) |
527 | 538 | ||
528 | struct ath_bus_ops { | ||
529 | void (*read_cachesize)(struct ath_softc *sc, int *csz); | ||
530 | void (*cleanup)(struct ath_softc *sc); | ||
531 | bool (*eeprom_read)(struct ath_hw *ah, u32 off, u16 *data); | ||
532 | }; | ||
533 | |||
534 | struct ath_wiphy; | 539 | struct ath_wiphy; |
535 | 540 | ||
536 | struct ath_softc { | 541 | struct ath_softc { |
537 | struct ieee80211_hw *hw; | 542 | struct ieee80211_hw *hw; |
538 | struct device *dev; | 543 | struct device *dev; |
539 | 544 | ||
540 | struct ath_common common; | ||
541 | |||
542 | spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ | 545 | spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ |
543 | struct ath_wiphy *pri_wiphy; | 546 | struct ath_wiphy *pri_wiphy; |
544 | struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may | 547 | struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may |
@@ -565,24 +568,17 @@ struct ath_softc { | |||
565 | spinlock_t sc_pm_lock; | 568 | spinlock_t sc_pm_lock; |
566 | struct mutex mutex; | 569 | struct mutex mutex; |
567 | 570 | ||
568 | u8 curbssid[ETH_ALEN]; | ||
569 | u8 bssidmask[ETH_ALEN]; | ||
570 | u32 intrstatus; | 571 | u32 intrstatus; |
571 | u32 sc_flags; /* SC_OP_* */ | 572 | u32 sc_flags; /* SC_OP_* */ |
572 | u16 curtxpow; | 573 | u16 curtxpow; |
573 | u16 curaid; | ||
574 | u8 nbcnvifs; | 574 | u8 nbcnvifs; |
575 | u16 nvifs; | 575 | u16 nvifs; |
576 | u8 tx_chainmask; | ||
577 | u8 rx_chainmask; | ||
578 | u32 keymax; | 576 | u32 keymax; |
579 | DECLARE_BITMAP(keymap, ATH_KEYMAX); | 577 | DECLARE_BITMAP(keymap, ATH_KEYMAX); |
580 | u8 splitmic; | 578 | u8 splitmic; |
581 | bool ps_enabled; | 579 | bool ps_enabled; |
582 | unsigned long ps_usecount; | 580 | unsigned long ps_usecount; |
583 | enum ath9k_int imask; | 581 | enum ath9k_int imask; |
584 | enum ath9k_ht_extprotspacing ht_extprotspacing; | ||
585 | enum ath9k_ht_macmode tx_chan_width; | ||
586 | 582 | ||
587 | struct ath_config config; | 583 | struct ath_config config; |
588 | struct ath_rx rx; | 584 | struct ath_rx rx; |
@@ -609,10 +605,9 @@ struct ath_softc { | |||
609 | #ifdef CONFIG_ATH9K_DEBUG | 605 | #ifdef CONFIG_ATH9K_DEBUG |
610 | struct ath9k_debug debug; | 606 | struct ath9k_debug debug; |
611 | #endif | 607 | #endif |
612 | struct ath_bus_ops *bus_ops; | ||
613 | struct ath_beacon_config cur_beacon_conf; | 608 | struct ath_beacon_config cur_beacon_conf; |
614 | struct delayed_work tx_complete_work; | 609 | struct delayed_work tx_complete_work; |
615 | struct ath_btcoex_info btcoex_info; | 610 | struct ath_btcoex btcoex; |
616 | }; | 611 | }; |
617 | 612 | ||
618 | struct ath_wiphy { | 613 | struct ath_wiphy { |
@@ -634,31 +629,22 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); | |||
634 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); | 629 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); |
635 | int ath_cabq_update(struct ath_softc *); | 630 | int ath_cabq_update(struct ath_softc *); |
636 | 631 | ||
637 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) | 632 | static inline void ath_read_cachesize(struct ath_common *common, int *csz) |
638 | { | ||
639 | return &ah->ah_sc->common; | ||
640 | } | ||
641 | |||
642 | static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) | ||
643 | { | 633 | { |
644 | return &(ath9k_hw_common(ah)->regulatory); | 634 | common->bus_ops->read_cachesize(common, csz); |
645 | } | 635 | } |
646 | 636 | ||
647 | static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) | 637 | static inline void ath_bus_cleanup(struct ath_common *common) |
648 | { | 638 | { |
649 | sc->bus_ops->read_cachesize(sc, csz); | 639 | common->bus_ops->cleanup(common); |
650 | } | ||
651 | |||
652 | static inline void ath_bus_cleanup(struct ath_softc *sc) | ||
653 | { | ||
654 | sc->bus_ops->cleanup(sc); | ||
655 | } | 640 | } |
656 | 641 | ||
657 | extern struct ieee80211_ops ath9k_ops; | 642 | extern struct ieee80211_ops ath9k_ops; |
658 | 643 | ||
659 | irqreturn_t ath_isr(int irq, void *dev); | 644 | irqreturn_t ath_isr(int irq, void *dev); |
660 | void ath_cleanup(struct ath_softc *sc); | 645 | void ath_cleanup(struct ath_softc *sc); |
661 | int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid); | 646 | int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, |
647 | const struct ath_bus_ops *bus_ops); | ||
662 | void ath_detach(struct ath_softc *sc); | 648 | void ath_detach(struct ath_softc *sc); |
663 | const char *ath_mac_bb_name(u32 mac_bb_version); | 649 | const char *ath_mac_bb_name(u32 mac_bb_version); |
664 | const char *ath_rf_name(u16 rf_version); | 650 | const char *ath_rf_name(u16 rf_version); |
@@ -706,8 +692,5 @@ bool ath9k_wiphy_scanning(struct ath_softc *sc); | |||
706 | void ath9k_wiphy_work(struct work_struct *work); | 692 | void ath9k_wiphy_work(struct work_struct *work); |
707 | bool ath9k_all_wiphys_idle(struct ath_softc *sc); | 693 | bool ath9k_all_wiphys_idle(struct ath_softc *sc); |
708 | 694 | ||
709 | void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); | ||
710 | unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); | ||
711 | |||
712 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); | 695 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); |
713 | #endif /* ATH9K_H */ | 696 | #endif /* ATH9K_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 45c4ea57616b..b10c884f2933 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -26,6 +26,7 @@ | |||
26 | static int ath_beaconq_config(struct ath_softc *sc) | 26 | static int ath_beaconq_config(struct ath_softc *sc) |
27 | { | 27 | { |
28 | struct ath_hw *ah = sc->sc_ah; | 28 | struct ath_hw *ah = sc->sc_ah; |
29 | struct ath_common *common = ath9k_hw_common(ah); | ||
29 | struct ath9k_tx_queue_info qi; | 30 | struct ath9k_tx_queue_info qi; |
30 | 31 | ||
31 | ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); | 32 | ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); |
@@ -42,8 +43,8 @@ static int ath_beaconq_config(struct ath_softc *sc) | |||
42 | } | 43 | } |
43 | 44 | ||
44 | if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { | 45 | if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { |
45 | DPRINTF(sc, ATH_DBG_FATAL, | 46 | ath_print(common, ATH_DBG_FATAL, |
46 | "Unable to update h/w beacon queue parameters\n"); | 47 | "Unable to update h/w beacon queue parameters\n"); |
47 | return 0; | 48 | return 0; |
48 | } else { | 49 | } else { |
49 | ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); | 50 | ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); |
@@ -61,6 +62,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
61 | { | 62 | { |
62 | struct sk_buff *skb = bf->bf_mpdu; | 63 | struct sk_buff *skb = bf->bf_mpdu; |
63 | struct ath_hw *ah = sc->sc_ah; | 64 | struct ath_hw *ah = sc->sc_ah; |
65 | struct ath_common *common = ath9k_hw_common(ah); | ||
64 | struct ath_desc *ds; | 66 | struct ath_desc *ds; |
65 | struct ath9k_11n_rate_series series[4]; | 67 | struct ath9k_11n_rate_series series[4]; |
66 | const struct ath_rate_table *rt; | 68 | const struct ath_rate_table *rt; |
@@ -108,7 +110,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
108 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); | 110 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); |
109 | series[0].Tries = 1; | 111 | series[0].Tries = 1; |
110 | series[0].Rate = rate; | 112 | series[0].Rate = rate; |
111 | series[0].ChSel = sc->tx_chainmask; | 113 | series[0].ChSel = common->tx_chainmask; |
112 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; | 114 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; |
113 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, | 115 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, |
114 | series, 4, 0); | 116 | series, 4, 0); |
@@ -119,6 +121,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
119 | { | 121 | { |
120 | struct ath_wiphy *aphy = hw->priv; | 122 | struct ath_wiphy *aphy = hw->priv; |
121 | struct ath_softc *sc = aphy->sc; | 123 | struct ath_softc *sc = aphy->sc; |
124 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
122 | struct ath_buf *bf; | 125 | struct ath_buf *bf; |
123 | struct ath_vif *avp; | 126 | struct ath_vif *avp; |
124 | struct sk_buff *skb; | 127 | struct sk_buff *skb; |
@@ -172,7 +175,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
172 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { | 175 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { |
173 | dev_kfree_skb_any(skb); | 176 | dev_kfree_skb_any(skb); |
174 | bf->bf_mpdu = NULL; | 177 | bf->bf_mpdu = NULL; |
175 | DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n"); | 178 | ath_print(common, ATH_DBG_FATAL, |
179 | "dma_mapping_error on beaconing\n"); | ||
176 | return NULL; | 180 | return NULL; |
177 | } | 181 | } |
178 | 182 | ||
@@ -192,8 +196,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
192 | 196 | ||
193 | if (skb && cabq_depth) { | 197 | if (skb && cabq_depth) { |
194 | if (sc->nvifs > 1) { | 198 | if (sc->nvifs > 1) { |
195 | DPRINTF(sc, ATH_DBG_BEACON, | 199 | ath_print(common, ATH_DBG_BEACON, |
196 | "Flushing previous cabq traffic\n"); | 200 | "Flushing previous cabq traffic\n"); |
197 | ath_draintxq(sc, cabq, false); | 201 | ath_draintxq(sc, cabq, false); |
198 | } | 202 | } |
199 | } | 203 | } |
@@ -216,6 +220,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, | |||
216 | struct ieee80211_vif *vif) | 220 | struct ieee80211_vif *vif) |
217 | { | 221 | { |
218 | struct ath_hw *ah = sc->sc_ah; | 222 | struct ath_hw *ah = sc->sc_ah; |
223 | struct ath_common *common = ath9k_hw_common(ah); | ||
219 | struct ath_buf *bf; | 224 | struct ath_buf *bf; |
220 | struct ath_vif *avp; | 225 | struct ath_vif *avp; |
221 | struct sk_buff *skb; | 226 | struct sk_buff *skb; |
@@ -233,25 +238,14 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, | |||
233 | /* NB: caller is known to have already stopped tx dma */ | 238 | /* NB: caller is known to have already stopped tx dma */ |
234 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); | 239 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); |
235 | ath9k_hw_txstart(ah, sc->beacon.beaconq); | 240 | ath9k_hw_txstart(ah, sc->beacon.beaconq); |
236 | DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n", | 241 | ath_print(common, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n", |
237 | sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc); | 242 | sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc); |
238 | } | ||
239 | |||
240 | int ath_beaconq_setup(struct ath_hw *ah) | ||
241 | { | ||
242 | struct ath9k_tx_queue_info qi; | ||
243 | |||
244 | memset(&qi, 0, sizeof(qi)); | ||
245 | qi.tqi_aifs = 1; | ||
246 | qi.tqi_cwmin = 0; | ||
247 | qi.tqi_cwmax = 0; | ||
248 | /* NB: don't enable any interrupts */ | ||
249 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); | ||
250 | } | 243 | } |
251 | 244 | ||
252 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | 245 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) |
253 | { | 246 | { |
254 | struct ath_softc *sc = aphy->sc; | 247 | struct ath_softc *sc = aphy->sc; |
248 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
255 | struct ath_vif *avp; | 249 | struct ath_vif *avp; |
256 | struct ath_buf *bf; | 250 | struct ath_buf *bf; |
257 | struct sk_buff *skb; | 251 | struct sk_buff *skb; |
@@ -309,7 +303,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
309 | /* NB: the beacon data buffer must be 32-bit aligned. */ | 303 | /* NB: the beacon data buffer must be 32-bit aligned. */ |
310 | skb = ieee80211_beacon_get(sc->hw, vif); | 304 | skb = ieee80211_beacon_get(sc->hw, vif); |
311 | if (skb == NULL) { | 305 | if (skb == NULL) { |
312 | DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n"); | 306 | ath_print(common, ATH_DBG_BEACON, "cannot get skb\n"); |
313 | return -ENOMEM; | 307 | return -ENOMEM; |
314 | } | 308 | } |
315 | 309 | ||
@@ -333,9 +327,10 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
333 | tsfadjust = intval * avp->av_bslot / ATH_BCBUF; | 327 | tsfadjust = intval * avp->av_bslot / ATH_BCBUF; |
334 | avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); | 328 | avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); |
335 | 329 | ||
336 | DPRINTF(sc, ATH_DBG_BEACON, | 330 | ath_print(common, ATH_DBG_BEACON, |
337 | "stagger beacons, bslot %d intval %u tsfadjust %llu\n", | 331 | "stagger beacons, bslot %d intval " |
338 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | 332 | "%u tsfadjust %llu\n", |
333 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | ||
339 | 334 | ||
340 | ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = | 335 | ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = |
341 | avp->tsf_adjust; | 336 | avp->tsf_adjust; |
@@ -349,8 +344,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
349 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { | 344 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { |
350 | dev_kfree_skb_any(skb); | 345 | dev_kfree_skb_any(skb); |
351 | bf->bf_mpdu = NULL; | 346 | bf->bf_mpdu = NULL; |
352 | DPRINTF(sc, ATH_DBG_FATAL, | 347 | ath_print(common, ATH_DBG_FATAL, |
353 | "dma_mapping_error on beacon alloc\n"); | 348 | "dma_mapping_error on beacon alloc\n"); |
354 | return -ENOMEM; | 349 | return -ENOMEM; |
355 | } | 350 | } |
356 | 351 | ||
@@ -386,6 +381,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
386 | { | 381 | { |
387 | struct ath_softc *sc = (struct ath_softc *)data; | 382 | struct ath_softc *sc = (struct ath_softc *)data; |
388 | struct ath_hw *ah = sc->sc_ah; | 383 | struct ath_hw *ah = sc->sc_ah; |
384 | struct ath_common *common = ath9k_hw_common(ah); | ||
389 | struct ath_buf *bf = NULL; | 385 | struct ath_buf *bf = NULL; |
390 | struct ieee80211_vif *vif; | 386 | struct ieee80211_vif *vif; |
391 | struct ath_wiphy *aphy; | 387 | struct ath_wiphy *aphy; |
@@ -405,12 +401,12 @@ void ath_beacon_tasklet(unsigned long data) | |||
405 | sc->beacon.bmisscnt++; | 401 | sc->beacon.bmisscnt++; |
406 | 402 | ||
407 | if (sc->beacon.bmisscnt < BSTUCK_THRESH) { | 403 | if (sc->beacon.bmisscnt < BSTUCK_THRESH) { |
408 | DPRINTF(sc, ATH_DBG_BEACON, | 404 | ath_print(common, ATH_DBG_BEACON, |
409 | "missed %u consecutive beacons\n", | 405 | "missed %u consecutive beacons\n", |
410 | sc->beacon.bmisscnt); | 406 | sc->beacon.bmisscnt); |
411 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { | 407 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { |
412 | DPRINTF(sc, ATH_DBG_BEACON, | 408 | ath_print(common, ATH_DBG_BEACON, |
413 | "beacon is officially stuck\n"); | 409 | "beacon is officially stuck\n"); |
414 | sc->sc_flags |= SC_OP_TSF_RESET; | 410 | sc->sc_flags |= SC_OP_TSF_RESET; |
415 | ath_reset(sc, false); | 411 | ath_reset(sc, false); |
416 | } | 412 | } |
@@ -419,9 +415,9 @@ void ath_beacon_tasklet(unsigned long data) | |||
419 | } | 415 | } |
420 | 416 | ||
421 | if (sc->beacon.bmisscnt != 0) { | 417 | if (sc->beacon.bmisscnt != 0) { |
422 | DPRINTF(sc, ATH_DBG_BEACON, | 418 | ath_print(common, ATH_DBG_BEACON, |
423 | "resume beacon xmit after %u misses\n", | 419 | "resume beacon xmit after %u misses\n", |
424 | sc->beacon.bmisscnt); | 420 | sc->beacon.bmisscnt); |
425 | sc->beacon.bmisscnt = 0; | 421 | sc->beacon.bmisscnt = 0; |
426 | } | 422 | } |
427 | 423 | ||
@@ -447,9 +443,9 @@ void ath_beacon_tasklet(unsigned long data) | |||
447 | vif = sc->beacon.bslot[slot]; | 443 | vif = sc->beacon.bslot[slot]; |
448 | aphy = sc->beacon.bslot_aphy[slot]; | 444 | aphy = sc->beacon.bslot_aphy[slot]; |
449 | 445 | ||
450 | DPRINTF(sc, ATH_DBG_BEACON, | 446 | ath_print(common, ATH_DBG_BEACON, |
451 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", | 447 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", |
452 | slot, tsf, tsftu, intval, vif); | 448 | slot, tsf, tsftu, intval, vif); |
453 | 449 | ||
454 | bfaddr = 0; | 450 | bfaddr = 0; |
455 | if (vif) { | 451 | if (vif) { |
@@ -490,7 +486,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
490 | * are still pending on the queue. | 486 | * are still pending on the queue. |
491 | */ | 487 | */ |
492 | if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { | 488 | if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { |
493 | DPRINTF(sc, ATH_DBG_FATAL, | 489 | ath_print(common, ATH_DBG_FATAL, |
494 | "beacon queue %u did not stop?\n", sc->beacon.beaconq); | 490 | "beacon queue %u did not stop?\n", sc->beacon.beaconq); |
495 | } | 491 | } |
496 | 492 | ||
@@ -502,6 +498,19 @@ void ath_beacon_tasklet(unsigned long data) | |||
502 | } | 498 | } |
503 | } | 499 | } |
504 | 500 | ||
501 | static void ath9k_beacon_init(struct ath_softc *sc, | ||
502 | u32 next_beacon, | ||
503 | u32 beacon_period) | ||
504 | { | ||
505 | if (beacon_period & ATH9K_BEACON_RESET_TSF) | ||
506 | ath9k_ps_wakeup(sc); | ||
507 | |||
508 | ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); | ||
509 | |||
510 | if (beacon_period & ATH9K_BEACON_RESET_TSF) | ||
511 | ath9k_ps_restore(sc); | ||
512 | } | ||
513 | |||
505 | /* | 514 | /* |
506 | * For multi-bss ap support beacons are either staggered evenly over N slots or | 515 | * For multi-bss ap support beacons are either staggered evenly over N slots or |
507 | * burst together. For the former arrange for the SWBA to be delivered for each | 516 | * burst together. For the former arrange for the SWBA to be delivered for each |
@@ -534,7 +543,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
534 | /* Set the computed AP beacon timers */ | 543 | /* Set the computed AP beacon timers */ |
535 | 544 | ||
536 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 545 | ath9k_hw_set_interrupts(sc->sc_ah, 0); |
537 | ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); | 546 | ath9k_beacon_init(sc, nexttbtt, intval); |
538 | sc->beacon.bmisscnt = 0; | 547 | sc->beacon.bmisscnt = 0; |
539 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 548 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); |
540 | 549 | ||
@@ -555,6 +564,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
555 | static void ath_beacon_config_sta(struct ath_softc *sc, | 564 | static void ath_beacon_config_sta(struct ath_softc *sc, |
556 | struct ath_beacon_config *conf) | 565 | struct ath_beacon_config *conf) |
557 | { | 566 | { |
567 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
558 | struct ath9k_beacon_state bs; | 568 | struct ath9k_beacon_state bs; |
559 | int dtimperiod, dtimcount, sleepduration; | 569 | int dtimperiod, dtimcount, sleepduration; |
560 | int cfpperiod, cfpcount; | 570 | int cfpperiod, cfpcount; |
@@ -651,11 +661,11 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
651 | /* TSF out of range threshold fixed at 1 second */ | 661 | /* TSF out of range threshold fixed at 1 second */ |
652 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | 662 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; |
653 | 663 | ||
654 | DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); | 664 | ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); |
655 | DPRINTF(sc, ATH_DBG_BEACON, | 665 | ath_print(common, ATH_DBG_BEACON, |
656 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", | 666 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", |
657 | bs.bs_bmissthreshold, bs.bs_sleepduration, | 667 | bs.bs_bmissthreshold, bs.bs_sleepduration, |
658 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | 668 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); |
659 | 669 | ||
660 | /* Set the computed STA beacon timers */ | 670 | /* Set the computed STA beacon timers */ |
661 | 671 | ||
@@ -669,6 +679,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
669 | struct ath_beacon_config *conf, | 679 | struct ath_beacon_config *conf, |
670 | struct ieee80211_vif *vif) | 680 | struct ieee80211_vif *vif) |
671 | { | 681 | { |
682 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
672 | u64 tsf; | 683 | u64 tsf; |
673 | u32 tsftu, intval, nexttbtt; | 684 | u32 tsftu, intval, nexttbtt; |
674 | 685 | ||
@@ -689,9 +700,9 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
689 | nexttbtt += intval; | 700 | nexttbtt += intval; |
690 | } while (nexttbtt < tsftu); | 701 | } while (nexttbtt < tsftu); |
691 | 702 | ||
692 | DPRINTF(sc, ATH_DBG_BEACON, | 703 | ath_print(common, ATH_DBG_BEACON, |
693 | "IBSS nexttbtt %u intval %u (%u)\n", | 704 | "IBSS nexttbtt %u intval %u (%u)\n", |
694 | nexttbtt, intval, conf->beacon_interval); | 705 | nexttbtt, intval, conf->beacon_interval); |
695 | 706 | ||
696 | /* | 707 | /* |
697 | * In IBSS mode enable the beacon timers but only enable SWBA interrupts | 708 | * In IBSS mode enable the beacon timers but only enable SWBA interrupts |
@@ -707,7 +718,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
707 | /* Set the computed ADHOC beacon timers */ | 718 | /* Set the computed ADHOC beacon timers */ |
708 | 719 | ||
709 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 720 | ath9k_hw_set_interrupts(sc->sc_ah, 0); |
710 | ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); | 721 | ath9k_beacon_init(sc, nexttbtt, intval); |
711 | sc->beacon.bmisscnt = 0; | 722 | sc->beacon.bmisscnt = 0; |
712 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 723 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); |
713 | 724 | ||
@@ -719,6 +730,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
719 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | 730 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) |
720 | { | 731 | { |
721 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | 732 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; |
733 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
722 | enum nl80211_iftype iftype; | 734 | enum nl80211_iftype iftype; |
723 | 735 | ||
724 | /* Setup the beacon configuration parameters */ | 736 | /* Setup the beacon configuration parameters */ |
@@ -759,8 +771,8 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
759 | ath_beacon_config_sta(sc, cur_conf); | 771 | ath_beacon_config_sta(sc, cur_conf); |
760 | break; | 772 | break; |
761 | default: | 773 | default: |
762 | DPRINTF(sc, ATH_DBG_CONFIG, | 774 | ath_print(common, ATH_DBG_CONFIG, |
763 | "Unsupported beaconing mode\n"); | 775 | "Unsupported beaconing mode\n"); |
764 | return; | 776 | return; |
765 | } | 777 | } |
766 | 778 | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 55f607b7699e..fb4ac15f3b93 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -14,10 +14,26 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | static const struct ath_btcoex_config ath_bt_config = { 0, true, true, | 19 | enum ath_bt_mode { |
20 | ATH_BT_COEX_MODE_SLOTTED, true, true, 2, 5, true }; | 20 | ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */ |
21 | ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */ | ||
22 | ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */ | ||
23 | ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */ | ||
24 | }; | ||
25 | |||
26 | struct ath_btcoex_config { | ||
27 | u8 bt_time_extend; | ||
28 | bool bt_txstate_extend; | ||
29 | bool bt_txframe_extend; | ||
30 | enum ath_bt_mode bt_mode; /* coexistence mode */ | ||
31 | bool bt_quiet_collision; | ||
32 | bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/ | ||
33 | u8 bt_priority_time; | ||
34 | u8 bt_first_slot_time; | ||
35 | bool bt_hold_rx_clear; | ||
36 | }; | ||
21 | 37 | ||
22 | static const u16 ath_subsysid_tbl[] = { | 38 | static const u16 ath_subsysid_tbl[] = { |
23 | AR9280_COEX2WIRE_SUBSYSID, | 39 | AR9280_COEX2WIRE_SUBSYSID, |
@@ -29,141 +45,38 @@ static const u16 ath_subsysid_tbl[] = { | |||
29 | * Checks the subsystem id of the device to see if it | 45 | * Checks the subsystem id of the device to see if it |
30 | * supports btcoex | 46 | * supports btcoex |
31 | */ | 47 | */ |
32 | bool ath_btcoex_supported(u16 subsysid) | 48 | bool ath9k_hw_btcoex_supported(struct ath_hw *ah) |
33 | { | 49 | { |
34 | int i; | 50 | int i; |
35 | 51 | ||
36 | if (!subsysid) | 52 | if (!ah->hw_version.subsysid) |
37 | return false; | 53 | return false; |
38 | 54 | ||
39 | for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++) | 55 | for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++) |
40 | if (subsysid == ath_subsysid_tbl[i]) | 56 | if (ah->hw_version.subsysid == ath_subsysid_tbl[i]) |
41 | return true; | 57 | return true; |
42 | 58 | ||
43 | return false; | 59 | return false; |
44 | } | 60 | } |
45 | 61 | ||
46 | /* | 62 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) |
47 | * Detects if there is any priority bt traffic | ||
48 | */ | ||
49 | static void ath_detect_bt_priority(struct ath_softc *sc) | ||
50 | { | ||
51 | struct ath_btcoex_info *btinfo = &sc->btcoex_info; | ||
52 | |||
53 | if (ath9k_hw_gpio_get(sc->sc_ah, btinfo->btpriority_gpio)) | ||
54 | btinfo->bt_priority_cnt++; | ||
55 | |||
56 | if (time_after(jiffies, btinfo->bt_priority_time + | ||
57 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { | ||
58 | if (btinfo->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | ||
59 | DPRINTF(sc, ATH_DBG_BTCOEX, | ||
60 | "BT priority traffic detected"); | ||
61 | sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; | ||
62 | } else { | ||
63 | sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; | ||
64 | } | ||
65 | |||
66 | btinfo->bt_priority_cnt = 0; | ||
67 | btinfo->bt_priority_time = jiffies; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * Configures appropriate weight based on stomp type. | ||
73 | */ | ||
74 | static void ath_btcoex_bt_stomp(struct ath_softc *sc, | ||
75 | struct ath_btcoex_info *btinfo, | ||
76 | int stomp_type) | ||
77 | { | ||
78 | |||
79 | switch (stomp_type) { | ||
80 | case ATH_BTCOEX_STOMP_ALL: | ||
81 | ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, | ||
82 | AR_STOMP_ALL_WLAN_WGHT); | ||
83 | break; | ||
84 | case ATH_BTCOEX_STOMP_LOW: | ||
85 | ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, | ||
86 | AR_STOMP_LOW_WLAN_WGHT); | ||
87 | break; | ||
88 | case ATH_BTCOEX_STOMP_NONE: | ||
89 | ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, | ||
90 | AR_STOMP_NONE_WLAN_WGHT); | ||
91 | break; | ||
92 | default: | ||
93 | DPRINTF(sc, ATH_DBG_BTCOEX, "Invalid Stomptype\n"); | ||
94 | break; | ||
95 | } | ||
96 | |||
97 | ath9k_hw_btcoex_enable(sc->sc_ah); | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * This is the master bt coex timer which runs for every | ||
102 | * 45ms, bt traffic will be given priority during 55% of this | ||
103 | * period while wlan gets remaining 45% | ||
104 | */ | ||
105 | |||
106 | static void ath_btcoex_period_timer(unsigned long data) | ||
107 | { | ||
108 | struct ath_softc *sc = (struct ath_softc *) data; | ||
109 | struct ath_btcoex_info *btinfo = &sc->btcoex_info; | ||
110 | |||
111 | ath_detect_bt_priority(sc); | ||
112 | |||
113 | spin_lock_bh(&btinfo->btcoex_lock); | ||
114 | |||
115 | ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type); | ||
116 | |||
117 | spin_unlock_bh(&btinfo->btcoex_lock); | ||
118 | |||
119 | if (btinfo->btcoex_period != btinfo->btcoex_no_stomp) { | ||
120 | if (btinfo->hw_timer_enabled) | ||
121 | ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); | ||
122 | |||
123 | ath_gen_timer_start(sc->sc_ah, | ||
124 | btinfo->no_stomp_timer, | ||
125 | (ath9k_hw_gettsf32(sc->sc_ah) + | ||
126 | btinfo->btcoex_no_stomp), | ||
127 | btinfo->btcoex_no_stomp * 10); | ||
128 | btinfo->hw_timer_enabled = true; | ||
129 | } | ||
130 | |||
131 | mod_timer(&btinfo->period_timer, jiffies + | ||
132 | msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * Generic tsf based hw timer which configures weight | ||
137 | * registers to time slice between wlan and bt traffic | ||
138 | */ | ||
139 | |||
140 | static void ath_btcoex_no_stomp_timer(void *arg) | ||
141 | { | ||
142 | struct ath_softc *sc = (struct ath_softc *)arg; | ||
143 | struct ath_btcoex_info *btinfo = &sc->btcoex_info; | ||
144 | |||
145 | DPRINTF(sc, ATH_DBG_BTCOEX, "no stomp timer running \n"); | ||
146 | |||
147 | spin_lock_bh(&btinfo->btcoex_lock); | ||
148 | |||
149 | if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) | ||
150 | ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE); | ||
151 | else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | ||
152 | ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW); | ||
153 | |||
154 | spin_unlock_bh(&btinfo->btcoex_lock); | ||
155 | } | ||
156 | |||
157 | static int ath_init_btcoex_info(struct ath_hw *hw, | ||
158 | struct ath_btcoex_info *btcoex_info) | ||
159 | { | 63 | { |
64 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | ||
65 | const struct ath_btcoex_config ath_bt_config = { | ||
66 | .bt_time_extend = 0, | ||
67 | .bt_txstate_extend = true, | ||
68 | .bt_txframe_extend = true, | ||
69 | .bt_mode = ATH_BT_COEX_MODE_SLOTTED, | ||
70 | .bt_quiet_collision = true, | ||
71 | .bt_rxclear_polarity = true, | ||
72 | .bt_priority_time = 2, | ||
73 | .bt_first_slot_time = 5, | ||
74 | .bt_hold_rx_clear = true, | ||
75 | }; | ||
160 | u32 i; | 76 | u32 i; |
161 | int qnum; | ||
162 | 77 | ||
163 | qnum = ath_tx_get_qnum(hw->ah_sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | 78 | btcoex_hw->bt_coex_mode = |
164 | 79 | (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) | | |
165 | btcoex_info->bt_coex_mode = | ||
166 | (btcoex_info->bt_coex_mode & AR_BT_QCU_THRESH) | | ||
167 | SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) | | 80 | SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) | |
168 | SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | | 81 | SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | |
169 | SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | | 82 | SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | |
@@ -174,167 +87,141 @@ static int ath_init_btcoex_info(struct ath_hw *hw, | |||
174 | SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | | 87 | SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | |
175 | SM(qnum, AR_BT_QCU_THRESH); | 88 | SM(qnum, AR_BT_QCU_THRESH); |
176 | 89 | ||
177 | btcoex_info->bt_coex_mode2 = | 90 | btcoex_hw->bt_coex_mode2 = |
178 | SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | | 91 | SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | |
179 | SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | | 92 | SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | |
180 | AR_BT_DISABLE_BT_ANT; | 93 | AR_BT_DISABLE_BT_ANT; |
181 | 94 | ||
182 | btcoex_info->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | 95 | for (i = 0; i < 32; i++) |
96 | ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; | ||
97 | } | ||
98 | EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw); | ||
183 | 99 | ||
184 | btcoex_info->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; | 100 | void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah) |
101 | { | ||
102 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | ||
185 | 103 | ||
186 | btcoex_info->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * | 104 | /* connect bt_active to baseband */ |
187 | btcoex_info->btcoex_period / 100; | 105 | REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, |
106 | (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | | ||
107 | AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); | ||
188 | 108 | ||
189 | for (i = 0; i < 32; i++) | 109 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, |
190 | hw->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; | 110 | AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); |
191 | 111 | ||
192 | setup_timer(&btcoex_info->period_timer, ath_btcoex_period_timer, | 112 | /* Set input mux for bt_active to gpio pin */ |
193 | (unsigned long) hw->ah_sc); | 113 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, |
114 | AR_GPIO_INPUT_MUX1_BT_ACTIVE, | ||
115 | btcoex_hw->btactive_gpio); | ||
194 | 116 | ||
195 | btcoex_info->no_stomp_timer = ath_gen_timer_alloc(hw, | 117 | /* Configure the desired gpio port for input */ |
196 | ath_btcoex_no_stomp_timer, | 118 | ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio); |
197 | ath_btcoex_no_stomp_timer, | 119 | } |
198 | (void *)hw->ah_sc, AR_FIRST_NDP_TIMER); | 120 | EXPORT_SYMBOL(ath9k_hw_btcoex_init_2wire); |
121 | |||
122 | void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah) | ||
123 | { | ||
124 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | ||
199 | 125 | ||
200 | if (btcoex_info->no_stomp_timer == NULL) | 126 | /* btcoex 3-wire */ |
201 | return -ENOMEM; | 127 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, |
128 | (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB | | ||
129 | AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB)); | ||
202 | 130 | ||
203 | spin_lock_init(&btcoex_info->btcoex_lock); | 131 | /* Set input mux for bt_prority_async and |
132 | * bt_active_async to GPIO pins */ | ||
133 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, | ||
134 | AR_GPIO_INPUT_MUX1_BT_ACTIVE, | ||
135 | btcoex_hw->btactive_gpio); | ||
204 | 136 | ||
205 | return 0; | 137 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, |
138 | AR_GPIO_INPUT_MUX1_BT_PRIORITY, | ||
139 | btcoex_hw->btpriority_gpio); | ||
140 | |||
141 | /* Configure the desired GPIO ports for input */ | ||
142 | |||
143 | ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio); | ||
144 | ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btpriority_gpio); | ||
206 | } | 145 | } |
146 | EXPORT_SYMBOL(ath9k_hw_btcoex_init_3wire); | ||
207 | 147 | ||
208 | int ath9k_hw_btcoex_init(struct ath_hw *ah) | 148 | static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah) |
209 | { | 149 | { |
210 | struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; | 150 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
211 | int ret = 0; | ||
212 | |||
213 | if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) { | ||
214 | /* connect bt_active to baseband */ | ||
215 | REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
216 | (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | | ||
217 | AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); | ||
218 | |||
219 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
220 | AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); | ||
221 | |||
222 | /* Set input mux for bt_active to gpio pin */ | ||
223 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, | ||
224 | AR_GPIO_INPUT_MUX1_BT_ACTIVE, | ||
225 | btcoex_info->btactive_gpio); | ||
226 | |||
227 | /* Configure the desired gpio port for input */ | ||
228 | ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); | ||
229 | } else { | ||
230 | /* btcoex 3-wire */ | ||
231 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
232 | (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB | | ||
233 | AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB)); | ||
234 | |||
235 | /* Set input mux for bt_prority_async and | ||
236 | * bt_active_async to GPIO pins */ | ||
237 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, | ||
238 | AR_GPIO_INPUT_MUX1_BT_ACTIVE, | ||
239 | btcoex_info->btactive_gpio); | ||
240 | |||
241 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, | ||
242 | AR_GPIO_INPUT_MUX1_BT_PRIORITY, | ||
243 | btcoex_info->btpriority_gpio); | ||
244 | |||
245 | /* Configure the desired GPIO ports for input */ | ||
246 | |||
247 | ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); | ||
248 | ath9k_hw_cfg_gpio_input(ah, btcoex_info->btpriority_gpio); | ||
249 | |||
250 | ret = ath_init_btcoex_info(ah, btcoex_info); | ||
251 | } | ||
252 | 151 | ||
253 | return ret; | 152 | /* Configure the desired GPIO port for TX_FRAME output */ |
153 | ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio, | ||
154 | AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); | ||
254 | } | 155 | } |
255 | 156 | ||
256 | void ath9k_hw_btcoex_enable(struct ath_hw *ah) | 157 | void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, |
158 | u32 bt_weight, | ||
159 | u32 wlan_weight) | ||
257 | { | 160 | { |
258 | struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; | 161 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
259 | |||
260 | if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) { | ||
261 | /* Configure the desired GPIO port for TX_FRAME output */ | ||
262 | ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, | ||
263 | AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); | ||
264 | } else { | ||
265 | /* | ||
266 | * Program coex mode and weight registers to | ||
267 | * enable coex 3-wire | ||
268 | */ | ||
269 | REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_info->bt_coex_mode); | ||
270 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_info->bt_coex_weights); | ||
271 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_info->bt_coex_mode2); | ||
272 | |||
273 | REG_RMW_FIELD(ah, AR_QUIET1, | ||
274 | AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); | ||
275 | REG_RMW_FIELD(ah, AR_PCU_MISC, | ||
276 | AR_PCU_BT_ANT_PREVENT_RX, 0); | ||
277 | |||
278 | ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, | ||
279 | AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL); | ||
280 | } | ||
281 | 162 | ||
282 | REG_RMW(ah, AR_GPIO_PDPU, | 163 | btcoex_hw->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) | |
283 | (0x2 << (btcoex_info->btactive_gpio * 2)), | 164 | SM(wlan_weight, AR_BTCOEX_WL_WGHT); |
284 | (0x3 << (btcoex_info->btactive_gpio * 2))); | ||
285 | |||
286 | ah->ah_sc->sc_flags |= SC_OP_BTCOEX_ENABLED; | ||
287 | } | 165 | } |
166 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); | ||
288 | 167 | ||
289 | void ath9k_hw_btcoex_disable(struct ath_hw *ah) | 168 | static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) |
290 | { | 169 | { |
291 | struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; | 170 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
292 | 171 | ||
293 | ath9k_hw_set_gpio(ah, btcoex_info->wlanactive_gpio, 0); | 172 | /* |
173 | * Program coex mode and weight registers to | ||
174 | * enable coex 3-wire | ||
175 | */ | ||
176 | REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode); | ||
177 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); | ||
178 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); | ||
294 | 179 | ||
295 | ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, | 180 | REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); |
296 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 181 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); |
297 | 182 | ||
298 | if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) { | 183 | ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio, |
299 | REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); | 184 | AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL); |
300 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); | ||
301 | REG_WRITE(ah, AR_BT_COEX_MODE2, 0); | ||
302 | } | ||
303 | |||
304 | ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED; | ||
305 | } | 185 | } |
306 | 186 | ||
307 | /* | 187 | void ath9k_hw_btcoex_enable(struct ath_hw *ah) |
308 | * Pause btcoex timer and bt duty cycle timer | ||
309 | */ | ||
310 | void ath_btcoex_timer_pause(struct ath_softc *sc, | ||
311 | struct ath_btcoex_info *btinfo) | ||
312 | { | 188 | { |
189 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | ||
313 | 190 | ||
314 | del_timer_sync(&btinfo->period_timer); | 191 | switch (btcoex_hw->scheme) { |
192 | case ATH_BTCOEX_CFG_NONE: | ||
193 | break; | ||
194 | case ATH_BTCOEX_CFG_2WIRE: | ||
195 | ath9k_hw_btcoex_enable_2wire(ah); | ||
196 | break; | ||
197 | case ATH_BTCOEX_CFG_3WIRE: | ||
198 | ath9k_hw_btcoex_enable_3wire(ah); | ||
199 | break; | ||
200 | } | ||
315 | 201 | ||
316 | if (btinfo->hw_timer_enabled) | 202 | REG_RMW(ah, AR_GPIO_PDPU, |
317 | ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); | 203 | (0x2 << (btcoex_hw->btactive_gpio * 2)), |
204 | (0x3 << (btcoex_hw->btactive_gpio * 2))); | ||
318 | 205 | ||
319 | btinfo->hw_timer_enabled = false; | 206 | ah->btcoex_hw.enabled = true; |
320 | } | 207 | } |
208 | EXPORT_SYMBOL(ath9k_hw_btcoex_enable); | ||
321 | 209 | ||
322 | /* | 210 | void ath9k_hw_btcoex_disable(struct ath_hw *ah) |
323 | * (Re)start btcoex timers | ||
324 | */ | ||
325 | void ath_btcoex_timer_resume(struct ath_softc *sc, | ||
326 | struct ath_btcoex_info *btinfo) | ||
327 | { | 211 | { |
212 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | ||
328 | 213 | ||
329 | DPRINTF(sc, ATH_DBG_BTCOEX, "Starting btcoex timers"); | 214 | ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0); |
330 | 215 | ||
331 | /* make sure duty cycle timer is also stopped when resuming */ | 216 | ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio, |
332 | if (btinfo->hw_timer_enabled) | 217 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
333 | ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); | ||
334 | 218 | ||
335 | btinfo->bt_priority_cnt = 0; | 219 | if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) { |
336 | btinfo->bt_priority_time = jiffies; | 220 | REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); |
337 | sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; | 221 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); |
222 | REG_WRITE(ah, AR_BT_COEX_MODE2, 0); | ||
223 | } | ||
338 | 224 | ||
339 | mod_timer(&btinfo->period_timer, jiffies); | 225 | ah->btcoex_hw.enabled = false; |
340 | } | 226 | } |
227 | EXPORT_SYMBOL(ath9k_hw_btcoex_disable); | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 297b027fd3c3..1ba31a73317c 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h | |||
@@ -17,6 +17,8 @@ | |||
17 | #ifndef BTCOEX_H | 17 | #ifndef BTCOEX_H |
18 | #define BTCOEX_H | 18 | #define BTCOEX_H |
19 | 19 | ||
20 | #include "hw.h" | ||
21 | |||
20 | #define ATH_WLANACTIVE_GPIO 5 | 22 | #define ATH_WLANACTIVE_GPIO 5 |
21 | #define ATH_BTACTIVE_GPIO 6 | 23 | #define ATH_BTACTIVE_GPIO 6 |
22 | #define ATH_BTPRIORITY_GPIO 7 | 24 | #define ATH_BTPRIORITY_GPIO 7 |
@@ -34,67 +36,25 @@ enum ath_btcoex_scheme { | |||
34 | ATH_BTCOEX_CFG_3WIRE, | 36 | ATH_BTCOEX_CFG_3WIRE, |
35 | }; | 37 | }; |
36 | 38 | ||
37 | enum ath_stomp_type { | 39 | struct ath_btcoex_hw { |
38 | ATH_BTCOEX_NO_STOMP, | 40 | enum ath_btcoex_scheme scheme; |
39 | ATH_BTCOEX_STOMP_ALL, | 41 | bool enabled; |
40 | ATH_BTCOEX_STOMP_LOW, | ||
41 | ATH_BTCOEX_STOMP_NONE | ||
42 | }; | ||
43 | |||
44 | enum ath_bt_mode { | ||
45 | ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */ | ||
46 | ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */ | ||
47 | ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */ | ||
48 | ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */ | ||
49 | }; | ||
50 | |||
51 | struct ath_btcoex_config { | ||
52 | u8 bt_time_extend; | ||
53 | bool bt_txstate_extend; | ||
54 | bool bt_txframe_extend; | ||
55 | enum ath_bt_mode bt_mode; /* coexistence mode */ | ||
56 | bool bt_quiet_collision; | ||
57 | bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/ | ||
58 | u8 bt_priority_time; | ||
59 | u8 bt_first_slot_time; | ||
60 | bool bt_hold_rx_clear; | ||
61 | }; | ||
62 | |||
63 | struct ath_btcoex_info { | ||
64 | enum ath_btcoex_scheme btcoex_scheme; | ||
65 | u8 wlanactive_gpio; | 42 | u8 wlanactive_gpio; |
66 | u8 btactive_gpio; | 43 | u8 btactive_gpio; |
67 | u8 btpriority_gpio; | 44 | u8 btpriority_gpio; |
68 | u8 bt_duty_cycle; /* BT duty cycle in percentage */ | ||
69 | int bt_stomp_type; /* Types of BT stomping */ | ||
70 | u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */ | 45 | u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */ |
71 | u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */ | 46 | u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */ |
72 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ | 47 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ |
73 | u32 btcoex_no_stomp; /* in usec */ | ||
74 | u32 btcoex_period; /* in usec */ | ||
75 | u32 bt_priority_cnt; | ||
76 | unsigned long bt_priority_time; | ||
77 | bool hw_timer_enabled; | ||
78 | spinlock_t btcoex_lock; | ||
79 | struct timer_list period_timer; /* Timer for BT period */ | ||
80 | struct ath_gen_timer *no_stomp_timer; /*Timer for no BT stomping*/ | ||
81 | }; | 48 | }; |
82 | 49 | ||
83 | bool ath_btcoex_supported(u16 subsysid); | 50 | bool ath9k_hw_btcoex_supported(struct ath_hw *ah); |
84 | int ath9k_hw_btcoex_init(struct ath_hw *ah); | 51 | void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); |
52 | void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah); | ||
53 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); | ||
54 | void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, | ||
55 | u32 bt_weight, | ||
56 | u32 wlan_weight); | ||
85 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); | 57 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); |
86 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); | 58 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); |
87 | void ath_btcoex_timer_resume(struct ath_softc *sc, | ||
88 | struct ath_btcoex_info *btinfo); | ||
89 | void ath_btcoex_timer_pause(struct ath_softc *sc, | ||
90 | struct ath_btcoex_info *btinfo); | ||
91 | |||
92 | static inline void ath_btcoex_set_weight(struct ath_btcoex_info *btcoex_info, | ||
93 | u32 bt_weight, | ||
94 | u32 wlan_weight) | ||
95 | { | ||
96 | btcoex_info->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) | | ||
97 | SM(wlan_weight, AR_BTCOEX_WL_WGHT); | ||
98 | } | ||
99 | 59 | ||
100 | #endif | 60 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 0ad6d0b76e9e..f46bd05df443 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
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 |
@@ -26,11 +26,11 @@ | |||
26 | static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) | 26 | static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) |
27 | { | 27 | { |
28 | if (nf > ATH9K_NF_TOO_LOW) { | 28 | if (nf > ATH9K_NF_TOO_LOW) { |
29 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 29 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
30 | "noise floor value detected (%d) is " | 30 | "noise floor value detected (%d) is " |
31 | "lower than what we think is a " | 31 | "lower than what we think is a " |
32 | "reasonable value (%d)\n", | 32 | "reasonable value (%d)\n", |
33 | nf, ATH9K_NF_TOO_LOW); | 33 | nf, ATH9K_NF_TOO_LOW); |
34 | return false; | 34 | return false; |
35 | } | 35 | } |
36 | return true; | 36 | return true; |
@@ -89,6 +89,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | |||
89 | static void ath9k_hw_do_getnf(struct ath_hw *ah, | 89 | static void ath9k_hw_do_getnf(struct ath_hw *ah, |
90 | int16_t nfarray[NUM_NF_READINGS]) | 90 | int16_t nfarray[NUM_NF_READINGS]) |
91 | { | 91 | { |
92 | struct ath_common *common = ath9k_hw_common(ah); | ||
92 | int16_t nf; | 93 | int16_t nf; |
93 | 94 | ||
94 | if (AR_SREV_9280_10_OR_LATER(ah)) | 95 | if (AR_SREV_9280_10_OR_LATER(ah)) |
@@ -98,8 +99,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
98 | 99 | ||
99 | if (nf & 0x100) | 100 | if (nf & 0x100) |
100 | nf = 0 - ((nf ^ 0x1ff) + 1); | 101 | nf = 0 - ((nf ^ 0x1ff) + 1); |
101 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 102 | ath_print(common, ATH_DBG_CALIBRATE, |
102 | "NF calibrated [ctl] [chain 0] is %d\n", nf); | 103 | "NF calibrated [ctl] [chain 0] is %d\n", nf); |
103 | nfarray[0] = nf; | 104 | nfarray[0] = nf; |
104 | 105 | ||
105 | if (!AR_SREV_9285(ah)) { | 106 | if (!AR_SREV_9285(ah)) { |
@@ -112,8 +113,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
112 | 113 | ||
113 | if (nf & 0x100) | 114 | if (nf & 0x100) |
114 | nf = 0 - ((nf ^ 0x1ff) + 1); | 115 | nf = 0 - ((nf ^ 0x1ff) + 1); |
115 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 116 | ath_print(common, ATH_DBG_CALIBRATE, |
116 | "NF calibrated [ctl] [chain 1] is %d\n", nf); | 117 | "NF calibrated [ctl] [chain 1] is %d\n", nf); |
117 | nfarray[1] = nf; | 118 | nfarray[1] = nf; |
118 | 119 | ||
119 | if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { | 120 | if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { |
@@ -121,8 +122,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
121 | AR_PHY_CH2_MINCCA_PWR); | 122 | AR_PHY_CH2_MINCCA_PWR); |
122 | if (nf & 0x100) | 123 | if (nf & 0x100) |
123 | nf = 0 - ((nf ^ 0x1ff) + 1); | 124 | nf = 0 - ((nf ^ 0x1ff) + 1); |
124 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 125 | ath_print(common, ATH_DBG_CALIBRATE, |
125 | "NF calibrated [ctl] [chain 2] is %d\n", nf); | 126 | "NF calibrated [ctl] [chain 2] is %d\n", nf); |
126 | nfarray[2] = nf; | 127 | nfarray[2] = nf; |
127 | } | 128 | } |
128 | } | 129 | } |
@@ -136,8 +137,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
136 | 137 | ||
137 | if (nf & 0x100) | 138 | if (nf & 0x100) |
138 | nf = 0 - ((nf ^ 0x1ff) + 1); | 139 | nf = 0 - ((nf ^ 0x1ff) + 1); |
139 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 140 | ath_print(common, ATH_DBG_CALIBRATE, |
140 | "NF calibrated [ext] [chain 0] is %d\n", nf); | 141 | "NF calibrated [ext] [chain 0] is %d\n", nf); |
141 | nfarray[3] = nf; | 142 | nfarray[3] = nf; |
142 | 143 | ||
143 | if (!AR_SREV_9285(ah)) { | 144 | if (!AR_SREV_9285(ah)) { |
@@ -150,8 +151,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
150 | 151 | ||
151 | if (nf & 0x100) | 152 | if (nf & 0x100) |
152 | nf = 0 - ((nf ^ 0x1ff) + 1); | 153 | nf = 0 - ((nf ^ 0x1ff) + 1); |
153 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 154 | ath_print(common, ATH_DBG_CALIBRATE, |
154 | "NF calibrated [ext] [chain 1] is %d\n", nf); | 155 | "NF calibrated [ext] [chain 1] is %d\n", nf); |
155 | nfarray[4] = nf; | 156 | nfarray[4] = nf; |
156 | 157 | ||
157 | if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { | 158 | if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { |
@@ -159,8 +160,8 @@ static void ath9k_hw_do_getnf(struct ath_hw *ah, | |||
159 | AR_PHY_CH2_EXT_MINCCA_PWR); | 160 | AR_PHY_CH2_EXT_MINCCA_PWR); |
160 | if (nf & 0x100) | 161 | if (nf & 0x100) |
161 | nf = 0 - ((nf ^ 0x1ff) + 1); | 162 | nf = 0 - ((nf ^ 0x1ff) + 1); |
162 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 163 | ath_print(common, ATH_DBG_CALIBRATE, |
163 | "NF calibrated [ext] [chain 2] is %d\n", nf); | 164 | "NF calibrated [ext] [chain 2] is %d\n", nf); |
164 | nfarray[5] = nf; | 165 | nfarray[5] = nf; |
165 | } | 166 | } |
166 | } | 167 | } |
@@ -188,6 +189,8 @@ static bool getNoiseFloorThresh(struct ath_hw *ah, | |||
188 | static void ath9k_hw_setup_calibration(struct ath_hw *ah, | 189 | static void ath9k_hw_setup_calibration(struct ath_hw *ah, |
189 | struct ath9k_cal_list *currCal) | 190 | struct ath9k_cal_list *currCal) |
190 | { | 191 | { |
192 | struct ath_common *common = ath9k_hw_common(ah); | ||
193 | |||
191 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), | 194 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), |
192 | AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, | 195 | AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, |
193 | currCal->calData->calCountMax); | 196 | currCal->calData->calCountMax); |
@@ -195,23 +198,23 @@ static void ath9k_hw_setup_calibration(struct ath_hw *ah, | |||
195 | switch (currCal->calData->calType) { | 198 | switch (currCal->calData->calType) { |
196 | case IQ_MISMATCH_CAL: | 199 | case IQ_MISMATCH_CAL: |
197 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); | 200 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); |
198 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 201 | ath_print(common, ATH_DBG_CALIBRATE, |
199 | "starting IQ Mismatch Calibration\n"); | 202 | "starting IQ Mismatch Calibration\n"); |
200 | break; | 203 | break; |
201 | case ADC_GAIN_CAL: | 204 | case ADC_GAIN_CAL: |
202 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); | 205 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); |
203 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 206 | ath_print(common, ATH_DBG_CALIBRATE, |
204 | "starting ADC Gain Calibration\n"); | 207 | "starting ADC Gain Calibration\n"); |
205 | break; | 208 | break; |
206 | case ADC_DC_CAL: | 209 | case ADC_DC_CAL: |
207 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); | 210 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); |
208 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 211 | ath_print(common, ATH_DBG_CALIBRATE, |
209 | "starting ADC DC Calibration\n"); | 212 | "starting ADC DC Calibration\n"); |
210 | break; | 213 | break; |
211 | case ADC_DC_INIT_CAL: | 214 | case ADC_DC_INIT_CAL: |
212 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); | 215 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); |
213 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 216 | ath_print(common, ATH_DBG_CALIBRATE, |
214 | "starting Init ADC DC Calibration\n"); | 217 | "starting Init ADC DC Calibration\n"); |
215 | break; | 218 | break; |
216 | } | 219 | } |
217 | 220 | ||
@@ -278,7 +281,7 @@ static bool ath9k_hw_per_calibration(struct ath_hw *ah, | |||
278 | static bool ath9k_hw_iscal_supported(struct ath_hw *ah, | 281 | static bool ath9k_hw_iscal_supported(struct ath_hw *ah, |
279 | enum ath9k_cal_types calType) | 282 | enum ath9k_cal_types calType) |
280 | { | 283 | { |
281 | struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; | 284 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
282 | 285 | ||
283 | switch (calType & ah->supp_cals) { | 286 | switch (calType & ah->supp_cals) { |
284 | case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ | 287 | case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ |
@@ -304,11 +307,11 @@ static void ath9k_hw_iqcal_collect(struct ath_hw *ah) | |||
304 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | 307 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); |
305 | ah->totalIqCorrMeas[i] += | 308 | ah->totalIqCorrMeas[i] += |
306 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | 309 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); |
307 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 310 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
308 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", | 311 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", |
309 | ah->cal_samples, i, ah->totalPowerMeasI[i], | 312 | ah->cal_samples, i, ah->totalPowerMeasI[i], |
310 | ah->totalPowerMeasQ[i], | 313 | ah->totalPowerMeasQ[i], |
311 | ah->totalIqCorrMeas[i]); | 314 | ah->totalIqCorrMeas[i]); |
312 | } | 315 | } |
313 | } | 316 | } |
314 | 317 | ||
@@ -326,14 +329,14 @@ static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah) | |||
326 | ah->totalAdcQEvenPhase[i] += | 329 | ah->totalAdcQEvenPhase[i] += |
327 | REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | 330 | REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); |
328 | 331 | ||
329 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 332 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
330 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | 333 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " |
331 | "oddq=0x%08x; evenq=0x%08x;\n", | 334 | "oddq=0x%08x; evenq=0x%08x;\n", |
332 | ah->cal_samples, i, | 335 | ah->cal_samples, i, |
333 | ah->totalAdcIOddPhase[i], | 336 | ah->totalAdcIOddPhase[i], |
334 | ah->totalAdcIEvenPhase[i], | 337 | ah->totalAdcIEvenPhase[i], |
335 | ah->totalAdcQOddPhase[i], | 338 | ah->totalAdcQOddPhase[i], |
336 | ah->totalAdcQEvenPhase[i]); | 339 | ah->totalAdcQEvenPhase[i]); |
337 | } | 340 | } |
338 | } | 341 | } |
339 | 342 | ||
@@ -351,19 +354,20 @@ static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah) | |||
351 | ah->totalAdcDcOffsetQEvenPhase[i] += | 354 | ah->totalAdcDcOffsetQEvenPhase[i] += |
352 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | 355 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); |
353 | 356 | ||
354 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 357 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
355 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | 358 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " |
356 | "oddq=0x%08x; evenq=0x%08x;\n", | 359 | "oddq=0x%08x; evenq=0x%08x;\n", |
357 | ah->cal_samples, i, | 360 | ah->cal_samples, i, |
358 | ah->totalAdcDcOffsetIOddPhase[i], | 361 | ah->totalAdcDcOffsetIOddPhase[i], |
359 | ah->totalAdcDcOffsetIEvenPhase[i], | 362 | ah->totalAdcDcOffsetIEvenPhase[i], |
360 | ah->totalAdcDcOffsetQOddPhase[i], | 363 | ah->totalAdcDcOffsetQOddPhase[i], |
361 | ah->totalAdcDcOffsetQEvenPhase[i]); | 364 | ah->totalAdcDcOffsetQEvenPhase[i]); |
362 | } | 365 | } |
363 | } | 366 | } |
364 | 367 | ||
365 | static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | 368 | static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) |
366 | { | 369 | { |
370 | struct ath_common *common = ath9k_hw_common(ah); | ||
367 | u32 powerMeasQ, powerMeasI, iqCorrMeas; | 371 | u32 powerMeasQ, powerMeasI, iqCorrMeas; |
368 | u32 qCoffDenom, iCoffDenom; | 372 | u32 qCoffDenom, iCoffDenom; |
369 | int32_t qCoff, iCoff; | 373 | int32_t qCoff, iCoff; |
@@ -374,13 +378,13 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
374 | powerMeasQ = ah->totalPowerMeasQ[i]; | 378 | powerMeasQ = ah->totalPowerMeasQ[i]; |
375 | iqCorrMeas = ah->totalIqCorrMeas[i]; | 379 | iqCorrMeas = ah->totalIqCorrMeas[i]; |
376 | 380 | ||
377 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 381 | ath_print(common, ATH_DBG_CALIBRATE, |
378 | "Starting IQ Cal and Correction for Chain %d\n", | 382 | "Starting IQ Cal and Correction for Chain %d\n", |
379 | i); | 383 | i); |
380 | 384 | ||
381 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 385 | ath_print(common, ATH_DBG_CALIBRATE, |
382 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", | 386 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", |
383 | i, ah->totalIqCorrMeas[i]); | 387 | i, ah->totalIqCorrMeas[i]); |
384 | 388 | ||
385 | iqCorrNeg = 0; | 389 | iqCorrNeg = 0; |
386 | 390 | ||
@@ -389,27 +393,28 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
389 | iqCorrNeg = 1; | 393 | iqCorrNeg = 1; |
390 | } | 394 | } |
391 | 395 | ||
392 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 396 | ath_print(common, ATH_DBG_CALIBRATE, |
393 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); | 397 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); |
394 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 398 | ath_print(common, ATH_DBG_CALIBRATE, |
395 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); | 399 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); |
396 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", | 400 | ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", |
397 | iqCorrNeg); | 401 | iqCorrNeg); |
398 | 402 | ||
399 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; | 403 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; |
400 | qCoffDenom = powerMeasQ / 64; | 404 | qCoffDenom = powerMeasQ / 64; |
401 | 405 | ||
402 | if (powerMeasQ != 0) { | 406 | if ((powerMeasQ != 0) && (iCoffDenom != 0) && |
407 | (qCoffDenom != 0)) { | ||
403 | iCoff = iqCorrMeas / iCoffDenom; | 408 | iCoff = iqCorrMeas / iCoffDenom; |
404 | qCoff = powerMeasI / qCoffDenom - 64; | 409 | qCoff = powerMeasI / qCoffDenom - 64; |
405 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 410 | ath_print(common, ATH_DBG_CALIBRATE, |
406 | "Chn %d iCoff = 0x%08x\n", i, iCoff); | 411 | "Chn %d iCoff = 0x%08x\n", i, iCoff); |
407 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 412 | ath_print(common, ATH_DBG_CALIBRATE, |
408 | "Chn %d qCoff = 0x%08x\n", i, qCoff); | 413 | "Chn %d qCoff = 0x%08x\n", i, qCoff); |
409 | 414 | ||
410 | iCoff = iCoff & 0x3f; | 415 | iCoff = iCoff & 0x3f; |
411 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 416 | ath_print(common, ATH_DBG_CALIBRATE, |
412 | "New: Chn %d iCoff = 0x%08x\n", i, iCoff); | 417 | "New: Chn %d iCoff = 0x%08x\n", i, iCoff); |
413 | if (iqCorrNeg == 0x0) | 418 | if (iqCorrNeg == 0x0) |
414 | iCoff = 0x40 - iCoff; | 419 | iCoff = 0x40 - iCoff; |
415 | 420 | ||
@@ -418,9 +423,9 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
418 | else if (qCoff <= -16) | 423 | else if (qCoff <= -16) |
419 | qCoff = 16; | 424 | qCoff = 16; |
420 | 425 | ||
421 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 426 | ath_print(common, ATH_DBG_CALIBRATE, |
422 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", | 427 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", |
423 | i, iCoff, qCoff); | 428 | i, iCoff, qCoff); |
424 | 429 | ||
425 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | 430 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), |
426 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, | 431 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, |
@@ -428,9 +433,9 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
428 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | 433 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), |
429 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, | 434 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, |
430 | qCoff); | 435 | qCoff); |
431 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 436 | ath_print(common, ATH_DBG_CALIBRATE, |
432 | "IQ Cal and Correction done for Chain %d\n", | 437 | "IQ Cal and Correction done for Chain %d\n", |
433 | i); | 438 | i); |
434 | } | 439 | } |
435 | } | 440 | } |
436 | 441 | ||
@@ -440,6 +445,7 @@ static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
440 | 445 | ||
441 | static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) | 446 | static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) |
442 | { | 447 | { |
448 | struct ath_common *common = ath9k_hw_common(ah); | ||
443 | u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; | 449 | u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; |
444 | u32 qGainMismatch, iGainMismatch, val, i; | 450 | u32 qGainMismatch, iGainMismatch, val, i; |
445 | 451 | ||
@@ -449,21 +455,21 @@ static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) | |||
449 | qOddMeasOffset = ah->totalAdcQOddPhase[i]; | 455 | qOddMeasOffset = ah->totalAdcQOddPhase[i]; |
450 | qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; | 456 | qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; |
451 | 457 | ||
452 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 458 | ath_print(common, ATH_DBG_CALIBRATE, |
453 | "Starting ADC Gain Cal for Chain %d\n", i); | 459 | "Starting ADC Gain Cal for Chain %d\n", i); |
454 | 460 | ||
455 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 461 | ath_print(common, ATH_DBG_CALIBRATE, |
456 | "Chn %d pwr_meas_odd_i = 0x%08x\n", i, | 462 | "Chn %d pwr_meas_odd_i = 0x%08x\n", i, |
457 | iOddMeasOffset); | 463 | iOddMeasOffset); |
458 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 464 | ath_print(common, ATH_DBG_CALIBRATE, |
459 | "Chn %d pwr_meas_even_i = 0x%08x\n", i, | 465 | "Chn %d pwr_meas_even_i = 0x%08x\n", i, |
460 | iEvenMeasOffset); | 466 | iEvenMeasOffset); |
461 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 467 | ath_print(common, ATH_DBG_CALIBRATE, |
462 | "Chn %d pwr_meas_odd_q = 0x%08x\n", i, | 468 | "Chn %d pwr_meas_odd_q = 0x%08x\n", i, |
463 | qOddMeasOffset); | 469 | qOddMeasOffset); |
464 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 470 | ath_print(common, ATH_DBG_CALIBRATE, |
465 | "Chn %d pwr_meas_even_q = 0x%08x\n", i, | 471 | "Chn %d pwr_meas_even_q = 0x%08x\n", i, |
466 | qEvenMeasOffset); | 472 | qEvenMeasOffset); |
467 | 473 | ||
468 | if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { | 474 | if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { |
469 | iGainMismatch = | 475 | iGainMismatch = |
@@ -473,20 +479,20 @@ static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) | |||
473 | ((qOddMeasOffset * 32) / | 479 | ((qOddMeasOffset * 32) / |
474 | qEvenMeasOffset) & 0x3f; | 480 | qEvenMeasOffset) & 0x3f; |
475 | 481 | ||
476 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 482 | ath_print(common, ATH_DBG_CALIBRATE, |
477 | "Chn %d gain_mismatch_i = 0x%08x\n", i, | 483 | "Chn %d gain_mismatch_i = 0x%08x\n", i, |
478 | iGainMismatch); | 484 | iGainMismatch); |
479 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 485 | ath_print(common, ATH_DBG_CALIBRATE, |
480 | "Chn %d gain_mismatch_q = 0x%08x\n", i, | 486 | "Chn %d gain_mismatch_q = 0x%08x\n", i, |
481 | qGainMismatch); | 487 | qGainMismatch); |
482 | 488 | ||
483 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | 489 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); |
484 | val &= 0xfffff000; | 490 | val &= 0xfffff000; |
485 | val |= (qGainMismatch) | (iGainMismatch << 6); | 491 | val |= (qGainMismatch) | (iGainMismatch << 6); |
486 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | 492 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); |
487 | 493 | ||
488 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 494 | ath_print(common, ATH_DBG_CALIBRATE, |
489 | "ADC Gain Cal done for Chain %d\n", i); | 495 | "ADC Gain Cal done for Chain %d\n", i); |
490 | } | 496 | } |
491 | } | 497 | } |
492 | 498 | ||
@@ -497,6 +503,7 @@ static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) | |||
497 | 503 | ||
498 | static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) | 504 | static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) |
499 | { | 505 | { |
506 | struct ath_common *common = ath9k_hw_common(ah); | ||
500 | u32 iOddMeasOffset, iEvenMeasOffset, val, i; | 507 | u32 iOddMeasOffset, iEvenMeasOffset, val, i; |
501 | int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; | 508 | int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; |
502 | const struct ath9k_percal_data *calData = | 509 | const struct ath9k_percal_data *calData = |
@@ -510,41 +517,41 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) | |||
510 | qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; | 517 | qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; |
511 | qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; | 518 | qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; |
512 | 519 | ||
513 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 520 | ath_print(common, ATH_DBG_CALIBRATE, |
514 | "Starting ADC DC Offset Cal for Chain %d\n", i); | 521 | "Starting ADC DC Offset Cal for Chain %d\n", i); |
515 | 522 | ||
516 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 523 | ath_print(common, ATH_DBG_CALIBRATE, |
517 | "Chn %d pwr_meas_odd_i = %d\n", i, | 524 | "Chn %d pwr_meas_odd_i = %d\n", i, |
518 | iOddMeasOffset); | 525 | iOddMeasOffset); |
519 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 526 | ath_print(common, ATH_DBG_CALIBRATE, |
520 | "Chn %d pwr_meas_even_i = %d\n", i, | 527 | "Chn %d pwr_meas_even_i = %d\n", i, |
521 | iEvenMeasOffset); | 528 | iEvenMeasOffset); |
522 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 529 | ath_print(common, ATH_DBG_CALIBRATE, |
523 | "Chn %d pwr_meas_odd_q = %d\n", i, | 530 | "Chn %d pwr_meas_odd_q = %d\n", i, |
524 | qOddMeasOffset); | 531 | qOddMeasOffset); |
525 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 532 | ath_print(common, ATH_DBG_CALIBRATE, |
526 | "Chn %d pwr_meas_even_q = %d\n", i, | 533 | "Chn %d pwr_meas_even_q = %d\n", i, |
527 | qEvenMeasOffset); | 534 | qEvenMeasOffset); |
528 | 535 | ||
529 | iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / | 536 | iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / |
530 | numSamples) & 0x1ff; | 537 | numSamples) & 0x1ff; |
531 | qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / | 538 | qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / |
532 | numSamples) & 0x1ff; | 539 | numSamples) & 0x1ff; |
533 | 540 | ||
534 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 541 | ath_print(common, ATH_DBG_CALIBRATE, |
535 | "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, | 542 | "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, |
536 | iDcMismatch); | 543 | iDcMismatch); |
537 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 544 | ath_print(common, ATH_DBG_CALIBRATE, |
538 | "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, | 545 | "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, |
539 | qDcMismatch); | 546 | qDcMismatch); |
540 | 547 | ||
541 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | 548 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); |
542 | val &= 0xc0000fff; | 549 | val &= 0xc0000fff; |
543 | val |= (qDcMismatch << 12) | (iDcMismatch << 21); | 550 | val |= (qDcMismatch << 12) | (iDcMismatch << 21); |
544 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | 551 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); |
545 | 552 | ||
546 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 553 | ath_print(common, ATH_DBG_CALIBRATE, |
547 | "ADC DC Offset Cal done for Chain %d\n", i); | 554 | "ADC DC Offset Cal done for Chain %d\n", i); |
548 | } | 555 | } |
549 | 556 | ||
550 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | 557 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), |
@@ -555,7 +562,8 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) | |||
555 | /* This is done for the currently configured channel */ | 562 | /* This is done for the currently configured channel */ |
556 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | 563 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
557 | { | 564 | { |
558 | struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; | 565 | struct ath_common *common = ath9k_hw_common(ah); |
566 | struct ieee80211_conf *conf = &common->hw->conf; | ||
559 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | 567 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
560 | 568 | ||
561 | if (!ah->curchan) | 569 | if (!ah->curchan) |
@@ -568,24 +576,25 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | |||
568 | return true; | 576 | return true; |
569 | 577 | ||
570 | if (currCal->calState != CAL_DONE) { | 578 | if (currCal->calState != CAL_DONE) { |
571 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 579 | ath_print(common, ATH_DBG_CALIBRATE, |
572 | "Calibration state incorrect, %d\n", | 580 | "Calibration state incorrect, %d\n", |
573 | currCal->calState); | 581 | currCal->calState); |
574 | return true; | 582 | return true; |
575 | } | 583 | } |
576 | 584 | ||
577 | if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) | 585 | if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) |
578 | return true; | 586 | return true; |
579 | 587 | ||
580 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 588 | ath_print(common, ATH_DBG_CALIBRATE, |
581 | "Resetting Cal %d state for channel %u\n", | 589 | "Resetting Cal %d state for channel %u\n", |
582 | currCal->calData->calType, conf->channel->center_freq); | 590 | currCal->calData->calType, conf->channel->center_freq); |
583 | 591 | ||
584 | ah->curchan->CalValid &= ~currCal->calData->calType; | 592 | ah->curchan->CalValid &= ~currCal->calData->calType; |
585 | currCal->calState = CAL_WAITING; | 593 | currCal->calState = CAL_WAITING; |
586 | 594 | ||
587 | return false; | 595 | return false; |
588 | } | 596 | } |
597 | EXPORT_SYMBOL(ath9k_hw_reset_calvalid); | ||
589 | 598 | ||
590 | void ath9k_hw_start_nfcal(struct ath_hw *ah) | 599 | void ath9k_hw_start_nfcal(struct ath_hw *ah) |
591 | { | 600 | { |
@@ -645,11 +654,11 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
645 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | 654 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); |
646 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | 655 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); |
647 | 656 | ||
648 | for (j = 0; j < 1000; j++) { | 657 | for (j = 0; j < 5; j++) { |
649 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & | 658 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & |
650 | AR_PHY_AGC_CONTROL_NF) == 0) | 659 | AR_PHY_AGC_CONTROL_NF) == 0) |
651 | break; | 660 | break; |
652 | udelay(10); | 661 | udelay(50); |
653 | } | 662 | } |
654 | 663 | ||
655 | for (i = 0; i < NUM_NF_READINGS; i++) { | 664 | for (i = 0; i < NUM_NF_READINGS; i++) { |
@@ -665,6 +674,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
665 | int16_t ath9k_hw_getnf(struct ath_hw *ah, | 674 | int16_t ath9k_hw_getnf(struct ath_hw *ah, |
666 | struct ath9k_channel *chan) | 675 | struct ath9k_channel *chan) |
667 | { | 676 | { |
677 | struct ath_common *common = ath9k_hw_common(ah); | ||
668 | int16_t nf, nfThresh; | 678 | int16_t nf, nfThresh; |
669 | int16_t nfarray[NUM_NF_READINGS] = { 0 }; | 679 | int16_t nfarray[NUM_NF_READINGS] = { 0 }; |
670 | struct ath9k_nfcal_hist *h; | 680 | struct ath9k_nfcal_hist *h; |
@@ -672,8 +682,8 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, | |||
672 | 682 | ||
673 | chan->channelFlags &= (~CHANNEL_CW_INT); | 683 | chan->channelFlags &= (~CHANNEL_CW_INT); |
674 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { | 684 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { |
675 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 685 | ath_print(common, ATH_DBG_CALIBRATE, |
676 | "NF did not complete in calibration window\n"); | 686 | "NF did not complete in calibration window\n"); |
677 | nf = 0; | 687 | nf = 0; |
678 | chan->rawNoiseFloor = nf; | 688 | chan->rawNoiseFloor = nf; |
679 | return chan->rawNoiseFloor; | 689 | return chan->rawNoiseFloor; |
@@ -682,10 +692,10 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah, | |||
682 | nf = nfarray[0]; | 692 | nf = nfarray[0]; |
683 | if (getNoiseFloorThresh(ah, c->band, &nfThresh) | 693 | if (getNoiseFloorThresh(ah, c->band, &nfThresh) |
684 | && nf > nfThresh) { | 694 | && nf > nfThresh) { |
685 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 695 | ath_print(common, ATH_DBG_CALIBRATE, |
686 | "noise floor failed detected; " | 696 | "noise floor failed detected; " |
687 | "detected %d, threshold %d\n", | 697 | "detected %d, threshold %d\n", |
688 | nf, nfThresh); | 698 | nf, nfThresh); |
689 | chan->channelFlags |= CHANNEL_CW_INT; | 699 | chan->channelFlags |= CHANNEL_CW_INT; |
690 | } | 700 | } |
691 | } | 701 | } |
@@ -737,45 +747,67 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | |||
737 | 747 | ||
738 | return nf; | 748 | return nf; |
739 | } | 749 | } |
750 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); | ||
740 | 751 | ||
741 | static void ath9k_olc_temp_compensation(struct ath_hw *ah) | 752 | static void ath9k_olc_temp_compensation_9287(struct ath_hw *ah) |
742 | { | 753 | { |
743 | u32 rddata, i; | 754 | u32 rddata; |
744 | int delta, currPDADC, regval, slope; | 755 | int32_t delta, currPDADC, slope; |
745 | 756 | ||
746 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); | 757 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); |
747 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); | 758 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); |
748 | 759 | ||
760 | if (ah->initPDADC == 0 || currPDADC == 0) { | ||
761 | /* | ||
762 | * Zero value indicates that no frames have been transmitted yet, | ||
763 | * can't do temperature compensation until frames are transmitted. | ||
764 | */ | ||
765 | return; | ||
766 | } else { | ||
767 | slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); | ||
768 | |||
769 | if (slope == 0) { /* to avoid divide by zero case */ | ||
770 | delta = 0; | ||
771 | } else { | ||
772 | delta = ((currPDADC - ah->initPDADC)*4) / slope; | ||
773 | } | ||
774 | REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, | ||
775 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | ||
776 | REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, | ||
777 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | ||
778 | } | ||
779 | } | ||
780 | |||
781 | static void ath9k_olc_temp_compensation(struct ath_hw *ah) | ||
782 | { | ||
783 | u32 rddata, i; | ||
784 | int delta, currPDADC, regval; | ||
749 | 785 | ||
750 | if (OLC_FOR_AR9287_10_LATER) { | 786 | if (OLC_FOR_AR9287_10_LATER) { |
787 | ath9k_olc_temp_compensation_9287(ah); | ||
788 | } else { | ||
789 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); | ||
790 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); | ||
791 | |||
751 | if (ah->initPDADC == 0 || currPDADC == 0) { | 792 | if (ah->initPDADC == 0 || currPDADC == 0) { |
752 | return; | 793 | return; |
753 | } else { | 794 | } else { |
754 | slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); | 795 | if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) |
755 | if (slope == 0) | 796 | delta = (currPDADC - ah->initPDADC + 4) / 8; |
756 | delta = 0; | ||
757 | else | 797 | else |
758 | delta = ((currPDADC - ah->initPDADC)*4) / slope; | 798 | delta = (currPDADC - ah->initPDADC + 5) / 10; |
759 | REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, | 799 | |
760 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | 800 | if (delta != ah->PDADCdelta) { |
761 | REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, | 801 | ah->PDADCdelta = delta; |
762 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | 802 | for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { |
763 | } | 803 | regval = ah->originalGain[i] - delta; |
764 | } else { | 804 | if (regval < 0) |
765 | if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) | 805 | regval = 0; |
766 | delta = (currPDADC - ah->initPDADC + 4) / 8; | 806 | |
767 | else | 807 | REG_RMW_FIELD(ah, |
768 | delta = (currPDADC - ah->initPDADC + 5) / 10; | 808 | AR_PHY_TX_GAIN_TBL1 + i * 4, |
769 | 809 | AR_PHY_TX_GAIN, regval); | |
770 | if (delta != ah->PDADCdelta) { | 810 | } |
771 | ah->PDADCdelta = delta; | ||
772 | for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { | ||
773 | regval = ah->originalGain[i] - delta; | ||
774 | if (regval < 0) | ||
775 | regval = 0; | ||
776 | |||
777 | REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, | ||
778 | AR_PHY_TX_GAIN, regval); | ||
779 | } | 811 | } |
780 | } | 812 | } |
781 | } | 813 | } |
@@ -875,7 +907,7 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) | |||
875 | 907 | ||
876 | static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) | 908 | static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) |
877 | { | 909 | { |
878 | 910 | struct ath_common *common = ath9k_hw_common(ah); | |
879 | u32 regVal; | 911 | u32 regVal; |
880 | int i, offset, offs_6_1, offs_0; | 912 | int i, offset, offs_6_1, offs_0; |
881 | u32 ccomp_org, reg_field; | 913 | u32 ccomp_org, reg_field; |
@@ -889,7 +921,7 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) | |||
889 | { 0x7838, 0 }, | 921 | { 0x7838, 0 }, |
890 | }; | 922 | }; |
891 | 923 | ||
892 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); | 924 | ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); |
893 | 925 | ||
894 | /* PA CAL is not needed for high power solution */ | 926 | /* PA CAL is not needed for high power solution */ |
895 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == | 927 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == |
@@ -1036,9 +1068,12 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1036 | 1068 | ||
1037 | return iscaldone; | 1069 | return iscaldone; |
1038 | } | 1070 | } |
1071 | EXPORT_SYMBOL(ath9k_hw_calibrate); | ||
1039 | 1072 | ||
1040 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | 1073 | static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) |
1041 | { | 1074 | { |
1075 | struct ath_common *common = ath9k_hw_common(ah); | ||
1076 | |||
1042 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); | 1077 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); |
1043 | if (IS_CHAN_HT20(chan)) { | 1078 | if (IS_CHAN_HT20(chan)) { |
1044 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); | 1079 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); |
@@ -1049,9 +1084,9 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1049 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | 1084 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); |
1050 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | 1085 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, |
1051 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { | 1086 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { |
1052 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset " | 1087 | ath_print(common, ATH_DBG_CALIBRATE, "offset " |
1053 | "calibration failed to complete in " | 1088 | "calibration failed to complete in " |
1054 | "1ms; noisy ??\n"); | 1089 | "1ms; noisy ??\n"); |
1055 | return false; | 1090 | return false; |
1056 | } | 1091 | } |
1057 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | 1092 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); |
@@ -1064,8 +1099,8 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1064 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | 1099 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); |
1065 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | 1100 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, |
1066 | 0, AH_WAIT_TIMEOUT)) { | 1101 | 0, AH_WAIT_TIMEOUT)) { |
1067 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration " | 1102 | ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " |
1068 | "failed to complete in 1ms; noisy ??\n"); | 1103 | "failed to complete in 1ms; noisy ??\n"); |
1069 | return false; | 1104 | return false; |
1070 | } | 1105 | } |
1071 | 1106 | ||
@@ -1078,6 +1113,8 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1078 | 1113 | ||
1079 | bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | 1114 | bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) |
1080 | { | 1115 | { |
1116 | struct ath_common *common = ath9k_hw_common(ah); | ||
1117 | |||
1081 | if (AR_SREV_9285_12_OR_LATER(ah)) { | 1118 | if (AR_SREV_9285_12_OR_LATER(ah)) { |
1082 | if (!ar9285_clc(ah, chan)) | 1119 | if (!ar9285_clc(ah, chan)) |
1083 | return false; | 1120 | return false; |
@@ -1098,9 +1135,9 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1098 | /* Poll for offset calibration complete */ | 1135 | /* Poll for offset calibration complete */ |
1099 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | 1136 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, |
1100 | 0, AH_WAIT_TIMEOUT)) { | 1137 | 0, AH_WAIT_TIMEOUT)) { |
1101 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 1138 | ath_print(common, ATH_DBG_CALIBRATE, |
1102 | "offset calibration failed to complete in 1ms; " | 1139 | "offset calibration failed to " |
1103 | "noisy environment?\n"); | 1140 | "complete in 1ms; noisy environment?\n"); |
1104 | return false; | 1141 | return false; |
1105 | } | 1142 | } |
1106 | 1143 | ||
@@ -1128,20 +1165,20 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1128 | if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { | 1165 | if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { |
1129 | INIT_CAL(&ah->adcgain_caldata); | 1166 | INIT_CAL(&ah->adcgain_caldata); |
1130 | INSERT_CAL(ah, &ah->adcgain_caldata); | 1167 | INSERT_CAL(ah, &ah->adcgain_caldata); |
1131 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 1168 | ath_print(common, ATH_DBG_CALIBRATE, |
1132 | "enabling ADC Gain Calibration.\n"); | 1169 | "enabling ADC Gain Calibration.\n"); |
1133 | } | 1170 | } |
1134 | if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { | 1171 | if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { |
1135 | INIT_CAL(&ah->adcdc_caldata); | 1172 | INIT_CAL(&ah->adcdc_caldata); |
1136 | INSERT_CAL(ah, &ah->adcdc_caldata); | 1173 | INSERT_CAL(ah, &ah->adcdc_caldata); |
1137 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 1174 | ath_print(common, ATH_DBG_CALIBRATE, |
1138 | "enabling ADC DC Calibration.\n"); | 1175 | "enabling ADC DC Calibration.\n"); |
1139 | } | 1176 | } |
1140 | if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { | 1177 | if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { |
1141 | INIT_CAL(&ah->iq_caldata); | 1178 | INIT_CAL(&ah->iq_caldata); |
1142 | INSERT_CAL(ah, &ah->iq_caldata); | 1179 | INSERT_CAL(ah, &ah->iq_caldata); |
1143 | DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, | 1180 | ath_print(common, ATH_DBG_CALIBRATE, |
1144 | "enabling IQ Calibration.\n"); | 1181 | "enabling IQ Calibration.\n"); |
1145 | } | 1182 | } |
1146 | 1183 | ||
1147 | ah->cal_list_curr = ah->cal_list; | 1184 | ah->cal_list_curr = ah->cal_list; |
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 9028ab193e42..b2c873e97485 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -17,6 +17,8 @@ | |||
17 | #ifndef CALIB_H | 17 | #ifndef CALIB_H |
18 | #define CALIB_H | 18 | #define CALIB_H |
19 | 19 | ||
20 | #include "hw.h" | ||
21 | |||
20 | extern const struct ath9k_percal_data iq_cal_multi_sample; | 22 | extern const struct ath9k_percal_data iq_cal_multi_sample; |
21 | extern const struct ath9k_percal_data iq_cal_single_sample; | 23 | extern const struct ath9k_percal_data iq_cal_single_sample; |
22 | extern const struct ath9k_percal_data adc_gain_cal_multi_sample; | 24 | extern const struct ath9k_percal_data adc_gain_cal_multi_sample; |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 2be4c2252047..84f44269de47 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -18,26 +18,13 @@ | |||
18 | 18 | ||
19 | #include "ath9k.h" | 19 | #include "ath9k.h" |
20 | 20 | ||
21 | static unsigned int ath9k_debug = DBG_DEFAULT; | 21 | #define REG_WRITE_D(_ah, _reg, _val) \ |
22 | module_param_named(debug, ath9k_debug, uint, 0); | 22 | ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg)) |
23 | #define REG_READ_D(_ah, _reg) \ | ||
24 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) | ||
23 | 25 | ||
24 | static struct dentry *ath9k_debugfs_root; | 26 | static struct dentry *ath9k_debugfs_root; |
25 | 27 | ||
26 | void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...) | ||
27 | { | ||
28 | if (!sc) | ||
29 | return; | ||
30 | |||
31 | if (sc->debug.debug_mask & dbg_mask) { | ||
32 | va_list args; | ||
33 | |||
34 | va_start(args, fmt); | ||
35 | printk(KERN_DEBUG "ath9k: "); | ||
36 | vprintk(fmt, args); | ||
37 | va_end(args); | ||
38 | } | ||
39 | } | ||
40 | |||
41 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | 28 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) |
42 | { | 29 | { |
43 | file->private_data = inode->i_private; | 30 | file->private_data = inode->i_private; |
@@ -48,10 +35,11 @@ static ssize_t read_file_debug(struct file *file, char __user *user_buf, | |||
48 | size_t count, loff_t *ppos) | 35 | size_t count, loff_t *ppos) |
49 | { | 36 | { |
50 | struct ath_softc *sc = file->private_data; | 37 | struct ath_softc *sc = file->private_data; |
38 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
51 | char buf[32]; | 39 | char buf[32]; |
52 | unsigned int len; | 40 | unsigned int len; |
53 | 41 | ||
54 | len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.debug_mask); | 42 | len = snprintf(buf, sizeof(buf), "0x%08x\n", common->debug_mask); |
55 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 43 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
56 | } | 44 | } |
57 | 45 | ||
@@ -59,6 +47,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf, | |||
59 | size_t count, loff_t *ppos) | 47 | size_t count, loff_t *ppos) |
60 | { | 48 | { |
61 | struct ath_softc *sc = file->private_data; | 49 | struct ath_softc *sc = file->private_data; |
50 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
62 | unsigned long mask; | 51 | unsigned long mask; |
63 | char buf[32]; | 52 | char buf[32]; |
64 | ssize_t len; | 53 | ssize_t len; |
@@ -71,7 +60,7 @@ static ssize_t write_file_debug(struct file *file, const char __user *user_buf, | |||
71 | if (strict_strtoul(buf, 0, &mask)) | 60 | if (strict_strtoul(buf, 0, &mask)) |
72 | return -EINVAL; | 61 | return -EINVAL; |
73 | 62 | ||
74 | sc->debug.debug_mask = mask; | 63 | common->debug_mask = mask; |
75 | return count; | 64 | return count; |
76 | } | 65 | } |
77 | 66 | ||
@@ -95,7 +84,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
95 | 84 | ||
96 | ath9k_ps_wakeup(sc); | 85 | ath9k_ps_wakeup(sc); |
97 | 86 | ||
98 | REG_WRITE(ah, AR_MACMISC, | 87 | REG_WRITE_D(ah, AR_MACMISC, |
99 | ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | | 88 | ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | |
100 | (AR_MACMISC_MISC_OBS_BUS_1 << | 89 | (AR_MACMISC_MISC_OBS_BUS_1 << |
101 | AR_MACMISC_MISC_OBS_BUS_MSB_S))); | 90 | AR_MACMISC_MISC_OBS_BUS_MSB_S))); |
@@ -107,7 +96,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
107 | if (i % 4 == 0) | 96 | if (i % 4 == 0) |
108 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | 97 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); |
109 | 98 | ||
110 | val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32))); | 99 | val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32))); |
111 | len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ", | 100 | len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ", |
112 | i, val[i]); | 101 | i, val[i]); |
113 | } | 102 | } |
@@ -157,9 +146,9 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
157 | (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); | 146 | (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); |
158 | 147 | ||
159 | len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n", | 148 | len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n", |
160 | REG_READ(ah, AR_OBS_BUS_1)); | 149 | REG_READ_D(ah, AR_OBS_BUS_1)); |
161 | len += snprintf(buf + len, sizeof(buf) - len, | 150 | len += snprintf(buf + len, sizeof(buf) - len, |
162 | "AR_CR: 0x%x \n", REG_READ(ah, AR_CR)); | 151 | "AR_CR: 0x%x \n", REG_READ_D(ah, AR_CR)); |
163 | 152 | ||
164 | ath9k_ps_restore(sc); | 153 | ath9k_ps_restore(sc); |
165 | 154 | ||
@@ -376,12 +365,12 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
376 | aphy->chan_idx, aphy->chan_is_ht); | 365 | aphy->chan_idx, aphy->chan_is_ht); |
377 | } | 366 | } |
378 | 367 | ||
379 | put_unaligned_le32(REG_READ(sc->sc_ah, AR_STA_ID0), addr); | 368 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); |
380 | put_unaligned_le16(REG_READ(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); | 369 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); |
381 | len += snprintf(buf + len, sizeof(buf) - len, | 370 | len += snprintf(buf + len, sizeof(buf) - len, |
382 | "addr: %pM\n", addr); | 371 | "addr: %pM\n", addr); |
383 | put_unaligned_le32(REG_READ(sc->sc_ah, AR_BSSMSKL), addr); | 372 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_BSSMSKL), addr); |
384 | put_unaligned_le16(REG_READ(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); | 373 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); |
385 | len += snprintf(buf + len, sizeof(buf) - len, | 374 | len += snprintf(buf + len, sizeof(buf) - len, |
386 | "addrmask: %pM\n", addr); | 375 | "addrmask: %pM\n", addr); |
387 | 376 | ||
@@ -568,9 +557,10 @@ static const struct file_operations fops_xmit = { | |||
568 | .owner = THIS_MODULE | 557 | .owner = THIS_MODULE |
569 | }; | 558 | }; |
570 | 559 | ||
571 | int ath9k_init_debug(struct ath_softc *sc) | 560 | int ath9k_init_debug(struct ath_hw *ah) |
572 | { | 561 | { |
573 | sc->debug.debug_mask = ath9k_debug; | 562 | struct ath_common *common = ath9k_hw_common(ah); |
563 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
574 | 564 | ||
575 | if (!ath9k_debugfs_root) | 565 | if (!ath9k_debugfs_root) |
576 | return -ENOENT; | 566 | return -ENOENT; |
@@ -619,12 +609,15 @@ int ath9k_init_debug(struct ath_softc *sc) | |||
619 | 609 | ||
620 | return 0; | 610 | return 0; |
621 | err: | 611 | err: |
622 | ath9k_exit_debug(sc); | 612 | ath9k_exit_debug(ah); |
623 | return -ENOMEM; | 613 | return -ENOMEM; |
624 | } | 614 | } |
625 | 615 | ||
626 | void ath9k_exit_debug(struct ath_softc *sc) | 616 | void ath9k_exit_debug(struct ath_hw *ah) |
627 | { | 617 | { |
618 | struct ath_common *common = ath9k_hw_common(ah); | ||
619 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
620 | |||
628 | debugfs_remove(sc->debug.debugfs_xmit); | 621 | debugfs_remove(sc->debug.debugfs_xmit); |
629 | debugfs_remove(sc->debug.debugfs_wiphy); | 622 | debugfs_remove(sc->debug.debugfs_wiphy); |
630 | debugfs_remove(sc->debug.debugfs_rcstat); | 623 | debugfs_remove(sc->debug.debugfs_rcstat); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 7241f4748338..749e85d57551 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -17,25 +17,7 @@ | |||
17 | #ifndef DEBUG_H | 17 | #ifndef DEBUG_H |
18 | #define DEBUG_H | 18 | #define DEBUG_H |
19 | 19 | ||
20 | enum ATH_DEBUG { | 20 | #include "hw.h" |
21 | ATH_DBG_RESET = 0x00000001, | ||
22 | ATH_DBG_QUEUE = 0x00000002, | ||
23 | ATH_DBG_EEPROM = 0x00000004, | ||
24 | ATH_DBG_CALIBRATE = 0x00000008, | ||
25 | ATH_DBG_INTERRUPT = 0x00000010, | ||
26 | ATH_DBG_REGULATORY = 0x00000020, | ||
27 | ATH_DBG_ANI = 0x00000040, | ||
28 | ATH_DBG_XMIT = 0x00000080, | ||
29 | ATH_DBG_BEACON = 0x00000100, | ||
30 | ATH_DBG_CONFIG = 0x00000200, | ||
31 | ATH_DBG_FATAL = 0x00000400, | ||
32 | ATH_DBG_PS = 0x00000800, | ||
33 | ATH_DBG_HWTIMER = 0x00001000, | ||
34 | ATH_DBG_BTCOEX = 0x00002000, | ||
35 | ATH_DBG_ANY = 0xffffffff | ||
36 | }; | ||
37 | |||
38 | #define DBG_DEFAULT (ATH_DBG_FATAL) | ||
39 | 21 | ||
40 | struct ath_txq; | 22 | struct ath_txq; |
41 | struct ath_buf; | 23 | struct ath_buf; |
@@ -140,7 +122,6 @@ struct ath_stats { | |||
140 | }; | 122 | }; |
141 | 123 | ||
142 | struct ath9k_debug { | 124 | struct ath9k_debug { |
143 | int debug_mask; | ||
144 | struct dentry *debugfs_phy; | 125 | struct dentry *debugfs_phy; |
145 | struct dentry *debugfs_debug; | 126 | struct dentry *debugfs_debug; |
146 | struct dentry *debugfs_dma; | 127 | struct dentry *debugfs_dma; |
@@ -151,9 +132,9 @@ struct ath9k_debug { | |||
151 | struct ath_stats stats; | 132 | struct ath_stats stats; |
152 | }; | 133 | }; |
153 | 134 | ||
154 | void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...); | 135 | int ath9k_init_debug(struct ath_hw *ah); |
155 | int ath9k_init_debug(struct ath_softc *sc); | 136 | void ath9k_exit_debug(struct ath_hw *ah); |
156 | void ath9k_exit_debug(struct ath_softc *sc); | 137 | |
157 | int ath9k_debug_create_root(void); | 138 | int ath9k_debug_create_root(void); |
158 | void ath9k_debug_remove_root(void); | 139 | void ath9k_debug_remove_root(void); |
159 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | 140 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); |
@@ -165,17 +146,12 @@ void ath_debug_stat_retries(struct ath_softc *sc, int rix, | |||
165 | 146 | ||
166 | #else | 147 | #else |
167 | 148 | ||
168 | static inline void DPRINTF(struct ath_softc *sc, int dbg_mask, | 149 | static inline int ath9k_init_debug(struct ath_hw *ah) |
169 | const char *fmt, ...) | ||
170 | { | ||
171 | } | ||
172 | |||
173 | static inline int ath9k_init_debug(struct ath_softc *sc) | ||
174 | { | 150 | { |
175 | return 0; | 151 | return 0; |
176 | } | 152 | } |
177 | 153 | ||
178 | static inline void ath9k_exit_debug(struct ath_softc *sc) | 154 | static inline void ath9k_exit_debug(struct ath_hw *ah) |
179 | { | 155 | { |
180 | } | 156 | } |
181 | 157 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index b6e52d0f8c48..dacaae934148 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) | 19 | static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) |
20 | { | 20 | { |
@@ -83,11 +83,9 @@ bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, | |||
83 | return false; | 83 | return false; |
84 | } | 84 | } |
85 | 85 | ||
86 | bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) | 86 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data) |
87 | { | 87 | { |
88 | struct ath_softc *sc = ah->ah_sc; | 88 | return common->bus_ops->eeprom_read(common, off, data); |
89 | |||
90 | return sc->bus_ops->eeprom_read(ah, off, data); | ||
91 | } | 89 | } |
92 | 90 | ||
93 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, | 91 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 4fe33f7eee9d..2f2993b50e2f 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #ifndef EEPROM_H | 17 | #ifndef EEPROM_H |
18 | #define EEPROM_H | 18 | #define EEPROM_H |
19 | 19 | ||
20 | #include "../ath.h" | ||
20 | #include <net/cfg80211.h> | 21 | #include <net/cfg80211.h> |
21 | 22 | ||
22 | #define AH_USE_EEPROM 0x1 | 23 | #define AH_USE_EEPROM 0x1 |
@@ -133,6 +134,7 @@ | |||
133 | #define AR5416_EEP_MINOR_VER_17 0x11 | 134 | #define AR5416_EEP_MINOR_VER_17 0x11 |
134 | #define AR5416_EEP_MINOR_VER_19 0x13 | 135 | #define AR5416_EEP_MINOR_VER_19 0x13 |
135 | #define AR5416_EEP_MINOR_VER_20 0x14 | 136 | #define AR5416_EEP_MINOR_VER_20 0x14 |
137 | #define AR5416_EEP_MINOR_VER_21 0x15 | ||
136 | #define AR5416_EEP_MINOR_VER_22 0x16 | 138 | #define AR5416_EEP_MINOR_VER_22 0x16 |
137 | 139 | ||
138 | #define AR5416_NUM_5G_CAL_PIERS 8 | 140 | #define AR5416_NUM_5G_CAL_PIERS 8 |
@@ -153,7 +155,7 @@ | |||
153 | #define AR5416_BCHAN_UNUSED 0xFF | 155 | #define AR5416_BCHAN_UNUSED 0xFF |
154 | #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 | 156 | #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 |
155 | #define AR5416_MAX_CHAINS 3 | 157 | #define AR5416_MAX_CHAINS 3 |
156 | #define AR5416_PWR_TABLE_OFFSET -5 | 158 | #define AR5416_PWR_TABLE_OFFSET_DB -5 |
157 | 159 | ||
158 | /* Rx gain type values */ | 160 | /* Rx gain type values */ |
159 | #define AR5416_EEP_RXGAIN_23DB_BACKOFF 0 | 161 | #define AR5416_EEP_RXGAIN_23DB_BACKOFF 0 |
@@ -301,7 +303,7 @@ struct base_eep_header { | |||
301 | u8 txGainType; | 303 | u8 txGainType; |
302 | u8 rcChainMask; | 304 | u8 rcChainMask; |
303 | u8 desiredScaleCCK; | 305 | u8 desiredScaleCCK; |
304 | u8 power_table_offset; | 306 | u8 pwr_table_offset; |
305 | u8 frac_n_5g; | 307 | u8 frac_n_5g; |
306 | u8 futureBase_3[21]; | 308 | u8 futureBase_3[21]; |
307 | } __packed; | 309 | } __packed; |
@@ -638,6 +640,7 @@ struct ar9287_eeprom { | |||
638 | } __packed; | 640 | } __packed; |
639 | 641 | ||
640 | enum reg_ext_bitmap { | 642 | enum reg_ext_bitmap { |
643 | REG_EXT_FCC_MIDBAND = 0, | ||
641 | REG_EXT_JAPAN_MIDBAND = 1, | 644 | REG_EXT_JAPAN_MIDBAND = 1, |
642 | REG_EXT_FCC_DFS_HT40 = 2, | 645 | REG_EXT_FCC_DFS_HT40 = 2, |
643 | REG_EXT_JAPAN_NONDFS_HT40 = 3, | 646 | REG_EXT_JAPAN_NONDFS_HT40 = 3, |
@@ -684,7 +687,7 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, | |||
684 | int16_t targetRight); | 687 | int16_t targetRight); |
685 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, | 688 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, |
686 | u16 *indexL, u16 *indexR); | 689 | u16 *indexL, u16 *indexR); |
687 | bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data); | 690 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data); |
688 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, | 691 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, |
689 | u8 *pVpdList, u16 numIntercepts, | 692 | u8 *pVpdList, u16 numIntercepts, |
690 | u8 *pRetVpdList); | 693 | u8 *pRetVpdList); |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index b8eca7be5f3a..58167d861dc6 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) | 19 | static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) |
20 | { | 20 | { |
@@ -29,20 +29,21 @@ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) | |||
29 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | 29 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) |
30 | { | 30 | { |
31 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | 31 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) |
32 | struct ath_common *common = ath9k_hw_common(ah); | ||
32 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; | 33 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; |
33 | int addr, eep_start_loc = 0; | 34 | int addr, eep_start_loc = 0; |
34 | 35 | ||
35 | eep_start_loc = 64; | 36 | eep_start_loc = 64; |
36 | 37 | ||
37 | if (!ath9k_hw_use_flash(ah)) { | 38 | if (!ath9k_hw_use_flash(ah)) { |
38 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 39 | ath_print(common, ATH_DBG_EEPROM, |
39 | "Reading from EEPROM, not flash\n"); | 40 | "Reading from EEPROM, not flash\n"); |
40 | } | 41 | } |
41 | 42 | ||
42 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { | 43 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { |
43 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | 44 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { |
44 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 45 | ath_print(common, ATH_DBG_EEPROM, |
45 | "Unable to read eeprom region \n"); | 46 | "Unable to read eeprom region \n"); |
46 | return false; | 47 | return false; |
47 | } | 48 | } |
48 | eep_data++; | 49 | eep_data++; |
@@ -55,6 +56,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | |||
55 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | 56 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) |
56 | { | 57 | { |
57 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | 58 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) |
59 | struct ath_common *common = ath9k_hw_common(ah); | ||
58 | struct ar5416_eeprom_4k *eep = | 60 | struct ar5416_eeprom_4k *eep = |
59 | (struct ar5416_eeprom_4k *) &ah->eeprom.map4k; | 61 | (struct ar5416_eeprom_4k *) &ah->eeprom.map4k; |
60 | u16 *eepdata, temp, magic, magic2; | 62 | u16 *eepdata, temp, magic, magic2; |
@@ -64,15 +66,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
64 | 66 | ||
65 | 67 | ||
66 | if (!ath9k_hw_use_flash(ah)) { | 68 | if (!ath9k_hw_use_flash(ah)) { |
67 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, | 69 | if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, |
68 | &magic)) { | 70 | &magic)) { |
69 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 71 | ath_print(common, ATH_DBG_FATAL, |
70 | "Reading Magic # failed\n"); | 72 | "Reading Magic # failed\n"); |
71 | return false; | 73 | return false; |
72 | } | 74 | } |
73 | 75 | ||
74 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 76 | ath_print(common, ATH_DBG_EEPROM, |
75 | "Read Magic = 0x%04X\n", magic); | 77 | "Read Magic = 0x%04X\n", magic); |
76 | 78 | ||
77 | if (magic != AR5416_EEPROM_MAGIC) { | 79 | if (magic != AR5416_EEPROM_MAGIC) { |
78 | magic2 = swab16(magic); | 80 | magic2 = swab16(magic); |
@@ -87,16 +89,16 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
87 | eepdata++; | 89 | eepdata++; |
88 | } | 90 | } |
89 | } else { | 91 | } else { |
90 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 92 | ath_print(common, ATH_DBG_FATAL, |
91 | "Invalid EEPROM Magic. " | 93 | "Invalid EEPROM Magic. " |
92 | "endianness mismatch.\n"); | 94 | "endianness mismatch.\n"); |
93 | return -EINVAL; | 95 | return -EINVAL; |
94 | } | 96 | } |
95 | } | 97 | } |
96 | } | 98 | } |
97 | 99 | ||
98 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", | 100 | ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", |
99 | need_swap ? "True" : "False"); | 101 | need_swap ? "True" : "False"); |
100 | 102 | ||
101 | if (need_swap) | 103 | if (need_swap) |
102 | el = swab16(ah->eeprom.map4k.baseEepHeader.length); | 104 | el = swab16(ah->eeprom.map4k.baseEepHeader.length); |
@@ -117,8 +119,8 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
117 | u32 integer; | 119 | u32 integer; |
118 | u16 word; | 120 | u16 word; |
119 | 121 | ||
120 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 122 | ath_print(common, ATH_DBG_EEPROM, |
121 | "EEPROM Endianness is not native.. Changing\n"); | 123 | "EEPROM Endianness is not native.. Changing\n"); |
122 | 124 | ||
123 | word = swab16(eep->baseEepHeader.length); | 125 | word = swab16(eep->baseEepHeader.length); |
124 | eep->baseEepHeader.length = word; | 126 | eep->baseEepHeader.length = word; |
@@ -160,9 +162,9 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
160 | 162 | ||
161 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | 163 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || |
162 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 164 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { |
163 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 165 | ath_print(common, ATH_DBG_FATAL, |
164 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | 166 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", |
165 | sum, ah->eep_ops->get_eeprom_ver(ah)); | 167 | sum, ah->eep_ops->get_eeprom_ver(ah)); |
166 | return -EINVAL; | 168 | return -EINVAL; |
167 | } | 169 | } |
168 | 170 | ||
@@ -208,6 +210,8 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | |||
208 | return pBase->rxMask; | 210 | return pBase->rxMask; |
209 | case EEP_FRAC_N_5G: | 211 | case EEP_FRAC_N_5G: |
210 | return 0; | 212 | return 0; |
213 | case EEP_PWR_TABLE_OFFSET: | ||
214 | return AR5416_PWR_TABLE_OFFSET_DB; | ||
211 | default: | 215 | default: |
212 | return 0; | 216 | return 0; |
213 | } | 217 | } |
@@ -385,6 +389,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
385 | struct ath9k_channel *chan, | 389 | struct ath9k_channel *chan, |
386 | int16_t *pTxPowerIndexOffset) | 390 | int16_t *pTxPowerIndexOffset) |
387 | { | 391 | { |
392 | struct ath_common *common = ath9k_hw_common(ah); | ||
388 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | 393 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; |
389 | struct cal_data_per_freq_4k *pRawDataset; | 394 | struct cal_data_per_freq_4k *pRawDataset; |
390 | u8 *pCalBChans = NULL; | 395 | u8 *pCalBChans = NULL; |
@@ -470,21 +475,21 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
470 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); | 475 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); |
471 | REG_WRITE(ah, regOffset, reg32); | 476 | REG_WRITE(ah, regOffset, reg32); |
472 | 477 | ||
473 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 478 | ath_print(common, ATH_DBG_EEPROM, |
474 | "PDADC (%d,%4x): %4.4x %8.8x\n", | 479 | "PDADC (%d,%4x): %4.4x %8.8x\n", |
475 | i, regChainOffset, regOffset, | 480 | i, regChainOffset, regOffset, |
476 | reg32); | 481 | reg32); |
477 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 482 | ath_print(common, ATH_DBG_EEPROM, |
478 | "PDADC: Chain %d | " | 483 | "PDADC: Chain %d | " |
479 | "PDADC %3d Value %3d | " | 484 | "PDADC %3d Value %3d | " |
480 | "PDADC %3d Value %3d | " | 485 | "PDADC %3d Value %3d | " |
481 | "PDADC %3d Value %3d | " | 486 | "PDADC %3d Value %3d | " |
482 | "PDADC %3d Value %3d |\n", | 487 | "PDADC %3d Value %3d |\n", |
483 | i, 4 * j, pdadcValues[4 * j], | 488 | i, 4 * j, pdadcValues[4 * j], |
484 | 4 * j + 1, pdadcValues[4 * j + 1], | 489 | 4 * j + 1, pdadcValues[4 * j + 1], |
485 | 4 * j + 2, pdadcValues[4 * j + 2], | 490 | 4 * j + 2, pdadcValues[4 * j + 2], |
486 | 4 * j + 3, | 491 | 4 * j + 3, |
487 | pdadcValues[4 * j + 3]); | 492 | pdadcValues[4 * j + 3]); |
488 | 493 | ||
489 | regOffset += 4; | 494 | regOffset += 4; |
490 | } | 495 | } |
@@ -750,7 +755,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
750 | 755 | ||
751 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 756 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
752 | for (i = 0; i < Ar5416RateSize; i++) | 757 | for (i = 0; i < Ar5416RateSize; i++) |
753 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | 758 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; |
754 | } | 759 | } |
755 | 760 | ||
756 | /* OFDM power per rate */ | 761 | /* OFDM power per rate */ |
@@ -1148,20 +1153,21 @@ static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | |||
1148 | { | 1153 | { |
1149 | #define EEP_MAP4K_SPURCHAN \ | 1154 | #define EEP_MAP4K_SPURCHAN \ |
1150 | (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan) | 1155 | (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan) |
1156 | struct ath_common *common = ath9k_hw_common(ah); | ||
1151 | 1157 | ||
1152 | u16 spur_val = AR_NO_SPUR; | 1158 | u16 spur_val = AR_NO_SPUR; |
1153 | 1159 | ||
1154 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 1160 | ath_print(common, ATH_DBG_ANI, |
1155 | "Getting spur idx %d is2Ghz. %d val %x\n", | 1161 | "Getting spur idx %d is2Ghz. %d val %x\n", |
1156 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | 1162 | i, is2GHz, ah->config.spurchans[i][is2GHz]); |
1157 | 1163 | ||
1158 | switch (ah->config.spurmode) { | 1164 | switch (ah->config.spurmode) { |
1159 | case SPUR_DISABLE: | 1165 | case SPUR_DISABLE: |
1160 | break; | 1166 | break; |
1161 | case SPUR_ENABLE_IOCTL: | 1167 | case SPUR_ENABLE_IOCTL: |
1162 | spur_val = ah->config.spurchans[i][is2GHz]; | 1168 | spur_val = ah->config.spurchans[i][is2GHz]; |
1163 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 1169 | ath_print(common, ATH_DBG_ANI, |
1164 | "Getting spur val from new loc. %d\n", spur_val); | 1170 | "Getting spur val from new loc. %d\n", spur_val); |
1165 | break; | 1171 | break; |
1166 | case SPUR_ENABLE_EEPROM: | 1172 | case SPUR_ENABLE_EEPROM: |
1167 | spur_val = EEP_MAP4K_SPURCHAN; | 1173 | spur_val = EEP_MAP4K_SPURCHAN; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index c20c21a79b21..839d05a1df29 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah) | 19 | static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah) |
20 | { | 20 | { |
@@ -29,20 +29,22 @@ static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah) | |||
29 | static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) | 29 | static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) |
30 | { | 30 | { |
31 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 31 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
32 | struct ath_common *common = ath9k_hw_common(ah); | ||
32 | u16 *eep_data; | 33 | u16 *eep_data; |
33 | int addr, eep_start_loc = AR9287_EEP_START_LOC; | 34 | int addr, eep_start_loc = AR9287_EEP_START_LOC; |
34 | eep_data = (u16 *)eep; | 35 | eep_data = (u16 *)eep; |
35 | 36 | ||
36 | if (!ath9k_hw_use_flash(ah)) { | 37 | if (!ath9k_hw_use_flash(ah)) { |
37 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 38 | ath_print(common, ATH_DBG_EEPROM, |
38 | "Reading from EEPROM, not flash\n"); | 39 | "Reading from EEPROM, not flash\n"); |
39 | } | 40 | } |
40 | 41 | ||
41 | for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16); | 42 | for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16); |
42 | addr++) { | 43 | addr++) { |
43 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | 44 | if (!ath9k_hw_nvram_read(common, |
44 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 45 | addr + eep_start_loc, eep_data)) { |
45 | "Unable to read eeprom region \n"); | 46 | ath_print(common, ATH_DBG_EEPROM, |
47 | "Unable to read eeprom region \n"); | ||
46 | return false; | 48 | return false; |
47 | } | 49 | } |
48 | eep_data++; | 50 | eep_data++; |
@@ -57,17 +59,18 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
57 | int i, addr; | 59 | int i, addr; |
58 | bool need_swap = false; | 60 | bool need_swap = false; |
59 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 61 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
62 | struct ath_common *common = ath9k_hw_common(ah); | ||
60 | 63 | ||
61 | if (!ath9k_hw_use_flash(ah)) { | 64 | if (!ath9k_hw_use_flash(ah)) { |
62 | if (!ath9k_hw_nvram_read | 65 | if (!ath9k_hw_nvram_read(common, |
63 | (ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | 66 | AR5416_EEPROM_MAGIC_OFFSET, &magic)) { |
64 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 67 | ath_print(common, ATH_DBG_FATAL, |
65 | "Reading Magic # failed\n"); | 68 | "Reading Magic # failed\n"); |
66 | return false; | 69 | return false; |
67 | } | 70 | } |
68 | 71 | ||
69 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 72 | ath_print(common, ATH_DBG_EEPROM, |
70 | "Read Magic = 0x%04X\n", magic); | 73 | "Read Magic = 0x%04X\n", magic); |
71 | if (magic != AR5416_EEPROM_MAGIC) { | 74 | if (magic != AR5416_EEPROM_MAGIC) { |
72 | magic2 = swab16(magic); | 75 | magic2 = swab16(magic); |
73 | 76 | ||
@@ -83,15 +86,15 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
83 | eepdata++; | 86 | eepdata++; |
84 | } | 87 | } |
85 | } else { | 88 | } else { |
86 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 89 | ath_print(common, ATH_DBG_FATAL, |
87 | "Invalid EEPROM Magic. " | 90 | "Invalid EEPROM Magic. " |
88 | "endianness mismatch.\n"); | 91 | "endianness mismatch.\n"); |
89 | return -EINVAL; | 92 | return -EINVAL; |
90 | } | 93 | } |
91 | } | 94 | } |
92 | } | 95 | } |
93 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ? | 96 | ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ? |
94 | "True" : "False"); | 97 | "True" : "False"); |
95 | 98 | ||
96 | if (need_swap) | 99 | if (need_swap) |
97 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); | 100 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); |
@@ -148,9 +151,9 @@ static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) | |||
148 | 151 | ||
149 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER | 152 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER |
150 | || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 153 | || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { |
151 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 154 | ath_print(common, ATH_DBG_FATAL, |
152 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | 155 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", |
153 | sum, ah->eep_ops->get_eeprom_ver(ah)); | 156 | sum, ah->eep_ops->get_eeprom_ver(ah)); |
154 | return -EINVAL; | 157 | return -EINVAL; |
155 | } | 158 | } |
156 | 159 | ||
@@ -436,6 +439,7 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | |||
436 | struct ath9k_channel *chan, | 439 | struct ath9k_channel *chan, |
437 | int16_t *pTxPowerIndexOffset) | 440 | int16_t *pTxPowerIndexOffset) |
438 | { | 441 | { |
442 | struct ath_common *common = ath9k_hw_common(ah); | ||
439 | struct cal_data_per_freq_ar9287 *pRawDataset; | 443 | struct cal_data_per_freq_ar9287 *pRawDataset; |
440 | struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; | 444 | struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; |
441 | u8 *pCalBChans = NULL; | 445 | u8 *pCalBChans = NULL; |
@@ -564,24 +568,25 @@ static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, | |||
564 | & 0xFF) << 24) ; | 568 | & 0xFF) << 24) ; |
565 | REG_WRITE(ah, regOffset, reg32); | 569 | REG_WRITE(ah, regOffset, reg32); |
566 | 570 | ||
567 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 571 | ath_print(common, ATH_DBG_EEPROM, |
568 | "PDADC (%d,%4x): %4.4x %8.8x\n", | 572 | "PDADC (%d,%4x): %4.4x " |
569 | i, regChainOffset, regOffset, | 573 | "%8.8x\n", |
570 | reg32); | 574 | i, regChainOffset, regOffset, |
571 | 575 | reg32); | |
572 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 576 | |
573 | "PDADC: Chain %d | " | 577 | ath_print(common, ATH_DBG_EEPROM, |
574 | "PDADC %3d Value %3d | " | 578 | "PDADC: Chain %d | " |
575 | "PDADC %3d Value %3d | " | 579 | "PDADC %3d Value %3d | " |
576 | "PDADC %3d Value %3d | " | 580 | "PDADC %3d Value %3d | " |
577 | "PDADC %3d Value %3d |\n", | 581 | "PDADC %3d Value %3d | " |
578 | i, 4 * j, pdadcValues[4 * j], | 582 | "PDADC %3d Value %3d |\n", |
579 | 4 * j + 1, | 583 | i, 4 * j, pdadcValues[4 * j], |
580 | pdadcValues[4 * j + 1], | 584 | 4 * j + 1, |
581 | 4 * j + 2, | 585 | pdadcValues[4 * j + 1], |
582 | pdadcValues[4 * j + 2], | 586 | 4 * j + 2, |
583 | 4 * j + 3, | 587 | pdadcValues[4 * j + 2], |
584 | pdadcValues[4 * j + 3]); | 588 | 4 * j + 3, |
589 | pdadcValues[4 * j + 3]); | ||
585 | 590 | ||
586 | regOffset += 4; | 591 | regOffset += 4; |
587 | } | 592 | } |
@@ -831,6 +836,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
831 | { | 836 | { |
832 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 | 837 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 |
833 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 | 838 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 |
839 | struct ath_common *common = ath9k_hw_common(ah); | ||
834 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 840 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
835 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | 841 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
836 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; | 842 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; |
@@ -966,8 +972,8 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
966 | INCREASE_MAXPOW_BY_THREE_CHAIN; | 972 | INCREASE_MAXPOW_BY_THREE_CHAIN; |
967 | break; | 973 | break; |
968 | default: | 974 | default: |
969 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 975 | ath_print(common, ATH_DBG_EEPROM, |
970 | "Invalid chainmask configuration\n"); | 976 | "Invalid chainmask configuration\n"); |
971 | break; | 977 | break; |
972 | } | 978 | } |
973 | } | 979 | } |
@@ -1138,19 +1144,20 @@ static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, | |||
1138 | { | 1144 | { |
1139 | #define EEP_MAP9287_SPURCHAN \ | 1145 | #define EEP_MAP9287_SPURCHAN \ |
1140 | (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) | 1146 | (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) |
1147 | struct ath_common *common = ath9k_hw_common(ah); | ||
1141 | u16 spur_val = AR_NO_SPUR; | 1148 | u16 spur_val = AR_NO_SPUR; |
1142 | 1149 | ||
1143 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 1150 | ath_print(common, ATH_DBG_ANI, |
1144 | "Getting spur idx %d is2Ghz. %d val %x\n", | 1151 | "Getting spur idx %d is2Ghz. %d val %x\n", |
1145 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | 1152 | i, is2GHz, ah->config.spurchans[i][is2GHz]); |
1146 | 1153 | ||
1147 | switch (ah->config.spurmode) { | 1154 | switch (ah->config.spurmode) { |
1148 | case SPUR_DISABLE: | 1155 | case SPUR_DISABLE: |
1149 | break; | 1156 | break; |
1150 | case SPUR_ENABLE_IOCTL: | 1157 | case SPUR_ENABLE_IOCTL: |
1151 | spur_val = ah->config.spurchans[i][is2GHz]; | 1158 | spur_val = ah->config.spurchans[i][is2GHz]; |
1152 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 1159 | ath_print(common, ATH_DBG_ANI, |
1153 | "Getting spur val from new loc. %d\n", spur_val); | 1160 | "Getting spur val from new loc. %d\n", spur_val); |
1154 | break; | 1161 | break; |
1155 | case SPUR_ENABLE_EEPROM: | 1162 | case SPUR_ENABLE_EEPROM: |
1156 | spur_val = EEP_MAP9287_SPURCHAN; | 1163 | spur_val = EEP_MAP9287_SPURCHAN; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 4071fc91da0a..404a0341242c 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | static void ath9k_get_txgain_index(struct ath_hw *ah, | 19 | static void ath9k_get_txgain_index(struct ath_hw *ah, |
20 | struct ath9k_channel *chan, | 20 | struct ath9k_channel *chan, |
@@ -89,14 +89,15 @@ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) | |||
89 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | 89 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) |
90 | { | 90 | { |
91 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) | 91 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) |
92 | struct ath_common *common = ath9k_hw_common(ah); | ||
92 | u16 *eep_data = (u16 *)&ah->eeprom.def; | 93 | u16 *eep_data = (u16 *)&ah->eeprom.def; |
93 | int addr, ar5416_eep_start_loc = 0x100; | 94 | int addr, ar5416_eep_start_loc = 0x100; |
94 | 95 | ||
95 | for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { | 96 | for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { |
96 | if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, | 97 | if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc, |
97 | eep_data)) { | 98 | eep_data)) { |
98 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 99 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
99 | "Unable to read eeprom region\n"); | 100 | "Unable to read eeprom region\n"); |
100 | return false; | 101 | return false; |
101 | } | 102 | } |
102 | eep_data++; | 103 | eep_data++; |
@@ -109,19 +110,20 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
109 | { | 110 | { |
110 | struct ar5416_eeprom_def *eep = | 111 | struct ar5416_eeprom_def *eep = |
111 | (struct ar5416_eeprom_def *) &ah->eeprom.def; | 112 | (struct ar5416_eeprom_def *) &ah->eeprom.def; |
113 | struct ath_common *common = ath9k_hw_common(ah); | ||
112 | u16 *eepdata, temp, magic, magic2; | 114 | u16 *eepdata, temp, magic, magic2; |
113 | u32 sum = 0, el; | 115 | u32 sum = 0, el; |
114 | bool need_swap = false; | 116 | bool need_swap = false; |
115 | int i, addr, size; | 117 | int i, addr, size; |
116 | 118 | ||
117 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | 119 | if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { |
118 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n"); | 120 | ath_print(common, ATH_DBG_FATAL, "Reading Magic # failed\n"); |
119 | return false; | 121 | return false; |
120 | } | 122 | } |
121 | 123 | ||
122 | if (!ath9k_hw_use_flash(ah)) { | 124 | if (!ath9k_hw_use_flash(ah)) { |
123 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 125 | ath_print(common, ATH_DBG_EEPROM, |
124 | "Read Magic = 0x%04X\n", magic); | 126 | "Read Magic = 0x%04X\n", magic); |
125 | 127 | ||
126 | if (magic != AR5416_EEPROM_MAGIC) { | 128 | if (magic != AR5416_EEPROM_MAGIC) { |
127 | magic2 = swab16(magic); | 129 | magic2 = swab16(magic); |
@@ -137,16 +139,16 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
137 | eepdata++; | 139 | eepdata++; |
138 | } | 140 | } |
139 | } else { | 141 | } else { |
140 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 142 | ath_print(common, ATH_DBG_FATAL, |
141 | "Invalid EEPROM Magic. " | 143 | "Invalid EEPROM Magic. " |
142 | "Endianness mismatch.\n"); | 144 | "Endianness mismatch.\n"); |
143 | return -EINVAL; | 145 | return -EINVAL; |
144 | } | 146 | } |
145 | } | 147 | } |
146 | } | 148 | } |
147 | 149 | ||
148 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", | 150 | ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", |
149 | need_swap ? "True" : "False"); | 151 | need_swap ? "True" : "False"); |
150 | 152 | ||
151 | if (need_swap) | 153 | if (need_swap) |
152 | el = swab16(ah->eeprom.def.baseEepHeader.length); | 154 | el = swab16(ah->eeprom.def.baseEepHeader.length); |
@@ -167,8 +169,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
167 | u32 integer, j; | 169 | u32 integer, j; |
168 | u16 word; | 170 | u16 word; |
169 | 171 | ||
170 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 172 | ath_print(common, ATH_DBG_EEPROM, |
171 | "EEPROM Endianness is not native.. Changing.\n"); | 173 | "EEPROM Endianness is not native.. Changing.\n"); |
172 | 174 | ||
173 | word = swab16(eep->baseEepHeader.length); | 175 | word = swab16(eep->baseEepHeader.length); |
174 | eep->baseEepHeader.length = word; | 176 | eep->baseEepHeader.length = word; |
@@ -214,8 +216,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
214 | 216 | ||
215 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | 217 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || |
216 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 218 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { |
217 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 219 | ath_print(common, ATH_DBG_FATAL, |
218 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | 220 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", |
219 | sum, ah->eep_ops->get_eeprom_ver(ah)); | 221 | sum, ah->eep_ops->get_eeprom_ver(ah)); |
220 | return -EINVAL; | 222 | return -EINVAL; |
221 | } | 223 | } |
@@ -289,6 +291,11 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, | |||
289 | return pBase->frac_n_5g; | 291 | return pBase->frac_n_5g; |
290 | else | 292 | else |
291 | return 0; | 293 | return 0; |
294 | case EEP_PWR_TABLE_OFFSET: | ||
295 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_21) | ||
296 | return pBase->pwr_table_offset; | ||
297 | else | ||
298 | return AR5416_PWR_TABLE_OFFSET_DB; | ||
292 | default: | 299 | default: |
293 | return 0; | 300 | return 0; |
294 | } | 301 | } |
@@ -739,6 +746,76 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, | |||
739 | return; | 746 | return; |
740 | } | 747 | } |
741 | 748 | ||
749 | static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah, | ||
750 | u16 *gb, | ||
751 | u16 numXpdGain, | ||
752 | u16 pdGainOverlap_t2, | ||
753 | int8_t pwr_table_offset, | ||
754 | int16_t *diff) | ||
755 | |||
756 | { | ||
757 | u16 k; | ||
758 | |||
759 | /* Prior to writing the boundaries or the pdadc vs. power table | ||
760 | * into the chip registers the default starting point on the pdadc | ||
761 | * vs. power table needs to be checked and the curve boundaries | ||
762 | * adjusted accordingly | ||
763 | */ | ||
764 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
765 | u16 gb_limit; | ||
766 | |||
767 | if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { | ||
768 | /* get the difference in dB */ | ||
769 | *diff = (u16)(pwr_table_offset - AR5416_PWR_TABLE_OFFSET_DB); | ||
770 | /* get the number of half dB steps */ | ||
771 | *diff *= 2; | ||
772 | /* change the original gain boundary settings | ||
773 | * by the number of half dB steps | ||
774 | */ | ||
775 | for (k = 0; k < numXpdGain; k++) | ||
776 | gb[k] = (u16)(gb[k] - *diff); | ||
777 | } | ||
778 | /* Because of a hardware limitation, ensure the gain boundary | ||
779 | * is not larger than (63 - overlap) | ||
780 | */ | ||
781 | gb_limit = (u16)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2); | ||
782 | |||
783 | for (k = 0; k < numXpdGain; k++) | ||
784 | gb[k] = (u16)min(gb_limit, gb[k]); | ||
785 | } | ||
786 | |||
787 | return *diff; | ||
788 | } | ||
789 | |||
790 | static void ath9k_adjust_pdadc_values(struct ath_hw *ah, | ||
791 | int8_t pwr_table_offset, | ||
792 | int16_t diff, | ||
793 | u8 *pdadcValues) | ||
794 | { | ||
795 | #define NUM_PDADC(diff) (AR5416_NUM_PDADC_VALUES - diff) | ||
796 | u16 k; | ||
797 | |||
798 | /* If this is a board that has a pwrTableOffset that differs from | ||
799 | * the default AR5416_PWR_TABLE_OFFSET_DB then the start of the | ||
800 | * pdadc vs pwr table needs to be adjusted prior to writing to the | ||
801 | * chip. | ||
802 | */ | ||
803 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
804 | if (AR5416_PWR_TABLE_OFFSET_DB != pwr_table_offset) { | ||
805 | /* shift the table to start at the new offset */ | ||
806 | for (k = 0; k < (u16)NUM_PDADC(diff); k++ ) { | ||
807 | pdadcValues[k] = pdadcValues[k + diff]; | ||
808 | } | ||
809 | |||
810 | /* fill the back of the table */ | ||
811 | for (k = (u16)NUM_PDADC(diff); k < NUM_PDADC(0); k++) { | ||
812 | pdadcValues[k] = pdadcValues[NUM_PDADC(diff)]; | ||
813 | } | ||
814 | } | ||
815 | } | ||
816 | #undef NUM_PDADC | ||
817 | } | ||
818 | |||
742 | static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | 819 | static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, |
743 | struct ath9k_channel *chan, | 820 | struct ath9k_channel *chan, |
744 | int16_t *pTxPowerIndexOffset) | 821 | int16_t *pTxPowerIndexOffset) |
@@ -746,7 +823,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
746 | #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) | 823 | #define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) |
747 | #define SM_PDGAIN_B(x, y) \ | 824 | #define SM_PDGAIN_B(x, y) \ |
748 | SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y) | 825 | SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y) |
749 | 826 | struct ath_common *common = ath9k_hw_common(ah); | |
750 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 827 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
751 | struct cal_data_per_freq *pRawDataset; | 828 | struct cal_data_per_freq *pRawDataset; |
752 | u8 *pCalBChans = NULL; | 829 | u8 *pCalBChans = NULL; |
@@ -754,15 +831,18 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
754 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | 831 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; |
755 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; | 832 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; |
756 | u16 numPiers, i, j; | 833 | u16 numPiers, i, j; |
757 | int16_t tMinCalPower; | 834 | int16_t tMinCalPower, diff = 0; |
758 | u16 numXpdGain, xpdMask; | 835 | u16 numXpdGain, xpdMask; |
759 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; | 836 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; |
760 | u32 reg32, regOffset, regChainOffset; | 837 | u32 reg32, regOffset, regChainOffset; |
761 | int16_t modalIdx; | 838 | int16_t modalIdx; |
839 | int8_t pwr_table_offset; | ||
762 | 840 | ||
763 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | 841 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; |
764 | xpdMask = pEepData->modalHeader[modalIdx].xpdGain; | 842 | xpdMask = pEepData->modalHeader[modalIdx].xpdGain; |
765 | 843 | ||
844 | pwr_table_offset = ah->eep_ops->get_eeprom(ah, EEP_PWR_TABLE_OFFSET); | ||
845 | |||
766 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | 846 | if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= |
767 | AR5416_EEP_MINOR_VER_2) { | 847 | AR5416_EEP_MINOR_VER_2) { |
768 | pdGainOverlap_t2 = | 848 | pdGainOverlap_t2 = |
@@ -842,6 +922,13 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
842 | numXpdGain); | 922 | numXpdGain); |
843 | } | 923 | } |
844 | 924 | ||
925 | diff = ath9k_change_gain_boundary_setting(ah, | ||
926 | gainBoundaries, | ||
927 | numXpdGain, | ||
928 | pdGainOverlap_t2, | ||
929 | pwr_table_offset, | ||
930 | &diff); | ||
931 | |||
845 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | 932 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { |
846 | if (OLC_FOR_AR9280_20_LATER) { | 933 | if (OLC_FOR_AR9280_20_LATER) { |
847 | REG_WRITE(ah, | 934 | REG_WRITE(ah, |
@@ -862,6 +949,10 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
862 | } | 949 | } |
863 | } | 950 | } |
864 | 951 | ||
952 | |||
953 | ath9k_adjust_pdadc_values(ah, pwr_table_offset, | ||
954 | diff, pdadcValues); | ||
955 | |||
865 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; | 956 | regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; |
866 | for (j = 0; j < 32; j++) { | 957 | for (j = 0; j < 32; j++) { |
867 | reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | | 958 | reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | |
@@ -870,20 +961,20 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
870 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); | 961 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); |
871 | REG_WRITE(ah, regOffset, reg32); | 962 | REG_WRITE(ah, regOffset, reg32); |
872 | 963 | ||
873 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 964 | ath_print(common, ATH_DBG_EEPROM, |
874 | "PDADC (%d,%4x): %4.4x %8.8x\n", | 965 | "PDADC (%d,%4x): %4.4x %8.8x\n", |
875 | i, regChainOffset, regOffset, | 966 | i, regChainOffset, regOffset, |
876 | reg32); | 967 | reg32); |
877 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 968 | ath_print(common, ATH_DBG_EEPROM, |
878 | "PDADC: Chain %d | PDADC %3d " | 969 | "PDADC: Chain %d | PDADC %3d " |
879 | "Value %3d | PDADC %3d Value %3d | " | 970 | "Value %3d | PDADC %3d Value %3d | " |
880 | "PDADC %3d Value %3d | PDADC %3d " | 971 | "PDADC %3d Value %3d | PDADC %3d " |
881 | "Value %3d |\n", | 972 | "Value %3d |\n", |
882 | i, 4 * j, pdadcValues[4 * j], | 973 | i, 4 * j, pdadcValues[4 * j], |
883 | 4 * j + 1, pdadcValues[4 * j + 1], | 974 | 4 * j + 1, pdadcValues[4 * j + 1], |
884 | 4 * j + 2, pdadcValues[4 * j + 2], | 975 | 4 * j + 2, pdadcValues[4 * j + 2], |
885 | 4 * j + 3, | 976 | 4 * j + 3, |
886 | pdadcValues[4 * j + 3]); | 977 | pdadcValues[4 * j + 3]); |
887 | 978 | ||
888 | regOffset += 4; | 979 | regOffset += 4; |
889 | } | 980 | } |
@@ -1197,8 +1288,13 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1197 | } | 1288 | } |
1198 | 1289 | ||
1199 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 1290 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
1200 | for (i = 0; i < Ar5416RateSize; i++) | 1291 | for (i = 0; i < Ar5416RateSize; i++) { |
1201 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; | 1292 | int8_t pwr_table_offset; |
1293 | |||
1294 | pwr_table_offset = ah->eep_ops->get_eeprom(ah, | ||
1295 | EEP_PWR_TABLE_OFFSET); | ||
1296 | ratesArray[i] -= pwr_table_offset * 2; | ||
1297 | } | ||
1202 | } | 1298 | } |
1203 | 1299 | ||
1204 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | 1300 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, |
@@ -1297,7 +1393,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1297 | 1393 | ||
1298 | if (AR_SREV_9280_10_OR_LATER(ah)) | 1394 | if (AR_SREV_9280_10_OR_LATER(ah)) |
1299 | regulatory->max_power_level = | 1395 | regulatory->max_power_level = |
1300 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; | 1396 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; |
1301 | else | 1397 | else |
1302 | regulatory->max_power_level = ratesArray[i]; | 1398 | regulatory->max_power_level = ratesArray[i]; |
1303 | 1399 | ||
@@ -1311,8 +1407,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1311 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | 1407 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; |
1312 | break; | 1408 | break; |
1313 | default: | 1409 | default: |
1314 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1410 | ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, |
1315 | "Invalid chainmask configuration\n"); | 1411 | "Invalid chainmask configuration\n"); |
1316 | break; | 1412 | break; |
1317 | } | 1413 | } |
1318 | } | 1414 | } |
@@ -1349,20 +1445,21 @@ static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | |||
1349 | { | 1445 | { |
1350 | #define EEP_DEF_SPURCHAN \ | 1446 | #define EEP_DEF_SPURCHAN \ |
1351 | (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan) | 1447 | (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan) |
1448 | struct ath_common *common = ath9k_hw_common(ah); | ||
1352 | 1449 | ||
1353 | u16 spur_val = AR_NO_SPUR; | 1450 | u16 spur_val = AR_NO_SPUR; |
1354 | 1451 | ||
1355 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 1452 | ath_print(common, ATH_DBG_ANI, |
1356 | "Getting spur idx %d is2Ghz. %d val %x\n", | 1453 | "Getting spur idx %d is2Ghz. %d val %x\n", |
1357 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | 1454 | i, is2GHz, ah->config.spurchans[i][is2GHz]); |
1358 | 1455 | ||
1359 | switch (ah->config.spurmode) { | 1456 | switch (ah->config.spurmode) { |
1360 | case SPUR_DISABLE: | 1457 | case SPUR_DISABLE: |
1361 | break; | 1458 | break; |
1362 | case SPUR_ENABLE_IOCTL: | 1459 | case SPUR_ENABLE_IOCTL: |
1363 | spur_val = ah->config.spurchans[i][is2GHz]; | 1460 | spur_val = ah->config.spurchans[i][is2GHz]; |
1364 | DPRINTF(ah->ah_sc, ATH_DBG_ANI, | 1461 | ath_print(common, ATH_DBG_ANI, |
1365 | "Getting spur val from new loc. %d\n", spur_val); | 1462 | "Getting spur val from new loc. %d\n", spur_val); |
1366 | break; | 1463 | break; |
1367 | case SPUR_ENABLE_EEPROM: | 1464 | case SPUR_ENABLE_EEPROM: |
1368 | spur_val = EEP_DEF_SPURCHAN; | 1465 | spur_val = EEP_DEF_SPURCHAN; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index ca7694caf364..cab17c6c8a37 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -16,9 +16,9 @@ | |||
16 | 16 | ||
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <asm/unaligned.h> | 18 | #include <asm/unaligned.h> |
19 | #include <linux/pci.h> | ||
20 | 19 | ||
21 | #include "ath9k.h" | 20 | #include "hw.h" |
21 | #include "rc.h" | ||
22 | #include "initvals.h" | 22 | #include "initvals.h" |
23 | 23 | ||
24 | #define ATH9K_CLOCK_RATE_CCK 22 | 24 | #define ATH9K_CLOCK_RATE_CCK 22 |
@@ -26,21 +26,37 @@ | |||
26 | #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 | 26 | #define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 |
27 | 27 | ||
28 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); | 28 | static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); |
29 | static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, | 29 | static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan); |
30 | enum ath9k_ht_macmode macmode); | ||
31 | static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, | 30 | static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, |
32 | struct ar5416_eeprom_def *pEepData, | 31 | struct ar5416_eeprom_def *pEepData, |
33 | u32 reg, u32 value); | 32 | u32 reg, u32 value); |
34 | static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); | 33 | static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); |
35 | static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); | 34 | static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); |
36 | 35 | ||
36 | MODULE_AUTHOR("Atheros Communications"); | ||
37 | MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); | ||
38 | MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); | ||
39 | MODULE_LICENSE("Dual BSD/GPL"); | ||
40 | |||
41 | static int __init ath9k_init(void) | ||
42 | { | ||
43 | return 0; | ||
44 | } | ||
45 | module_init(ath9k_init); | ||
46 | |||
47 | static void __exit ath9k_exit(void) | ||
48 | { | ||
49 | return; | ||
50 | } | ||
51 | module_exit(ath9k_exit); | ||
52 | |||
37 | /********************/ | 53 | /********************/ |
38 | /* Helper Functions */ | 54 | /* Helper Functions */ |
39 | /********************/ | 55 | /********************/ |
40 | 56 | ||
41 | static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) | 57 | static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) |
42 | { | 58 | { |
43 | struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; | 59 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
44 | 60 | ||
45 | if (!ah->curchan) /* should really check for CCK instead */ | 61 | if (!ah->curchan) /* should really check for CCK instead */ |
46 | return clks / ATH9K_CLOCK_RATE_CCK; | 62 | return clks / ATH9K_CLOCK_RATE_CCK; |
@@ -52,7 +68,7 @@ static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) | |||
52 | 68 | ||
53 | static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) | 69 | static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) |
54 | { | 70 | { |
55 | struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; | 71 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
56 | 72 | ||
57 | if (conf_is_ht40(conf)) | 73 | if (conf_is_ht40(conf)) |
58 | return ath9k_hw_mac_usec(ah, clks) / 2; | 74 | return ath9k_hw_mac_usec(ah, clks) / 2; |
@@ -62,7 +78,7 @@ static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) | |||
62 | 78 | ||
63 | static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) | 79 | static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) |
64 | { | 80 | { |
65 | struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; | 81 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
66 | 82 | ||
67 | if (!ah->curchan) /* should really check for CCK instead */ | 83 | if (!ah->curchan) /* should really check for CCK instead */ |
68 | return usecs *ATH9K_CLOCK_RATE_CCK; | 84 | return usecs *ATH9K_CLOCK_RATE_CCK; |
@@ -73,7 +89,7 @@ static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) | |||
73 | 89 | ||
74 | static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) | 90 | static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) |
75 | { | 91 | { |
76 | struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; | 92 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
77 | 93 | ||
78 | if (conf_is_ht40(conf)) | 94 | if (conf_is_ht40(conf)) |
79 | return ath9k_hw_mac_clks(ah, usecs) * 2; | 95 | return ath9k_hw_mac_clks(ah, usecs) * 2; |
@@ -81,38 +97,6 @@ static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) | |||
81 | return ath9k_hw_mac_clks(ah, usecs); | 97 | return ath9k_hw_mac_clks(ah, usecs); |
82 | } | 98 | } |
83 | 99 | ||
84 | /* | ||
85 | * Read and write, they both share the same lock. We do this to serialize | ||
86 | * reads and writes on Atheros 802.11n PCI devices only. This is required | ||
87 | * as the FIFO on these devices can only accept sanely 2 requests. After | ||
88 | * that the device goes bananas. Serializing the reads/writes prevents this | ||
89 | * from happening. | ||
90 | */ | ||
91 | |||
92 | void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val) | ||
93 | { | ||
94 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) { | ||
95 | unsigned long flags; | ||
96 | spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); | ||
97 | iowrite32(val, ah->ah_sc->mem + reg_offset); | ||
98 | spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); | ||
99 | } else | ||
100 | iowrite32(val, ah->ah_sc->mem + reg_offset); | ||
101 | } | ||
102 | |||
103 | unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset) | ||
104 | { | ||
105 | u32 val; | ||
106 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) { | ||
107 | unsigned long flags; | ||
108 | spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); | ||
109 | val = ioread32(ah->ah_sc->mem + reg_offset); | ||
110 | spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); | ||
111 | } else | ||
112 | val = ioread32(ah->ah_sc->mem + reg_offset); | ||
113 | return val; | ||
114 | } | ||
115 | |||
116 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) | 100 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) |
117 | { | 101 | { |
118 | int i; | 102 | int i; |
@@ -126,12 +110,13 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) | |||
126 | udelay(AH_TIME_QUANTUM); | 110 | udelay(AH_TIME_QUANTUM); |
127 | } | 111 | } |
128 | 112 | ||
129 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | 113 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, |
130 | "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", | 114 | "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", |
131 | timeout, reg, REG_READ(ah, reg), mask, val); | 115 | timeout, reg, REG_READ(ah, reg), mask, val); |
132 | 116 | ||
133 | return false; | 117 | return false; |
134 | } | 118 | } |
119 | EXPORT_SYMBOL(ath9k_hw_wait); | ||
135 | 120 | ||
136 | u32 ath9k_hw_reverse_bits(u32 val, u32 n) | 121 | u32 ath9k_hw_reverse_bits(u32 val, u32 n) |
137 | { | 122 | { |
@@ -210,15 +195,16 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, | |||
210 | } | 195 | } |
211 | break; | 196 | break; |
212 | default: | 197 | default: |
213 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 198 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
214 | "Unknown phy %u (rate ix %u)\n", | 199 | "Unknown phy %u (rate ix %u)\n", |
215 | rates->info[rateix].phy, rateix); | 200 | rates->info[rateix].phy, rateix); |
216 | txTime = 0; | 201 | txTime = 0; |
217 | break; | 202 | break; |
218 | } | 203 | } |
219 | 204 | ||
220 | return txTime; | 205 | return txTime; |
221 | } | 206 | } |
207 | EXPORT_SYMBOL(ath9k_hw_computetxtime); | ||
222 | 208 | ||
223 | void ath9k_hw_get_channel_centers(struct ath_hw *ah, | 209 | void ath9k_hw_get_channel_centers(struct ath_hw *ah, |
224 | struct ath9k_channel *chan, | 210 | struct ath9k_channel *chan, |
@@ -245,10 +231,9 @@ void ath9k_hw_get_channel_centers(struct ath_hw *ah, | |||
245 | 231 | ||
246 | centers->ctl_center = | 232 | centers->ctl_center = |
247 | centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT); | 233 | centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT); |
234 | /* 25 MHz spacing is supported by hw but not on upper layers */ | ||
248 | centers->ext_center = | 235 | centers->ext_center = |
249 | centers->synth_center + (extoff * | 236 | centers->synth_center + (extoff * HT40_CHANNEL_CENTER_SHIFT); |
250 | ((ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ? | ||
251 | HT40_CHANNEL_CENTER_SHIFT : 15)); | ||
252 | } | 237 | } |
253 | 238 | ||
254 | /******************/ | 239 | /******************/ |
@@ -317,6 +302,7 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) | |||
317 | 302 | ||
318 | static bool ath9k_hw_chip_test(struct ath_hw *ah) | 303 | static bool ath9k_hw_chip_test(struct ath_hw *ah) |
319 | { | 304 | { |
305 | struct ath_common *common = ath9k_hw_common(ah); | ||
320 | u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) }; | 306 | u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) }; |
321 | u32 regHold[2]; | 307 | u32 regHold[2]; |
322 | u32 patternData[4] = { 0x55555555, | 308 | u32 patternData[4] = { 0x55555555, |
@@ -335,10 +321,11 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
335 | REG_WRITE(ah, addr, wrData); | 321 | REG_WRITE(ah, addr, wrData); |
336 | rdData = REG_READ(ah, addr); | 322 | rdData = REG_READ(ah, addr); |
337 | if (rdData != wrData) { | 323 | if (rdData != wrData) { |
338 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 324 | ath_print(common, ATH_DBG_FATAL, |
339 | "address test failed " | 325 | "address test failed " |
340 | "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", | 326 | "addr: 0x%08x - wr:0x%08x != " |
341 | addr, wrData, rdData); | 327 | "rd:0x%08x\n", |
328 | addr, wrData, rdData); | ||
342 | return false; | 329 | return false; |
343 | } | 330 | } |
344 | } | 331 | } |
@@ -347,10 +334,11 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
347 | REG_WRITE(ah, addr, wrData); | 334 | REG_WRITE(ah, addr, wrData); |
348 | rdData = REG_READ(ah, addr); | 335 | rdData = REG_READ(ah, addr); |
349 | if (wrData != rdData) { | 336 | if (wrData != rdData) { |
350 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 337 | ath_print(common, ATH_DBG_FATAL, |
351 | "address test failed " | 338 | "address test failed " |
352 | "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", | 339 | "addr: 0x%08x - wr:0x%08x != " |
353 | addr, wrData, rdData); | 340 | "rd:0x%08x\n", |
341 | addr, wrData, rdData); | ||
354 | return false; | 342 | return false; |
355 | } | 343 | } |
356 | } | 344 | } |
@@ -433,6 +421,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
433 | if (num_possible_cpus() > 1) | 421 | if (num_possible_cpus() > 1) |
434 | ah->config.serialize_regmode = SER_REG_MODE_AUTO; | 422 | ah->config.serialize_regmode = SER_REG_MODE_AUTO; |
435 | } | 423 | } |
424 | EXPORT_SYMBOL(ath9k_hw_init); | ||
436 | 425 | ||
437 | static void ath9k_hw_init_defaults(struct ath_hw *ah) | 426 | static void ath9k_hw_init_defaults(struct ath_hw *ah) |
438 | { | 427 | { |
@@ -472,8 +461,8 @@ static int ath9k_hw_rfattach(struct ath_hw *ah) | |||
472 | 461 | ||
473 | rfStatus = ath9k_hw_init_rf(ah, &ecode); | 462 | rfStatus = ath9k_hw_init_rf(ah, &ecode); |
474 | if (!rfStatus) { | 463 | if (!rfStatus) { |
475 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 464 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
476 | "RF setup failed, status: %u\n", ecode); | 465 | "RF setup failed, status: %u\n", ecode); |
477 | return ecode; | 466 | return ecode; |
478 | } | 467 | } |
479 | 468 | ||
@@ -497,9 +486,9 @@ static int ath9k_hw_rf_claim(struct ath_hw *ah) | |||
497 | case AR_RAD2122_SREV_MAJOR: | 486 | case AR_RAD2122_SREV_MAJOR: |
498 | break; | 487 | break; |
499 | default: | 488 | default: |
500 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 489 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
501 | "Radio Chip Rev 0x%02X not supported\n", | 490 | "Radio Chip Rev 0x%02X not supported\n", |
502 | val & AR_RADIO_SREV_MAJOR); | 491 | val & AR_RADIO_SREV_MAJOR); |
503 | return -EOPNOTSUPP; | 492 | return -EOPNOTSUPP; |
504 | } | 493 | } |
505 | 494 | ||
@@ -510,6 +499,7 @@ static int ath9k_hw_rf_claim(struct ath_hw *ah) | |||
510 | 499 | ||
511 | static int ath9k_hw_init_macaddr(struct ath_hw *ah) | 500 | static int ath9k_hw_init_macaddr(struct ath_hw *ah) |
512 | { | 501 | { |
502 | struct ath_common *common = ath9k_hw_common(ah); | ||
513 | u32 sum; | 503 | u32 sum; |
514 | int i; | 504 | int i; |
515 | u16 eeval; | 505 | u16 eeval; |
@@ -518,8 +508,8 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) | |||
518 | for (i = 0; i < 3; i++) { | 508 | for (i = 0; i < 3; i++) { |
519 | eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i)); | 509 | eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i)); |
520 | sum += eeval; | 510 | sum += eeval; |
521 | ah->macaddr[2 * i] = eeval >> 8; | 511 | common->macaddr[2 * i] = eeval >> 8; |
522 | ah->macaddr[2 * i + 1] = eeval & 0xff; | 512 | common->macaddr[2 * i + 1] = eeval & 0xff; |
523 | } | 513 | } |
524 | if (sum == 0 || sum == 0xffff * 3) | 514 | if (sum == 0 || sum == 0xffff * 3) |
525 | return -EADDRNOTAVAIL; | 515 | return -EADDRNOTAVAIL; |
@@ -590,8 +580,10 @@ static int ath9k_hw_post_init(struct ath_hw *ah) | |||
590 | if (ecode != 0) | 580 | if (ecode != 0) |
591 | return ecode; | 581 | return ecode; |
592 | 582 | ||
593 | DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n", | 583 | ath_print(ath9k_hw_common(ah), ATH_DBG_CONFIG, |
594 | ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); | 584 | "Eeprom VER: %d, REV: %d\n", |
585 | ah->eep_ops->get_eeprom_ver(ah), | ||
586 | ah->eep_ops->get_eeprom_rev(ah)); | ||
595 | 587 | ||
596 | ecode = ath9k_hw_rfattach(ah); | 588 | ecode = ath9k_hw_rfattach(ah); |
597 | if (ecode != 0) | 589 | if (ecode != 0) |
@@ -617,6 +609,7 @@ static bool ath9k_hw_devid_supported(u16 devid) | |||
617 | case AR9285_DEVID_PCIE: | 609 | case AR9285_DEVID_PCIE: |
618 | case AR5416_DEVID_AR9287_PCI: | 610 | case AR5416_DEVID_AR9287_PCI: |
619 | case AR5416_DEVID_AR9287_PCIE: | 611 | case AR5416_DEVID_AR9287_PCIE: |
612 | case AR9271_USB: | ||
620 | return true; | 613 | return true; |
621 | default: | 614 | default: |
622 | break; | 615 | break; |
@@ -634,9 +627,8 @@ static bool ath9k_hw_macversion_supported(u32 macversion) | |||
634 | case AR_SREV_VERSION_9280: | 627 | case AR_SREV_VERSION_9280: |
635 | case AR_SREV_VERSION_9285: | 628 | case AR_SREV_VERSION_9285: |
636 | case AR_SREV_VERSION_9287: | 629 | case AR_SREV_VERSION_9287: |
637 | return true; | ||
638 | /* Not yet */ | ||
639 | case AR_SREV_VERSION_9271: | 630 | case AR_SREV_VERSION_9271: |
631 | return true; | ||
640 | default: | 632 | default: |
641 | break; | 633 | break; |
642 | } | 634 | } |
@@ -905,21 +897,27 @@ static void ath9k_hw_init_11a_eeprom_fix(struct ath_hw *ah) | |||
905 | 897 | ||
906 | int ath9k_hw_init(struct ath_hw *ah) | 898 | int ath9k_hw_init(struct ath_hw *ah) |
907 | { | 899 | { |
900 | struct ath_common *common = ath9k_hw_common(ah); | ||
908 | int r = 0; | 901 | int r = 0; |
909 | 902 | ||
910 | if (!ath9k_hw_devid_supported(ah->hw_version.devid)) | 903 | if (!ath9k_hw_devid_supported(ah->hw_version.devid)) { |
904 | ath_print(common, ATH_DBG_FATAL, | ||
905 | "Unsupported device ID: 0x%0x\n", | ||
906 | ah->hw_version.devid); | ||
911 | return -EOPNOTSUPP; | 907 | return -EOPNOTSUPP; |
908 | } | ||
912 | 909 | ||
913 | ath9k_hw_init_defaults(ah); | 910 | ath9k_hw_init_defaults(ah); |
914 | ath9k_hw_init_config(ah); | 911 | ath9k_hw_init_config(ah); |
915 | 912 | ||
916 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { | 913 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { |
917 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't reset chip\n"); | 914 | ath_print(common, ATH_DBG_FATAL, |
915 | "Couldn't reset chip\n"); | ||
918 | return -EIO; | 916 | return -EIO; |
919 | } | 917 | } |
920 | 918 | ||
921 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { | 919 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { |
922 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); | 920 | ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); |
923 | return -EIO; | 921 | return -EIO; |
924 | } | 922 | } |
925 | 923 | ||
@@ -934,14 +932,14 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
934 | } | 932 | } |
935 | } | 933 | } |
936 | 934 | ||
937 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "serialize_regmode is %d\n", | 935 | ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n", |
938 | ah->config.serialize_regmode); | 936 | ah->config.serialize_regmode); |
939 | 937 | ||
940 | if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { | 938 | if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { |
941 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 939 | ath_print(common, ATH_DBG_FATAL, |
942 | "Mac Chip Rev 0x%02x.%x is not supported by " | 940 | "Mac Chip Rev 0x%02x.%x is not supported by " |
943 | "this driver\n", ah->hw_version.macVersion, | 941 | "this driver\n", ah->hw_version.macVersion, |
944 | ah->hw_version.macRev); | 942 | ah->hw_version.macRev); |
945 | return -EOPNOTSUPP; | 943 | return -EOPNOTSUPP; |
946 | } | 944 | } |
947 | 945 | ||
@@ -969,6 +967,16 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
969 | else | 967 | else |
970 | ath9k_hw_disablepcie(ah); | 968 | ath9k_hw_disablepcie(ah); |
971 | 969 | ||
970 | /* Support for Japan ch.14 (2484) spread */ | ||
971 | if (AR_SREV_9287_11_OR_LATER(ah)) { | ||
972 | INIT_INI_ARRAY(&ah->iniCckfirNormal, | ||
973 | ar9287Common_normal_cck_fir_coeff_92871_1, | ||
974 | ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_92871_1), 2); | ||
975 | INIT_INI_ARRAY(&ah->iniCckfirJapan2484, | ||
976 | ar9287Common_japan_2484_cck_fir_coeff_92871_1, | ||
977 | ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_92871_1), 2); | ||
978 | } | ||
979 | |||
972 | r = ath9k_hw_post_init(ah); | 980 | r = ath9k_hw_post_init(ah); |
973 | if (r) | 981 | if (r) |
974 | return r; | 982 | return r; |
@@ -979,8 +987,8 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
979 | 987 | ||
980 | r = ath9k_hw_init_macaddr(ah); | 988 | r = ath9k_hw_init_macaddr(ah); |
981 | if (r) { | 989 | if (r) { |
982 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 990 | ath_print(common, ATH_DBG_FATAL, |
983 | "Failed to initialize MAC address\n"); | 991 | "Failed to initialize MAC address\n"); |
984 | return r; | 992 | return r; |
985 | } | 993 | } |
986 | 994 | ||
@@ -991,6 +999,8 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
991 | 999 | ||
992 | ath9k_init_nfcal_hist_buffer(ah); | 1000 | ath9k_init_nfcal_hist_buffer(ah); |
993 | 1001 | ||
1002 | common->state = ATH_HW_INITIALIZED; | ||
1003 | |||
994 | return 0; | 1004 | return 0; |
995 | } | 1005 | } |
996 | 1006 | ||
@@ -1164,7 +1174,8 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
1164 | static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) | 1174 | static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) |
1165 | { | 1175 | { |
1166 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { | 1176 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { |
1167 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad ack timeout %u\n", us); | 1177 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, |
1178 | "bad ack timeout %u\n", us); | ||
1168 | ah->acktimeout = (u32) -1; | 1179 | ah->acktimeout = (u32) -1; |
1169 | return false; | 1180 | return false; |
1170 | } else { | 1181 | } else { |
@@ -1178,7 +1189,8 @@ static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) | |||
1178 | static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) | 1189 | static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) |
1179 | { | 1190 | { |
1180 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { | 1191 | if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { |
1181 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad cts timeout %u\n", us); | 1192 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, |
1193 | "bad cts timeout %u\n", us); | ||
1182 | ah->ctstimeout = (u32) -1; | 1194 | ah->ctstimeout = (u32) -1; |
1183 | return false; | 1195 | return false; |
1184 | } else { | 1196 | } else { |
@@ -1192,8 +1204,8 @@ static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) | |||
1192 | static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) | 1204 | static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) |
1193 | { | 1205 | { |
1194 | if (tu > 0xFFFF) { | 1206 | if (tu > 0xFFFF) { |
1195 | DPRINTF(ah->ah_sc, ATH_DBG_XMIT, | 1207 | ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, |
1196 | "bad global tx timeout %u\n", tu); | 1208 | "bad global tx timeout %u\n", tu); |
1197 | ah->globaltxtimeout = (u32) -1; | 1209 | ah->globaltxtimeout = (u32) -1; |
1198 | return false; | 1210 | return false; |
1199 | } else { | 1211 | } else { |
@@ -1205,8 +1217,8 @@ static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) | |||
1205 | 1217 | ||
1206 | static void ath9k_hw_init_user_settings(struct ath_hw *ah) | 1218 | static void ath9k_hw_init_user_settings(struct ath_hw *ah) |
1207 | { | 1219 | { |
1208 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "ah->misc_mode 0x%x\n", | 1220 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", |
1209 | ah->misc_mode); | 1221 | ah->misc_mode); |
1210 | 1222 | ||
1211 | if (ah->misc_mode != 0) | 1223 | if (ah->misc_mode != 0) |
1212 | REG_WRITE(ah, AR_PCU_MISC, | 1224 | REG_WRITE(ah, AR_PCU_MISC, |
@@ -1229,14 +1241,22 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid) | |||
1229 | 1241 | ||
1230 | void ath9k_hw_detach(struct ath_hw *ah) | 1242 | void ath9k_hw_detach(struct ath_hw *ah) |
1231 | { | 1243 | { |
1244 | struct ath_common *common = ath9k_hw_common(ah); | ||
1245 | |||
1246 | if (common->state <= ATH_HW_INITIALIZED) | ||
1247 | goto free_hw; | ||
1248 | |||
1232 | if (!AR_SREV_9100(ah)) | 1249 | if (!AR_SREV_9100(ah)) |
1233 | ath9k_hw_ani_disable(ah); | 1250 | ath9k_hw_ani_disable(ah); |
1234 | 1251 | ||
1235 | ath9k_hw_rf_free(ah); | ||
1236 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | 1252 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); |
1253 | |||
1254 | free_hw: | ||
1255 | ath9k_hw_rf_free(ah); | ||
1237 | kfree(ah); | 1256 | kfree(ah); |
1238 | ah = NULL; | 1257 | ah = NULL; |
1239 | } | 1258 | } |
1259 | EXPORT_SYMBOL(ath9k_hw_detach); | ||
1240 | 1260 | ||
1241 | /*******/ | 1261 | /*******/ |
1242 | /* INI */ | 1262 | /* INI */ |
@@ -1298,28 +1318,29 @@ static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, | |||
1298 | u32 reg, u32 value) | 1318 | u32 reg, u32 value) |
1299 | { | 1319 | { |
1300 | struct base_eep_header *pBase = &(pEepData->baseEepHeader); | 1320 | struct base_eep_header *pBase = &(pEepData->baseEepHeader); |
1321 | struct ath_common *common = ath9k_hw_common(ah); | ||
1301 | 1322 | ||
1302 | switch (ah->hw_version.devid) { | 1323 | switch (ah->hw_version.devid) { |
1303 | case AR9280_DEVID_PCI: | 1324 | case AR9280_DEVID_PCI: |
1304 | if (reg == 0x7894) { | 1325 | if (reg == 0x7894) { |
1305 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1326 | ath_print(common, ATH_DBG_EEPROM, |
1306 | "ini VAL: %x EEPROM: %x\n", value, | 1327 | "ini VAL: %x EEPROM: %x\n", value, |
1307 | (pBase->version & 0xff)); | 1328 | (pBase->version & 0xff)); |
1308 | 1329 | ||
1309 | if ((pBase->version & 0xff) > 0x0a) { | 1330 | if ((pBase->version & 0xff) > 0x0a) { |
1310 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1331 | ath_print(common, ATH_DBG_EEPROM, |
1311 | "PWDCLKIND: %d\n", | 1332 | "PWDCLKIND: %d\n", |
1312 | pBase->pwdclkind); | 1333 | pBase->pwdclkind); |
1313 | value &= ~AR_AN_TOP2_PWDCLKIND; | 1334 | value &= ~AR_AN_TOP2_PWDCLKIND; |
1314 | value |= AR_AN_TOP2_PWDCLKIND & | 1335 | value |= AR_AN_TOP2_PWDCLKIND & |
1315 | (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); | 1336 | (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); |
1316 | } else { | 1337 | } else { |
1317 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1338 | ath_print(common, ATH_DBG_EEPROM, |
1318 | "PWDCLKIND Earlier Rev\n"); | 1339 | "PWDCLKIND Earlier Rev\n"); |
1319 | } | 1340 | } |
1320 | 1341 | ||
1321 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1342 | ath_print(common, ATH_DBG_EEPROM, |
1322 | "final ini VAL: %x\n", value); | 1343 | "final ini VAL: %x\n", value); |
1323 | } | 1344 | } |
1324 | break; | 1345 | break; |
1325 | } | 1346 | } |
@@ -1374,8 +1395,7 @@ static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, | |||
1374 | } | 1395 | } |
1375 | 1396 | ||
1376 | static int ath9k_hw_process_ini(struct ath_hw *ah, | 1397 | static int ath9k_hw_process_ini(struct ath_hw *ah, |
1377 | struct ath9k_channel *chan, | 1398 | struct ath9k_channel *chan) |
1378 | enum ath9k_ht_macmode macmode) | ||
1379 | { | 1399 | { |
1380 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 1400 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
1381 | int i, regWrites = 0; | 1401 | int i, regWrites = 0; |
@@ -1477,7 +1497,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1477 | } | 1497 | } |
1478 | 1498 | ||
1479 | ath9k_hw_override_ini(ah, chan); | 1499 | ath9k_hw_override_ini(ah, chan); |
1480 | ath9k_hw_set_regs(ah, chan, macmode); | 1500 | ath9k_hw_set_regs(ah, chan); |
1481 | ath9k_hw_init_chain_masks(ah); | 1501 | ath9k_hw_init_chain_masks(ah); |
1482 | 1502 | ||
1483 | if (OLC_FOR_AR9280_20_LATER) | 1503 | if (OLC_FOR_AR9280_20_LATER) |
@@ -1491,8 +1511,8 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1491 | (u32) regulatory->power_limit)); | 1511 | (u32) regulatory->power_limit)); |
1492 | 1512 | ||
1493 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { | 1513 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { |
1494 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 1514 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
1495 | "ar5416SetRfRegs failed\n"); | 1515 | "ar5416SetRfRegs failed\n"); |
1496 | return -EIO; | 1516 | return -EIO; |
1497 | } | 1517 | } |
1498 | 1518 | ||
@@ -1697,16 +1717,14 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1697 | 1717 | ||
1698 | REG_WRITE(ah, AR_RTC_RC, 0); | 1718 | REG_WRITE(ah, AR_RTC_RC, 0); |
1699 | if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { | 1719 | if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { |
1700 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | 1720 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, |
1701 | "RTC stuck in MAC reset\n"); | 1721 | "RTC stuck in MAC reset\n"); |
1702 | return false; | 1722 | return false; |
1703 | } | 1723 | } |
1704 | 1724 | ||
1705 | if (!AR_SREV_9100(ah)) | 1725 | if (!AR_SREV_9100(ah)) |
1706 | REG_WRITE(ah, AR_RC, 0); | 1726 | REG_WRITE(ah, AR_RC, 0); |
1707 | 1727 | ||
1708 | ath9k_hw_init_pll(ah, NULL); | ||
1709 | |||
1710 | if (AR_SREV_9100(ah)) | 1728 | if (AR_SREV_9100(ah)) |
1711 | udelay(50); | 1729 | udelay(50); |
1712 | 1730 | ||
@@ -1734,7 +1752,8 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1734 | AR_RTC_STATUS_M, | 1752 | AR_RTC_STATUS_M, |
1735 | AR_RTC_STATUS_ON, | 1753 | AR_RTC_STATUS_ON, |
1736 | AH_WAIT_TIMEOUT)) { | 1754 | AH_WAIT_TIMEOUT)) { |
1737 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n"); | 1755 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, |
1756 | "RTC not waking up\n"); | ||
1738 | return false; | 1757 | return false; |
1739 | } | 1758 | } |
1740 | 1759 | ||
@@ -1759,8 +1778,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) | |||
1759 | } | 1778 | } |
1760 | } | 1779 | } |
1761 | 1780 | ||
1762 | static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, | 1781 | static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan) |
1763 | enum ath9k_ht_macmode macmode) | ||
1764 | { | 1782 | { |
1765 | u32 phymode; | 1783 | u32 phymode; |
1766 | u32 enableDacFifo = 0; | 1784 | u32 enableDacFifo = 0; |
@@ -1779,12 +1797,10 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1779 | (chan->chanmode == CHANNEL_G_HT40PLUS)) | 1797 | (chan->chanmode == CHANNEL_G_HT40PLUS)) |
1780 | phymode |= AR_PHY_FC_DYN2040_PRI_CH; | 1798 | phymode |= AR_PHY_FC_DYN2040_PRI_CH; |
1781 | 1799 | ||
1782 | if (ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_25) | ||
1783 | phymode |= AR_PHY_FC_DYN2040_EXT_CH; | ||
1784 | } | 1800 | } |
1785 | REG_WRITE(ah, AR_PHY_TURBO, phymode); | 1801 | REG_WRITE(ah, AR_PHY_TURBO, phymode); |
1786 | 1802 | ||
1787 | ath9k_hw_set11nmac2040(ah, macmode); | 1803 | ath9k_hw_set11nmac2040(ah); |
1788 | 1804 | ||
1789 | REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); | 1805 | REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); |
1790 | REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); | 1806 | REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); |
@@ -1810,17 +1826,18 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, | |||
1810 | } | 1826 | } |
1811 | 1827 | ||
1812 | static bool ath9k_hw_channel_change(struct ath_hw *ah, | 1828 | static bool ath9k_hw_channel_change(struct ath_hw *ah, |
1813 | struct ath9k_channel *chan, | 1829 | struct ath9k_channel *chan) |
1814 | enum ath9k_ht_macmode macmode) | ||
1815 | { | 1830 | { |
1816 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 1831 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
1832 | struct ath_common *common = ath9k_hw_common(ah); | ||
1817 | struct ieee80211_channel *channel = chan->chan; | 1833 | struct ieee80211_channel *channel = chan->chan; |
1818 | u32 synthDelay, qnum; | 1834 | u32 synthDelay, qnum; |
1819 | 1835 | ||
1820 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { | 1836 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { |
1821 | if (ath9k_hw_numtxpending(ah, qnum)) { | 1837 | if (ath9k_hw_numtxpending(ah, qnum)) { |
1822 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | 1838 | ath_print(common, ATH_DBG_QUEUE, |
1823 | "Transmit frames pending on queue %d\n", qnum); | 1839 | "Transmit frames pending on " |
1840 | "queue %d\n", qnum); | ||
1824 | return false; | 1841 | return false; |
1825 | } | 1842 | } |
1826 | } | 1843 | } |
@@ -1828,19 +1845,19 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1828 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); | 1845 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); |
1829 | if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, | 1846 | if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, |
1830 | AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { | 1847 | AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { |
1831 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 1848 | ath_print(common, ATH_DBG_FATAL, |
1832 | "Could not kill baseband RX\n"); | 1849 | "Could not kill baseband RX\n"); |
1833 | return false; | 1850 | return false; |
1834 | } | 1851 | } |
1835 | 1852 | ||
1836 | ath9k_hw_set_regs(ah, chan, macmode); | 1853 | ath9k_hw_set_regs(ah, chan); |
1837 | 1854 | ||
1838 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 1855 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
1839 | ath9k_hw_ar9280_set_channel(ah, chan); | 1856 | ath9k_hw_ar9280_set_channel(ah, chan); |
1840 | } else { | 1857 | } else { |
1841 | if (!(ath9k_hw_set_channel(ah, chan))) { | 1858 | if (!(ath9k_hw_set_channel(ah, chan))) { |
1842 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 1859 | ath_print(common, ATH_DBG_FATAL, |
1843 | "Failed to set channel\n"); | 1860 | "Failed to set channel\n"); |
1844 | return false; | 1861 | return false; |
1845 | } | 1862 | } |
1846 | } | 1863 | } |
@@ -2342,17 +2359,16 @@ static void ath9k_enable_rfkill(struct ath_hw *ah) | |||
2342 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 2359 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
2343 | bool bChannelChange) | 2360 | bool bChannelChange) |
2344 | { | 2361 | { |
2362 | struct ath_common *common = ath9k_hw_common(ah); | ||
2345 | u32 saveLedState; | 2363 | u32 saveLedState; |
2346 | struct ath_softc *sc = ah->ah_sc; | ||
2347 | struct ath9k_channel *curchan = ah->curchan; | 2364 | struct ath9k_channel *curchan = ah->curchan; |
2348 | u32 saveDefAntenna; | 2365 | u32 saveDefAntenna; |
2349 | u32 macStaId1; | 2366 | u32 macStaId1; |
2350 | u64 tsf = 0; | 2367 | u64 tsf = 0; |
2351 | int i, rx_chainmask, r; | 2368 | int i, rx_chainmask, r; |
2352 | 2369 | ||
2353 | ah->extprotspacing = sc->ht_extprotspacing; | 2370 | ah->txchainmask = common->tx_chainmask; |
2354 | ah->txchainmask = sc->tx_chainmask; | 2371 | ah->rxchainmask = common->rx_chainmask; |
2355 | ah->rxchainmask = sc->rx_chainmask; | ||
2356 | 2372 | ||
2357 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 2373 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
2358 | return -EIO; | 2374 | return -EIO; |
@@ -2369,7 +2385,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2369 | !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) || | 2385 | !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) || |
2370 | IS_CHAN_A_5MHZ_SPACED(ah->curchan))) { | 2386 | IS_CHAN_A_5MHZ_SPACED(ah->curchan))) { |
2371 | 2387 | ||
2372 | if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { | 2388 | if (ath9k_hw_channel_change(ah, chan)) { |
2373 | ath9k_hw_loadnf(ah, ah->curchan); | 2389 | ath9k_hw_loadnf(ah, ah->curchan); |
2374 | ath9k_hw_start_nfcal(ah); | 2390 | ath9k_hw_start_nfcal(ah); |
2375 | return 0; | 2391 | return 0; |
@@ -2400,7 +2416,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2400 | } | 2416 | } |
2401 | 2417 | ||
2402 | if (!ath9k_hw_chip_reset(ah, chan)) { | 2418 | if (!ath9k_hw_chip_reset(ah, chan)) { |
2403 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n"); | 2419 | ath_print(common, ATH_DBG_FATAL, "Chip reset failed\n"); |
2404 | return -EINVAL; | 2420 | return -EINVAL; |
2405 | } | 2421 | } |
2406 | 2422 | ||
@@ -2429,7 +2445,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2429 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | 2445 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, |
2430 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); | 2446 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); |
2431 | } | 2447 | } |
2432 | r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); | 2448 | r = ath9k_hw_process_ini(ah, chan); |
2433 | if (r) | 2449 | if (r) |
2434 | return r; | 2450 | return r; |
2435 | 2451 | ||
@@ -2462,8 +2478,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2462 | 2478 | ||
2463 | ath9k_hw_decrease_chain_power(ah, chan); | 2479 | ath9k_hw_decrease_chain_power(ah, chan); |
2464 | 2480 | ||
2465 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ah->macaddr)); | 2481 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); |
2466 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ah->macaddr + 4) | 2482 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) |
2467 | | macStaId1 | 2483 | | macStaId1 |
2468 | | AR_STA_ID1_RTS_USE_DEF | 2484 | | AR_STA_ID1_RTS_USE_DEF |
2469 | | (ah->config. | 2485 | | (ah->config. |
@@ -2471,14 +2487,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2471 | | ah->sta_id1_defaults); | 2487 | | ah->sta_id1_defaults); |
2472 | ath9k_hw_set_operating_mode(ah, ah->opmode); | 2488 | ath9k_hw_set_operating_mode(ah, ah->opmode); |
2473 | 2489 | ||
2474 | REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); | 2490 | ath_hw_setbssidmask(common); |
2475 | REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); | ||
2476 | 2491 | ||
2477 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); | 2492 | REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); |
2478 | 2493 | ||
2479 | REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); | 2494 | ath9k_hw_write_associd(ah); |
2480 | REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | | ||
2481 | ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); | ||
2482 | 2495 | ||
2483 | REG_WRITE(ah, AR_ISR, ~0); | 2496 | REG_WRITE(ah, AR_ISR, ~0); |
2484 | 2497 | ||
@@ -2558,13 +2571,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2558 | u32 mask; | 2571 | u32 mask; |
2559 | mask = REG_READ(ah, AR_CFG); | 2572 | mask = REG_READ(ah, AR_CFG); |
2560 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | 2573 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { |
2561 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | 2574 | ath_print(common, ATH_DBG_RESET, |
2562 | "CFG Byte Swap Set 0x%x\n", mask); | 2575 | "CFG Byte Swap Set 0x%x\n", mask); |
2563 | } else { | 2576 | } else { |
2564 | mask = | 2577 | mask = |
2565 | INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | 2578 | INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; |
2566 | REG_WRITE(ah, AR_CFG, mask); | 2579 | REG_WRITE(ah, AR_CFG, mask); |
2567 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | 2580 | ath_print(common, ATH_DBG_RESET, |
2568 | "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); | 2581 | "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); |
2569 | } | 2582 | } |
2570 | } else { | 2583 | } else { |
@@ -2577,11 +2590,12 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2577 | #endif | 2590 | #endif |
2578 | } | 2591 | } |
2579 | 2592 | ||
2580 | if (ah->ah_sc->sc_flags & SC_OP_BTCOEX_ENABLED) | 2593 | if (ah->btcoex_hw.enabled) |
2581 | ath9k_hw_btcoex_enable(ah); | 2594 | ath9k_hw_btcoex_enable(ah); |
2582 | 2595 | ||
2583 | return 0; | 2596 | return 0; |
2584 | } | 2597 | } |
2598 | EXPORT_SYMBOL(ath9k_hw_reset); | ||
2585 | 2599 | ||
2586 | /************************/ | 2600 | /************************/ |
2587 | /* Key Cache Management */ | 2601 | /* Key Cache Management */ |
@@ -2592,8 +2606,8 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) | |||
2592 | u32 keyType; | 2606 | u32 keyType; |
2593 | 2607 | ||
2594 | if (entry >= ah->caps.keycache_size) { | 2608 | if (entry >= ah->caps.keycache_size) { |
2595 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 2609 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
2596 | "keychache entry %u out of range\n", entry); | 2610 | "keychache entry %u out of range\n", entry); |
2597 | return false; | 2611 | return false; |
2598 | } | 2612 | } |
2599 | 2613 | ||
@@ -2620,14 +2634,15 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) | |||
2620 | 2634 | ||
2621 | return true; | 2635 | return true; |
2622 | } | 2636 | } |
2637 | EXPORT_SYMBOL(ath9k_hw_keyreset); | ||
2623 | 2638 | ||
2624 | bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) | 2639 | bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) |
2625 | { | 2640 | { |
2626 | u32 macHi, macLo; | 2641 | u32 macHi, macLo; |
2627 | 2642 | ||
2628 | if (entry >= ah->caps.keycache_size) { | 2643 | if (entry >= ah->caps.keycache_size) { |
2629 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 2644 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
2630 | "keychache entry %u out of range\n", entry); | 2645 | "keychache entry %u out of range\n", entry); |
2631 | return false; | 2646 | return false; |
2632 | } | 2647 | } |
2633 | 2648 | ||
@@ -2648,18 +2663,20 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) | |||
2648 | 2663 | ||
2649 | return true; | 2664 | return true; |
2650 | } | 2665 | } |
2666 | EXPORT_SYMBOL(ath9k_hw_keysetmac); | ||
2651 | 2667 | ||
2652 | bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | 2668 | bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, |
2653 | const struct ath9k_keyval *k, | 2669 | const struct ath9k_keyval *k, |
2654 | const u8 *mac) | 2670 | const u8 *mac) |
2655 | { | 2671 | { |
2656 | const struct ath9k_hw_capabilities *pCap = &ah->caps; | 2672 | const struct ath9k_hw_capabilities *pCap = &ah->caps; |
2673 | struct ath_common *common = ath9k_hw_common(ah); | ||
2657 | u32 key0, key1, key2, key3, key4; | 2674 | u32 key0, key1, key2, key3, key4; |
2658 | u32 keyType; | 2675 | u32 keyType; |
2659 | 2676 | ||
2660 | if (entry >= pCap->keycache_size) { | 2677 | if (entry >= pCap->keycache_size) { |
2661 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 2678 | ath_print(common, ATH_DBG_FATAL, |
2662 | "keycache entry %u out of range\n", entry); | 2679 | "keycache entry %u out of range\n", entry); |
2663 | return false; | 2680 | return false; |
2664 | } | 2681 | } |
2665 | 2682 | ||
@@ -2669,9 +2686,9 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | |||
2669 | break; | 2686 | break; |
2670 | case ATH9K_CIPHER_AES_CCM: | 2687 | case ATH9K_CIPHER_AES_CCM: |
2671 | if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { | 2688 | if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { |
2672 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | 2689 | ath_print(common, ATH_DBG_ANY, |
2673 | "AES-CCM not supported by mac rev 0x%x\n", | 2690 | "AES-CCM not supported by mac rev 0x%x\n", |
2674 | ah->hw_version.macRev); | 2691 | ah->hw_version.macRev); |
2675 | return false; | 2692 | return false; |
2676 | } | 2693 | } |
2677 | keyType = AR_KEYTABLE_TYPE_CCM; | 2694 | keyType = AR_KEYTABLE_TYPE_CCM; |
@@ -2680,15 +2697,15 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | |||
2680 | keyType = AR_KEYTABLE_TYPE_TKIP; | 2697 | keyType = AR_KEYTABLE_TYPE_TKIP; |
2681 | if (ATH9K_IS_MIC_ENABLED(ah) | 2698 | if (ATH9K_IS_MIC_ENABLED(ah) |
2682 | && entry + 64 >= pCap->keycache_size) { | 2699 | && entry + 64 >= pCap->keycache_size) { |
2683 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | 2700 | ath_print(common, ATH_DBG_ANY, |
2684 | "entry %u inappropriate for TKIP\n", entry); | 2701 | "entry %u inappropriate for TKIP\n", entry); |
2685 | return false; | 2702 | return false; |
2686 | } | 2703 | } |
2687 | break; | 2704 | break; |
2688 | case ATH9K_CIPHER_WEP: | 2705 | case ATH9K_CIPHER_WEP: |
2689 | if (k->kv_len < WLAN_KEY_LEN_WEP40) { | 2706 | if (k->kv_len < WLAN_KEY_LEN_WEP40) { |
2690 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | 2707 | ath_print(common, ATH_DBG_ANY, |
2691 | "WEP key length %u too small\n", k->kv_len); | 2708 | "WEP key length %u too small\n", k->kv_len); |
2692 | return false; | 2709 | return false; |
2693 | } | 2710 | } |
2694 | if (k->kv_len <= WLAN_KEY_LEN_WEP40) | 2711 | if (k->kv_len <= WLAN_KEY_LEN_WEP40) |
@@ -2702,8 +2719,8 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | |||
2702 | keyType = AR_KEYTABLE_TYPE_CLR; | 2719 | keyType = AR_KEYTABLE_TYPE_CLR; |
2703 | break; | 2720 | break; |
2704 | default: | 2721 | default: |
2705 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 2722 | ath_print(common, ATH_DBG_FATAL, |
2706 | "cipher %u not supported\n", k->kv_type); | 2723 | "cipher %u not supported\n", k->kv_type); |
2707 | return false; | 2724 | return false; |
2708 | } | 2725 | } |
2709 | 2726 | ||
@@ -2845,6 +2862,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | |||
2845 | 2862 | ||
2846 | return true; | 2863 | return true; |
2847 | } | 2864 | } |
2865 | EXPORT_SYMBOL(ath9k_hw_set_keycache_entry); | ||
2848 | 2866 | ||
2849 | bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry) | 2867 | bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry) |
2850 | { | 2868 | { |
@@ -2855,6 +2873,7 @@ bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry) | |||
2855 | } | 2873 | } |
2856 | return false; | 2874 | return false; |
2857 | } | 2875 | } |
2876 | EXPORT_SYMBOL(ath9k_hw_keyisvalid); | ||
2858 | 2877 | ||
2859 | /******************************/ | 2878 | /******************************/ |
2860 | /* Power Management (Chipset) */ | 2879 | /* Power Management (Chipset) */ |
@@ -2869,8 +2888,9 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) | |||
2869 | if (!AR_SREV_9100(ah)) | 2888 | if (!AR_SREV_9100(ah)) |
2870 | REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); | 2889 | REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); |
2871 | 2890 | ||
2872 | REG_CLR_BIT(ah, (AR_RTC_RESET), | 2891 | if(!AR_SREV_5416(ah)) |
2873 | AR_RTC_RESET_EN); | 2892 | REG_CLR_BIT(ah, (AR_RTC_RESET), |
2893 | AR_RTC_RESET_EN); | ||
2874 | } | 2894 | } |
2875 | } | 2895 | } |
2876 | 2896 | ||
@@ -2902,6 +2922,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | |||
2902 | ATH9K_RESET_POWER_ON) != true) { | 2922 | ATH9K_RESET_POWER_ON) != true) { |
2903 | return false; | 2923 | return false; |
2904 | } | 2924 | } |
2925 | ath9k_hw_init_pll(ah, NULL); | ||
2905 | } | 2926 | } |
2906 | if (AR_SREV_9100(ah)) | 2927 | if (AR_SREV_9100(ah)) |
2907 | REG_SET_BIT(ah, AR_RTC_RESET, | 2928 | REG_SET_BIT(ah, AR_RTC_RESET, |
@@ -2920,8 +2941,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | |||
2920 | AR_RTC_FORCE_WAKE_EN); | 2941 | AR_RTC_FORCE_WAKE_EN); |
2921 | } | 2942 | } |
2922 | if (i == 0) { | 2943 | if (i == 0) { |
2923 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 2944 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
2924 | "Failed to wakeup in %uus\n", POWER_UP_TIME / 20); | 2945 | "Failed to wakeup in %uus\n", |
2946 | POWER_UP_TIME / 20); | ||
2925 | return false; | 2947 | return false; |
2926 | } | 2948 | } |
2927 | } | 2949 | } |
@@ -2931,9 +2953,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | |||
2931 | return true; | 2953 | return true; |
2932 | } | 2954 | } |
2933 | 2955 | ||
2934 | static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, | 2956 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) |
2935 | enum ath9k_power_mode mode) | ||
2936 | { | 2957 | { |
2958 | struct ath_common *common = ath9k_hw_common(ah); | ||
2937 | int status = true, setChip = true; | 2959 | int status = true, setChip = true; |
2938 | static const char *modes[] = { | 2960 | static const char *modes[] = { |
2939 | "AWAKE", | 2961 | "AWAKE", |
@@ -2945,8 +2967,8 @@ static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, | |||
2945 | if (ah->power_mode == mode) | 2967 | if (ah->power_mode == mode) |
2946 | return status; | 2968 | return status; |
2947 | 2969 | ||
2948 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n", | 2970 | ath_print(common, ATH_DBG_RESET, "%s -> %s\n", |
2949 | modes[ah->power_mode], modes[mode]); | 2971 | modes[ah->power_mode], modes[mode]); |
2950 | 2972 | ||
2951 | switch (mode) { | 2973 | switch (mode) { |
2952 | case ATH9K_PM_AWAKE: | 2974 | case ATH9K_PM_AWAKE: |
@@ -2960,59 +2982,15 @@ static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, | |||
2960 | ath9k_set_power_network_sleep(ah, setChip); | 2982 | ath9k_set_power_network_sleep(ah, setChip); |
2961 | break; | 2983 | break; |
2962 | default: | 2984 | default: |
2963 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 2985 | ath_print(common, ATH_DBG_FATAL, |
2964 | "Unknown power mode %u\n", mode); | 2986 | "Unknown power mode %u\n", mode); |
2965 | return false; | 2987 | return false; |
2966 | } | 2988 | } |
2967 | ah->power_mode = mode; | 2989 | ah->power_mode = mode; |
2968 | 2990 | ||
2969 | return status; | 2991 | return status; |
2970 | } | 2992 | } |
2971 | 2993 | EXPORT_SYMBOL(ath9k_hw_setpower); | |
2972 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | ||
2973 | { | ||
2974 | unsigned long flags; | ||
2975 | bool ret; | ||
2976 | |||
2977 | spin_lock_irqsave(&ah->ah_sc->sc_pm_lock, flags); | ||
2978 | ret = ath9k_hw_setpower_nolock(ah, mode); | ||
2979 | spin_unlock_irqrestore(&ah->ah_sc->sc_pm_lock, flags); | ||
2980 | |||
2981 | return ret; | ||
2982 | } | ||
2983 | |||
2984 | void ath9k_ps_wakeup(struct ath_softc *sc) | ||
2985 | { | ||
2986 | unsigned long flags; | ||
2987 | |||
2988 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
2989 | if (++sc->ps_usecount != 1) | ||
2990 | goto unlock; | ||
2991 | |||
2992 | ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE); | ||
2993 | |||
2994 | unlock: | ||
2995 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
2996 | } | ||
2997 | |||
2998 | void ath9k_ps_restore(struct ath_softc *sc) | ||
2999 | { | ||
3000 | unsigned long flags; | ||
3001 | |||
3002 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
3003 | if (--sc->ps_usecount != 0) | ||
3004 | goto unlock; | ||
3005 | |||
3006 | if (sc->ps_enabled && | ||
3007 | !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | | ||
3008 | SC_OP_WAIT_FOR_CAB | | ||
3009 | SC_OP_WAIT_FOR_PSPOLL_DATA | | ||
3010 | SC_OP_WAIT_FOR_TX_ACK))) | ||
3011 | ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); | ||
3012 | |||
3013 | unlock: | ||
3014 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
3015 | } | ||
3016 | 2994 | ||
3017 | /* | 2995 | /* |
3018 | * Helper for ASPM support. | 2996 | * Helper for ASPM support. |
@@ -3145,6 +3123,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) | |||
3145 | } | 3123 | } |
3146 | } | 3124 | } |
3147 | } | 3125 | } |
3126 | EXPORT_SYMBOL(ath9k_hw_configpcipowersave); | ||
3148 | 3127 | ||
3149 | /**********************/ | 3128 | /**********************/ |
3150 | /* Interrupt Handling */ | 3129 | /* Interrupt Handling */ |
@@ -3168,6 +3147,7 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) | |||
3168 | 3147 | ||
3169 | return false; | 3148 | return false; |
3170 | } | 3149 | } |
3150 | EXPORT_SYMBOL(ath9k_hw_intrpend); | ||
3171 | 3151 | ||
3172 | bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | 3152 | bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) |
3173 | { | 3153 | { |
@@ -3176,6 +3156,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | |||
3176 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 3156 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
3177 | u32 sync_cause = 0; | 3157 | u32 sync_cause = 0; |
3178 | bool fatal_int = false; | 3158 | bool fatal_int = false; |
3159 | struct ath_common *common = ath9k_hw_common(ah); | ||
3179 | 3160 | ||
3180 | if (!AR_SREV_9100(ah)) { | 3161 | if (!AR_SREV_9100(ah)) { |
3181 | if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { | 3162 | if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { |
@@ -3249,8 +3230,8 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | |||
3249 | } | 3230 | } |
3250 | 3231 | ||
3251 | if (isr & AR_ISR_RXORN) { | 3232 | if (isr & AR_ISR_RXORN) { |
3252 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | 3233 | ath_print(common, ATH_DBG_INTERRUPT, |
3253 | "receive FIFO overrun interrupt\n"); | 3234 | "receive FIFO overrun interrupt\n"); |
3254 | } | 3235 | } |
3255 | 3236 | ||
3256 | if (!AR_SREV_9100(ah)) { | 3237 | if (!AR_SREV_9100(ah)) { |
@@ -3292,25 +3273,25 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | |||
3292 | 3273 | ||
3293 | if (fatal_int) { | 3274 | if (fatal_int) { |
3294 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { | 3275 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { |
3295 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | 3276 | ath_print(common, ATH_DBG_ANY, |
3296 | "received PCI FATAL interrupt\n"); | 3277 | "received PCI FATAL interrupt\n"); |
3297 | } | 3278 | } |
3298 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { | 3279 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { |
3299 | DPRINTF(ah->ah_sc, ATH_DBG_ANY, | 3280 | ath_print(common, ATH_DBG_ANY, |
3300 | "received PCI PERR interrupt\n"); | 3281 | "received PCI PERR interrupt\n"); |
3301 | } | 3282 | } |
3302 | *masked |= ATH9K_INT_FATAL; | 3283 | *masked |= ATH9K_INT_FATAL; |
3303 | } | 3284 | } |
3304 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { | 3285 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { |
3305 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | 3286 | ath_print(common, ATH_DBG_INTERRUPT, |
3306 | "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); | 3287 | "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); |
3307 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); | 3288 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); |
3308 | REG_WRITE(ah, AR_RC, 0); | 3289 | REG_WRITE(ah, AR_RC, 0); |
3309 | *masked |= ATH9K_INT_FATAL; | 3290 | *masked |= ATH9K_INT_FATAL; |
3310 | } | 3291 | } |
3311 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { | 3292 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { |
3312 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | 3293 | ath_print(common, ATH_DBG_INTERRUPT, |
3313 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); | 3294 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); |
3314 | } | 3295 | } |
3315 | 3296 | ||
3316 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); | 3297 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); |
@@ -3319,17 +3300,19 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) | |||
3319 | 3300 | ||
3320 | return true; | 3301 | return true; |
3321 | } | 3302 | } |
3303 | EXPORT_SYMBOL(ath9k_hw_getisr); | ||
3322 | 3304 | ||
3323 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | 3305 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) |
3324 | { | 3306 | { |
3325 | u32 omask = ah->mask_reg; | 3307 | u32 omask = ah->mask_reg; |
3326 | u32 mask, mask2; | 3308 | u32 mask, mask2; |
3327 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 3309 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
3310 | struct ath_common *common = ath9k_hw_common(ah); | ||
3328 | 3311 | ||
3329 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); | 3312 | ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); |
3330 | 3313 | ||
3331 | if (omask & ATH9K_INT_GLOBAL) { | 3314 | if (omask & ATH9K_INT_GLOBAL) { |
3332 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "disable IER\n"); | 3315 | ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); |
3333 | REG_WRITE(ah, AR_IER, AR_IER_DISABLE); | 3316 | REG_WRITE(ah, AR_IER, AR_IER_DISABLE); |
3334 | (void) REG_READ(ah, AR_IER); | 3317 | (void) REG_READ(ah, AR_IER); |
3335 | if (!AR_SREV_9100(ah)) { | 3318 | if (!AR_SREV_9100(ah)) { |
@@ -3386,7 +3369,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | |||
3386 | mask2 |= AR_IMR_S2_CST; | 3369 | mask2 |= AR_IMR_S2_CST; |
3387 | } | 3370 | } |
3388 | 3371 | ||
3389 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); | 3372 | ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); |
3390 | REG_WRITE(ah, AR_IMR, mask); | 3373 | REG_WRITE(ah, AR_IMR, mask); |
3391 | mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | | 3374 | mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | |
3392 | AR_IMR_S2_DTIM | | 3375 | AR_IMR_S2_DTIM | |
@@ -3406,7 +3389,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | |||
3406 | } | 3389 | } |
3407 | 3390 | ||
3408 | if (ints & ATH9K_INT_GLOBAL) { | 3391 | if (ints & ATH9K_INT_GLOBAL) { |
3409 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "enable IER\n"); | 3392 | ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); |
3410 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); | 3393 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); |
3411 | if (!AR_SREV_9100(ah)) { | 3394 | if (!AR_SREV_9100(ah)) { |
3412 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, | 3395 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, |
@@ -3419,12 +3402,13 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | |||
3419 | REG_WRITE(ah, AR_INTR_SYNC_MASK, | 3402 | REG_WRITE(ah, AR_INTR_SYNC_MASK, |
3420 | AR_INTR_SYNC_DEFAULT); | 3403 | AR_INTR_SYNC_DEFAULT); |
3421 | } | 3404 | } |
3422 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", | 3405 | ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", |
3423 | REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); | 3406 | REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); |
3424 | } | 3407 | } |
3425 | 3408 | ||
3426 | return omask; | 3409 | return omask; |
3427 | } | 3410 | } |
3411 | EXPORT_SYMBOL(ath9k_hw_set_interrupts); | ||
3428 | 3412 | ||
3429 | /*******************/ | 3413 | /*******************/ |
3430 | /* Beacon Handling */ | 3414 | /* Beacon Handling */ |
@@ -3467,9 +3451,9 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) | |||
3467 | AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; | 3451 | AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; |
3468 | break; | 3452 | break; |
3469 | default: | 3453 | default: |
3470 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, | 3454 | ath_print(ath9k_hw_common(ah), ATH_DBG_BEACON, |
3471 | "%s: unsupported opmode: %d\n", | 3455 | "%s: unsupported opmode: %d\n", |
3472 | __func__, ah->opmode); | 3456 | __func__, ah->opmode); |
3473 | return; | 3457 | return; |
3474 | break; | 3458 | break; |
3475 | } | 3459 | } |
@@ -3481,18 +3465,19 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) | |||
3481 | 3465 | ||
3482 | beacon_period &= ~ATH9K_BEACON_ENA; | 3466 | beacon_period &= ~ATH9K_BEACON_ENA; |
3483 | if (beacon_period & ATH9K_BEACON_RESET_TSF) { | 3467 | if (beacon_period & ATH9K_BEACON_RESET_TSF) { |
3484 | beacon_period &= ~ATH9K_BEACON_RESET_TSF; | ||
3485 | ath9k_hw_reset_tsf(ah); | 3468 | ath9k_hw_reset_tsf(ah); |
3486 | } | 3469 | } |
3487 | 3470 | ||
3488 | REG_SET_BIT(ah, AR_TIMER_MODE, flags); | 3471 | REG_SET_BIT(ah, AR_TIMER_MODE, flags); |
3489 | } | 3472 | } |
3473 | EXPORT_SYMBOL(ath9k_hw_beaconinit); | ||
3490 | 3474 | ||
3491 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | 3475 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, |
3492 | const struct ath9k_beacon_state *bs) | 3476 | const struct ath9k_beacon_state *bs) |
3493 | { | 3477 | { |
3494 | u32 nextTbtt, beaconintval, dtimperiod, beacontimeout; | 3478 | u32 nextTbtt, beaconintval, dtimperiod, beacontimeout; |
3495 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 3479 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
3480 | struct ath_common *common = ath9k_hw_common(ah); | ||
3496 | 3481 | ||
3497 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); | 3482 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); |
3498 | 3483 | ||
@@ -3518,10 +3503,10 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
3518 | else | 3503 | else |
3519 | nextTbtt = bs->bs_nexttbtt; | 3504 | nextTbtt = bs->bs_nexttbtt; |
3520 | 3505 | ||
3521 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); | 3506 | ath_print(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); |
3522 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); | 3507 | ath_print(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); |
3523 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); | 3508 | ath_print(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); |
3524 | DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); | 3509 | ath_print(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); |
3525 | 3510 | ||
3526 | REG_WRITE(ah, AR_NEXT_DTIM, | 3511 | REG_WRITE(ah, AR_NEXT_DTIM, |
3527 | TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); | 3512 | TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); |
@@ -3549,6 +3534,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
3549 | /* TSF Out of Range Threshold */ | 3534 | /* TSF Out of Range Threshold */ |
3550 | REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); | 3535 | REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); |
3551 | } | 3536 | } |
3537 | EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers); | ||
3552 | 3538 | ||
3553 | /*******************/ | 3539 | /*******************/ |
3554 | /* HW Capabilities */ | 3540 | /* HW Capabilities */ |
@@ -3558,7 +3544,8 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3558 | { | 3544 | { |
3559 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 3545 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
3560 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 3546 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
3561 | struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; | 3547 | struct ath_common *common = ath9k_hw_common(ah); |
3548 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | ||
3562 | 3549 | ||
3563 | u16 capField = 0, eeval; | 3550 | u16 capField = 0, eeval; |
3564 | 3551 | ||
@@ -3579,8 +3566,8 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3579 | regulatory->current_rd += 5; | 3566 | regulatory->current_rd += 5; |
3580 | else if (regulatory->current_rd == 0x41) | 3567 | else if (regulatory->current_rd == 0x41) |
3581 | regulatory->current_rd = 0x43; | 3568 | regulatory->current_rd = 0x43; |
3582 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | 3569 | ath_print(common, ATH_DBG_REGULATORY, |
3583 | "regdomain mapped to 0x%x\n", regulatory->current_rd); | 3570 | "regdomain mapped to 0x%x\n", regulatory->current_rd); |
3584 | } | 3571 | } |
3585 | 3572 | ||
3586 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); | 3573 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); |
@@ -3719,7 +3706,10 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3719 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; | 3706 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; |
3720 | } | 3707 | } |
3721 | 3708 | ||
3722 | pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; | 3709 | /* Advertise midband for AR5416 with FCC midband set in eeprom */ |
3710 | if (regulatory->current_rd_ext & (1 << REG_EXT_FCC_MIDBAND) && | ||
3711 | AR_SREV_5416(ah)) | ||
3712 | pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; | ||
3723 | 3713 | ||
3724 | pCap->num_antcfg_5ghz = | 3714 | pCap->num_antcfg_5ghz = |
3725 | ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ); | 3715 | ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ); |
@@ -3727,18 +3717,18 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3727 | ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); | 3717 | ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); |
3728 | 3718 | ||
3729 | if (AR_SREV_9280_10_OR_LATER(ah) && | 3719 | if (AR_SREV_9280_10_OR_LATER(ah) && |
3730 | ath_btcoex_supported(ah->hw_version.subsysid)) { | 3720 | ath9k_hw_btcoex_supported(ah)) { |
3731 | btcoex_info->btactive_gpio = ATH_BTACTIVE_GPIO; | 3721 | btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; |
3732 | btcoex_info->wlanactive_gpio = ATH_WLANACTIVE_GPIO; | 3722 | btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; |
3733 | 3723 | ||
3734 | if (AR_SREV_9285(ah)) { | 3724 | if (AR_SREV_9285(ah)) { |
3735 | btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_3WIRE; | 3725 | btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; |
3736 | btcoex_info->btpriority_gpio = ATH_BTPRIORITY_GPIO; | 3726 | btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO; |
3737 | } else { | 3727 | } else { |
3738 | btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_2WIRE; | 3728 | btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; |
3739 | } | 3729 | } |
3740 | } else { | 3730 | } else { |
3741 | btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_NONE; | 3731 | btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; |
3742 | } | 3732 | } |
3743 | } | 3733 | } |
3744 | 3734 | ||
@@ -3812,6 +3802,7 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, | |||
3812 | return false; | 3802 | return false; |
3813 | } | 3803 | } |
3814 | } | 3804 | } |
3805 | EXPORT_SYMBOL(ath9k_hw_getcapability); | ||
3815 | 3806 | ||
3816 | bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, | 3807 | bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, |
3817 | u32 capability, u32 setting, int *status) | 3808 | u32 capability, u32 setting, int *status) |
@@ -3845,6 +3836,7 @@ bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, | |||
3845 | return false; | 3836 | return false; |
3846 | } | 3837 | } |
3847 | } | 3838 | } |
3839 | EXPORT_SYMBOL(ath9k_hw_setcapability); | ||
3848 | 3840 | ||
3849 | /****************************/ | 3841 | /****************************/ |
3850 | /* GPIO / RFKILL / Antennae */ | 3842 | /* GPIO / RFKILL / Antennae */ |
@@ -3882,7 +3874,7 @@ void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) | |||
3882 | { | 3874 | { |
3883 | u32 gpio_shift; | 3875 | u32 gpio_shift; |
3884 | 3876 | ||
3885 | ASSERT(gpio < ah->caps.num_gpio_pins); | 3877 | BUG_ON(gpio >= ah->caps.num_gpio_pins); |
3886 | 3878 | ||
3887 | gpio_shift = gpio << 1; | 3879 | gpio_shift = gpio << 1; |
3888 | 3880 | ||
@@ -3891,6 +3883,7 @@ void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) | |||
3891 | (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), | 3883 | (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), |
3892 | (AR_GPIO_OE_OUT_DRV << gpio_shift)); | 3884 | (AR_GPIO_OE_OUT_DRV << gpio_shift)); |
3893 | } | 3885 | } |
3886 | EXPORT_SYMBOL(ath9k_hw_cfg_gpio_input); | ||
3894 | 3887 | ||
3895 | u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) | 3888 | u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) |
3896 | { | 3889 | { |
@@ -3909,6 +3902,7 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) | |||
3909 | else | 3902 | else |
3910 | return MS_REG_READ(AR, gpio) != 0; | 3903 | return MS_REG_READ(AR, gpio) != 0; |
3911 | } | 3904 | } |
3905 | EXPORT_SYMBOL(ath9k_hw_gpio_get); | ||
3912 | 3906 | ||
3913 | void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, | 3907 | void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, |
3914 | u32 ah_signal_type) | 3908 | u32 ah_signal_type) |
@@ -3924,22 +3918,26 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, | |||
3924 | (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), | 3918 | (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), |
3925 | (AR_GPIO_OE_OUT_DRV << gpio_shift)); | 3919 | (AR_GPIO_OE_OUT_DRV << gpio_shift)); |
3926 | } | 3920 | } |
3921 | EXPORT_SYMBOL(ath9k_hw_cfg_output); | ||
3927 | 3922 | ||
3928 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) | 3923 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) |
3929 | { | 3924 | { |
3930 | REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), | 3925 | REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), |
3931 | AR_GPIO_BIT(gpio)); | 3926 | AR_GPIO_BIT(gpio)); |
3932 | } | 3927 | } |
3928 | EXPORT_SYMBOL(ath9k_hw_set_gpio); | ||
3933 | 3929 | ||
3934 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah) | 3930 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah) |
3935 | { | 3931 | { |
3936 | return REG_READ(ah, AR_DEF_ANTENNA) & 0x7; | 3932 | return REG_READ(ah, AR_DEF_ANTENNA) & 0x7; |
3937 | } | 3933 | } |
3934 | EXPORT_SYMBOL(ath9k_hw_getdefantenna); | ||
3938 | 3935 | ||
3939 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) | 3936 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) |
3940 | { | 3937 | { |
3941 | REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); | 3938 | REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); |
3942 | } | 3939 | } |
3940 | EXPORT_SYMBOL(ath9k_hw_setantenna); | ||
3943 | 3941 | ||
3944 | bool ath9k_hw_setantennaswitch(struct ath_hw *ah, | 3942 | bool ath9k_hw_setantennaswitch(struct ath_hw *ah, |
3945 | enum ath9k_ant_setting settings, | 3943 | enum ath9k_ant_setting settings, |
@@ -4002,6 +4000,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah) | |||
4002 | 4000 | ||
4003 | return bits; | 4001 | return bits; |
4004 | } | 4002 | } |
4003 | EXPORT_SYMBOL(ath9k_hw_getrxfilter); | ||
4005 | 4004 | ||
4006 | void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) | 4005 | void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) |
4007 | { | 4006 | { |
@@ -4023,19 +4022,30 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) | |||
4023 | REG_WRITE(ah, AR_RXCFG, | 4022 | REG_WRITE(ah, AR_RXCFG, |
4024 | REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); | 4023 | REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); |
4025 | } | 4024 | } |
4025 | EXPORT_SYMBOL(ath9k_hw_setrxfilter); | ||
4026 | 4026 | ||
4027 | bool ath9k_hw_phy_disable(struct ath_hw *ah) | 4027 | bool ath9k_hw_phy_disable(struct ath_hw *ah) |
4028 | { | 4028 | { |
4029 | return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM); | 4029 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) |
4030 | return false; | ||
4031 | |||
4032 | ath9k_hw_init_pll(ah, NULL); | ||
4033 | return true; | ||
4030 | } | 4034 | } |
4035 | EXPORT_SYMBOL(ath9k_hw_phy_disable); | ||
4031 | 4036 | ||
4032 | bool ath9k_hw_disable(struct ath_hw *ah) | 4037 | bool ath9k_hw_disable(struct ath_hw *ah) |
4033 | { | 4038 | { |
4034 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 4039 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
4035 | return false; | 4040 | return false; |
4036 | 4041 | ||
4037 | return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); | 4042 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD)) |
4043 | return false; | ||
4044 | |||
4045 | ath9k_hw_init_pll(ah, NULL); | ||
4046 | return true; | ||
4038 | } | 4047 | } |
4048 | EXPORT_SYMBOL(ath9k_hw_disable); | ||
4039 | 4049 | ||
4040 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) | 4050 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) |
4041 | { | 4051 | { |
@@ -4052,35 +4062,36 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) | |||
4052 | min((u32) MAX_RATE_POWER, | 4062 | min((u32) MAX_RATE_POWER, |
4053 | (u32) regulatory->power_limit)); | 4063 | (u32) regulatory->power_limit)); |
4054 | } | 4064 | } |
4065 | EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); | ||
4055 | 4066 | ||
4056 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) | 4067 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) |
4057 | { | 4068 | { |
4058 | memcpy(ah->macaddr, mac, ETH_ALEN); | 4069 | memcpy(ath9k_hw_common(ah)->macaddr, mac, ETH_ALEN); |
4059 | } | 4070 | } |
4071 | EXPORT_SYMBOL(ath9k_hw_setmac); | ||
4060 | 4072 | ||
4061 | void ath9k_hw_setopmode(struct ath_hw *ah) | 4073 | void ath9k_hw_setopmode(struct ath_hw *ah) |
4062 | { | 4074 | { |
4063 | ath9k_hw_set_operating_mode(ah, ah->opmode); | 4075 | ath9k_hw_set_operating_mode(ah, ah->opmode); |
4064 | } | 4076 | } |
4077 | EXPORT_SYMBOL(ath9k_hw_setopmode); | ||
4065 | 4078 | ||
4066 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1) | 4079 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1) |
4067 | { | 4080 | { |
4068 | REG_WRITE(ah, AR_MCAST_FIL0, filter0); | 4081 | REG_WRITE(ah, AR_MCAST_FIL0, filter0); |
4069 | REG_WRITE(ah, AR_MCAST_FIL1, filter1); | 4082 | REG_WRITE(ah, AR_MCAST_FIL1, filter1); |
4070 | } | 4083 | } |
4084 | EXPORT_SYMBOL(ath9k_hw_setmcastfilter); | ||
4071 | 4085 | ||
4072 | void ath9k_hw_setbssidmask(struct ath_softc *sc) | 4086 | void ath9k_hw_write_associd(struct ath_hw *ah) |
4073 | { | 4087 | { |
4074 | REG_WRITE(sc->sc_ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); | 4088 | struct ath_common *common = ath9k_hw_common(ah); |
4075 | REG_WRITE(sc->sc_ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); | ||
4076 | } | ||
4077 | 4089 | ||
4078 | void ath9k_hw_write_associd(struct ath_softc *sc) | 4090 | REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(common->curbssid)); |
4079 | { | 4091 | REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(common->curbssid + 4) | |
4080 | REG_WRITE(sc->sc_ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); | 4092 | ((common->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); |
4081 | REG_WRITE(sc->sc_ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | | ||
4082 | ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); | ||
4083 | } | 4093 | } |
4094 | EXPORT_SYMBOL(ath9k_hw_write_associd); | ||
4084 | 4095 | ||
4085 | u64 ath9k_hw_gettsf64(struct ath_hw *ah) | 4096 | u64 ath9k_hw_gettsf64(struct ath_hw *ah) |
4086 | { | 4097 | { |
@@ -4091,24 +4102,25 @@ u64 ath9k_hw_gettsf64(struct ath_hw *ah) | |||
4091 | 4102 | ||
4092 | return tsf; | 4103 | return tsf; |
4093 | } | 4104 | } |
4105 | EXPORT_SYMBOL(ath9k_hw_gettsf64); | ||
4094 | 4106 | ||
4095 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64) | 4107 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64) |
4096 | { | 4108 | { |
4097 | REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); | 4109 | REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); |
4098 | REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); | 4110 | REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); |
4099 | } | 4111 | } |
4112 | EXPORT_SYMBOL(ath9k_hw_settsf64); | ||
4100 | 4113 | ||
4101 | void ath9k_hw_reset_tsf(struct ath_hw *ah) | 4114 | void ath9k_hw_reset_tsf(struct ath_hw *ah) |
4102 | { | 4115 | { |
4103 | ath9k_ps_wakeup(ah->ah_sc); | ||
4104 | if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, | 4116 | if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, |
4105 | AH_TSF_WRITE_TIMEOUT)) | 4117 | AH_TSF_WRITE_TIMEOUT)) |
4106 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, | 4118 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, |
4107 | "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); | 4119 | "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); |
4108 | 4120 | ||
4109 | REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); | 4121 | REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); |
4110 | ath9k_ps_restore(ah->ah_sc); | ||
4111 | } | 4122 | } |
4123 | EXPORT_SYMBOL(ath9k_hw_reset_tsf); | ||
4112 | 4124 | ||
4113 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) | 4125 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) |
4114 | { | 4126 | { |
@@ -4117,11 +4129,13 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) | |||
4117 | else | 4129 | else |
4118 | ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; | 4130 | ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; |
4119 | } | 4131 | } |
4132 | EXPORT_SYMBOL(ath9k_hw_set_tsfadjust); | ||
4120 | 4133 | ||
4121 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) | 4134 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) |
4122 | { | 4135 | { |
4123 | if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { | 4136 | if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { |
4124 | DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad slot time %u\n", us); | 4137 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, |
4138 | "bad slot time %u\n", us); | ||
4125 | ah->slottime = (u32) -1; | 4139 | ah->slottime = (u32) -1; |
4126 | return false; | 4140 | return false; |
4127 | } else { | 4141 | } else { |
@@ -4130,13 +4144,14 @@ bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) | |||
4130 | return true; | 4144 | return true; |
4131 | } | 4145 | } |
4132 | } | 4146 | } |
4147 | EXPORT_SYMBOL(ath9k_hw_setslottime); | ||
4133 | 4148 | ||
4134 | void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode) | 4149 | void ath9k_hw_set11nmac2040(struct ath_hw *ah) |
4135 | { | 4150 | { |
4151 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
4136 | u32 macmode; | 4152 | u32 macmode; |
4137 | 4153 | ||
4138 | if (mode == ATH9K_HT_MACMODE_2040 && | 4154 | if (conf_is_ht40(conf) && !ah->config.cwm_ignore_extcca) |
4139 | !ah->config.cwm_ignore_extcca) | ||
4140 | macmode = AR_2040_JOINED_RX_CLEAR; | 4155 | macmode = AR_2040_JOINED_RX_CLEAR; |
4141 | else | 4156 | else |
4142 | macmode = 0; | 4157 | macmode = 0; |
@@ -4193,6 +4208,7 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah) | |||
4193 | { | 4208 | { |
4194 | return REG_READ(ah, AR_TSF_L32); | 4209 | return REG_READ(ah, AR_TSF_L32); |
4195 | } | 4210 | } |
4211 | EXPORT_SYMBOL(ath9k_hw_gettsf32); | ||
4196 | 4212 | ||
4197 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | 4213 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, |
4198 | void (*trigger)(void *), | 4214 | void (*trigger)(void *), |
@@ -4206,8 +4222,9 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | |||
4206 | timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); | 4222 | timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); |
4207 | 4223 | ||
4208 | if (timer == NULL) { | 4224 | if (timer == NULL) { |
4209 | printk(KERN_DEBUG "Failed to allocate memory" | 4225 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
4210 | "for hw timer[%d]\n", timer_index); | 4226 | "Failed to allocate memory" |
4227 | "for hw timer[%d]\n", timer_index); | ||
4211 | return NULL; | 4228 | return NULL; |
4212 | } | 4229 | } |
4213 | 4230 | ||
@@ -4220,10 +4237,12 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | |||
4220 | 4237 | ||
4221 | return timer; | 4238 | return timer; |
4222 | } | 4239 | } |
4240 | EXPORT_SYMBOL(ath_gen_timer_alloc); | ||
4223 | 4241 | ||
4224 | void ath_gen_timer_start(struct ath_hw *ah, | 4242 | void ath9k_hw_gen_timer_start(struct ath_hw *ah, |
4225 | struct ath_gen_timer *timer, | 4243 | struct ath_gen_timer *timer, |
4226 | u32 timer_next, u32 timer_period) | 4244 | u32 timer_next, |
4245 | u32 timer_period) | ||
4227 | { | 4246 | { |
4228 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 4247 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
4229 | u32 tsf; | 4248 | u32 tsf; |
@@ -4234,8 +4253,9 @@ void ath_gen_timer_start(struct ath_hw *ah, | |||
4234 | 4253 | ||
4235 | tsf = ath9k_hw_gettsf32(ah); | 4254 | tsf = ath9k_hw_gettsf32(ah); |
4236 | 4255 | ||
4237 | DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, "curent tsf %x period %x" | 4256 | ath_print(ath9k_hw_common(ah), ATH_DBG_HWTIMER, |
4238 | "timer_next %x\n", tsf, timer_period, timer_next); | 4257 | "curent tsf %x period %x" |
4258 | "timer_next %x\n", tsf, timer_period, timer_next); | ||
4239 | 4259 | ||
4240 | /* | 4260 | /* |
4241 | * Pull timer_next forward if the current TSF already passed it | 4261 | * Pull timer_next forward if the current TSF already passed it |
@@ -4258,15 +4278,10 @@ void ath_gen_timer_start(struct ath_hw *ah, | |||
4258 | REG_SET_BIT(ah, AR_IMR_S5, | 4278 | REG_SET_BIT(ah, AR_IMR_S5, |
4259 | (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | | 4279 | (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | |
4260 | SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); | 4280 | SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); |
4261 | |||
4262 | if ((ah->ah_sc->imask & ATH9K_INT_GENTIMER) == 0) { | ||
4263 | ath9k_hw_set_interrupts(ah, 0); | ||
4264 | ah->ah_sc->imask |= ATH9K_INT_GENTIMER; | ||
4265 | ath9k_hw_set_interrupts(ah, ah->ah_sc->imask); | ||
4266 | } | ||
4267 | } | 4281 | } |
4282 | EXPORT_SYMBOL(ath9k_hw_gen_timer_start); | ||
4268 | 4283 | ||
4269 | void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | 4284 | void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) |
4270 | { | 4285 | { |
4271 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 4286 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
4272 | 4287 | ||
@@ -4285,14 +4300,8 @@ void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | |||
4285 | SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); | 4300 | SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); |
4286 | 4301 | ||
4287 | clear_bit(timer->index, &timer_table->timer_mask.timer_bits); | 4302 | clear_bit(timer->index, &timer_table->timer_mask.timer_bits); |
4288 | |||
4289 | /* if no timer is enabled, turn off interrupt mask */ | ||
4290 | if (timer_table->timer_mask.val == 0) { | ||
4291 | ath9k_hw_set_interrupts(ah, 0); | ||
4292 | ah->ah_sc->imask &= ~ATH9K_INT_GENTIMER; | ||
4293 | ath9k_hw_set_interrupts(ah, ah->ah_sc->imask); | ||
4294 | } | ||
4295 | } | 4303 | } |
4304 | EXPORT_SYMBOL(ath9k_hw_gen_timer_stop); | ||
4296 | 4305 | ||
4297 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer) | 4306 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer) |
4298 | { | 4307 | { |
@@ -4302,6 +4311,7 @@ void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer) | |||
4302 | timer_table->timers[timer->index] = NULL; | 4311 | timer_table->timers[timer->index] = NULL; |
4303 | kfree(timer); | 4312 | kfree(timer); |
4304 | } | 4313 | } |
4314 | EXPORT_SYMBOL(ath_gen_timer_free); | ||
4305 | 4315 | ||
4306 | /* | 4316 | /* |
4307 | * Generic Timer Interrupts handling | 4317 | * Generic Timer Interrupts handling |
@@ -4310,6 +4320,7 @@ void ath_gen_timer_isr(struct ath_hw *ah) | |||
4310 | { | 4320 | { |
4311 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 4321 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
4312 | struct ath_gen_timer *timer; | 4322 | struct ath_gen_timer *timer; |
4323 | struct ath_common *common = ath9k_hw_common(ah); | ||
4313 | u32 trigger_mask, thresh_mask, index; | 4324 | u32 trigger_mask, thresh_mask, index; |
4314 | 4325 | ||
4315 | /* get hardware generic timer interrupt status */ | 4326 | /* get hardware generic timer interrupt status */ |
@@ -4324,8 +4335,8 @@ void ath_gen_timer_isr(struct ath_hw *ah) | |||
4324 | index = rightmost_index(timer_table, &thresh_mask); | 4335 | index = rightmost_index(timer_table, &thresh_mask); |
4325 | timer = timer_table->timers[index]; | 4336 | timer = timer_table->timers[index]; |
4326 | BUG_ON(!timer); | 4337 | BUG_ON(!timer); |
4327 | DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, | 4338 | ath_print(common, ATH_DBG_HWTIMER, |
4328 | "TSF overflow for Gen timer %d\n", index); | 4339 | "TSF overflow for Gen timer %d\n", index); |
4329 | timer->overflow(timer->arg); | 4340 | timer->overflow(timer->arg); |
4330 | } | 4341 | } |
4331 | 4342 | ||
@@ -4333,21 +4344,9 @@ void ath_gen_timer_isr(struct ath_hw *ah) | |||
4333 | index = rightmost_index(timer_table, &trigger_mask); | 4344 | index = rightmost_index(timer_table, &trigger_mask); |
4334 | timer = timer_table->timers[index]; | 4345 | timer = timer_table->timers[index]; |
4335 | BUG_ON(!timer); | 4346 | BUG_ON(!timer); |
4336 | DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, | 4347 | ath_print(common, ATH_DBG_HWTIMER, |
4337 | "Gen timer[%d] trigger\n", index); | 4348 | "Gen timer[%d] trigger\n", index); |
4338 | timer->trigger(timer->arg); | 4349 | timer->trigger(timer->arg); |
4339 | } | 4350 | } |
4340 | } | 4351 | } |
4341 | 4352 | EXPORT_SYMBOL(ath_gen_timer_isr); | |
4342 | /* | ||
4343 | * Primitive to disable ASPM | ||
4344 | */ | ||
4345 | void ath_pcie_aspm_disable(struct ath_softc *sc) | ||
4346 | { | ||
4347 | struct pci_dev *pdev = to_pci_dev(sc->dev); | ||
4348 | u8 aspm; | ||
4349 | |||
4350 | pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); | ||
4351 | aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1); | ||
4352 | pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); | ||
4353 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index b89234571829..cdaec526db35 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -27,17 +27,24 @@ | |||
27 | #include "calib.h" | 27 | #include "calib.h" |
28 | #include "reg.h" | 28 | #include "reg.h" |
29 | #include "phy.h" | 29 | #include "phy.h" |
30 | #include "btcoex.h" | ||
30 | 31 | ||
31 | #include "../regd.h" | 32 | #include "../regd.h" |
33 | #include "../debug.h" | ||
32 | 34 | ||
33 | #define ATHEROS_VENDOR_ID 0x168c | 35 | #define ATHEROS_VENDOR_ID 0x168c |
36 | |||
34 | #define AR5416_DEVID_PCI 0x0023 | 37 | #define AR5416_DEVID_PCI 0x0023 |
35 | #define AR5416_DEVID_PCIE 0x0024 | 38 | #define AR5416_DEVID_PCIE 0x0024 |
36 | #define AR9160_DEVID_PCI 0x0027 | 39 | #define AR9160_DEVID_PCI 0x0027 |
37 | #define AR9280_DEVID_PCI 0x0029 | 40 | #define AR9280_DEVID_PCI 0x0029 |
38 | #define AR9280_DEVID_PCIE 0x002a | 41 | #define AR9280_DEVID_PCIE 0x002a |
39 | #define AR9285_DEVID_PCIE 0x002b | 42 | #define AR9285_DEVID_PCIE 0x002b |
43 | |||
40 | #define AR5416_AR9100_DEVID 0x000b | 44 | #define AR5416_AR9100_DEVID 0x000b |
45 | |||
46 | #define AR9271_USB 0x9271 | ||
47 | |||
41 | #define AR_SUBVENDOR_ID_NOG 0x0e11 | 48 | #define AR_SUBVENDOR_ID_NOG 0x0e11 |
42 | #define AR_SUBVENDOR_ID_NEW_A 0x7065 | 49 | #define AR_SUBVENDOR_ID_NEW_A 0x7065 |
43 | #define AR5416_MAGIC 0x19641014 | 50 | #define AR5416_MAGIC 0x19641014 |
@@ -49,9 +56,18 @@ | |||
49 | #define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa | 56 | #define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa |
50 | #define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab | 57 | #define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab |
51 | 58 | ||
59 | #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) | ||
60 | |||
61 | #define ATH_DEFAULT_NOISE_FLOOR -95 | ||
62 | |||
63 | #define ATH9K_RSSI_BAD 0x80 | ||
64 | |||
52 | /* Register read/write primitives */ | 65 | /* Register read/write primitives */ |
53 | #define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) | 66 | #define REG_WRITE(_ah, _reg, _val) \ |
54 | #define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) | 67 | ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg)) |
68 | |||
69 | #define REG_READ(_ah, _reg) \ | ||
70 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) | ||
55 | 71 | ||
56 | #define SM(_v, _f) (((_v) << _f##_S) & _f) | 72 | #define SM(_v, _f) (((_v) << _f##_S) & _f) |
57 | #define MS(_v, _f) (((_v) & _f) >> _f##_S) | 73 | #define MS(_v, _f) (((_v) & _f) >> _f##_S) |
@@ -91,7 +107,7 @@ | |||
91 | #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) | 107 | #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) |
92 | 108 | ||
93 | #define BASE_ACTIVATE_DELAY 100 | 109 | #define BASE_ACTIVATE_DELAY 100 |
94 | #define RTC_PLL_SETTLE_DELAY 1000 | 110 | #define RTC_PLL_SETTLE_DELAY 100 |
95 | #define COEF_SCALE_S 24 | 111 | #define COEF_SCALE_S 24 |
96 | #define HT40_CHANNEL_CENTER_SHIFT 10 | 112 | #define HT40_CHANNEL_CENTER_SHIFT 10 |
97 | 113 | ||
@@ -433,7 +449,8 @@ struct ath_gen_timer_table { | |||
433 | }; | 449 | }; |
434 | 450 | ||
435 | struct ath_hw { | 451 | struct ath_hw { |
436 | struct ath_softc *ah_sc; | 452 | struct ieee80211_hw *hw; |
453 | struct ath_common common; | ||
437 | struct ath9k_hw_version hw_version; | 454 | struct ath9k_hw_version hw_version; |
438 | struct ath9k_ops_config config; | 455 | struct ath9k_ops_config config; |
439 | struct ath9k_hw_capabilities caps; | 456 | struct ath9k_hw_capabilities caps; |
@@ -450,7 +467,6 @@ struct ath_hw { | |||
450 | 467 | ||
451 | bool sw_mgmt_crypto; | 468 | bool sw_mgmt_crypto; |
452 | bool is_pciexpress; | 469 | bool is_pciexpress; |
453 | u8 macaddr[ETH_ALEN]; | ||
454 | u16 tx_trig_level; | 470 | u16 tx_trig_level; |
455 | u16 rfsilent; | 471 | u16 rfsilent; |
456 | u32 rfkill_gpio; | 472 | u32 rfkill_gpio; |
@@ -553,8 +569,10 @@ struct ath_hw { | |||
553 | int firpwr[5]; | 569 | int firpwr[5]; |
554 | enum ath9k_ani_cmd ani_function; | 570 | enum ath9k_ani_cmd ani_function; |
555 | 571 | ||
572 | /* Bluetooth coexistance */ | ||
573 | struct ath_btcoex_hw btcoex_hw; | ||
574 | |||
556 | u32 intr_txqs; | 575 | u32 intr_txqs; |
557 | enum ath9k_ht_extprotspacing extprotspacing; | ||
558 | u8 txchainmask; | 576 | u8 txchainmask; |
559 | u8 rxchainmask; | 577 | u8 rxchainmask; |
560 | 578 | ||
@@ -578,12 +596,24 @@ struct ath_hw { | |||
578 | struct ar5416IniArray iniModesAdditional; | 596 | struct ar5416IniArray iniModesAdditional; |
579 | struct ar5416IniArray iniModesRxGain; | 597 | struct ar5416IniArray iniModesRxGain; |
580 | struct ar5416IniArray iniModesTxGain; | 598 | struct ar5416IniArray iniModesTxGain; |
599 | struct ar5416IniArray iniCckfirNormal; | ||
600 | struct ar5416IniArray iniCckfirJapan2484; | ||
581 | 601 | ||
582 | u32 intr_gen_timer_trigger; | 602 | u32 intr_gen_timer_trigger; |
583 | u32 intr_gen_timer_thresh; | 603 | u32 intr_gen_timer_thresh; |
584 | struct ath_gen_timer_table hw_gen_timers; | 604 | struct ath_gen_timer_table hw_gen_timers; |
585 | }; | 605 | }; |
586 | 606 | ||
607 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) | ||
608 | { | ||
609 | return &ah->common; | ||
610 | } | ||
611 | |||
612 | static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) | ||
613 | { | ||
614 | return &(ath9k_hw_common(ah)->regulatory); | ||
615 | } | ||
616 | |||
587 | /* Initialization, Detach, Reset */ | 617 | /* Initialization, Detach, Reset */ |
588 | const char *ath9k_hw_probe(u16 vendorid, u16 devid); | 618 | const char *ath9k_hw_probe(u16 vendorid, u16 devid); |
589 | void ath9k_hw_detach(struct ath_hw *ah); | 619 | void ath9k_hw_detach(struct ath_hw *ah); |
@@ -637,19 +667,20 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); | |||
637 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); | 667 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); |
638 | void ath9k_hw_setopmode(struct ath_hw *ah); | 668 | void ath9k_hw_setopmode(struct ath_hw *ah); |
639 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); | 669 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); |
640 | void ath9k_hw_setbssidmask(struct ath_softc *sc); | 670 | void ath9k_hw_setbssidmask(struct ath_hw *ah); |
641 | void ath9k_hw_write_associd(struct ath_softc *sc); | 671 | void ath9k_hw_write_associd(struct ath_hw *ah); |
642 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); | 672 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); |
643 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); | 673 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); |
644 | void ath9k_hw_reset_tsf(struct ath_hw *ah); | 674 | void ath9k_hw_reset_tsf(struct ath_hw *ah); |
645 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); | 675 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); |
646 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); | 676 | bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); |
647 | void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode); | 677 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); |
648 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 678 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
649 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | 679 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, |
650 | const struct ath9k_beacon_state *bs); | 680 | const struct ath9k_beacon_state *bs); |
651 | bool ath9k_hw_setpower(struct ath_hw *ah, | 681 | |
652 | enum ath9k_power_mode mode); | 682 | bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode); |
683 | |||
653 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off); | 684 | void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off); |
654 | 685 | ||
655 | /* Interrupt Handling */ | 686 | /* Interrupt Handling */ |
@@ -663,9 +694,12 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | |||
663 | void (*overflow)(void *), | 694 | void (*overflow)(void *), |
664 | void *arg, | 695 | void *arg, |
665 | u8 timer_index); | 696 | u8 timer_index); |
666 | void ath_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, | 697 | void ath9k_hw_gen_timer_start(struct ath_hw *ah, |
667 | u32 timer_next, u32 timer_period); | 698 | struct ath_gen_timer *timer, |
668 | void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); | 699 | u32 timer_next, |
700 | u32 timer_period); | ||
701 | void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); | ||
702 | |||
669 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); | 703 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); |
670 | void ath_gen_timer_isr(struct ath_hw *hw); | 704 | void ath_gen_timer_isr(struct ath_hw *hw); |
671 | u32 ath9k_hw_gettsf32(struct ath_hw *ah); | 705 | u32 ath9k_hw_gettsf32(struct ath_hw *ah); |
@@ -674,5 +708,4 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah); | |||
674 | #define ATH_PCIE_CAP_LINK_L0S 1 | 708 | #define ATH_PCIE_CAP_LINK_L0S 1 |
675 | #define ATH_PCIE_CAP_LINK_L1 2 | 709 | #define ATH_PCIE_CAP_LINK_L1 2 |
676 | 710 | ||
677 | void ath_pcie_aspm_disable(struct ath_softc *sc); | ||
678 | #endif | 711 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h index 8622265a030a..3ee6658d809b 100644 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ b/drivers/net/wireless/ath/ath9k/initvals.h | |||
@@ -21,6 +21,8 @@ static const u32 ar5416Modes[][6] = { | |||
21 | { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, | 21 | { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, |
22 | { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, | 22 | { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, |
23 | { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, | 23 | { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, |
24 | { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, | ||
25 | { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, | ||
24 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, | 26 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, |
25 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, | 27 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, |
26 | { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | 28 | { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, |
@@ -31,11 +33,11 @@ static const u32 ar5416Modes[][6] = { | |||
31 | { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | 33 | { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, |
32 | { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | 34 | { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, |
33 | { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | 35 | { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, |
34 | { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de }, | 36 | { 0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de }, |
35 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, | 37 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, |
36 | { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, | 38 | { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, |
37 | { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, | 39 | { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, |
38 | { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | 40 | { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, |
39 | { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, | 41 | { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, |
40 | { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, | 42 | { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, |
41 | { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, | 43 | { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, |
@@ -46,10 +48,10 @@ static const u32 ar5416Modes[][6] = { | |||
46 | { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, | 48 | { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, |
47 | { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, | 49 | { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, |
48 | { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, | 50 | { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, |
49 | { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, | 51 | { 0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, |
50 | { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, | 52 | { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, |
51 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | 53 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, |
52 | { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, | 54 | { 0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c }, |
53 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, | 55 | { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, |
54 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, | 56 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, |
55 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 57 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
@@ -199,7 +201,6 @@ static const u32 ar5416Common[][2] = { | |||
199 | { 0x00008110, 0x00000168 }, | 201 | { 0x00008110, 0x00000168 }, |
200 | { 0x00008118, 0x000100aa }, | 202 | { 0x00008118, 0x000100aa }, |
201 | { 0x0000811c, 0x00003210 }, | 203 | { 0x0000811c, 0x00003210 }, |
202 | { 0x00008120, 0x08f04800 }, | ||
203 | { 0x00008124, 0x00000000 }, | 204 | { 0x00008124, 0x00000000 }, |
204 | { 0x00008128, 0x00000000 }, | 205 | { 0x00008128, 0x00000000 }, |
205 | { 0x0000812c, 0x00000000 }, | 206 | { 0x0000812c, 0x00000000 }, |
@@ -215,7 +216,6 @@ static const u32 ar5416Common[][2] = { | |||
215 | { 0x00008178, 0x00000100 }, | 216 | { 0x00008178, 0x00000100 }, |
216 | { 0x0000817c, 0x00000000 }, | 217 | { 0x0000817c, 0x00000000 }, |
217 | { 0x000081c4, 0x00000000 }, | 218 | { 0x000081c4, 0x00000000 }, |
218 | { 0x000081d0, 0x00003210 }, | ||
219 | { 0x000081ec, 0x00000000 }, | 219 | { 0x000081ec, 0x00000000 }, |
220 | { 0x000081f0, 0x00000000 }, | 220 | { 0x000081f0, 0x00000000 }, |
221 | { 0x000081f4, 0x00000000 }, | 221 | { 0x000081f4, 0x00000000 }, |
@@ -246,6 +246,7 @@ static const u32 ar5416Common[][2] = { | |||
246 | { 0x00008258, 0x00000000 }, | 246 | { 0x00008258, 0x00000000 }, |
247 | { 0x0000825c, 0x400000ff }, | 247 | { 0x0000825c, 0x400000ff }, |
248 | { 0x00008260, 0x00080922 }, | 248 | { 0x00008260, 0x00080922 }, |
249 | { 0x00008264, 0xa8000010 }, | ||
249 | { 0x00008270, 0x00000000 }, | 250 | { 0x00008270, 0x00000000 }, |
250 | { 0x00008274, 0x40000000 }, | 251 | { 0x00008274, 0x40000000 }, |
251 | { 0x00008278, 0x003e4180 }, | 252 | { 0x00008278, 0x003e4180 }, |
@@ -406,9 +407,9 @@ static const u32 ar5416Common[][2] = { | |||
406 | { 0x0000a25c, 0x0f0f0f01 }, | 407 | { 0x0000a25c, 0x0f0f0f01 }, |
407 | { 0x0000a260, 0xdfa91f01 }, | 408 | { 0x0000a260, 0xdfa91f01 }, |
408 | { 0x0000a268, 0x00000000 }, | 409 | { 0x0000a268, 0x00000000 }, |
409 | { 0x0000a26c, 0x0ebae9c6 }, | 410 | { 0x0000a26c, 0x0e79e5c6 }, |
410 | { 0x0000b26c, 0x0ebae9c6 }, | 411 | { 0x0000b26c, 0x0e79e5c6 }, |
411 | { 0x0000c26c, 0x0ebae9c6 }, | 412 | { 0x0000c26c, 0x0e79e5c6 }, |
412 | { 0x0000d270, 0x00820820 }, | 413 | { 0x0000d270, 0x00820820 }, |
413 | { 0x0000a278, 0x1ce739ce }, | 414 | { 0x0000a278, 0x1ce739ce }, |
414 | { 0x0000a27c, 0x051701ce }, | 415 | { 0x0000a27c, 0x051701ce }, |
@@ -2551,26 +2552,27 @@ static const u32 ar9280Modes_9280_2[][6] = { | |||
2551 | { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, | 2552 | { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, |
2552 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, | 2553 | { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, |
2553 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, | 2554 | { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, |
2554 | { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | 2555 | { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, |
2555 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, | 2556 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, |
2556 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | 2557 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, |
2557 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, | 2558 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, |
2558 | { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, | 2559 | { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, |
2559 | { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, | 2560 | { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, |
2560 | { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, | 2561 | { 0x00009850, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, |
2561 | { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, | 2562 | { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, |
2562 | { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e }, | 2563 | { 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e }, |
2563 | { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, | 2564 | { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, |
2564 | { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | 2565 | { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, |
2565 | { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, | 2566 | { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, |
2566 | { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, | 2567 | { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, |
2567 | { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, | 2568 | { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, |
2568 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, | 2569 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000268, 0x0000000b, 0x00000016 }, |
2569 | { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, | 2570 | { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, |
2570 | { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, | 2571 | { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, |
2571 | { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, | 2572 | { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, |
2572 | { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, | 2573 | { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, |
2573 | { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, | 2574 | { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, |
2575 | { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, | ||
2574 | { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, | 2576 | { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, |
2575 | { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, | 2577 | { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, |
2576 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, | 2578 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, |
@@ -2585,8 +2587,10 @@ static const u32 ar9280Modes_9280_2[][6] = { | |||
2585 | { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, | 2587 | { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, |
2586 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, | 2588 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, |
2587 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | 2589 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, |
2590 | { 0x0000a23c, 0x13c88000, 0x13c88000, 0x13c88001, 0x13c88000, 0x13c88000 }, | ||
2588 | { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, | 2591 | { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, |
2589 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, | 2592 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, |
2593 | { 0x0000a388, 0x0c000000, 0x0c000000, 0x08000000, 0x0c000000, 0x0c000000 }, | ||
2590 | { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 2594 | { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
2591 | { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, | 2595 | { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, |
2592 | }; | 2596 | }; |
@@ -2813,7 +2817,6 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2813 | { 0x00009958, 0x2108ecff }, | 2817 | { 0x00009958, 0x2108ecff }, |
2814 | { 0x00009940, 0x14750604 }, | 2818 | { 0x00009940, 0x14750604 }, |
2815 | { 0x0000c95c, 0x004b6a8e }, | 2819 | { 0x0000c95c, 0x004b6a8e }, |
2816 | { 0x0000c968, 0x000003ce }, | ||
2817 | { 0x00009970, 0x190fb515 }, | 2820 | { 0x00009970, 0x190fb515 }, |
2818 | { 0x00009974, 0x00000000 }, | 2821 | { 0x00009974, 0x00000000 }, |
2819 | { 0x00009978, 0x00000001 }, | 2822 | { 0x00009978, 0x00000001 }, |
@@ -2849,7 +2852,6 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2849 | { 0x0000a22c, 0x233f7180 }, | 2852 | { 0x0000a22c, 0x233f7180 }, |
2850 | { 0x0000a234, 0x20202020 }, | 2853 | { 0x0000a234, 0x20202020 }, |
2851 | { 0x0000a238, 0x20202020 }, | 2854 | { 0x0000a238, 0x20202020 }, |
2852 | { 0x0000a23c, 0x13c88000 }, | ||
2853 | { 0x0000a240, 0x38490a20 }, | 2855 | { 0x0000a240, 0x38490a20 }, |
2854 | { 0x0000a244, 0x00007bb6 }, | 2856 | { 0x0000a244, 0x00007bb6 }, |
2855 | { 0x0000a248, 0x0fff3ffc }, | 2857 | { 0x0000a248, 0x0fff3ffc }, |
@@ -2859,8 +2861,8 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2859 | { 0x0000a25c, 0x0f0f0f01 }, | 2861 | { 0x0000a25c, 0x0f0f0f01 }, |
2860 | { 0x0000a260, 0xdfa91f01 }, | 2862 | { 0x0000a260, 0xdfa91f01 }, |
2861 | { 0x0000a268, 0x00000000 }, | 2863 | { 0x0000a268, 0x00000000 }, |
2862 | { 0x0000a26c, 0x0ebae9c6 }, | 2864 | { 0x0000a26c, 0x0e79e5c6 }, |
2863 | { 0x0000b26c, 0x0ebae9c6 }, | 2865 | { 0x0000b26c, 0x0e79e5c6 }, |
2864 | { 0x0000d270, 0x00820820 }, | 2866 | { 0x0000d270, 0x00820820 }, |
2865 | { 0x0000a278, 0x1ce739ce }, | 2867 | { 0x0000a278, 0x1ce739ce }, |
2866 | { 0x0000d35c, 0x07ffffef }, | 2868 | { 0x0000d35c, 0x07ffffef }, |
@@ -2874,7 +2876,6 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2874 | { 0x0000d37c, 0x7fffffe2 }, | 2876 | { 0x0000d37c, 0x7fffffe2 }, |
2875 | { 0x0000d380, 0x7f3c7bba }, | 2877 | { 0x0000d380, 0x7f3c7bba }, |
2876 | { 0x0000d384, 0xf3307ff0 }, | 2878 | { 0x0000d384, 0xf3307ff0 }, |
2877 | { 0x0000a388, 0x0c000000 }, | ||
2878 | { 0x0000a38c, 0x20202020 }, | 2879 | { 0x0000a38c, 0x20202020 }, |
2879 | { 0x0000a390, 0x20202020 }, | 2880 | { 0x0000a390, 0x20202020 }, |
2880 | { 0x0000a394, 0x1ce739ce }, | 2881 | { 0x0000a394, 0x1ce739ce }, |
@@ -2940,7 +2941,7 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = { | |||
2940 | { 0x0000801c, 0x148ec02b, 0x148ec057 }, | 2941 | { 0x0000801c, 0x148ec02b, 0x148ec057 }, |
2941 | { 0x00008318, 0x000044c0, 0x00008980 }, | 2942 | { 0x00008318, 0x000044c0, 0x00008980 }, |
2942 | { 0x00009820, 0x02020200, 0x02020200 }, | 2943 | { 0x00009820, 0x02020200, 0x02020200 }, |
2943 | { 0x00009824, 0x00000f0f, 0x00000f0f }, | 2944 | { 0x00009824, 0x01000f0f, 0x01000f0f }, |
2944 | { 0x00009828, 0x0b020001, 0x0b020001 }, | 2945 | { 0x00009828, 0x0b020001, 0x0b020001 }, |
2945 | { 0x00009834, 0x00000f0f, 0x00000f0f }, | 2946 | { 0x00009834, 0x00000f0f, 0x00000f0f }, |
2946 | { 0x00009844, 0x03721821, 0x03721821 }, | 2947 | { 0x00009844, 0x03721821, 0x03721821 }, |
@@ -3348,6 +3349,8 @@ static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { | |||
3348 | }; | 3349 | }; |
3349 | 3350 | ||
3350 | static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { | 3351 | static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { |
3352 | { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, | ||
3353 | { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, | ||
3351 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 3354 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
3352 | { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, | 3355 | { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, |
3353 | { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, | 3356 | { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, |
@@ -3376,11 +3379,11 @@ static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { | |||
3376 | { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, | 3379 | { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, |
3377 | { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, | 3380 | { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, |
3378 | { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, | 3381 | { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, |
3379 | { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, | ||
3380 | { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, | ||
3381 | }; | 3382 | }; |
3382 | 3383 | ||
3383 | static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { | 3384 | static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { |
3385 | { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, | ||
3386 | { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, | ||
3384 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 3387 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
3385 | { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, | 3388 | { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, |
3386 | { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, | 3389 | { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, |
@@ -3409,8 +3412,6 @@ static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { | |||
3409 | { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, | 3412 | { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, |
3410 | { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, | 3413 | { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, |
3411 | { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, | 3414 | { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, |
3412 | { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, | ||
3413 | { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, | ||
3414 | }; | 3415 | }; |
3415 | 3416 | ||
3416 | static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { | 3417 | static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { |
@@ -5918,9 +5919,6 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = { | |||
5918 | { 0x000099ec, 0x0cc80caa }, | 5919 | { 0x000099ec, 0x0cc80caa }, |
5919 | { 0x000099f0, 0x00000000 }, | 5920 | { 0x000099f0, 0x00000000 }, |
5920 | { 0x000099fc, 0x00001042 }, | 5921 | { 0x000099fc, 0x00001042 }, |
5921 | { 0x0000a1f4, 0x00fffeff }, | ||
5922 | { 0x0000a1f8, 0x00f5f9ff }, | ||
5923 | { 0x0000a1fc, 0xb79f6427 }, | ||
5924 | { 0x0000a208, 0x803e4788 }, | 5922 | { 0x0000a208, 0x803e4788 }, |
5925 | { 0x0000a210, 0x4080a333 }, | 5923 | { 0x0000a210, 0x4080a333 }, |
5926 | { 0x0000a214, 0x40206c10 }, | 5924 | { 0x0000a214, 0x40206c10 }, |
@@ -5980,7 +5978,7 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = { | |||
5980 | { 0x0000b3f4, 0x00000000 }, | 5978 | { 0x0000b3f4, 0x00000000 }, |
5981 | { 0x0000a7d8, 0x000003f1 }, | 5979 | { 0x0000a7d8, 0x000003f1 }, |
5982 | { 0x00007800, 0x00000800 }, | 5980 | { 0x00007800, 0x00000800 }, |
5983 | { 0x00007804, 0x6c35ffc2 }, | 5981 | { 0x00007804, 0x6c35ffd2 }, |
5984 | { 0x00007808, 0x6db6c000 }, | 5982 | { 0x00007808, 0x6db6c000 }, |
5985 | { 0x0000780c, 0x6db6cb30 }, | 5983 | { 0x0000780c, 0x6db6cb30 }, |
5986 | { 0x00007810, 0x6db6cb6c }, | 5984 | { 0x00007810, 0x6db6cb6c }, |
@@ -6000,7 +5998,7 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = { | |||
6000 | { 0x00007848, 0x934934a8 }, | 5998 | { 0x00007848, 0x934934a8 }, |
6001 | { 0x00007850, 0x00000000 }, | 5999 | { 0x00007850, 0x00000000 }, |
6002 | { 0x00007854, 0x00000800 }, | 6000 | { 0x00007854, 0x00000800 }, |
6003 | { 0x00007858, 0x6c35ffc2 }, | 6001 | { 0x00007858, 0x6c35ffd2 }, |
6004 | { 0x0000785c, 0x6db6c000 }, | 6002 | { 0x0000785c, 0x6db6c000 }, |
6005 | { 0x00007860, 0x6db6cb30 }, | 6003 | { 0x00007860, 0x6db6cb30 }, |
6006 | { 0x00007864, 0x6db6cb6c }, | 6004 | { 0x00007864, 0x6db6cb6c }, |
@@ -6027,6 +6025,22 @@ static const u_int32_t ar9287Common_9287_1_1[][2] = { | |||
6027 | { 0x000078b8, 0x2a850160 }, | 6025 | { 0x000078b8, 0x2a850160 }, |
6028 | }; | 6026 | }; |
6029 | 6027 | ||
6028 | /* | ||
6029 | * For Japanese regulatory requirements, 2484 MHz requires the following three | ||
6030 | * registers be programmed differently from the channel between 2412 and 2472 MHz. | ||
6031 | */ | ||
6032 | static const u_int32_t ar9287Common_normal_cck_fir_coeff_92871_1[][2] = { | ||
6033 | { 0x0000a1f4, 0x00fffeff }, | ||
6034 | { 0x0000a1f8, 0x00f5f9ff }, | ||
6035 | { 0x0000a1fc, 0xb79f6427 }, | ||
6036 | }; | ||
6037 | |||
6038 | static const u_int32_t ar9287Common_japan_2484_cck_fir_coeff_92871_1[][2] = { | ||
6039 | { 0x0000a1f4, 0x00000000 }, | ||
6040 | { 0x0000a1f8, 0xefff0301 }, | ||
6041 | { 0x0000a1fc, 0xca9228ee }, | ||
6042 | }; | ||
6043 | |||
6030 | static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = { | 6044 | static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = { |
6031 | /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ | 6045 | /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ |
6032 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 6046 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 800bfab94635..46466ffebcb0 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -14,16 +14,16 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | 19 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, |
20 | struct ath9k_tx_queue_info *qi) | 20 | struct ath9k_tx_queue_info *qi) |
21 | { | 21 | { |
22 | DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, | 22 | ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, |
23 | "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", | 23 | "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", |
24 | ah->txok_interrupt_mask, ah->txerr_interrupt_mask, | 24 | ah->txok_interrupt_mask, ah->txerr_interrupt_mask, |
25 | ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, | 25 | ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, |
26 | ah->txurn_interrupt_mask); | 26 | ah->txurn_interrupt_mask); |
27 | 27 | ||
28 | REG_WRITE(ah, AR_IMR_S0, | 28 | REG_WRITE(ah, AR_IMR_S0, |
29 | SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) | 29 | SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) |
@@ -39,17 +39,21 @@ u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) | |||
39 | { | 39 | { |
40 | return REG_READ(ah, AR_QTXDP(q)); | 40 | return REG_READ(ah, AR_QTXDP(q)); |
41 | } | 41 | } |
42 | EXPORT_SYMBOL(ath9k_hw_gettxbuf); | ||
42 | 43 | ||
43 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) | 44 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) |
44 | { | 45 | { |
45 | REG_WRITE(ah, AR_QTXDP(q), txdp); | 46 | REG_WRITE(ah, AR_QTXDP(q), txdp); |
46 | } | 47 | } |
48 | EXPORT_SYMBOL(ath9k_hw_puttxbuf); | ||
47 | 49 | ||
48 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q) | 50 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q) |
49 | { | 51 | { |
50 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); | 52 | ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE, |
53 | "Enable TXE on queue: %u\n", q); | ||
51 | REG_WRITE(ah, AR_Q_TXE, 1 << q); | 54 | REG_WRITE(ah, AR_Q_TXE, 1 << q); |
52 | } | 55 | } |
56 | EXPORT_SYMBOL(ath9k_hw_txstart); | ||
53 | 57 | ||
54 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) | 58 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) |
55 | { | 59 | { |
@@ -64,6 +68,7 @@ u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) | |||
64 | 68 | ||
65 | return npend; | 69 | return npend; |
66 | } | 70 | } |
71 | EXPORT_SYMBOL(ath9k_hw_numtxpending); | ||
67 | 72 | ||
68 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | 73 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) |
69 | { | 74 | { |
@@ -93,27 +98,28 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | |||
93 | 98 | ||
94 | return newLevel != curLevel; | 99 | return newLevel != curLevel; |
95 | } | 100 | } |
101 | EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel); | ||
96 | 102 | ||
97 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | 103 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) |
98 | { | 104 | { |
99 | #define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ | 105 | #define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ |
100 | #define ATH9K_TIME_QUANTUM 100 /* usec */ | 106 | #define ATH9K_TIME_QUANTUM 100 /* usec */ |
101 | 107 | struct ath_common *common = ath9k_hw_common(ah); | |
102 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 108 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
103 | struct ath9k_tx_queue_info *qi; | 109 | struct ath9k_tx_queue_info *qi; |
104 | u32 tsfLow, j, wait; | 110 | u32 tsfLow, j, wait; |
105 | u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; | 111 | u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; |
106 | 112 | ||
107 | if (q >= pCap->total_queues) { | 113 | if (q >= pCap->total_queues) { |
108 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " | 114 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " |
109 | "invalid queue: %u\n", q); | 115 | "invalid queue: %u\n", q); |
110 | return false; | 116 | return false; |
111 | } | 117 | } |
112 | 118 | ||
113 | qi = &ah->txq[q]; | 119 | qi = &ah->txq[q]; |
114 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 120 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
115 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " | 121 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " |
116 | "inactive queue: %u\n", q); | 122 | "inactive queue: %u\n", q); |
117 | return false; | 123 | return false; |
118 | } | 124 | } |
119 | 125 | ||
@@ -126,9 +132,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | |||
126 | } | 132 | } |
127 | 133 | ||
128 | if (ath9k_hw_numtxpending(ah, q)) { | 134 | if (ath9k_hw_numtxpending(ah, q)) { |
129 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | 135 | ath_print(common, ATH_DBG_QUEUE, |
130 | "%s: Num of pending TX Frames %d on Q %d\n", | 136 | "%s: Num of pending TX Frames %d on Q %d\n", |
131 | __func__, ath9k_hw_numtxpending(ah, q), q); | 137 | __func__, ath9k_hw_numtxpending(ah, q), q); |
132 | 138 | ||
133 | for (j = 0; j < 2; j++) { | 139 | for (j = 0; j < 2; j++) { |
134 | tsfLow = REG_READ(ah, AR_TSF_L32); | 140 | tsfLow = REG_READ(ah, AR_TSF_L32); |
@@ -142,9 +148,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | |||
142 | if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) | 148 | if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) |
143 | break; | 149 | break; |
144 | 150 | ||
145 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | 151 | ath_print(common, ATH_DBG_QUEUE, |
146 | "TSF has moved while trying to set " | 152 | "TSF has moved while trying to set " |
147 | "quiet time TSF: 0x%08x\n", tsfLow); | 153 | "quiet time TSF: 0x%08x\n", tsfLow); |
148 | } | 154 | } |
149 | 155 | ||
150 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | 156 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); |
@@ -155,9 +161,9 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | |||
155 | wait = wait_time; | 161 | wait = wait_time; |
156 | while (ath9k_hw_numtxpending(ah, q)) { | 162 | while (ath9k_hw_numtxpending(ah, q)) { |
157 | if ((--wait) == 0) { | 163 | if ((--wait) == 0) { |
158 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, | 164 | ath_print(common, ATH_DBG_QUEUE, |
159 | "Failed to stop TX DMA in 100 " | 165 | "Failed to stop TX DMA in 100 " |
160 | "msec after killing last frame\n"); | 166 | "msec after killing last frame\n"); |
161 | break; | 167 | break; |
162 | } | 168 | } |
163 | udelay(ATH9K_TIME_QUANTUM); | 169 | udelay(ATH9K_TIME_QUANTUM); |
@@ -172,6 +178,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | |||
172 | #undef ATH9K_TX_STOP_DMA_TIMEOUT | 178 | #undef ATH9K_TX_STOP_DMA_TIMEOUT |
173 | #undef ATH9K_TIME_QUANTUM | 179 | #undef ATH9K_TIME_QUANTUM |
174 | } | 180 | } |
181 | EXPORT_SYMBOL(ath9k_hw_stoptxdma); | ||
175 | 182 | ||
176 | void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | 183 | void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, |
177 | u32 segLen, bool firstSeg, | 184 | u32 segLen, bool firstSeg, |
@@ -198,6 +205,7 @@ void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
198 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | 205 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; |
199 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | 206 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; |
200 | } | 207 | } |
208 | EXPORT_SYMBOL(ath9k_hw_filltxdesc); | ||
201 | 209 | ||
202 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) | 210 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) |
203 | { | 211 | { |
@@ -209,6 +217,7 @@ void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) | |||
209 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; | 217 | ads->ds_txstatus6 = ads->ds_txstatus7 = 0; |
210 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; | 218 | ads->ds_txstatus8 = ads->ds_txstatus9 = 0; |
211 | } | 219 | } |
220 | EXPORT_SYMBOL(ath9k_hw_cleartxdesc); | ||
212 | 221 | ||
213 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) | 222 | int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) |
214 | { | 223 | { |
@@ -284,6 +293,7 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) | |||
284 | 293 | ||
285 | return 0; | 294 | return 0; |
286 | } | 295 | } |
296 | EXPORT_SYMBOL(ath9k_hw_txprocdesc); | ||
287 | 297 | ||
288 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | 298 | void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, |
289 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, | 299 | u32 pktLen, enum ath9k_pkt_type type, u32 txPower, |
@@ -319,6 +329,7 @@ void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
319 | ads->ds_ctl11 = 0; | 329 | ads->ds_ctl11 = 0; |
320 | } | 330 | } |
321 | } | 331 | } |
332 | EXPORT_SYMBOL(ath9k_hw_set11n_txdesc); | ||
322 | 333 | ||
323 | void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, | 334 | void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, |
324 | struct ath_desc *lastds, | 335 | struct ath_desc *lastds, |
@@ -374,6 +385,7 @@ void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, | |||
374 | last_ads->ds_ctl2 = ads->ds_ctl2; | 385 | last_ads->ds_ctl2 = ads->ds_ctl2; |
375 | last_ads->ds_ctl3 = ads->ds_ctl3; | 386 | last_ads->ds_ctl3 = ads->ds_ctl3; |
376 | } | 387 | } |
388 | EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario); | ||
377 | 389 | ||
378 | void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, | 390 | void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, |
379 | u32 aggrLen) | 391 | u32 aggrLen) |
@@ -384,6 +396,7 @@ void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, | |||
384 | ads->ds_ctl6 &= ~AR_AggrLen; | 396 | ads->ds_ctl6 &= ~AR_AggrLen; |
385 | ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); | 397 | ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); |
386 | } | 398 | } |
399 | EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first); | ||
387 | 400 | ||
388 | void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, | 401 | void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, |
389 | u32 numDelims) | 402 | u32 numDelims) |
@@ -398,6 +411,7 @@ void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, | |||
398 | ctl6 |= SM(numDelims, AR_PadDelim); | 411 | ctl6 |= SM(numDelims, AR_PadDelim); |
399 | ads->ds_ctl6 = ctl6; | 412 | ads->ds_ctl6 = ctl6; |
400 | } | 413 | } |
414 | EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle); | ||
401 | 415 | ||
402 | void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) | 416 | void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) |
403 | { | 417 | { |
@@ -407,6 +421,7 @@ void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) | |||
407 | ads->ds_ctl1 &= ~AR_MoreAggr; | 421 | ads->ds_ctl1 &= ~AR_MoreAggr; |
408 | ads->ds_ctl6 &= ~AR_PadDelim; | 422 | ads->ds_ctl6 &= ~AR_PadDelim; |
409 | } | 423 | } |
424 | EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last); | ||
410 | 425 | ||
411 | void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) | 426 | void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) |
412 | { | 427 | { |
@@ -414,6 +429,7 @@ void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) | |||
414 | 429 | ||
415 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); | 430 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); |
416 | } | 431 | } |
432 | EXPORT_SYMBOL(ath9k_hw_clr11n_aggr); | ||
417 | 433 | ||
418 | void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, | 434 | void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, |
419 | u32 burstDuration) | 435 | u32 burstDuration) |
@@ -423,6 +439,7 @@ void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, | |||
423 | ads->ds_ctl2 &= ~AR_BurstDur; | 439 | ads->ds_ctl2 &= ~AR_BurstDur; |
424 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); | 440 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); |
425 | } | 441 | } |
442 | EXPORT_SYMBOL(ath9k_hw_set11n_burstduration); | ||
426 | 443 | ||
427 | void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, | 444 | void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, |
428 | u32 vmf) | 445 | u32 vmf) |
@@ -440,28 +457,30 @@ void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) | |||
440 | *txqs &= ah->intr_txqs; | 457 | *txqs &= ah->intr_txqs; |
441 | ah->intr_txqs &= ~(*txqs); | 458 | ah->intr_txqs &= ~(*txqs); |
442 | } | 459 | } |
460 | EXPORT_SYMBOL(ath9k_hw_gettxintrtxqs); | ||
443 | 461 | ||
444 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, | 462 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, |
445 | const struct ath9k_tx_queue_info *qinfo) | 463 | const struct ath9k_tx_queue_info *qinfo) |
446 | { | 464 | { |
447 | u32 cw; | 465 | u32 cw; |
466 | struct ath_common *common = ath9k_hw_common(ah); | ||
448 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 467 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
449 | struct ath9k_tx_queue_info *qi; | 468 | struct ath9k_tx_queue_info *qi; |
450 | 469 | ||
451 | if (q >= pCap->total_queues) { | 470 | if (q >= pCap->total_queues) { |
452 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " | 471 | ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " |
453 | "invalid queue: %u\n", q); | 472 | "invalid queue: %u\n", q); |
454 | return false; | 473 | return false; |
455 | } | 474 | } |
456 | 475 | ||
457 | qi = &ah->txq[q]; | 476 | qi = &ah->txq[q]; |
458 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 477 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
459 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " | 478 | ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " |
460 | "inactive queue: %u\n", q); | 479 | "inactive queue: %u\n", q); |
461 | return false; | 480 | return false; |
462 | } | 481 | } |
463 | 482 | ||
464 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); | 483 | ath_print(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); |
465 | 484 | ||
466 | qi->tqi_ver = qinfo->tqi_ver; | 485 | qi->tqi_ver = qinfo->tqi_ver; |
467 | qi->tqi_subtype = qinfo->tqi_subtype; | 486 | qi->tqi_subtype = qinfo->tqi_subtype; |
@@ -510,23 +529,25 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, | |||
510 | 529 | ||
511 | return true; | 530 | return true; |
512 | } | 531 | } |
532 | EXPORT_SYMBOL(ath9k_hw_set_txq_props); | ||
513 | 533 | ||
514 | bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, | 534 | bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, |
515 | struct ath9k_tx_queue_info *qinfo) | 535 | struct ath9k_tx_queue_info *qinfo) |
516 | { | 536 | { |
537 | struct ath_common *common = ath9k_hw_common(ah); | ||
517 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 538 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
518 | struct ath9k_tx_queue_info *qi; | 539 | struct ath9k_tx_queue_info *qi; |
519 | 540 | ||
520 | if (q >= pCap->total_queues) { | 541 | if (q >= pCap->total_queues) { |
521 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " | 542 | ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " |
522 | "invalid queue: %u\n", q); | 543 | "invalid queue: %u\n", q); |
523 | return false; | 544 | return false; |
524 | } | 545 | } |
525 | 546 | ||
526 | qi = &ah->txq[q]; | 547 | qi = &ah->txq[q]; |
527 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 548 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
528 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " | 549 | ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " |
529 | "inactive queue: %u\n", q); | 550 | "inactive queue: %u\n", q); |
530 | return false; | 551 | return false; |
531 | } | 552 | } |
532 | 553 | ||
@@ -547,10 +568,12 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, | |||
547 | 568 | ||
548 | return true; | 569 | return true; |
549 | } | 570 | } |
571 | EXPORT_SYMBOL(ath9k_hw_get_txq_props); | ||
550 | 572 | ||
551 | int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, | 573 | int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, |
552 | const struct ath9k_tx_queue_info *qinfo) | 574 | const struct ath9k_tx_queue_info *qinfo) |
553 | { | 575 | { |
576 | struct ath_common *common = ath9k_hw_common(ah); | ||
554 | struct ath9k_tx_queue_info *qi; | 577 | struct ath9k_tx_queue_info *qi; |
555 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 578 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
556 | int q; | 579 | int q; |
@@ -574,23 +597,23 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, | |||
574 | ATH9K_TX_QUEUE_INACTIVE) | 597 | ATH9K_TX_QUEUE_INACTIVE) |
575 | break; | 598 | break; |
576 | if (q == pCap->total_queues) { | 599 | if (q == pCap->total_queues) { |
577 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 600 | ath_print(common, ATH_DBG_FATAL, |
578 | "No available TX queue\n"); | 601 | "No available TX queue\n"); |
579 | return -1; | 602 | return -1; |
580 | } | 603 | } |
581 | break; | 604 | break; |
582 | default: | 605 | default: |
583 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n", | 606 | ath_print(common, ATH_DBG_FATAL, |
584 | type); | 607 | "Invalid TX queue type: %u\n", type); |
585 | return -1; | 608 | return -1; |
586 | } | 609 | } |
587 | 610 | ||
588 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); | 611 | ath_print(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); |
589 | 612 | ||
590 | qi = &ah->txq[q]; | 613 | qi = &ah->txq[q]; |
591 | if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { | 614 | if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { |
592 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 615 | ath_print(common, ATH_DBG_FATAL, |
593 | "TX queue: %u already active\n", q); | 616 | "TX queue: %u already active\n", q); |
594 | return -1; | 617 | return -1; |
595 | } | 618 | } |
596 | memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); | 619 | memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); |
@@ -613,25 +636,27 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, | |||
613 | 636 | ||
614 | return q; | 637 | return q; |
615 | } | 638 | } |
639 | EXPORT_SYMBOL(ath9k_hw_setuptxqueue); | ||
616 | 640 | ||
617 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) | 641 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) |
618 | { | 642 | { |
619 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 643 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
644 | struct ath_common *common = ath9k_hw_common(ah); | ||
620 | struct ath9k_tx_queue_info *qi; | 645 | struct ath9k_tx_queue_info *qi; |
621 | 646 | ||
622 | if (q >= pCap->total_queues) { | 647 | if (q >= pCap->total_queues) { |
623 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " | 648 | ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " |
624 | "invalid queue: %u\n", q); | 649 | "invalid queue: %u\n", q); |
625 | return false; | 650 | return false; |
626 | } | 651 | } |
627 | qi = &ah->txq[q]; | 652 | qi = &ah->txq[q]; |
628 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 653 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
629 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " | 654 | ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " |
630 | "inactive queue: %u\n", q); | 655 | "inactive queue: %u\n", q); |
631 | return false; | 656 | return false; |
632 | } | 657 | } |
633 | 658 | ||
634 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); | 659 | ath_print(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); |
635 | 660 | ||
636 | qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; | 661 | qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; |
637 | ah->txok_interrupt_mask &= ~(1 << q); | 662 | ah->txok_interrupt_mask &= ~(1 << q); |
@@ -643,28 +668,30 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) | |||
643 | 668 | ||
644 | return true; | 669 | return true; |
645 | } | 670 | } |
671 | EXPORT_SYMBOL(ath9k_hw_releasetxqueue); | ||
646 | 672 | ||
647 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | 673 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) |
648 | { | 674 | { |
649 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 675 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
676 | struct ath_common *common = ath9k_hw_common(ah); | ||
650 | struct ath9k_channel *chan = ah->curchan; | 677 | struct ath9k_channel *chan = ah->curchan; |
651 | struct ath9k_tx_queue_info *qi; | 678 | struct ath9k_tx_queue_info *qi; |
652 | u32 cwMin, chanCwMin, value; | 679 | u32 cwMin, chanCwMin, value; |
653 | 680 | ||
654 | if (q >= pCap->total_queues) { | 681 | if (q >= pCap->total_queues) { |
655 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " | 682 | ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " |
656 | "invalid queue: %u\n", q); | 683 | "invalid queue: %u\n", q); |
657 | return false; | 684 | return false; |
658 | } | 685 | } |
659 | 686 | ||
660 | qi = &ah->txq[q]; | 687 | qi = &ah->txq[q]; |
661 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 688 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
662 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " | 689 | ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " |
663 | "inactive queue: %u\n", q); | 690 | "inactive queue: %u\n", q); |
664 | return true; | 691 | return true; |
665 | } | 692 | } |
666 | 693 | ||
667 | DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); | 694 | ath_print(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); |
668 | 695 | ||
669 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { | 696 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { |
670 | if (chan && IS_CHAN_B(chan)) | 697 | if (chan && IS_CHAN_B(chan)) |
@@ -799,6 +826,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
799 | 826 | ||
800 | return true; | 827 | return true; |
801 | } | 828 | } |
829 | EXPORT_SYMBOL(ath9k_hw_resettxqueue); | ||
802 | 830 | ||
803 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | 831 | int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, |
804 | u32 pa, struct ath_desc *nds, u64 tsf) | 832 | u32 pa, struct ath_desc *nds, u64 tsf) |
@@ -880,6 +908,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
880 | 908 | ||
881 | return 0; | 909 | return 0; |
882 | } | 910 | } |
911 | EXPORT_SYMBOL(ath9k_hw_rxprocdesc); | ||
883 | 912 | ||
884 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | 913 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, |
885 | u32 size, u32 flags) | 914 | u32 size, u32 flags) |
@@ -895,6 +924,7 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
895 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 924 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
896 | memset(&(ads->u), 0, sizeof(ads->u)); | 925 | memset(&(ads->u), 0, sizeof(ads->u)); |
897 | } | 926 | } |
927 | EXPORT_SYMBOL(ath9k_hw_setuprxdesc); | ||
898 | 928 | ||
899 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) | 929 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) |
900 | { | 930 | { |
@@ -911,8 +941,9 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) | |||
911 | AR_DIAG_RX_ABORT)); | 941 | AR_DIAG_RX_ABORT)); |
912 | 942 | ||
913 | reg = REG_READ(ah, AR_OBS_BUS_1); | 943 | reg = REG_READ(ah, AR_OBS_BUS_1); |
914 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 944 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, |
915 | "RX failed to go idle in 10 ms RXSM=0x%x\n", reg); | 945 | "RX failed to go idle in 10 ms RXSM=0x%x\n", |
946 | reg); | ||
916 | 947 | ||
917 | return false; | 948 | return false; |
918 | } | 949 | } |
@@ -923,16 +954,19 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) | |||
923 | 954 | ||
924 | return true; | 955 | return true; |
925 | } | 956 | } |
957 | EXPORT_SYMBOL(ath9k_hw_setrxabort); | ||
926 | 958 | ||
927 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) | 959 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) |
928 | { | 960 | { |
929 | REG_WRITE(ah, AR_RXDP, rxdp); | 961 | REG_WRITE(ah, AR_RXDP, rxdp); |
930 | } | 962 | } |
963 | EXPORT_SYMBOL(ath9k_hw_putrxbuf); | ||
931 | 964 | ||
932 | void ath9k_hw_rxena(struct ath_hw *ah) | 965 | void ath9k_hw_rxena(struct ath_hw *ah) |
933 | { | 966 | { |
934 | REG_WRITE(ah, AR_CR, AR_CR_RXE); | 967 | REG_WRITE(ah, AR_CR, AR_CR_RXE); |
935 | } | 968 | } |
969 | EXPORT_SYMBOL(ath9k_hw_rxena); | ||
936 | 970 | ||
937 | void ath9k_hw_startpcureceive(struct ath_hw *ah) | 971 | void ath9k_hw_startpcureceive(struct ath_hw *ah) |
938 | { | 972 | { |
@@ -942,6 +976,7 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah) | |||
942 | 976 | ||
943 | REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 977 | REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
944 | } | 978 | } |
979 | EXPORT_SYMBOL(ath9k_hw_startpcureceive); | ||
945 | 980 | ||
946 | void ath9k_hw_stoppcurecv(struct ath_hw *ah) | 981 | void ath9k_hw_stoppcurecv(struct ath_hw *ah) |
947 | { | 982 | { |
@@ -949,12 +984,13 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah) | |||
949 | 984 | ||
950 | ath9k_hw_disable_mib_counters(ah); | 985 | ath9k_hw_disable_mib_counters(ah); |
951 | } | 986 | } |
987 | EXPORT_SYMBOL(ath9k_hw_stoppcurecv); | ||
952 | 988 | ||
953 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah) | 989 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah) |
954 | { | 990 | { |
955 | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ | 991 | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ |
956 | #define AH_RX_TIME_QUANTUM 100 /* usec */ | 992 | #define AH_RX_TIME_QUANTUM 100 /* usec */ |
957 | 993 | struct ath_common *common = ath9k_hw_common(ah); | |
958 | int i; | 994 | int i; |
959 | 995 | ||
960 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | 996 | REG_WRITE(ah, AR_CR, AR_CR_RXD); |
@@ -967,12 +1003,12 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah) | |||
967 | } | 1003 | } |
968 | 1004 | ||
969 | if (i == 0) { | 1005 | if (i == 0) { |
970 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 1006 | ath_print(common, ATH_DBG_FATAL, |
971 | "DMA failed to stop in %d ms " | 1007 | "DMA failed to stop in %d ms " |
972 | "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", | 1008 | "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", |
973 | AH_RX_STOP_DMA_TIMEOUT / 1000, | 1009 | AH_RX_STOP_DMA_TIMEOUT / 1000, |
974 | REG_READ(ah, AR_CR), | 1010 | REG_READ(ah, AR_CR), |
975 | REG_READ(ah, AR_DIAG_SW)); | 1011 | REG_READ(ah, AR_DIAG_SW)); |
976 | return false; | 1012 | return false; |
977 | } else { | 1013 | } else { |
978 | return true; | 1014 | return true; |
@@ -981,3 +1017,17 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah) | |||
981 | #undef AH_RX_TIME_QUANTUM | 1017 | #undef AH_RX_TIME_QUANTUM |
982 | #undef AH_RX_STOP_DMA_TIMEOUT | 1018 | #undef AH_RX_STOP_DMA_TIMEOUT |
983 | } | 1019 | } |
1020 | EXPORT_SYMBOL(ath9k_hw_stopdmarecv); | ||
1021 | |||
1022 | int ath9k_hw_beaconq_setup(struct ath_hw *ah) | ||
1023 | { | ||
1024 | struct ath9k_tx_queue_info qi; | ||
1025 | |||
1026 | memset(&qi, 0, sizeof(qi)); | ||
1027 | qi.tqi_aifs = 1; | ||
1028 | qi.tqi_cwmin = 0; | ||
1029 | qi.tqi_cwmax = 0; | ||
1030 | /* NB: don't enable any interrupts */ | ||
1031 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); | ||
1032 | } | ||
1033 | EXPORT_SYMBOL(ath9k_hw_beaconq_setup); | ||
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index f56e77da6c3e..fefb65dafb1c 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -614,16 +614,6 @@ enum ath9k_cipher { | |||
614 | ATH9K_CIPHER_MIC = 127 | 614 | ATH9K_CIPHER_MIC = 127 |
615 | }; | 615 | }; |
616 | 616 | ||
617 | enum ath9k_ht_macmode { | ||
618 | ATH9K_HT_MACMODE_20 = 0, | ||
619 | ATH9K_HT_MACMODE_2040 = 1, | ||
620 | }; | ||
621 | |||
622 | enum ath9k_ht_extprotspacing { | ||
623 | ATH9K_HT_EXTPROTSPACING_20 = 0, | ||
624 | ATH9K_HT_EXTPROTSPACING_25 = 1, | ||
625 | }; | ||
626 | |||
627 | struct ath_hw; | 617 | struct ath_hw; |
628 | struct ath9k_channel; | 618 | struct ath9k_channel; |
629 | struct ath_rate_table; | 619 | struct ath_rate_table; |
@@ -677,5 +667,6 @@ void ath9k_hw_rxena(struct ath_hw *ah); | |||
677 | void ath9k_hw_startpcureceive(struct ath_hw *ah); | 667 | void ath9k_hw_startpcureceive(struct ath_hw *ah); |
678 | void ath9k_hw_stoppcurecv(struct ath_hw *ah); | 668 | void ath9k_hw_stoppcurecv(struct ath_hw *ah); |
679 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah); | 669 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah); |
670 | int ath9k_hw_beaconq_setup(struct ath_hw *ah); | ||
680 | 671 | ||
681 | #endif /* MAC_H */ | 672 | #endif /* MAC_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 52bed89063d4..69cf702b18c2 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/nl80211.h> | 17 | #include <linux/nl80211.h> |
18 | #include "ath9k.h" | 18 | #include "ath9k.h" |
19 | #include "btcoex.h" | ||
19 | 20 | ||
20 | static char *dev_info = "ath9k"; | 21 | static char *dev_info = "ath9k"; |
21 | 22 | ||
@@ -28,6 +29,10 @@ static int modparam_nohwcrypt; | |||
28 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); | 29 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); |
29 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | 30 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); |
30 | 31 | ||
32 | static unsigned int ath9k_debug = ATH_DBG_DEFAULT; | ||
33 | module_param_named(debug, ath9k_debug, uint, 0); | ||
34 | MODULE_PARM_DESC(debug, "Debugging mask"); | ||
35 | |||
31 | /* We use the hw_value as an index into our private channel structure */ | 36 | /* We use the hw_value as an index into our private channel structure */ |
32 | 37 | ||
33 | #define CHAN2G(_freq, _idx) { \ | 38 | #define CHAN2G(_freq, _idx) { \ |
@@ -224,8 +229,9 @@ static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) | |||
224 | } | 229 | } |
225 | sband->n_bitrates++; | 230 | sband->n_bitrates++; |
226 | 231 | ||
227 | DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n", | 232 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, |
228 | rate[i].bitrate / 10, rate[i].hw_value); | 233 | "Rate: %2dMbps, ratecode: %2d\n", |
234 | rate[i].bitrate / 10, rate[i].hw_value); | ||
229 | } | 235 | } |
230 | } | 236 | } |
231 | 237 | ||
@@ -242,6 +248,51 @@ static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, | |||
242 | return channel; | 248 | return channel; |
243 | } | 249 | } |
244 | 250 | ||
251 | static bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) | ||
252 | { | ||
253 | unsigned long flags; | ||
254 | bool ret; | ||
255 | |||
256 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
257 | ret = ath9k_hw_setpower(sc->sc_ah, mode); | ||
258 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
259 | |||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | void ath9k_ps_wakeup(struct ath_softc *sc) | ||
264 | { | ||
265 | unsigned long flags; | ||
266 | |||
267 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
268 | if (++sc->ps_usecount != 1) | ||
269 | goto unlock; | ||
270 | |||
271 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | ||
272 | |||
273 | unlock: | ||
274 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
275 | } | ||
276 | |||
277 | void ath9k_ps_restore(struct ath_softc *sc) | ||
278 | { | ||
279 | unsigned long flags; | ||
280 | |||
281 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
282 | if (--sc->ps_usecount != 0) | ||
283 | goto unlock; | ||
284 | |||
285 | if (sc->ps_enabled && | ||
286 | !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | | ||
287 | SC_OP_WAIT_FOR_CAB | | ||
288 | SC_OP_WAIT_FOR_PSPOLL_DATA | | ||
289 | SC_OP_WAIT_FOR_TX_ACK))) | ||
290 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); | ||
291 | |||
292 | unlock: | ||
293 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
294 | } | ||
295 | |||
245 | /* | 296 | /* |
246 | * Set/change channels. If the channel is really being changed, it's done | 297 | * Set/change channels. If the channel is really being changed, it's done |
247 | * by reseting the chip. To accomplish this we must first cleanup any pending | 298 | * by reseting the chip. To accomplish this we must first cleanup any pending |
@@ -251,6 +302,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
251 | struct ath9k_channel *hchan) | 302 | struct ath9k_channel *hchan) |
252 | { | 303 | { |
253 | struct ath_hw *ah = sc->sc_ah; | 304 | struct ath_hw *ah = sc->sc_ah; |
305 | struct ath_common *common = ath9k_hw_common(ah); | ||
306 | struct ieee80211_conf *conf = &common->hw->conf; | ||
254 | bool fastcc = true, stopped; | 307 | bool fastcc = true, stopped; |
255 | struct ieee80211_channel *channel = hw->conf.channel; | 308 | struct ieee80211_channel *channel = hw->conf.channel; |
256 | int r; | 309 | int r; |
@@ -280,19 +333,19 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
280 | if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) | 333 | if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) |
281 | fastcc = false; | 334 | fastcc = false; |
282 | 335 | ||
283 | DPRINTF(sc, ATH_DBG_CONFIG, | 336 | ath_print(common, ATH_DBG_CONFIG, |
284 | "(%u MHz) -> (%u MHz), chanwidth: %d\n", | 337 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", |
285 | sc->sc_ah->curchan->channel, | 338 | sc->sc_ah->curchan->channel, |
286 | channel->center_freq, sc->tx_chan_width); | 339 | channel->center_freq, conf_is_ht40(conf)); |
287 | 340 | ||
288 | spin_lock_bh(&sc->sc_resetlock); | 341 | spin_lock_bh(&sc->sc_resetlock); |
289 | 342 | ||
290 | r = ath9k_hw_reset(ah, hchan, fastcc); | 343 | r = ath9k_hw_reset(ah, hchan, fastcc); |
291 | if (r) { | 344 | if (r) { |
292 | DPRINTF(sc, ATH_DBG_FATAL, | 345 | ath_print(common, ATH_DBG_FATAL, |
293 | "Unable to reset channel (%u Mhz) " | 346 | "Unable to reset channel (%u Mhz) " |
294 | "reset status %d\n", | 347 | "reset status %d\n", |
295 | channel->center_freq, r); | 348 | channel->center_freq, r); |
296 | spin_unlock_bh(&sc->sc_resetlock); | 349 | spin_unlock_bh(&sc->sc_resetlock); |
297 | goto ps_restore; | 350 | goto ps_restore; |
298 | } | 351 | } |
@@ -301,8 +354,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
301 | sc->sc_flags &= ~SC_OP_FULL_RESET; | 354 | sc->sc_flags &= ~SC_OP_FULL_RESET; |
302 | 355 | ||
303 | if (ath_startrecv(sc) != 0) { | 356 | if (ath_startrecv(sc) != 0) { |
304 | DPRINTF(sc, ATH_DBG_FATAL, | 357 | ath_print(common, ATH_DBG_FATAL, |
305 | "Unable to restart recv logic\n"); | 358 | "Unable to restart recv logic\n"); |
306 | r = -EIO; | 359 | r = -EIO; |
307 | goto ps_restore; | 360 | goto ps_restore; |
308 | } | 361 | } |
@@ -327,6 +380,7 @@ static void ath_ani_calibrate(unsigned long data) | |||
327 | { | 380 | { |
328 | struct ath_softc *sc = (struct ath_softc *)data; | 381 | struct ath_softc *sc = (struct ath_softc *)data; |
329 | struct ath_hw *ah = sc->sc_ah; | 382 | struct ath_hw *ah = sc->sc_ah; |
383 | struct ath_common *common = ath9k_hw_common(ah); | ||
330 | bool longcal = false; | 384 | bool longcal = false; |
331 | bool shortcal = false; | 385 | bool shortcal = false; |
332 | bool aniflag = false; | 386 | bool aniflag = false; |
@@ -353,7 +407,7 @@ static void ath_ani_calibrate(unsigned long data) | |||
353 | /* Long calibration runs independently of short calibration. */ | 407 | /* Long calibration runs independently of short calibration. */ |
354 | if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { | 408 | if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { |
355 | longcal = true; | 409 | longcal = true; |
356 | DPRINTF(sc, ATH_DBG_ANI, "longcal @%lu\n", jiffies); | 410 | ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); |
357 | sc->ani.longcal_timer = timestamp; | 411 | sc->ani.longcal_timer = timestamp; |
358 | } | 412 | } |
359 | 413 | ||
@@ -361,7 +415,8 @@ static void ath_ani_calibrate(unsigned long data) | |||
361 | if (!sc->ani.caldone) { | 415 | if (!sc->ani.caldone) { |
362 | if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) { | 416 | if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) { |
363 | shortcal = true; | 417 | shortcal = true; |
364 | DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies); | 418 | ath_print(common, ATH_DBG_ANI, |
419 | "shortcal @%lu\n", jiffies); | ||
365 | sc->ani.shortcal_timer = timestamp; | 420 | sc->ani.shortcal_timer = timestamp; |
366 | sc->ani.resetcal_timer = timestamp; | 421 | sc->ani.resetcal_timer = timestamp; |
367 | } | 422 | } |
@@ -388,16 +443,21 @@ static void ath_ani_calibrate(unsigned long data) | |||
388 | 443 | ||
389 | /* Perform calibration if necessary */ | 444 | /* Perform calibration if necessary */ |
390 | if (longcal || shortcal) { | 445 | if (longcal || shortcal) { |
391 | sc->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan, | 446 | sc->ani.caldone = |
392 | sc->rx_chainmask, longcal); | 447 | ath9k_hw_calibrate(ah, |
448 | ah->curchan, | ||
449 | common->rx_chainmask, | ||
450 | longcal); | ||
393 | 451 | ||
394 | if (longcal) | 452 | if (longcal) |
395 | sc->ani.noise_floor = ath9k_hw_getchan_noise(ah, | 453 | sc->ani.noise_floor = ath9k_hw_getchan_noise(ah, |
396 | ah->curchan); | 454 | ah->curchan); |
397 | 455 | ||
398 | DPRINTF(sc, ATH_DBG_ANI," calibrate chan %u/%x nf: %d\n", | 456 | ath_print(common, ATH_DBG_ANI, |
399 | ah->curchan->channel, ah->curchan->channelFlags, | 457 | " calibrate chan %u/%x nf: %d\n", |
400 | sc->ani.noise_floor); | 458 | ah->curchan->channel, |
459 | ah->curchan->channelFlags, | ||
460 | sc->ani.noise_floor); | ||
401 | } | 461 | } |
402 | } | 462 | } |
403 | 463 | ||
@@ -439,17 +499,22 @@ static void ath_start_ani(struct ath_softc *sc) | |||
439 | */ | 499 | */ |
440 | void ath_update_chainmask(struct ath_softc *sc, int is_ht) | 500 | void ath_update_chainmask(struct ath_softc *sc, int is_ht) |
441 | { | 501 | { |
502 | struct ath_hw *ah = sc->sc_ah; | ||
503 | struct ath_common *common = ath9k_hw_common(ah); | ||
504 | |||
442 | if ((sc->sc_flags & SC_OP_SCANNING) || is_ht || | 505 | if ((sc->sc_flags & SC_OP_SCANNING) || is_ht || |
443 | (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE)) { | 506 | (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { |
444 | sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask; | 507 | common->tx_chainmask = ah->caps.tx_chainmask; |
445 | sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask; | 508 | common->rx_chainmask = ah->caps.rx_chainmask; |
446 | } else { | 509 | } else { |
447 | sc->tx_chainmask = 1; | 510 | common->tx_chainmask = 1; |
448 | sc->rx_chainmask = 1; | 511 | common->rx_chainmask = 1; |
449 | } | 512 | } |
450 | 513 | ||
451 | DPRINTF(sc, ATH_DBG_CONFIG, "tx chmask: %d, rx chmask: %d\n", | 514 | ath_print(common, ATH_DBG_CONFIG, |
452 | sc->tx_chainmask, sc->rx_chainmask); | 515 | "tx chmask: %d, rx chmask: %d\n", |
516 | common->tx_chainmask, | ||
517 | common->rx_chainmask); | ||
453 | } | 518 | } |
454 | 519 | ||
455 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) | 520 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) |
@@ -478,6 +543,9 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
478 | static void ath9k_tasklet(unsigned long data) | 543 | static void ath9k_tasklet(unsigned long data) |
479 | { | 544 | { |
480 | struct ath_softc *sc = (struct ath_softc *)data; | 545 | struct ath_softc *sc = (struct ath_softc *)data; |
546 | struct ath_hw *ah = sc->sc_ah; | ||
547 | struct ath_common *common = ath9k_hw_common(ah); | ||
548 | |||
481 | u32 status = sc->intrstatus; | 549 | u32 status = sc->intrstatus; |
482 | 550 | ||
483 | ath9k_ps_wakeup(sc); | 551 | ath9k_ps_wakeup(sc); |
@@ -502,16 +570,17 @@ static void ath9k_tasklet(unsigned long data) | |||
502 | * TSF sync does not look correct; remain awake to sync with | 570 | * TSF sync does not look correct; remain awake to sync with |
503 | * the next Beacon. | 571 | * the next Beacon. |
504 | */ | 572 | */ |
505 | DPRINTF(sc, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n"); | 573 | ath_print(common, ATH_DBG_PS, |
574 | "TSFOOR - Sync with next Beacon\n"); | ||
506 | sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC; | 575 | sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC; |
507 | } | 576 | } |
508 | 577 | ||
509 | if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) | 578 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
510 | if (status & ATH9K_INT_GENTIMER) | 579 | if (status & ATH9K_INT_GENTIMER) |
511 | ath_gen_timer_isr(sc->sc_ah); | 580 | ath_gen_timer_isr(sc->sc_ah); |
512 | 581 | ||
513 | /* re-enable hardware interrupt */ | 582 | /* re-enable hardware interrupt */ |
514 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 583 | ath9k_hw_set_interrupts(ah, sc->imask); |
515 | ath9k_ps_restore(sc); | 584 | ath9k_ps_restore(sc); |
516 | } | 585 | } |
517 | 586 | ||
@@ -602,7 +671,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
602 | if (status & ATH9K_INT_TIM_TIMER) { | 671 | if (status & ATH9K_INT_TIM_TIMER) { |
603 | /* Clear RxAbort bit so that we can | 672 | /* Clear RxAbort bit so that we can |
604 | * receive frames */ | 673 | * receive frames */ |
605 | ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); | 674 | ath9k_setpower(sc, ATH9K_PM_AWAKE); |
606 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 675 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
607 | sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; | 676 | sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; |
608 | } | 677 | } |
@@ -702,8 +771,8 @@ static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key, | |||
702 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | 771 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); |
703 | if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) { | 772 | if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) { |
704 | /* TX MIC entry failed. No need to proceed further */ | 773 | /* TX MIC entry failed. No need to proceed further */ |
705 | DPRINTF(sc, ATH_DBG_FATAL, | 774 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
706 | "Setting TX MIC Key Failed\n"); | 775 | "Setting TX MIC Key Failed\n"); |
707 | return 0; | 776 | return 0; |
708 | } | 777 | } |
709 | 778 | ||
@@ -890,6 +959,7 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) | |||
890 | static void setup_ht_cap(struct ath_softc *sc, | 959 | static void setup_ht_cap(struct ath_softc *sc, |
891 | struct ieee80211_sta_ht_cap *ht_info) | 960 | struct ieee80211_sta_ht_cap *ht_info) |
892 | { | 961 | { |
962 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
893 | u8 tx_streams, rx_streams; | 963 | u8 tx_streams, rx_streams; |
894 | 964 | ||
895 | ht_info->ht_supported = true; | 965 | ht_info->ht_supported = true; |
@@ -903,12 +973,15 @@ static void setup_ht_cap(struct ath_softc *sc, | |||
903 | 973 | ||
904 | /* set up supported mcs set */ | 974 | /* set up supported mcs set */ |
905 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); | 975 | memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); |
906 | tx_streams = !(sc->tx_chainmask & (sc->tx_chainmask - 1)) ? 1 : 2; | 976 | tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? |
907 | rx_streams = !(sc->rx_chainmask & (sc->rx_chainmask - 1)) ? 1 : 2; | 977 | 1 : 2; |
978 | rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? | ||
979 | 1 : 2; | ||
908 | 980 | ||
909 | if (tx_streams != rx_streams) { | 981 | if (tx_streams != rx_streams) { |
910 | DPRINTF(sc, ATH_DBG_CONFIG, "TX streams %d, RX streams: %d\n", | 982 | ath_print(common, ATH_DBG_CONFIG, |
911 | tx_streams, rx_streams); | 983 | "TX streams %d, RX streams: %d\n", |
984 | tx_streams, rx_streams); | ||
912 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | 985 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; |
913 | ht_info->mcs.tx_params |= ((tx_streams - 1) << | 986 | ht_info->mcs.tx_params |= ((tx_streams - 1) << |
914 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); | 987 | IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); |
@@ -925,14 +998,17 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
925 | struct ieee80211_vif *vif, | 998 | struct ieee80211_vif *vif, |
926 | struct ieee80211_bss_conf *bss_conf) | 999 | struct ieee80211_bss_conf *bss_conf) |
927 | { | 1000 | { |
1001 | struct ath_hw *ah = sc->sc_ah; | ||
1002 | struct ath_common *common = ath9k_hw_common(ah); | ||
928 | 1003 | ||
929 | if (bss_conf->assoc) { | 1004 | if (bss_conf->assoc) { |
930 | DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n", | 1005 | ath_print(common, ATH_DBG_CONFIG, |
931 | bss_conf->aid, sc->curbssid); | 1006 | "Bss Info ASSOC %d, bssid: %pM\n", |
1007 | bss_conf->aid, common->curbssid); | ||
932 | 1008 | ||
933 | /* New association, store aid */ | 1009 | /* New association, store aid */ |
934 | sc->curaid = bss_conf->aid; | 1010 | common->curaid = bss_conf->aid; |
935 | ath9k_hw_write_associd(sc); | 1011 | ath9k_hw_write_associd(ah); |
936 | 1012 | ||
937 | /* | 1013 | /* |
938 | * Request a re-configuration of Beacon related timers | 1014 | * Request a re-configuration of Beacon related timers |
@@ -949,8 +1025,8 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
949 | 1025 | ||
950 | ath_start_ani(sc); | 1026 | ath_start_ani(sc); |
951 | } else { | 1027 | } else { |
952 | DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); | 1028 | ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); |
953 | sc->curaid = 0; | 1029 | common->curaid = 0; |
954 | /* Stop ANI */ | 1030 | /* Stop ANI */ |
955 | del_timer_sync(&sc->ani.timer); | 1031 | del_timer_sync(&sc->ani.timer); |
956 | } | 1032 | } |
@@ -1042,8 +1118,8 @@ static int ath_register_led(struct ath_softc *sc, struct ath_led *led, | |||
1042 | 1118 | ||
1043 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); | 1119 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); |
1044 | if (ret) | 1120 | if (ret) |
1045 | DPRINTF(sc, ATH_DBG_FATAL, | 1121 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
1046 | "Failed to register led:%s", led->name); | 1122 | "Failed to register led:%s", led->name); |
1047 | else | 1123 | else |
1048 | led->registered = 1; | 1124 | led->registered = 1; |
1049 | return ret; | 1125 | return ret; |
@@ -1127,6 +1203,7 @@ fail: | |||
1127 | void ath_radio_enable(struct ath_softc *sc) | 1203 | void ath_radio_enable(struct ath_softc *sc) |
1128 | { | 1204 | { |
1129 | struct ath_hw *ah = sc->sc_ah; | 1205 | struct ath_hw *ah = sc->sc_ah; |
1206 | struct ath_common *common = ath9k_hw_common(ah); | ||
1130 | struct ieee80211_channel *channel = sc->hw->conf.channel; | 1207 | struct ieee80211_channel *channel = sc->hw->conf.channel; |
1131 | int r; | 1208 | int r; |
1132 | 1209 | ||
@@ -1139,17 +1216,17 @@ void ath_radio_enable(struct ath_softc *sc) | |||
1139 | spin_lock_bh(&sc->sc_resetlock); | 1216 | spin_lock_bh(&sc->sc_resetlock); |
1140 | r = ath9k_hw_reset(ah, ah->curchan, false); | 1217 | r = ath9k_hw_reset(ah, ah->curchan, false); |
1141 | if (r) { | 1218 | if (r) { |
1142 | DPRINTF(sc, ATH_DBG_FATAL, | 1219 | ath_print(common, ATH_DBG_FATAL, |
1143 | "Unable to reset channel %u (%uMhz) ", | 1220 | "Unable to reset channel %u (%uMhz) ", |
1144 | "reset status %d\n", | 1221 | "reset status %d\n", |
1145 | channel->center_freq, r); | 1222 | channel->center_freq, r); |
1146 | } | 1223 | } |
1147 | spin_unlock_bh(&sc->sc_resetlock); | 1224 | spin_unlock_bh(&sc->sc_resetlock); |
1148 | 1225 | ||
1149 | ath_update_txpow(sc); | 1226 | ath_update_txpow(sc); |
1150 | if (ath_startrecv(sc) != 0) { | 1227 | if (ath_startrecv(sc) != 0) { |
1151 | DPRINTF(sc, ATH_DBG_FATAL, | 1228 | ath_print(common, ATH_DBG_FATAL, |
1152 | "Unable to restart recv logic\n"); | 1229 | "Unable to restart recv logic\n"); |
1153 | return; | 1230 | return; |
1154 | } | 1231 | } |
1155 | 1232 | ||
@@ -1194,17 +1271,17 @@ void ath_radio_disable(struct ath_softc *sc) | |||
1194 | spin_lock_bh(&sc->sc_resetlock); | 1271 | spin_lock_bh(&sc->sc_resetlock); |
1195 | r = ath9k_hw_reset(ah, ah->curchan, false); | 1272 | r = ath9k_hw_reset(ah, ah->curchan, false); |
1196 | if (r) { | 1273 | if (r) { |
1197 | DPRINTF(sc, ATH_DBG_FATAL, | 1274 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
1198 | "Unable to reset channel %u (%uMhz) " | 1275 | "Unable to reset channel %u (%uMhz) " |
1199 | "reset status %d\n", | 1276 | "reset status %d\n", |
1200 | channel->center_freq, r); | 1277 | channel->center_freq, r); |
1201 | } | 1278 | } |
1202 | spin_unlock_bh(&sc->sc_resetlock); | 1279 | spin_unlock_bh(&sc->sc_resetlock); |
1203 | 1280 | ||
1204 | ath9k_hw_phy_disable(ah); | 1281 | ath9k_hw_phy_disable(ah); |
1205 | ath9k_hw_configpcipowersave(ah, 1, 1); | 1282 | ath9k_hw_configpcipowersave(ah, 1, 1); |
1206 | ath9k_ps_restore(sc); | 1283 | ath9k_ps_restore(sc); |
1207 | ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); | 1284 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); |
1208 | } | 1285 | } |
1209 | 1286 | ||
1210 | /*******************/ | 1287 | /*******************/ |
@@ -1236,23 +1313,26 @@ static void ath_start_rfkill_poll(struct ath_softc *sc) | |||
1236 | wiphy_rfkill_start_polling(sc->hw->wiphy); | 1313 | wiphy_rfkill_start_polling(sc->hw->wiphy); |
1237 | } | 1314 | } |
1238 | 1315 | ||
1239 | void ath_cleanup(struct ath_softc *sc) | 1316 | static void ath9k_uninit_hw(struct ath_softc *sc) |
1240 | { | 1317 | { |
1241 | ath_detach(sc); | 1318 | struct ath_hw *ah = sc->sc_ah; |
1242 | free_irq(sc->irq, sc); | 1319 | |
1243 | ath_bus_cleanup(sc); | 1320 | BUG_ON(!ah); |
1244 | kfree(sc->sec_wiphy); | 1321 | |
1245 | ieee80211_free_hw(sc->hw); | 1322 | ath9k_exit_debug(ah); |
1323 | ath9k_hw_detach(ah); | ||
1324 | sc->sc_ah = NULL; | ||
1246 | } | 1325 | } |
1247 | 1326 | ||
1248 | void ath_detach(struct ath_softc *sc) | 1327 | static void ath_clean_core(struct ath_softc *sc) |
1249 | { | 1328 | { |
1250 | struct ieee80211_hw *hw = sc->hw; | 1329 | struct ieee80211_hw *hw = sc->hw; |
1330 | struct ath_hw *ah = sc->sc_ah; | ||
1251 | int i = 0; | 1331 | int i = 0; |
1252 | 1332 | ||
1253 | ath9k_ps_wakeup(sc); | 1333 | ath9k_ps_wakeup(sc); |
1254 | 1334 | ||
1255 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); | 1335 | dev_dbg(sc->dev, "Detach ATH hw\n"); |
1256 | 1336 | ||
1257 | ath_deinit_leds(sc); | 1337 | ath_deinit_leds(sc); |
1258 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | 1338 | wiphy_rfkill_stop_polling(sc->hw->wiphy); |
@@ -1273,20 +1353,36 @@ void ath_detach(struct ath_softc *sc) | |||
1273 | tasklet_kill(&sc->bcon_tasklet); | 1353 | tasklet_kill(&sc->bcon_tasklet); |
1274 | 1354 | ||
1275 | if (!(sc->sc_flags & SC_OP_INVALID)) | 1355 | if (!(sc->sc_flags & SC_OP_INVALID)) |
1276 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | 1356 | ath9k_setpower(sc, ATH9K_PM_AWAKE); |
1277 | 1357 | ||
1278 | /* cleanup tx queues */ | 1358 | /* cleanup tx queues */ |
1279 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 1359 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
1280 | if (ATH_TXQ_SETUP(sc, i)) | 1360 | if (ATH_TXQ_SETUP(sc, i)) |
1281 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 1361 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
1282 | 1362 | ||
1283 | if ((sc->btcoex_info.no_stomp_timer) && | 1363 | if ((sc->btcoex.no_stomp_timer) && |
1284 | sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) | 1364 | ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
1285 | ath_gen_timer_free(sc->sc_ah, sc->btcoex_info.no_stomp_timer); | 1365 | ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer); |
1366 | } | ||
1286 | 1367 | ||
1287 | ath9k_hw_detach(sc->sc_ah); | 1368 | void ath_detach(struct ath_softc *sc) |
1288 | sc->sc_ah = NULL; | 1369 | { |
1289 | ath9k_exit_debug(sc); | 1370 | ath_clean_core(sc); |
1371 | ath9k_uninit_hw(sc); | ||
1372 | } | ||
1373 | |||
1374 | void ath_cleanup(struct ath_softc *sc) | ||
1375 | { | ||
1376 | struct ath_hw *ah = sc->sc_ah; | ||
1377 | struct ath_common *common = ath9k_hw_common(ah); | ||
1378 | |||
1379 | ath_clean_core(sc); | ||
1380 | free_irq(sc->irq, sc); | ||
1381 | ath_bus_cleanup(common); | ||
1382 | kfree(sc->sec_wiphy); | ||
1383 | ieee80211_free_hw(sc->hw); | ||
1384 | |||
1385 | ath9k_uninit_hw(sc); | ||
1290 | } | 1386 | } |
1291 | 1387 | ||
1292 | static int ath9k_reg_notifier(struct wiphy *wiphy, | 1388 | static int ath9k_reg_notifier(struct wiphy *wiphy, |
@@ -1295,29 +1391,245 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, | |||
1295 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 1391 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
1296 | struct ath_wiphy *aphy = hw->priv; | 1392 | struct ath_wiphy *aphy = hw->priv; |
1297 | struct ath_softc *sc = aphy->sc; | 1393 | struct ath_softc *sc = aphy->sc; |
1298 | struct ath_regulatory *reg = &sc->common.regulatory; | 1394 | struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); |
1299 | 1395 | ||
1300 | return ath_reg_notifier_apply(wiphy, request, reg); | 1396 | return ath_reg_notifier_apply(wiphy, request, reg); |
1301 | } | 1397 | } |
1302 | 1398 | ||
1303 | /* | 1399 | /* |
1400 | * Detects if there is any priority bt traffic | ||
1401 | */ | ||
1402 | static void ath_detect_bt_priority(struct ath_softc *sc) | ||
1403 | { | ||
1404 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
1405 | struct ath_hw *ah = sc->sc_ah; | ||
1406 | |||
1407 | if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio)) | ||
1408 | btcoex->bt_priority_cnt++; | ||
1409 | |||
1410 | if (time_after(jiffies, btcoex->bt_priority_time + | ||
1411 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { | ||
1412 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | ||
1413 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, | ||
1414 | "BT priority traffic detected"); | ||
1415 | sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; | ||
1416 | } else { | ||
1417 | sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; | ||
1418 | } | ||
1419 | |||
1420 | btcoex->bt_priority_cnt = 0; | ||
1421 | btcoex->bt_priority_time = jiffies; | ||
1422 | } | ||
1423 | } | ||
1424 | |||
1425 | /* | ||
1426 | * Configures appropriate weight based on stomp type. | ||
1427 | */ | ||
1428 | static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, | ||
1429 | enum ath_stomp_type stomp_type) | ||
1430 | { | ||
1431 | struct ath_hw *ah = sc->sc_ah; | ||
1432 | |||
1433 | switch (stomp_type) { | ||
1434 | case ATH_BTCOEX_STOMP_ALL: | ||
1435 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
1436 | AR_STOMP_ALL_WLAN_WGHT); | ||
1437 | break; | ||
1438 | case ATH_BTCOEX_STOMP_LOW: | ||
1439 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
1440 | AR_STOMP_LOW_WLAN_WGHT); | ||
1441 | break; | ||
1442 | case ATH_BTCOEX_STOMP_NONE: | ||
1443 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
1444 | AR_STOMP_NONE_WLAN_WGHT); | ||
1445 | break; | ||
1446 | default: | ||
1447 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
1448 | "Invalid Stomptype\n"); | ||
1449 | break; | ||
1450 | } | ||
1451 | |||
1452 | ath9k_hw_btcoex_enable(ah); | ||
1453 | } | ||
1454 | |||
1455 | static void ath9k_gen_timer_start(struct ath_hw *ah, | ||
1456 | struct ath_gen_timer *timer, | ||
1457 | u32 timer_next, | ||
1458 | u32 timer_period) | ||
1459 | { | ||
1460 | struct ath_common *common = ath9k_hw_common(ah); | ||
1461 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
1462 | |||
1463 | ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); | ||
1464 | |||
1465 | if ((sc->imask & ATH9K_INT_GENTIMER) == 0) { | ||
1466 | ath9k_hw_set_interrupts(ah, 0); | ||
1467 | sc->imask |= ATH9K_INT_GENTIMER; | ||
1468 | ath9k_hw_set_interrupts(ah, sc->imask); | ||
1469 | } | ||
1470 | } | ||
1471 | |||
1472 | static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | ||
1473 | { | ||
1474 | struct ath_common *common = ath9k_hw_common(ah); | ||
1475 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
1476 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | ||
1477 | |||
1478 | ath9k_hw_gen_timer_stop(ah, timer); | ||
1479 | |||
1480 | /* if no timer is enabled, turn off interrupt mask */ | ||
1481 | if (timer_table->timer_mask.val == 0) { | ||
1482 | ath9k_hw_set_interrupts(ah, 0); | ||
1483 | sc->imask &= ~ATH9K_INT_GENTIMER; | ||
1484 | ath9k_hw_set_interrupts(ah, sc->imask); | ||
1485 | } | ||
1486 | } | ||
1487 | |||
1488 | /* | ||
1489 | * This is the master bt coex timer which runs for every | ||
1490 | * 45ms, bt traffic will be given priority during 55% of this | ||
1491 | * period while wlan gets remaining 45% | ||
1492 | */ | ||
1493 | static void ath_btcoex_period_timer(unsigned long data) | ||
1494 | { | ||
1495 | struct ath_softc *sc = (struct ath_softc *) data; | ||
1496 | struct ath_hw *ah = sc->sc_ah; | ||
1497 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
1498 | |||
1499 | ath_detect_bt_priority(sc); | ||
1500 | |||
1501 | spin_lock_bh(&btcoex->btcoex_lock); | ||
1502 | |||
1503 | ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type); | ||
1504 | |||
1505 | spin_unlock_bh(&btcoex->btcoex_lock); | ||
1506 | |||
1507 | if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) { | ||
1508 | if (btcoex->hw_timer_enabled) | ||
1509 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | ||
1510 | |||
1511 | ath9k_gen_timer_start(ah, | ||
1512 | btcoex->no_stomp_timer, | ||
1513 | (ath9k_hw_gettsf32(ah) + | ||
1514 | btcoex->btcoex_no_stomp), | ||
1515 | btcoex->btcoex_no_stomp * 10); | ||
1516 | btcoex->hw_timer_enabled = true; | ||
1517 | } | ||
1518 | |||
1519 | mod_timer(&btcoex->period_timer, jiffies + | ||
1520 | msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); | ||
1521 | } | ||
1522 | |||
1523 | /* | ||
1524 | * Generic tsf based hw timer which configures weight | ||
1525 | * registers to time slice between wlan and bt traffic | ||
1526 | */ | ||
1527 | static void ath_btcoex_no_stomp_timer(void *arg) | ||
1528 | { | ||
1529 | struct ath_softc *sc = (struct ath_softc *)arg; | ||
1530 | struct ath_hw *ah = sc->sc_ah; | ||
1531 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
1532 | |||
1533 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
1534 | "no stomp timer running \n"); | ||
1535 | |||
1536 | spin_lock_bh(&btcoex->btcoex_lock); | ||
1537 | |||
1538 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) | ||
1539 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); | ||
1540 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | ||
1541 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); | ||
1542 | |||
1543 | spin_unlock_bh(&btcoex->btcoex_lock); | ||
1544 | } | ||
1545 | |||
1546 | static int ath_init_btcoex_timer(struct ath_softc *sc) | ||
1547 | { | ||
1548 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
1549 | |||
1550 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; | ||
1551 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * | ||
1552 | btcoex->btcoex_period / 100; | ||
1553 | |||
1554 | setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, | ||
1555 | (unsigned long) sc); | ||
1556 | |||
1557 | spin_lock_init(&btcoex->btcoex_lock); | ||
1558 | |||
1559 | btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah, | ||
1560 | ath_btcoex_no_stomp_timer, | ||
1561 | ath_btcoex_no_stomp_timer, | ||
1562 | (void *) sc, AR_FIRST_NDP_TIMER); | ||
1563 | |||
1564 | if (!btcoex->no_stomp_timer) | ||
1565 | return -ENOMEM; | ||
1566 | |||
1567 | return 0; | ||
1568 | } | ||
1569 | |||
1570 | /* | ||
1571 | * Read and write, they both share the same lock. We do this to serialize | ||
1572 | * reads and writes on Atheros 802.11n PCI devices only. This is required | ||
1573 | * as the FIFO on these devices can only accept sanely 2 requests. After | ||
1574 | * that the device goes bananas. Serializing the reads/writes prevents this | ||
1575 | * from happening. | ||
1576 | */ | ||
1577 | |||
1578 | static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset) | ||
1579 | { | ||
1580 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
1581 | struct ath_common *common = ath9k_hw_common(ah); | ||
1582 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
1583 | |||
1584 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) { | ||
1585 | unsigned long flags; | ||
1586 | spin_lock_irqsave(&sc->sc_serial_rw, flags); | ||
1587 | iowrite32(val, sc->mem + reg_offset); | ||
1588 | spin_unlock_irqrestore(&sc->sc_serial_rw, flags); | ||
1589 | } else | ||
1590 | iowrite32(val, sc->mem + reg_offset); | ||
1591 | } | ||
1592 | |||
1593 | static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) | ||
1594 | { | ||
1595 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
1596 | struct ath_common *common = ath9k_hw_common(ah); | ||
1597 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
1598 | u32 val; | ||
1599 | |||
1600 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) { | ||
1601 | unsigned long flags; | ||
1602 | spin_lock_irqsave(&sc->sc_serial_rw, flags); | ||
1603 | val = ioread32(sc->mem + reg_offset); | ||
1604 | spin_unlock_irqrestore(&sc->sc_serial_rw, flags); | ||
1605 | } else | ||
1606 | val = ioread32(sc->mem + reg_offset); | ||
1607 | return val; | ||
1608 | } | ||
1609 | |||
1610 | static const struct ath_ops ath9k_common_ops = { | ||
1611 | .read = ath9k_ioread32, | ||
1612 | .write = ath9k_iowrite32, | ||
1613 | }; | ||
1614 | |||
1615 | /* | ||
1304 | * Initialize and fill ath_softc, ath_sofct is the | 1616 | * Initialize and fill ath_softc, ath_sofct is the |
1305 | * "Software Carrier" struct. Historically it has existed | 1617 | * "Software Carrier" struct. Historically it has existed |
1306 | * to allow the separation between hardware specific | 1618 | * to allow the separation between hardware specific |
1307 | * variables (now in ath_hw) and driver specific variables. | 1619 | * variables (now in ath_hw) and driver specific variables. |
1308 | */ | 1620 | */ |
1309 | static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) | 1621 | static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, |
1622 | const struct ath_bus_ops *bus_ops) | ||
1310 | { | 1623 | { |
1311 | struct ath_hw *ah = NULL; | 1624 | struct ath_hw *ah = NULL; |
1625 | struct ath_common *common; | ||
1312 | int r = 0, i; | 1626 | int r = 0, i; |
1313 | int csz = 0; | 1627 | int csz = 0; |
1628 | int qnum; | ||
1314 | 1629 | ||
1315 | /* XXX: hardware will not be ready until ath_open() being called */ | 1630 | /* XXX: hardware will not be ready until ath_open() being called */ |
1316 | sc->sc_flags |= SC_OP_INVALID; | 1631 | sc->sc_flags |= SC_OP_INVALID; |
1317 | 1632 | ||
1318 | if (ath9k_init_debug(sc) < 0) | ||
1319 | printk(KERN_ERR "Unable to create debugfs files\n"); | ||
1320 | |||
1321 | spin_lock_init(&sc->wiphy_lock); | 1633 | spin_lock_init(&sc->wiphy_lock); |
1322 | spin_lock_init(&sc->sc_resetlock); | 1634 | spin_lock_init(&sc->sc_resetlock); |
1323 | spin_lock_init(&sc->sc_serial_rw); | 1635 | spin_lock_init(&sc->sc_serial_rw); |
@@ -1328,39 +1640,50 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) | |||
1328 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, | 1640 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, |
1329 | (unsigned long)sc); | 1641 | (unsigned long)sc); |
1330 | 1642 | ||
1331 | /* | ||
1332 | * Cache line size is used to size and align various | ||
1333 | * structures used to communicate with the hardware. | ||
1334 | */ | ||
1335 | ath_read_cachesize(sc, &csz); | ||
1336 | /* XXX assert csz is non-zero */ | ||
1337 | sc->common.cachelsz = csz << 2; /* convert to bytes */ | ||
1338 | |||
1339 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); | 1643 | ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); |
1340 | if (!ah) { | 1644 | if (!ah) |
1341 | r = -ENOMEM; | 1645 | return -ENOMEM; |
1342 | goto bad_no_ah; | ||
1343 | } | ||
1344 | 1646 | ||
1345 | ah->ah_sc = sc; | ||
1346 | ah->hw_version.devid = devid; | 1647 | ah->hw_version.devid = devid; |
1347 | ah->hw_version.subsysid = subsysid; | 1648 | ah->hw_version.subsysid = subsysid; |
1348 | sc->sc_ah = ah; | 1649 | sc->sc_ah = ah; |
1349 | 1650 | ||
1651 | common = ath9k_hw_common(ah); | ||
1652 | common->ops = &ath9k_common_ops; | ||
1653 | common->bus_ops = bus_ops; | ||
1654 | common->ah = ah; | ||
1655 | common->hw = sc->hw; | ||
1656 | common->priv = sc; | ||
1657 | common->debug_mask = ath9k_debug; | ||
1658 | |||
1659 | /* | ||
1660 | * Cache line size is used to size and align various | ||
1661 | * structures used to communicate with the hardware. | ||
1662 | */ | ||
1663 | ath_read_cachesize(common, &csz); | ||
1664 | /* XXX assert csz is non-zero */ | ||
1665 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
1666 | |||
1350 | r = ath9k_hw_init(ah); | 1667 | r = ath9k_hw_init(ah); |
1351 | if (r) { | 1668 | if (r) { |
1352 | DPRINTF(sc, ATH_DBG_FATAL, | 1669 | ath_print(common, ATH_DBG_FATAL, |
1353 | "Unable to initialize hardware; " | 1670 | "Unable to initialize hardware; " |
1354 | "initialization status: %d\n", r); | 1671 | "initialization status: %d\n", r); |
1355 | goto bad; | 1672 | goto bad_free_hw; |
1673 | } | ||
1674 | |||
1675 | if (ath9k_init_debug(ah) < 0) { | ||
1676 | ath_print(common, ATH_DBG_FATAL, | ||
1677 | "Unable to create debugfs files\n"); | ||
1678 | goto bad_free_hw; | ||
1356 | } | 1679 | } |
1357 | 1680 | ||
1358 | /* Get the hardware key cache size. */ | 1681 | /* Get the hardware key cache size. */ |
1359 | sc->keymax = ah->caps.keycache_size; | 1682 | sc->keymax = ah->caps.keycache_size; |
1360 | if (sc->keymax > ATH_KEYMAX) { | 1683 | if (sc->keymax > ATH_KEYMAX) { |
1361 | DPRINTF(sc, ATH_DBG_ANY, | 1684 | ath_print(common, ATH_DBG_ANY, |
1362 | "Warning, using only %u entries in %u key cache\n", | 1685 | "Warning, using only %u entries in %u key cache\n", |
1363 | ATH_KEYMAX, sc->keymax); | 1686 | ATH_KEYMAX, sc->keymax); |
1364 | sc->keymax = ATH_KEYMAX; | 1687 | sc->keymax = ATH_KEYMAX; |
1365 | } | 1688 | } |
1366 | 1689 | ||
@@ -1386,17 +1709,17 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) | |||
1386 | * priority. Note that the hal handles reseting | 1709 | * priority. Note that the hal handles reseting |
1387 | * these queues at the needed time. | 1710 | * these queues at the needed time. |
1388 | */ | 1711 | */ |
1389 | sc->beacon.beaconq = ath_beaconq_setup(ah); | 1712 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(ah); |
1390 | if (sc->beacon.beaconq == -1) { | 1713 | if (sc->beacon.beaconq == -1) { |
1391 | DPRINTF(sc, ATH_DBG_FATAL, | 1714 | ath_print(common, ATH_DBG_FATAL, |
1392 | "Unable to setup a beacon xmit queue\n"); | 1715 | "Unable to setup a beacon xmit queue\n"); |
1393 | r = -EIO; | 1716 | r = -EIO; |
1394 | goto bad2; | 1717 | goto bad2; |
1395 | } | 1718 | } |
1396 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | 1719 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); |
1397 | if (sc->beacon.cabq == NULL) { | 1720 | if (sc->beacon.cabq == NULL) { |
1398 | DPRINTF(sc, ATH_DBG_FATAL, | 1721 | ath_print(common, ATH_DBG_FATAL, |
1399 | "Unable to setup CAB xmit queue\n"); | 1722 | "Unable to setup CAB xmit queue\n"); |
1400 | r = -EIO; | 1723 | r = -EIO; |
1401 | goto bad2; | 1724 | goto bad2; |
1402 | } | 1725 | } |
@@ -1410,27 +1733,27 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) | |||
1410 | /* Setup data queues */ | 1733 | /* Setup data queues */ |
1411 | /* NB: ensure BK queue is the lowest priority h/w queue */ | 1734 | /* NB: ensure BK queue is the lowest priority h/w queue */ |
1412 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | 1735 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { |
1413 | DPRINTF(sc, ATH_DBG_FATAL, | 1736 | ath_print(common, ATH_DBG_FATAL, |
1414 | "Unable to setup xmit queue for BK traffic\n"); | 1737 | "Unable to setup xmit queue for BK traffic\n"); |
1415 | r = -EIO; | 1738 | r = -EIO; |
1416 | goto bad2; | 1739 | goto bad2; |
1417 | } | 1740 | } |
1418 | 1741 | ||
1419 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | 1742 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { |
1420 | DPRINTF(sc, ATH_DBG_FATAL, | 1743 | ath_print(common, ATH_DBG_FATAL, |
1421 | "Unable to setup xmit queue for BE traffic\n"); | 1744 | "Unable to setup xmit queue for BE traffic\n"); |
1422 | r = -EIO; | 1745 | r = -EIO; |
1423 | goto bad2; | 1746 | goto bad2; |
1424 | } | 1747 | } |
1425 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | 1748 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { |
1426 | DPRINTF(sc, ATH_DBG_FATAL, | 1749 | ath_print(common, ATH_DBG_FATAL, |
1427 | "Unable to setup xmit queue for VI traffic\n"); | 1750 | "Unable to setup xmit queue for VI traffic\n"); |
1428 | r = -EIO; | 1751 | r = -EIO; |
1429 | goto bad2; | 1752 | goto bad2; |
1430 | } | 1753 | } |
1431 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | 1754 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { |
1432 | DPRINTF(sc, ATH_DBG_FATAL, | 1755 | ath_print(common, ATH_DBG_FATAL, |
1433 | "Unable to setup xmit queue for VO traffic\n"); | 1756 | "Unable to setup xmit queue for VO traffic\n"); |
1434 | r = -EIO; | 1757 | r = -EIO; |
1435 | goto bad2; | 1758 | goto bad2; |
1436 | } | 1759 | } |
@@ -1480,14 +1803,14 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) | |||
1480 | sc->sc_flags |= SC_OP_RXAGGR; | 1803 | sc->sc_flags |= SC_OP_RXAGGR; |
1481 | } | 1804 | } |
1482 | 1805 | ||
1483 | sc->tx_chainmask = ah->caps.tx_chainmask; | 1806 | common->tx_chainmask = ah->caps.tx_chainmask; |
1484 | sc->rx_chainmask = ah->caps.rx_chainmask; | 1807 | common->rx_chainmask = ah->caps.rx_chainmask; |
1485 | 1808 | ||
1486 | ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); | 1809 | ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); |
1487 | sc->rx.defant = ath9k_hw_getdefantenna(ah); | 1810 | sc->rx.defant = ath9k_hw_getdefantenna(ah); |
1488 | 1811 | ||
1489 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 1812 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) |
1490 | memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); | 1813 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
1491 | 1814 | ||
1492 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ | 1815 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ |
1493 | 1816 | ||
@@ -1515,10 +1838,24 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) | |||
1515 | ARRAY_SIZE(ath9k_5ghz_chantable); | 1838 | ARRAY_SIZE(ath9k_5ghz_chantable); |
1516 | } | 1839 | } |
1517 | 1840 | ||
1518 | if (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) { | 1841 | switch (ah->btcoex_hw.scheme) { |
1519 | r = ath9k_hw_btcoex_init(ah); | 1842 | case ATH_BTCOEX_CFG_NONE: |
1843 | break; | ||
1844 | case ATH_BTCOEX_CFG_2WIRE: | ||
1845 | ath9k_hw_btcoex_init_2wire(ah); | ||
1846 | break; | ||
1847 | case ATH_BTCOEX_CFG_3WIRE: | ||
1848 | ath9k_hw_btcoex_init_3wire(ah); | ||
1849 | r = ath_init_btcoex_timer(sc); | ||
1520 | if (r) | 1850 | if (r) |
1521 | goto bad2; | 1851 | goto bad2; |
1852 | qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
1853 | ath9k_hw_init_btcoex_hw(ah, qnum); | ||
1854 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
1855 | break; | ||
1856 | default: | ||
1857 | WARN_ON(1); | ||
1858 | break; | ||
1522 | } | 1859 | } |
1523 | 1860 | ||
1524 | return 0; | 1861 | return 0; |
@@ -1527,12 +1864,9 @@ bad2: | |||
1527 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 1864 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
1528 | if (ATH_TXQ_SETUP(sc, i)) | 1865 | if (ATH_TXQ_SETUP(sc, i)) |
1529 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 1866 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
1530 | bad: | ||
1531 | ath9k_hw_detach(ah); | ||
1532 | sc->sc_ah = NULL; | ||
1533 | bad_no_ah: | ||
1534 | ath9k_exit_debug(sc); | ||
1535 | 1867 | ||
1868 | bad_free_hw: | ||
1869 | ath9k_uninit_hw(sc); | ||
1536 | return r; | 1870 | return r; |
1537 | } | 1871 | } |
1538 | 1872 | ||
@@ -1574,34 +1908,40 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
1574 | } | 1908 | } |
1575 | 1909 | ||
1576 | /* Device driver core initialization */ | 1910 | /* Device driver core initialization */ |
1577 | int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid) | 1911 | int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, |
1912 | const struct ath_bus_ops *bus_ops) | ||
1578 | { | 1913 | { |
1579 | struct ieee80211_hw *hw = sc->hw; | 1914 | struct ieee80211_hw *hw = sc->hw; |
1915 | struct ath_common *common; | ||
1916 | struct ath_hw *ah; | ||
1580 | int error = 0, i; | 1917 | int error = 0, i; |
1581 | struct ath_regulatory *reg; | 1918 | struct ath_regulatory *reg; |
1582 | 1919 | ||
1583 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); | 1920 | dev_dbg(sc->dev, "Attach ATH hw\n"); |
1584 | 1921 | ||
1585 | error = ath_init_softc(devid, sc, subsysid); | 1922 | error = ath_init_softc(devid, sc, subsysid, bus_ops); |
1586 | if (error != 0) | 1923 | if (error != 0) |
1587 | return error; | 1924 | return error; |
1588 | 1925 | ||
1926 | ah = sc->sc_ah; | ||
1927 | common = ath9k_hw_common(ah); | ||
1928 | |||
1589 | /* get mac address from hardware and set in mac80211 */ | 1929 | /* get mac address from hardware and set in mac80211 */ |
1590 | 1930 | ||
1591 | SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr); | 1931 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); |
1592 | 1932 | ||
1593 | ath_set_hw_capab(sc, hw); | 1933 | ath_set_hw_capab(sc, hw); |
1594 | 1934 | ||
1595 | error = ath_regd_init(&sc->common.regulatory, sc->hw->wiphy, | 1935 | error = ath_regd_init(&common->regulatory, sc->hw->wiphy, |
1596 | ath9k_reg_notifier); | 1936 | ath9k_reg_notifier); |
1597 | if (error) | 1937 | if (error) |
1598 | return error; | 1938 | return error; |
1599 | 1939 | ||
1600 | reg = &sc->common.regulatory; | 1940 | reg = &common->regulatory; |
1601 | 1941 | ||
1602 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | 1942 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { |
1603 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | 1943 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); |
1604 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) | 1944 | if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) |
1605 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); | 1945 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); |
1606 | } | 1946 | } |
1607 | 1947 | ||
@@ -1639,9 +1979,7 @@ error_attach: | |||
1639 | if (ATH_TXQ_SETUP(sc, i)) | 1979 | if (ATH_TXQ_SETUP(sc, i)) |
1640 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 1980 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
1641 | 1981 | ||
1642 | ath9k_hw_detach(sc->sc_ah); | 1982 | ath9k_uninit_hw(sc); |
1643 | sc->sc_ah = NULL; | ||
1644 | ath9k_exit_debug(sc); | ||
1645 | 1983 | ||
1646 | return error; | 1984 | return error; |
1647 | } | 1985 | } |
@@ -1649,6 +1987,7 @@ error_attach: | |||
1649 | int ath_reset(struct ath_softc *sc, bool retry_tx) | 1987 | int ath_reset(struct ath_softc *sc, bool retry_tx) |
1650 | { | 1988 | { |
1651 | struct ath_hw *ah = sc->sc_ah; | 1989 | struct ath_hw *ah = sc->sc_ah; |
1990 | struct ath_common *common = ath9k_hw_common(ah); | ||
1652 | struct ieee80211_hw *hw = sc->hw; | 1991 | struct ieee80211_hw *hw = sc->hw; |
1653 | int r; | 1992 | int r; |
1654 | 1993 | ||
@@ -1660,12 +1999,13 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
1660 | spin_lock_bh(&sc->sc_resetlock); | 1999 | spin_lock_bh(&sc->sc_resetlock); |
1661 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); | 2000 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); |
1662 | if (r) | 2001 | if (r) |
1663 | DPRINTF(sc, ATH_DBG_FATAL, | 2002 | ath_print(common, ATH_DBG_FATAL, |
1664 | "Unable to reset hardware; reset status %d\n", r); | 2003 | "Unable to reset hardware; reset status %d\n", r); |
1665 | spin_unlock_bh(&sc->sc_resetlock); | 2004 | spin_unlock_bh(&sc->sc_resetlock); |
1666 | 2005 | ||
1667 | if (ath_startrecv(sc) != 0) | 2006 | if (ath_startrecv(sc) != 0) |
1668 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); | 2007 | ath_print(common, ATH_DBG_FATAL, |
2008 | "Unable to start recv logic\n"); | ||
1669 | 2009 | ||
1670 | /* | 2010 | /* |
1671 | * We may be doing a reset in response to a request | 2011 | * We may be doing a reset in response to a request |
@@ -1708,19 +2048,20 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
1708 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) | 2048 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) |
1709 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) | 2049 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) |
1710 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) | 2050 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) |
1711 | 2051 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | |
1712 | struct ath_desc *ds; | 2052 | struct ath_desc *ds; |
1713 | struct ath_buf *bf; | 2053 | struct ath_buf *bf; |
1714 | int i, bsize, error; | 2054 | int i, bsize, error; |
1715 | 2055 | ||
1716 | DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", | 2056 | ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", |
1717 | name, nbuf, ndesc); | 2057 | name, nbuf, ndesc); |
1718 | 2058 | ||
1719 | INIT_LIST_HEAD(head); | 2059 | INIT_LIST_HEAD(head); |
1720 | /* ath_desc must be a multiple of DWORDs */ | 2060 | /* ath_desc must be a multiple of DWORDs */ |
1721 | if ((sizeof(struct ath_desc) % 4) != 0) { | 2061 | if ((sizeof(struct ath_desc) % 4) != 0) { |
1722 | DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n"); | 2062 | ath_print(common, ATH_DBG_FATAL, |
1723 | ASSERT((sizeof(struct ath_desc) % 4) == 0); | 2063 | "ath_desc not DWORD aligned\n"); |
2064 | BUG_ON((sizeof(struct ath_desc) % 4) != 0); | ||
1724 | error = -ENOMEM; | 2065 | error = -ENOMEM; |
1725 | goto fail; | 2066 | goto fail; |
1726 | } | 2067 | } |
@@ -1753,9 +2094,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
1753 | goto fail; | 2094 | goto fail; |
1754 | } | 2095 | } |
1755 | ds = dd->dd_desc; | 2096 | ds = dd->dd_desc; |
1756 | DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", | 2097 | ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", |
1757 | name, ds, (u32) dd->dd_desc_len, | 2098 | name, ds, (u32) dd->dd_desc_len, |
1758 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | 2099 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); |
1759 | 2100 | ||
1760 | /* allocate buffers */ | 2101 | /* allocate buffers */ |
1761 | bsize = sizeof(struct ath_buf) * nbuf; | 2102 | bsize = sizeof(struct ath_buf) * nbuf; |
@@ -1778,7 +2119,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
1778 | * descriptor fetch. | 2119 | * descriptor fetch. |
1779 | */ | 2120 | */ |
1780 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | 2121 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { |
1781 | ASSERT((caddr_t) bf->bf_desc < | 2122 | BUG_ON((caddr_t) bf->bf_desc >= |
1782 | ((caddr_t) dd->dd_desc + | 2123 | ((caddr_t) dd->dd_desc + |
1783 | dd->dd_desc_len)); | 2124 | dd->dd_desc_len)); |
1784 | 2125 | ||
@@ -1882,31 +2223,50 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
1882 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; | 2223 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; |
1883 | } | 2224 | } |
1884 | 2225 | ||
1885 | sc->tx_chan_width = ATH9K_HT_MACMODE_20; | 2226 | if (conf_is_ht(conf)) |
1886 | |||
1887 | if (conf_is_ht(conf)) { | ||
1888 | if (conf_is_ht40(conf)) | ||
1889 | sc->tx_chan_width = ATH9K_HT_MACMODE_2040; | ||
1890 | |||
1891 | ichan->chanmode = ath_get_extchanmode(sc, chan, | 2227 | ichan->chanmode = ath_get_extchanmode(sc, chan, |
1892 | conf->channel_type); | 2228 | conf->channel_type); |
1893 | } | ||
1894 | } | 2229 | } |
1895 | 2230 | ||
1896 | /**********************/ | 2231 | /**********************/ |
1897 | /* mac80211 callbacks */ | 2232 | /* mac80211 callbacks */ |
1898 | /**********************/ | 2233 | /**********************/ |
1899 | 2234 | ||
2235 | /* | ||
2236 | * (Re)start btcoex timers | ||
2237 | */ | ||
2238 | static void ath9k_btcoex_timer_resume(struct ath_softc *sc) | ||
2239 | { | ||
2240 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
2241 | struct ath_hw *ah = sc->sc_ah; | ||
2242 | |||
2243 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
2244 | "Starting btcoex timers"); | ||
2245 | |||
2246 | /* make sure duty cycle timer is also stopped when resuming */ | ||
2247 | if (btcoex->hw_timer_enabled) | ||
2248 | ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); | ||
2249 | |||
2250 | btcoex->bt_priority_cnt = 0; | ||
2251 | btcoex->bt_priority_time = jiffies; | ||
2252 | sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; | ||
2253 | |||
2254 | mod_timer(&btcoex->period_timer, jiffies); | ||
2255 | } | ||
2256 | |||
1900 | static int ath9k_start(struct ieee80211_hw *hw) | 2257 | static int ath9k_start(struct ieee80211_hw *hw) |
1901 | { | 2258 | { |
1902 | struct ath_wiphy *aphy = hw->priv; | 2259 | struct ath_wiphy *aphy = hw->priv; |
1903 | struct ath_softc *sc = aphy->sc; | 2260 | struct ath_softc *sc = aphy->sc; |
2261 | struct ath_hw *ah = sc->sc_ah; | ||
2262 | struct ath_common *common = ath9k_hw_common(ah); | ||
1904 | struct ieee80211_channel *curchan = hw->conf.channel; | 2263 | struct ieee80211_channel *curchan = hw->conf.channel; |
1905 | struct ath9k_channel *init_channel; | 2264 | struct ath9k_channel *init_channel; |
1906 | int r; | 2265 | int r; |
1907 | 2266 | ||
1908 | DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with " | 2267 | ath_print(common, ATH_DBG_CONFIG, |
1909 | "initial channel: %d MHz\n", curchan->center_freq); | 2268 | "Starting driver with initial channel: %d MHz\n", |
2269 | curchan->center_freq); | ||
1910 | 2270 | ||
1911 | mutex_lock(&sc->mutex); | 2271 | mutex_lock(&sc->mutex); |
1912 | 2272 | ||
@@ -1938,7 +2298,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1938 | init_channel = ath_get_curchannel(sc, hw); | 2298 | init_channel = ath_get_curchannel(sc, hw); |
1939 | 2299 | ||
1940 | /* Reset SERDES registers */ | 2300 | /* Reset SERDES registers */ |
1941 | ath9k_hw_configpcipowersave(sc->sc_ah, 0, 0); | 2301 | ath9k_hw_configpcipowersave(ah, 0, 0); |
1942 | 2302 | ||
1943 | /* | 2303 | /* |
1944 | * The basic interface to setting the hardware in a good | 2304 | * The basic interface to setting the hardware in a good |
@@ -1948,12 +2308,12 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1948 | * and then setup of the interrupt mask. | 2308 | * and then setup of the interrupt mask. |
1949 | */ | 2309 | */ |
1950 | spin_lock_bh(&sc->sc_resetlock); | 2310 | spin_lock_bh(&sc->sc_resetlock); |
1951 | r = ath9k_hw_reset(sc->sc_ah, init_channel, false); | 2311 | r = ath9k_hw_reset(ah, init_channel, false); |
1952 | if (r) { | 2312 | if (r) { |
1953 | DPRINTF(sc, ATH_DBG_FATAL, | 2313 | ath_print(common, ATH_DBG_FATAL, |
1954 | "Unable to reset hardware; reset status %d " | 2314 | "Unable to reset hardware; reset status %d " |
1955 | "(freq %u MHz)\n", r, | 2315 | "(freq %u MHz)\n", r, |
1956 | curchan->center_freq); | 2316 | curchan->center_freq); |
1957 | spin_unlock_bh(&sc->sc_resetlock); | 2317 | spin_unlock_bh(&sc->sc_resetlock); |
1958 | goto mutex_unlock; | 2318 | goto mutex_unlock; |
1959 | } | 2319 | } |
@@ -1973,7 +2333,8 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1973 | * here except setup the interrupt mask. | 2333 | * here except setup the interrupt mask. |
1974 | */ | 2334 | */ |
1975 | if (ath_startrecv(sc) != 0) { | 2335 | if (ath_startrecv(sc) != 0) { |
1976 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); | 2336 | ath_print(common, ATH_DBG_FATAL, |
2337 | "Unable to start recv logic\n"); | ||
1977 | r = -EIO; | 2338 | r = -EIO; |
1978 | goto mutex_unlock; | 2339 | goto mutex_unlock; |
1979 | } | 2340 | } |
@@ -1983,10 +2344,10 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1983 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | 2344 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN |
1984 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; | 2345 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; |
1985 | 2346 | ||
1986 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_GTT) | 2347 | if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) |
1987 | sc->imask |= ATH9K_INT_GTT; | 2348 | sc->imask |= ATH9K_INT_GTT; |
1988 | 2349 | ||
1989 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 2350 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
1990 | sc->imask |= ATH9K_INT_CST; | 2351 | sc->imask |= ATH9K_INT_CST; |
1991 | 2352 | ||
1992 | ath_cache_conf_rate(sc, &hw->conf); | 2353 | ath_cache_conf_rate(sc, &hw->conf); |
@@ -1995,21 +2356,22 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1995 | 2356 | ||
1996 | /* Disable BMISS interrupt when we're not associated */ | 2357 | /* Disable BMISS interrupt when we're not associated */ |
1997 | sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | 2358 | sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); |
1998 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 2359 | ath9k_hw_set_interrupts(ah, sc->imask); |
1999 | 2360 | ||
2000 | ieee80211_wake_queues(hw); | 2361 | ieee80211_wake_queues(hw); |
2001 | 2362 | ||
2002 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 2363 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
2003 | 2364 | ||
2004 | if ((sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) && | 2365 | if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && |
2005 | !(sc->sc_flags & SC_OP_BTCOEX_ENABLED)) { | 2366 | !ah->btcoex_hw.enabled) { |
2006 | ath_btcoex_set_weight(&sc->btcoex_info, AR_BT_COEX_WGHT, | 2367 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, |
2007 | AR_STOMP_LOW_WLAN_WGHT); | 2368 | AR_STOMP_LOW_WLAN_WGHT); |
2008 | ath9k_hw_btcoex_enable(sc->sc_ah); | 2369 | ath9k_hw_btcoex_enable(ah); |
2009 | 2370 | ||
2010 | ath_pcie_aspm_disable(sc); | 2371 | if (common->bus_ops->bt_coex_prep) |
2011 | if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) | 2372 | common->bus_ops->bt_coex_prep(common); |
2012 | ath_btcoex_timer_resume(sc, &sc->btcoex_info); | 2373 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
2374 | ath9k_btcoex_timer_resume(sc); | ||
2013 | } | 2375 | } |
2014 | 2376 | ||
2015 | mutex_unlock: | 2377 | mutex_unlock: |
@@ -2024,12 +2386,14 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2024 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2386 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2025 | struct ath_wiphy *aphy = hw->priv; | 2387 | struct ath_wiphy *aphy = hw->priv; |
2026 | struct ath_softc *sc = aphy->sc; | 2388 | struct ath_softc *sc = aphy->sc; |
2389 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2027 | struct ath_tx_control txctl; | 2390 | struct ath_tx_control txctl; |
2028 | int hdrlen, padsize; | 2391 | int hdrlen, padsize; |
2029 | 2392 | ||
2030 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { | 2393 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { |
2031 | printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state " | 2394 | ath_print(common, ATH_DBG_XMIT, |
2032 | "%d\n", wiphy_name(hw->wiphy), aphy->state); | 2395 | "ath9k: %s: TX in unexpected wiphy state " |
2396 | "%d\n", wiphy_name(hw->wiphy), aphy->state); | ||
2033 | goto exit; | 2397 | goto exit; |
2034 | } | 2398 | } |
2035 | 2399 | ||
@@ -2042,8 +2406,8 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2042 | if (ieee80211_is_data(hdr->frame_control) && | 2406 | if (ieee80211_is_data(hdr->frame_control) && |
2043 | !ieee80211_is_nullfunc(hdr->frame_control) && | 2407 | !ieee80211_is_nullfunc(hdr->frame_control) && |
2044 | !ieee80211_has_pm(hdr->frame_control)) { | 2408 | !ieee80211_has_pm(hdr->frame_control)) { |
2045 | DPRINTF(sc, ATH_DBG_PS, "Add PM=1 for a TX frame " | 2409 | ath_print(common, ATH_DBG_PS, "Add PM=1 for a TX frame " |
2046 | "while in PS mode\n"); | 2410 | "while in PS mode\n"); |
2047 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); | 2411 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
2048 | } | 2412 | } |
2049 | } | 2413 | } |
@@ -2058,11 +2422,12 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2058 | ath9k_ps_wakeup(sc); | 2422 | ath9k_ps_wakeup(sc); |
2059 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 2423 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
2060 | if (ieee80211_is_pspoll(hdr->frame_control)) { | 2424 | if (ieee80211_is_pspoll(hdr->frame_control)) { |
2061 | DPRINTF(sc, ATH_DBG_PS, "Sending PS-Poll to pick a " | 2425 | ath_print(common, ATH_DBG_PS, |
2062 | "buffered frame\n"); | 2426 | "Sending PS-Poll to pick a buffered frame\n"); |
2063 | sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA; | 2427 | sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA; |
2064 | } else { | 2428 | } else { |
2065 | DPRINTF(sc, ATH_DBG_PS, "Wake up to complete TX\n"); | 2429 | ath_print(common, ATH_DBG_PS, |
2430 | "Wake up to complete TX\n"); | ||
2066 | sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK; | 2431 | sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK; |
2067 | } | 2432 | } |
2068 | /* | 2433 | /* |
@@ -2104,10 +2469,10 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2104 | if (!txctl.txq) | 2469 | if (!txctl.txq) |
2105 | goto exit; | 2470 | goto exit; |
2106 | 2471 | ||
2107 | DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); | 2472 | ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); |
2108 | 2473 | ||
2109 | if (ath_tx_start(hw, skb, &txctl) != 0) { | 2474 | if (ath_tx_start(hw, skb, &txctl) != 0) { |
2110 | DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n"); | 2475 | ath_print(common, ATH_DBG_XMIT, "TX failed\n"); |
2111 | goto exit; | 2476 | goto exit; |
2112 | } | 2477 | } |
2113 | 2478 | ||
@@ -2117,10 +2482,28 @@ exit: | |||
2117 | return 0; | 2482 | return 0; |
2118 | } | 2483 | } |
2119 | 2484 | ||
2485 | /* | ||
2486 | * Pause btcoex timer and bt duty cycle timer | ||
2487 | */ | ||
2488 | static void ath9k_btcoex_timer_pause(struct ath_softc *sc) | ||
2489 | { | ||
2490 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
2491 | struct ath_hw *ah = sc->sc_ah; | ||
2492 | |||
2493 | del_timer_sync(&btcoex->period_timer); | ||
2494 | |||
2495 | if (btcoex->hw_timer_enabled) | ||
2496 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | ||
2497 | |||
2498 | btcoex->hw_timer_enabled = false; | ||
2499 | } | ||
2500 | |||
2120 | static void ath9k_stop(struct ieee80211_hw *hw) | 2501 | static void ath9k_stop(struct ieee80211_hw *hw) |
2121 | { | 2502 | { |
2122 | struct ath_wiphy *aphy = hw->priv; | 2503 | struct ath_wiphy *aphy = hw->priv; |
2123 | struct ath_softc *sc = aphy->sc; | 2504 | struct ath_softc *sc = aphy->sc; |
2505 | struct ath_hw *ah = sc->sc_ah; | ||
2506 | struct ath_common *common = ath9k_hw_common(ah); | ||
2124 | 2507 | ||
2125 | mutex_lock(&sc->mutex); | 2508 | mutex_lock(&sc->mutex); |
2126 | 2509 | ||
@@ -2135,7 +2518,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2135 | } | 2518 | } |
2136 | 2519 | ||
2137 | if (sc->sc_flags & SC_OP_INVALID) { | 2520 | if (sc->sc_flags & SC_OP_INVALID) { |
2138 | DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); | 2521 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); |
2139 | mutex_unlock(&sc->mutex); | 2522 | mutex_unlock(&sc->mutex); |
2140 | return; | 2523 | return; |
2141 | } | 2524 | } |
@@ -2145,33 +2528,33 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2145 | return; /* another wiphy still in use */ | 2528 | return; /* another wiphy still in use */ |
2146 | } | 2529 | } |
2147 | 2530 | ||
2148 | if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) { | 2531 | if (ah->btcoex_hw.enabled) { |
2149 | ath9k_hw_btcoex_disable(sc->sc_ah); | 2532 | ath9k_hw_btcoex_disable(ah); |
2150 | if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) | 2533 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
2151 | ath_btcoex_timer_pause(sc, &sc->btcoex_info); | 2534 | ath9k_btcoex_timer_pause(sc); |
2152 | } | 2535 | } |
2153 | 2536 | ||
2154 | /* make sure h/w will not generate any interrupt | 2537 | /* make sure h/w will not generate any interrupt |
2155 | * before setting the invalid flag. */ | 2538 | * before setting the invalid flag. */ |
2156 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 2539 | ath9k_hw_set_interrupts(ah, 0); |
2157 | 2540 | ||
2158 | if (!(sc->sc_flags & SC_OP_INVALID)) { | 2541 | if (!(sc->sc_flags & SC_OP_INVALID)) { |
2159 | ath_drain_all_txq(sc, false); | 2542 | ath_drain_all_txq(sc, false); |
2160 | ath_stoprecv(sc); | 2543 | ath_stoprecv(sc); |
2161 | ath9k_hw_phy_disable(sc->sc_ah); | 2544 | ath9k_hw_phy_disable(ah); |
2162 | } else | 2545 | } else |
2163 | sc->rx.rxlink = NULL; | 2546 | sc->rx.rxlink = NULL; |
2164 | 2547 | ||
2165 | /* disable HAL and put h/w to sleep */ | 2548 | /* disable HAL and put h/w to sleep */ |
2166 | ath9k_hw_disable(sc->sc_ah); | 2549 | ath9k_hw_disable(ah); |
2167 | ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1); | 2550 | ath9k_hw_configpcipowersave(ah, 1, 1); |
2168 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); | 2551 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); |
2169 | 2552 | ||
2170 | sc->sc_flags |= SC_OP_INVALID; | 2553 | sc->sc_flags |= SC_OP_INVALID; |
2171 | 2554 | ||
2172 | mutex_unlock(&sc->mutex); | 2555 | mutex_unlock(&sc->mutex); |
2173 | 2556 | ||
2174 | DPRINTF(sc, ATH_DBG_CONFIG, "Driver halt\n"); | 2557 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); |
2175 | } | 2558 | } |
2176 | 2559 | ||
2177 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 2560 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
@@ -2179,6 +2562,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2179 | { | 2562 | { |
2180 | struct ath_wiphy *aphy = hw->priv; | 2563 | struct ath_wiphy *aphy = hw->priv; |
2181 | struct ath_softc *sc = aphy->sc; | 2564 | struct ath_softc *sc = aphy->sc; |
2565 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2182 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 2566 | struct ath_vif *avp = (void *)conf->vif->drv_priv; |
2183 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; | 2567 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; |
2184 | int ret = 0; | 2568 | int ret = 0; |
@@ -2205,13 +2589,14 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2205 | ic_opmode = conf->type; | 2589 | ic_opmode = conf->type; |
2206 | break; | 2590 | break; |
2207 | default: | 2591 | default: |
2208 | DPRINTF(sc, ATH_DBG_FATAL, | 2592 | ath_print(common, ATH_DBG_FATAL, |
2209 | "Interface type %d not yet supported\n", conf->type); | 2593 | "Interface type %d not yet supported\n", conf->type); |
2210 | ret = -EOPNOTSUPP; | 2594 | ret = -EOPNOTSUPP; |
2211 | goto out; | 2595 | goto out; |
2212 | } | 2596 | } |
2213 | 2597 | ||
2214 | DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode); | 2598 | ath_print(common, ATH_DBG_CONFIG, |
2599 | "Attach a VIF of type: %d\n", ic_opmode); | ||
2215 | 2600 | ||
2216 | /* Set the VIF opmode */ | 2601 | /* Set the VIF opmode */ |
2217 | avp->av_opmode = ic_opmode; | 2602 | avp->av_opmode = ic_opmode; |
@@ -2261,10 +2646,11 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
2261 | { | 2646 | { |
2262 | struct ath_wiphy *aphy = hw->priv; | 2647 | struct ath_wiphy *aphy = hw->priv; |
2263 | struct ath_softc *sc = aphy->sc; | 2648 | struct ath_softc *sc = aphy->sc; |
2649 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2264 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 2650 | struct ath_vif *avp = (void *)conf->vif->drv_priv; |
2265 | int i; | 2651 | int i; |
2266 | 2652 | ||
2267 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n"); | 2653 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); |
2268 | 2654 | ||
2269 | mutex_lock(&sc->mutex); | 2655 | mutex_lock(&sc->mutex); |
2270 | 2656 | ||
@@ -2299,6 +2685,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2299 | { | 2685 | { |
2300 | struct ath_wiphy *aphy = hw->priv; | 2686 | struct ath_wiphy *aphy = hw->priv; |
2301 | struct ath_softc *sc = aphy->sc; | 2687 | struct ath_softc *sc = aphy->sc; |
2688 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2302 | struct ieee80211_conf *conf = &hw->conf; | 2689 | struct ieee80211_conf *conf = &hw->conf; |
2303 | struct ath_hw *ah = sc->sc_ah; | 2690 | struct ath_hw *ah = sc->sc_ah; |
2304 | bool all_wiphys_idle = false, disable_radio = false; | 2691 | bool all_wiphys_idle = false, disable_radio = false; |
@@ -2318,8 +2705,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2318 | } | 2705 | } |
2319 | else if (all_wiphys_idle) { | 2706 | else if (all_wiphys_idle) { |
2320 | ath_radio_enable(sc); | 2707 | ath_radio_enable(sc); |
2321 | DPRINTF(sc, ATH_DBG_CONFIG, | 2708 | ath_print(common, ATH_DBG_CONFIG, |
2322 | "not-idle: enabling radio\n"); | 2709 | "not-idle: enabling radio\n"); |
2323 | } | 2710 | } |
2324 | } | 2711 | } |
2325 | 2712 | ||
@@ -2337,7 +2724,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2337 | sc->ps_enabled = true; | 2724 | sc->ps_enabled = true; |
2338 | } else { | 2725 | } else { |
2339 | sc->ps_enabled = false; | 2726 | sc->ps_enabled = false; |
2340 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | 2727 | ath9k_setpower(sc, ATH9K_PM_AWAKE); |
2341 | if (!(ah->caps.hw_caps & | 2728 | if (!(ah->caps.hw_caps & |
2342 | ATH9K_HW_CAP_AUTOSLEEP)) { | 2729 | ATH9K_HW_CAP_AUTOSLEEP)) { |
2343 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 2730 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
@@ -2372,8 +2759,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2372 | goto skip_chan_change; | 2759 | goto skip_chan_change; |
2373 | } | 2760 | } |
2374 | 2761 | ||
2375 | DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", | 2762 | ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", |
2376 | curchan->center_freq); | 2763 | curchan->center_freq); |
2377 | 2764 | ||
2378 | /* XXX: remove me eventualy */ | 2765 | /* XXX: remove me eventualy */ |
2379 | ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); | 2766 | ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); |
@@ -2381,7 +2768,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2381 | ath_update_chainmask(sc, conf_is_ht(conf)); | 2768 | ath_update_chainmask(sc, conf_is_ht(conf)); |
2382 | 2769 | ||
2383 | if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { | 2770 | if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { |
2384 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); | 2771 | ath_print(common, ATH_DBG_FATAL, |
2772 | "Unable to set channel\n"); | ||
2385 | mutex_unlock(&sc->mutex); | 2773 | mutex_unlock(&sc->mutex); |
2386 | return -EINVAL; | 2774 | return -EINVAL; |
2387 | } | 2775 | } |
@@ -2392,7 +2780,7 @@ skip_chan_change: | |||
2392 | sc->config.txpowlimit = 2 * conf->power_level; | 2780 | sc->config.txpowlimit = 2 * conf->power_level; |
2393 | 2781 | ||
2394 | if (disable_radio) { | 2782 | if (disable_radio) { |
2395 | DPRINTF(sc, ATH_DBG_CONFIG, "idle: disabling radio\n"); | 2783 | ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); |
2396 | ath_radio_disable(sc); | 2784 | ath_radio_disable(sc); |
2397 | } | 2785 | } |
2398 | 2786 | ||
@@ -2429,7 +2817,8 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, | |||
2429 | ath9k_hw_setrxfilter(sc->sc_ah, rfilt); | 2817 | ath9k_hw_setrxfilter(sc->sc_ah, rfilt); |
2430 | ath9k_ps_restore(sc); | 2818 | ath9k_ps_restore(sc); |
2431 | 2819 | ||
2432 | DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", rfilt); | 2820 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, |
2821 | "Set HW RX filter: 0x%x\n", rfilt); | ||
2433 | } | 2822 | } |
2434 | 2823 | ||
2435 | static void ath9k_sta_notify(struct ieee80211_hw *hw, | 2824 | static void ath9k_sta_notify(struct ieee80211_hw *hw, |
@@ -2457,6 +2846,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2457 | { | 2846 | { |
2458 | struct ath_wiphy *aphy = hw->priv; | 2847 | struct ath_wiphy *aphy = hw->priv; |
2459 | struct ath_softc *sc = aphy->sc; | 2848 | struct ath_softc *sc = aphy->sc; |
2849 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2460 | struct ath9k_tx_queue_info qi; | 2850 | struct ath9k_tx_queue_info qi; |
2461 | int ret = 0, qnum; | 2851 | int ret = 0, qnum; |
2462 | 2852 | ||
@@ -2473,15 +2863,15 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2473 | qi.tqi_burstTime = params->txop; | 2863 | qi.tqi_burstTime = params->txop; |
2474 | qnum = ath_get_hal_qnum(queue, sc); | 2864 | qnum = ath_get_hal_qnum(queue, sc); |
2475 | 2865 | ||
2476 | DPRINTF(sc, ATH_DBG_CONFIG, | 2866 | ath_print(common, ATH_DBG_CONFIG, |
2477 | "Configure tx [queue/halq] [%d/%d], " | 2867 | "Configure tx [queue/halq] [%d/%d], " |
2478 | "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", | 2868 | "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", |
2479 | queue, qnum, params->aifs, params->cw_min, | 2869 | queue, qnum, params->aifs, params->cw_min, |
2480 | params->cw_max, params->txop); | 2870 | params->cw_max, params->txop); |
2481 | 2871 | ||
2482 | ret = ath_txq_update(sc, qnum, &qi); | 2872 | ret = ath_txq_update(sc, qnum, &qi); |
2483 | if (ret) | 2873 | if (ret) |
2484 | DPRINTF(sc, ATH_DBG_FATAL, "TXQ Update failed\n"); | 2874 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); |
2485 | 2875 | ||
2486 | mutex_unlock(&sc->mutex); | 2876 | mutex_unlock(&sc->mutex); |
2487 | 2877 | ||
@@ -2496,6 +2886,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
2496 | { | 2886 | { |
2497 | struct ath_wiphy *aphy = hw->priv; | 2887 | struct ath_wiphy *aphy = hw->priv; |
2498 | struct ath_softc *sc = aphy->sc; | 2888 | struct ath_softc *sc = aphy->sc; |
2889 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2499 | int ret = 0; | 2890 | int ret = 0; |
2500 | 2891 | ||
2501 | if (modparam_nohwcrypt) | 2892 | if (modparam_nohwcrypt) |
@@ -2503,7 +2894,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
2503 | 2894 | ||
2504 | mutex_lock(&sc->mutex); | 2895 | mutex_lock(&sc->mutex); |
2505 | ath9k_ps_wakeup(sc); | 2896 | ath9k_ps_wakeup(sc); |
2506 | DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n"); | 2897 | ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); |
2507 | 2898 | ||
2508 | switch (cmd) { | 2899 | switch (cmd) { |
2509 | case SET_KEY: | 2900 | case SET_KEY: |
@@ -2540,6 +2931,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2540 | struct ath_wiphy *aphy = hw->priv; | 2931 | struct ath_wiphy *aphy = hw->priv; |
2541 | struct ath_softc *sc = aphy->sc; | 2932 | struct ath_softc *sc = aphy->sc; |
2542 | struct ath_hw *ah = sc->sc_ah; | 2933 | struct ath_hw *ah = sc->sc_ah; |
2934 | struct ath_common *common = ath9k_hw_common(ah); | ||
2543 | struct ath_vif *avp = (void *)vif->drv_priv; | 2935 | struct ath_vif *avp = (void *)vif->drv_priv; |
2544 | u32 rfilt = 0; | 2936 | u32 rfilt = 0; |
2545 | int error, i; | 2937 | int error, i; |
@@ -2555,9 +2947,9 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2555 | ah->opmode != NL80211_IFTYPE_AP) { | 2947 | ah->opmode != NL80211_IFTYPE_AP) { |
2556 | ah->opmode = NL80211_IFTYPE_STATION; | 2948 | ah->opmode = NL80211_IFTYPE_STATION; |
2557 | ath9k_hw_setopmode(ah); | 2949 | ath9k_hw_setopmode(ah); |
2558 | memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); | 2950 | memcpy(common->curbssid, common->macaddr, ETH_ALEN); |
2559 | sc->curaid = 0; | 2951 | common->curaid = 0; |
2560 | ath9k_hw_write_associd(sc); | 2952 | ath9k_hw_write_associd(ah); |
2561 | /* Request full reset to get hw opmode changed properly */ | 2953 | /* Request full reset to get hw opmode changed properly */ |
2562 | sc->sc_flags |= SC_OP_FULL_RESET; | 2954 | sc->sc_flags |= SC_OP_FULL_RESET; |
2563 | } | 2955 | } |
@@ -2569,17 +2961,17 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2569 | case NL80211_IFTYPE_ADHOC: | 2961 | case NL80211_IFTYPE_ADHOC: |
2570 | case NL80211_IFTYPE_MESH_POINT: | 2962 | case NL80211_IFTYPE_MESH_POINT: |
2571 | /* Set BSSID */ | 2963 | /* Set BSSID */ |
2572 | memcpy(sc->curbssid, bss_conf->bssid, ETH_ALEN); | 2964 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
2573 | memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); | 2965 | memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); |
2574 | sc->curaid = 0; | 2966 | common->curaid = 0; |
2575 | ath9k_hw_write_associd(sc); | 2967 | ath9k_hw_write_associd(ah); |
2576 | 2968 | ||
2577 | /* Set aggregation protection mode parameters */ | 2969 | /* Set aggregation protection mode parameters */ |
2578 | sc->config.ath_aggr_prot = 0; | 2970 | sc->config.ath_aggr_prot = 0; |
2579 | 2971 | ||
2580 | DPRINTF(sc, ATH_DBG_CONFIG, | 2972 | ath_print(common, ATH_DBG_CONFIG, |
2581 | "RX filter 0x%x bssid %pM aid 0x%x\n", | 2973 | "RX filter 0x%x bssid %pM aid 0x%x\n", |
2582 | rfilt, sc->curbssid, sc->curaid); | 2974 | rfilt, common->curbssid, common->curaid); |
2583 | 2975 | ||
2584 | /* need to reconfigure the beacon */ | 2976 | /* need to reconfigure the beacon */ |
2585 | sc->sc_flags &= ~SC_OP_BEACONS ; | 2977 | sc->sc_flags &= ~SC_OP_BEACONS ; |
@@ -2618,7 +3010,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2618 | if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) | 3010 | if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) |
2619 | ath9k_hw_keysetmac(sc->sc_ah, | 3011 | ath9k_hw_keysetmac(sc->sc_ah, |
2620 | (u16)i, | 3012 | (u16)i, |
2621 | sc->curbssid); | 3013 | common->curbssid); |
2622 | } | 3014 | } |
2623 | 3015 | ||
2624 | /* Only legacy IBSS for now */ | 3016 | /* Only legacy IBSS for now */ |
@@ -2626,8 +3018,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2626 | ath_update_chainmask(sc, 0); | 3018 | ath_update_chainmask(sc, 0); |
2627 | 3019 | ||
2628 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 3020 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
2629 | DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", | 3021 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", |
2630 | bss_conf->use_short_preamble); | 3022 | bss_conf->use_short_preamble); |
2631 | if (bss_conf->use_short_preamble) | 3023 | if (bss_conf->use_short_preamble) |
2632 | sc->sc_flags |= SC_OP_PREAMBLE_SHORT; | 3024 | sc->sc_flags |= SC_OP_PREAMBLE_SHORT; |
2633 | else | 3025 | else |
@@ -2635,8 +3027,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2635 | } | 3027 | } |
2636 | 3028 | ||
2637 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 3029 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
2638 | DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", | 3030 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", |
2639 | bss_conf->use_cts_prot); | 3031 | bss_conf->use_cts_prot); |
2640 | if (bss_conf->use_cts_prot && | 3032 | if (bss_conf->use_cts_prot && |
2641 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) | 3033 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) |
2642 | sc->sc_flags |= SC_OP_PROTECT_ENABLE; | 3034 | sc->sc_flags |= SC_OP_PROTECT_ENABLE; |
@@ -2645,7 +3037,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2645 | } | 3037 | } |
2646 | 3038 | ||
2647 | if (changed & BSS_CHANGED_ASSOC) { | 3039 | if (changed & BSS_CHANGED_ASSOC) { |
2648 | DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", | 3040 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", |
2649 | bss_conf->assoc); | 3041 | bss_conf->assoc); |
2650 | ath9k_bss_assoc_info(sc, vif, bss_conf); | 3042 | ath9k_bss_assoc_info(sc, vif, bss_conf); |
2651 | } | 3043 | } |
@@ -2694,7 +3086,11 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw) | |||
2694 | struct ath_softc *sc = aphy->sc; | 3086 | struct ath_softc *sc = aphy->sc; |
2695 | 3087 | ||
2696 | mutex_lock(&sc->mutex); | 3088 | mutex_lock(&sc->mutex); |
3089 | |||
3090 | ath9k_ps_wakeup(sc); | ||
2697 | ath9k_hw_reset_tsf(sc->sc_ah); | 3091 | ath9k_hw_reset_tsf(sc->sc_ah); |
3092 | ath9k_ps_restore(sc); | ||
3093 | |||
2698 | mutex_unlock(&sc->mutex); | 3094 | mutex_unlock(&sc->mutex); |
2699 | } | 3095 | } |
2700 | 3096 | ||
@@ -2726,7 +3122,8 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
2726 | ath_tx_aggr_resume(sc, sta, tid); | 3122 | ath_tx_aggr_resume(sc, sta, tid); |
2727 | break; | 3123 | break; |
2728 | default: | 3124 | default: |
2729 | DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n"); | 3125 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
3126 | "Unknown AMPDU action\n"); | ||
2730 | } | 3127 | } |
2731 | 3128 | ||
2732 | return ret; | 3129 | return ret; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 903dd8ad9d43..63059b6a90da 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -31,8 +31,9 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = { | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | /* return bus cachesize in 4B word units */ | 33 | /* return bus cachesize in 4B word units */ |
34 | static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) | 34 | static void ath_pci_read_cachesize(struct ath_common *common, int *csz) |
35 | { | 35 | { |
36 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
36 | u8 u8tmp; | 37 | u8 u8tmp; |
37 | 38 | ||
38 | pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, &u8tmp); | 39 | pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, &u8tmp); |
@@ -48,8 +49,9 @@ static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) | |||
48 | *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ | 49 | *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ |
49 | } | 50 | } |
50 | 51 | ||
51 | static void ath_pci_cleanup(struct ath_softc *sc) | 52 | static void ath_pci_cleanup(struct ath_common *common) |
52 | { | 53 | { |
54 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
53 | struct pci_dev *pdev = to_pci_dev(sc->dev); | 55 | struct pci_dev *pdev = to_pci_dev(sc->dev); |
54 | 56 | ||
55 | pci_iounmap(pdev, sc->mem); | 57 | pci_iounmap(pdev, sc->mem); |
@@ -57,9 +59,11 @@ static void ath_pci_cleanup(struct ath_softc *sc) | |||
57 | pci_release_region(pdev, 0); | 59 | pci_release_region(pdev, 0); |
58 | } | 60 | } |
59 | 61 | ||
60 | static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) | 62 | static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) |
61 | { | 63 | { |
62 | (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); | 64 | struct ath_hw *ah = (struct ath_hw *) common->ah; |
65 | |||
66 | common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); | ||
63 | 67 | ||
64 | if (!ath9k_hw_wait(ah, | 68 | if (!ath9k_hw_wait(ah, |
65 | AR_EEPROM_STATUS_DATA, | 69 | AR_EEPROM_STATUS_DATA, |
@@ -69,16 +73,34 @@ static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) | |||
69 | return false; | 73 | return false; |
70 | } | 74 | } |
71 | 75 | ||
72 | *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), | 76 | *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), |
73 | AR_EEPROM_STATUS_DATA_VAL); | 77 | AR_EEPROM_STATUS_DATA_VAL); |
74 | 78 | ||
75 | return true; | 79 | return true; |
76 | } | 80 | } |
77 | 81 | ||
78 | static struct ath_bus_ops ath_pci_bus_ops = { | 82 | /* |
83 | * Bluetooth coexistance requires disabling ASPM. | ||
84 | */ | ||
85 | static void ath_pci_bt_coex_prep(struct ath_common *common) | ||
86 | { | ||
87 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
88 | struct pci_dev *pdev = to_pci_dev(sc->dev); | ||
89 | u8 aspm; | ||
90 | |||
91 | if (!pdev->is_pcie) | ||
92 | return; | ||
93 | |||
94 | pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); | ||
95 | aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1); | ||
96 | pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); | ||
97 | } | ||
98 | |||
99 | const static struct ath_bus_ops ath_pci_bus_ops = { | ||
79 | .read_cachesize = ath_pci_read_cachesize, | 100 | .read_cachesize = ath_pci_read_cachesize, |
80 | .cleanup = ath_pci_cleanup, | 101 | .cleanup = ath_pci_cleanup, |
81 | .eeprom_read = ath_pci_eeprom_read, | 102 | .eeprom_read = ath_pci_eeprom_read, |
103 | .bt_coex_prep = ath_pci_bt_coex_prep, | ||
82 | }; | 104 | }; |
83 | 105 | ||
84 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 106 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
@@ -177,10 +199,9 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
177 | sc->hw = hw; | 199 | sc->hw = hw; |
178 | sc->dev = &pdev->dev; | 200 | sc->dev = &pdev->dev; |
179 | sc->mem = mem; | 201 | sc->mem = mem; |
180 | sc->bus_ops = &ath_pci_bus_ops; | ||
181 | 202 | ||
182 | pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); | 203 | pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); |
183 | ret = ath_init_device(id->device, sc, subsysid); | 204 | ret = ath_init_device(id->device, sc, subsysid, &ath_pci_bus_ops); |
184 | if (ret) { | 205 | if (ret) { |
185 | dev_err(&pdev->dev, "failed to initialize device\n"); | 206 | dev_err(&pdev->dev, "failed to initialize device\n"); |
186 | goto bad3; | 207 | goto bad3; |
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c index 63bf9a307c6a..72a17c43a5a0 100644 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ b/drivers/net/wireless/ath/ath9k/phy.c | |||
@@ -14,7 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "hw.h" |
18 | 18 | ||
19 | void | 19 | void |
20 | ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, | 20 | ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, |
@@ -26,6 +26,7 @@ ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, | |||
26 | bool | 26 | bool |
27 | ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | 27 | ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) |
28 | { | 28 | { |
29 | struct ath_common *common = ath9k_hw_common(ah); | ||
29 | u32 channelSel = 0; | 30 | u32 channelSel = 0; |
30 | u32 bModeSynth = 0; | 31 | u32 bModeSynth = 0; |
31 | u32 aModeRefSel = 0; | 32 | u32 aModeRefSel = 0; |
@@ -46,8 +47,8 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
46 | channelSel = ((freq - 704) * 2 - 3040) / 10; | 47 | channelSel = ((freq - 704) * 2 - 3040) / 10; |
47 | bModeSynth = 1; | 48 | bModeSynth = 1; |
48 | } else { | 49 | } else { |
49 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 50 | ath_print(common, ATH_DBG_FATAL, |
50 | "Invalid channel %u MHz\n", freq); | 51 | "Invalid channel %u MHz\n", freq); |
51 | return false; | 52 | return false; |
52 | } | 53 | } |
53 | 54 | ||
@@ -79,8 +80,8 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
79 | channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); | 80 | channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); |
80 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); | 81 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); |
81 | } else { | 82 | } else { |
82 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 83 | ath_print(common, ATH_DBG_FATAL, |
83 | "Invalid channel %u MHz\n", freq); | 84 | "Invalid channel %u MHz\n", freq); |
84 | return false; | 85 | return false; |
85 | } | 86 | } |
86 | 87 | ||
@@ -112,20 +113,31 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, | |||
112 | 113 | ||
113 | if (freq < 4800) { | 114 | if (freq < 4800) { |
114 | u32 txctl; | 115 | u32 txctl; |
116 | int regWrites = 0; | ||
115 | 117 | ||
116 | bMode = 1; | 118 | bMode = 1; |
117 | fracMode = 1; | 119 | fracMode = 1; |
118 | aModeRefSel = 0; | 120 | aModeRefSel = 0; |
119 | channelSel = (freq * 0x10000) / 15; | 121 | channelSel = (freq * 0x10000) / 15; |
120 | 122 | ||
121 | txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); | 123 | if (AR_SREV_9287_11_OR_LATER(ah)) { |
122 | if (freq == 2484) { | 124 | if (freq == 2484) { |
123 | 125 | REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, | |
124 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | 126 | 1, regWrites); |
125 | txctl | AR_PHY_CCK_TX_CTRL_JAPAN); | 127 | } else { |
128 | REG_WRITE_ARRAY(&ah->iniCckfirNormal, | ||
129 | 1, regWrites); | ||
130 | } | ||
126 | } else { | 131 | } else { |
127 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | 132 | txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); |
128 | txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); | 133 | if (freq == 2484) { |
134 | /* Enable channel spreading for channel 14 */ | ||
135 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | ||
136 | txctl | AR_PHY_CCK_TX_CTRL_JAPAN); | ||
137 | } else { | ||
138 | REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, | ||
139 | txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); | ||
140 | } | ||
129 | } | 141 | } |
130 | } else { | 142 | } else { |
131 | bMode = 0; | 143 | bMode = 0; |
@@ -285,6 +297,8 @@ ath9k_hw_rf_free(struct ath_hw *ah) | |||
285 | 297 | ||
286 | bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) | 298 | bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) |
287 | { | 299 | { |
300 | struct ath_common *common = ath9k_hw_common(ah); | ||
301 | |||
288 | if (!AR_SREV_9280_10_OR_LATER(ah)) { | 302 | if (!AR_SREV_9280_10_OR_LATER(ah)) { |
289 | ah->analogBank0Data = | 303 | ah->analogBank0Data = |
290 | kzalloc((sizeof(u32) * | 304 | kzalloc((sizeof(u32) * |
@@ -315,8 +329,8 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) | |||
315 | || ah->analogBank6Data == NULL | 329 | || ah->analogBank6Data == NULL |
316 | || ah->analogBank6TPCData == NULL | 330 | || ah->analogBank6TPCData == NULL |
317 | || ah->analogBank7Data == NULL) { | 331 | || ah->analogBank7Data == NULL) { |
318 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 332 | ath_print(common, ATH_DBG_FATAL, |
319 | "Cannot allocate RF banks\n"); | 333 | "Cannot allocate RF banks\n"); |
320 | *status = -ENOMEM; | 334 | *status = -ENOMEM; |
321 | return false; | 335 | return false; |
322 | } | 336 | } |
@@ -326,8 +340,8 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) | |||
326 | ah->iniAddac.ia_rows * | 340 | ah->iniAddac.ia_rows * |
327 | ah->iniAddac.ia_columns), GFP_KERNEL); | 341 | ah->iniAddac.ia_columns), GFP_KERNEL); |
328 | if (ah->addac5416_21 == NULL) { | 342 | if (ah->addac5416_21 == NULL) { |
329 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 343 | ath_print(common, ATH_DBG_FATAL, |
330 | "Cannot allocate addac5416_21\n"); | 344 | "Cannot allocate addac5416_21\n"); |
331 | *status = -ENOMEM; | 345 | *status = -ENOMEM; |
332 | return false; | 346 | return false; |
333 | } | 347 | } |
@@ -336,8 +350,8 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) | |||
336 | kzalloc((sizeof(u32) * | 350 | kzalloc((sizeof(u32) * |
337 | ah->iniBank6.ia_rows), GFP_KERNEL); | 351 | ah->iniBank6.ia_rows), GFP_KERNEL); |
338 | if (ah->bank6Temp == NULL) { | 352 | if (ah->bank6Temp == NULL) { |
339 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 353 | ath_print(common, ATH_DBG_FATAL, |
340 | "Cannot allocate bank6Temp\n"); | 354 | "Cannot allocate bank6Temp\n"); |
341 | *status = -ENOMEM; | 355 | *status = -ENOMEM; |
342 | return false; | 356 | return false; |
343 | } | 357 | } |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index dfda6f444648..140fef74c666 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -45,6 +45,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
45 | #define AR_PHY_FC_DYN2040_EN 0x00000004 | 45 | #define AR_PHY_FC_DYN2040_EN 0x00000004 |
46 | #define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 | 46 | #define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 |
47 | #define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 | 47 | #define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 |
48 | /* For 25 MHz channel spacing -- not used but supported by hw */ | ||
48 | #define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 | 49 | #define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 |
49 | #define AR_PHY_FC_HT_EN 0x00000040 | 50 | #define AR_PHY_FC_HT_EN 0x00000040 |
50 | #define AR_PHY_FC_SHORT_GI_40 0x00000080 | 51 | #define AR_PHY_FC_SHORT_GI_40 0x00000080 |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 16a271787b85..063936423d86 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -425,7 +425,7 @@ static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv) | |||
425 | static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, | 425 | static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, |
426 | u8 index, int valid_tx_rate) | 426 | u8 index, int valid_tx_rate) |
427 | { | 427 | { |
428 | ASSERT(index <= ath_rc_priv->rate_table_size); | 428 | BUG_ON(index > ath_rc_priv->rate_table_size); |
429 | ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; | 429 | ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; |
430 | } | 430 | } |
431 | 431 | ||
@@ -1160,6 +1160,7 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, | |||
1160 | bool is_cw_40) | 1160 | bool is_cw_40) |
1161 | { | 1161 | { |
1162 | int mode = 0; | 1162 | int mode = 0; |
1163 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1163 | 1164 | ||
1164 | switch(band) { | 1165 | switch(band) { |
1165 | case IEEE80211_BAND_2GHZ: | 1166 | case IEEE80211_BAND_2GHZ: |
@@ -1177,13 +1178,14 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, | |||
1177 | mode = ATH9K_MODE_11NA_HT40PLUS; | 1178 | mode = ATH9K_MODE_11NA_HT40PLUS; |
1178 | break; | 1179 | break; |
1179 | default: | 1180 | default: |
1180 | DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n"); | 1181 | ath_print(common, ATH_DBG_CONFIG, "Invalid band\n"); |
1181 | return NULL; | 1182 | return NULL; |
1182 | } | 1183 | } |
1183 | 1184 | ||
1184 | BUG_ON(mode >= ATH9K_MODE_MAX); | 1185 | BUG_ON(mode >= ATH9K_MODE_MAX); |
1185 | 1186 | ||
1186 | DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode); | 1187 | ath_print(common, ATH_DBG_CONFIG, |
1188 | "Choosing rate table for mode: %d\n", mode); | ||
1187 | return sc->hw_rate_table[mode]; | 1189 | return sc->hw_rate_table[mode]; |
1188 | } | 1190 | } |
1189 | 1191 | ||
@@ -1194,11 +1196,13 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1194 | const struct ath_rate_table *rate_table) | 1196 | const struct ath_rate_table *rate_table) |
1195 | { | 1197 | { |
1196 | struct ath_rateset *rateset = &ath_rc_priv->neg_rates; | 1198 | struct ath_rateset *rateset = &ath_rc_priv->neg_rates; |
1199 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1197 | u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; | 1200 | u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; |
1198 | u8 i, j, k, hi = 0, hthi = 0; | 1201 | u8 i, j, k, hi = 0, hthi = 0; |
1199 | 1202 | ||
1200 | if (!rate_table) { | 1203 | if (!rate_table) { |
1201 | DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n"); | 1204 | ath_print(common, ATH_DBG_FATAL, |
1205 | "Rate table not initialized\n"); | ||
1202 | return; | 1206 | return; |
1203 | } | 1207 | } |
1204 | 1208 | ||
@@ -1239,7 +1243,7 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1239 | 1243 | ||
1240 | ath_rc_priv->rate_table_size = hi + 1; | 1244 | ath_rc_priv->rate_table_size = hi + 1; |
1241 | ath_rc_priv->rate_max_phy = 0; | 1245 | ath_rc_priv->rate_max_phy = 0; |
1242 | ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); | 1246 | BUG_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); |
1243 | 1247 | ||
1244 | for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { | 1248 | for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { |
1245 | for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) { | 1249 | for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) { |
@@ -1253,16 +1257,17 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1253 | 1257 | ||
1254 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1]; | 1258 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1]; |
1255 | } | 1259 | } |
1256 | ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); | 1260 | BUG_ON(ath_rc_priv->rate_table_size > RATE_TABLE_SIZE); |
1257 | ASSERT(k <= RATE_TABLE_SIZE); | 1261 | BUG_ON(k > RATE_TABLE_SIZE); |
1258 | 1262 | ||
1259 | ath_rc_priv->max_valid_rate = k; | 1263 | ath_rc_priv->max_valid_rate = k; |
1260 | ath_rc_sort_validrates(rate_table, ath_rc_priv); | 1264 | ath_rc_sort_validrates(rate_table, ath_rc_priv); |
1261 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; | 1265 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; |
1262 | sc->cur_rate_table = rate_table; | 1266 | sc->cur_rate_table = rate_table; |
1263 | 1267 | ||
1264 | DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n", | 1268 | ath_print(common, ATH_DBG_CONFIG, |
1265 | ath_rc_priv->ht_cap); | 1269 | "RC Initialized with capabilities: 0x%x\n", |
1270 | ath_rc_priv->ht_cap); | ||
1266 | } | 1271 | } |
1267 | 1272 | ||
1268 | static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, | 1273 | static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, |
@@ -1438,9 +1443,9 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | |||
1438 | oper_cw40, oper_sgi40); | 1443 | oper_cw40, oper_sgi40); |
1439 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); | 1444 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); |
1440 | 1445 | ||
1441 | DPRINTF(sc, ATH_DBG_CONFIG, | 1446 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, |
1442 | "Operating HT Bandwidth changed to: %d\n", | 1447 | "Operating HT Bandwidth changed to: %d\n", |
1443 | sc->hw->conf.channel_type); | 1448 | sc->hw->conf.channel_type); |
1444 | } | 1449 | } |
1445 | } | 1450 | } |
1446 | } | 1451 | } |
@@ -1463,8 +1468,8 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp | |||
1463 | 1468 | ||
1464 | rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); | 1469 | rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); |
1465 | if (!rate_priv) { | 1470 | if (!rate_priv) { |
1466 | DPRINTF(sc, ATH_DBG_FATAL, | 1471 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
1467 | "Unable to allocate private rc structure\n"); | 1472 | "Unable to allocate private rc structure\n"); |
1468 | return NULL; | 1473 | return NULL; |
1469 | } | 1474 | } |
1470 | 1475 | ||
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ec0abf823995..c880a55939bf 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -59,7 +59,7 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
59 | 59 | ||
60 | /* virtual addr of the beginning of the buffer. */ | 60 | /* virtual addr of the beginning of the buffer. */ |
61 | skb = bf->bf_mpdu; | 61 | skb = bf->bf_mpdu; |
62 | ASSERT(skb != NULL); | 62 | BUG_ON(skb == NULL); |
63 | ds->ds_vdata = skb->data; | 63 | ds->ds_vdata = skb->data; |
64 | 64 | ||
65 | /* setup rx descriptors. The rx.bufsize here tells the harware | 65 | /* setup rx descriptors. The rx.bufsize here tells the harware |
@@ -272,6 +272,8 @@ rx_next: | |||
272 | static void ath_opmode_init(struct ath_softc *sc) | 272 | static void ath_opmode_init(struct ath_softc *sc) |
273 | { | 273 | { |
274 | struct ath_hw *ah = sc->sc_ah; | 274 | struct ath_hw *ah = sc->sc_ah; |
275 | struct ath_common *common = ath9k_hw_common(ah); | ||
276 | |||
275 | u32 rfilt, mfilt[2]; | 277 | u32 rfilt, mfilt[2]; |
276 | 278 | ||
277 | /* configure rx filter */ | 279 | /* configure rx filter */ |
@@ -280,13 +282,13 @@ static void ath_opmode_init(struct ath_softc *sc) | |||
280 | 282 | ||
281 | /* configure bssid mask */ | 283 | /* configure bssid mask */ |
282 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 284 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) |
283 | ath9k_hw_setbssidmask(sc); | 285 | ath_hw_setbssidmask(common); |
284 | 286 | ||
285 | /* configure operational mode */ | 287 | /* configure operational mode */ |
286 | ath9k_hw_setopmode(ah); | 288 | ath9k_hw_setopmode(ah); |
287 | 289 | ||
288 | /* Handle any link-level address change. */ | 290 | /* Handle any link-level address change. */ |
289 | ath9k_hw_setmac(ah, sc->sc_ah->macaddr); | 291 | ath9k_hw_setmac(ah, common->macaddr); |
290 | 292 | ||
291 | /* calculate and install multicast filter */ | 293 | /* calculate and install multicast filter */ |
292 | mfilt[0] = mfilt[1] = ~0; | 294 | mfilt[0] = mfilt[1] = ~0; |
@@ -295,6 +297,7 @@ static void ath_opmode_init(struct ath_softc *sc) | |||
295 | 297 | ||
296 | int ath_rx_init(struct ath_softc *sc, int nbufs) | 298 | int ath_rx_init(struct ath_softc *sc, int nbufs) |
297 | { | 299 | { |
300 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
298 | struct sk_buff *skb; | 301 | struct sk_buff *skb; |
299 | struct ath_buf *bf; | 302 | struct ath_buf *bf; |
300 | int error = 0; | 303 | int error = 0; |
@@ -304,23 +307,23 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
304 | spin_lock_init(&sc->rx.rxbuflock); | 307 | spin_lock_init(&sc->rx.rxbuflock); |
305 | 308 | ||
306 | sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, | 309 | sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, |
307 | min(sc->common.cachelsz, (u16)64)); | 310 | min(common->cachelsz, (u16)64)); |
308 | 311 | ||
309 | DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", | 312 | ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", |
310 | sc->common.cachelsz, sc->rx.bufsize); | 313 | common->cachelsz, sc->rx.bufsize); |
311 | 314 | ||
312 | /* Initialize rx descriptors */ | 315 | /* Initialize rx descriptors */ |
313 | 316 | ||
314 | error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, | 317 | error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, |
315 | "rx", nbufs, 1); | 318 | "rx", nbufs, 1); |
316 | if (error != 0) { | 319 | if (error != 0) { |
317 | DPRINTF(sc, ATH_DBG_FATAL, | 320 | ath_print(common, ATH_DBG_FATAL, |
318 | "failed to allocate rx descriptors: %d\n", error); | 321 | "failed to allocate rx descriptors: %d\n", error); |
319 | goto err; | 322 | goto err; |
320 | } | 323 | } |
321 | 324 | ||
322 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { | 325 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { |
323 | skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_KERNEL); | 326 | skb = ath_rxbuf_alloc(common, sc->rx.bufsize, GFP_KERNEL); |
324 | if (skb == NULL) { | 327 | if (skb == NULL) { |
325 | error = -ENOMEM; | 328 | error = -ENOMEM; |
326 | goto err; | 329 | goto err; |
@@ -334,8 +337,8 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
334 | bf->bf_buf_addr))) { | 337 | bf->bf_buf_addr))) { |
335 | dev_kfree_skb_any(skb); | 338 | dev_kfree_skb_any(skb); |
336 | bf->bf_mpdu = NULL; | 339 | bf->bf_mpdu = NULL; |
337 | DPRINTF(sc, ATH_DBG_FATAL, | 340 | ath_print(common, ATH_DBG_FATAL, |
338 | "dma_mapping_error() on RX init\n"); | 341 | "dma_mapping_error() on RX init\n"); |
339 | error = -ENOMEM; | 342 | error = -ENOMEM; |
340 | goto err; | 343 | goto err; |
341 | } | 344 | } |
@@ -420,7 +423,10 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
420 | else | 423 | else |
421 | rfilt |= ATH9K_RX_FILTER_BEACON; | 424 | rfilt |= ATH9K_RX_FILTER_BEACON; |
422 | 425 | ||
423 | if (sc->rx.rxfilter & FIF_PSPOLL) | 426 | if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) || |
427 | AR_SREV_9285_10_OR_LATER(sc->sc_ah)) && | ||
428 | (sc->sc_ah->opmode == NL80211_IFTYPE_AP) && | ||
429 | (sc->rx.rxfilter & FIF_PSPOLL)) | ||
424 | rfilt |= ATH9K_RX_FILTER_PSPOLL; | 430 | rfilt |= ATH9K_RX_FILTER_PSPOLL; |
425 | 431 | ||
426 | if (conf_is_ht(&sc->hw->conf)) | 432 | if (conf_is_ht(&sc->hw->conf)) |
@@ -527,20 +533,22 @@ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) | |||
527 | static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | 533 | static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) |
528 | { | 534 | { |
529 | struct ieee80211_mgmt *mgmt; | 535 | struct ieee80211_mgmt *mgmt; |
536 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
530 | 537 | ||
531 | if (skb->len < 24 + 8 + 2 + 2) | 538 | if (skb->len < 24 + 8 + 2 + 2) |
532 | return; | 539 | return; |
533 | 540 | ||
534 | mgmt = (struct ieee80211_mgmt *)skb->data; | 541 | mgmt = (struct ieee80211_mgmt *)skb->data; |
535 | if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0) | 542 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) |
536 | return; /* not from our current AP */ | 543 | return; /* not from our current AP */ |
537 | 544 | ||
538 | sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; | 545 | sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; |
539 | 546 | ||
540 | if (sc->sc_flags & SC_OP_BEACON_SYNC) { | 547 | if (sc->sc_flags & SC_OP_BEACON_SYNC) { |
541 | sc->sc_flags &= ~SC_OP_BEACON_SYNC; | 548 | sc->sc_flags &= ~SC_OP_BEACON_SYNC; |
542 | DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on " | 549 | ath_print(common, ATH_DBG_PS, |
543 | "timestamp from the AP\n"); | 550 | "Reconfigure Beacon timers based on " |
551 | "timestamp from the AP\n"); | ||
544 | ath_beacon_config(sc, NULL); | 552 | ath_beacon_config(sc, NULL); |
545 | } | 553 | } |
546 | 554 | ||
@@ -552,8 +560,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
552 | * a backup trigger for returning into NETWORK SLEEP state, | 560 | * a backup trigger for returning into NETWORK SLEEP state, |
553 | * so we are waiting for it as well. | 561 | * so we are waiting for it as well. |
554 | */ | 562 | */ |
555 | DPRINTF(sc, ATH_DBG_PS, "Received DTIM beacon indicating " | 563 | ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating " |
556 | "buffered broadcast/multicast frame(s)\n"); | 564 | "buffered broadcast/multicast frame(s)\n"); |
557 | sc->sc_flags |= SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_BEACON; | 565 | sc->sc_flags |= SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_BEACON; |
558 | return; | 566 | return; |
559 | } | 567 | } |
@@ -565,13 +573,15 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
565 | * been delivered. | 573 | * been delivered. |
566 | */ | 574 | */ |
567 | sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; | 575 | sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; |
568 | DPRINTF(sc, ATH_DBG_PS, "PS wait for CAB frames timed out\n"); | 576 | ath_print(common, ATH_DBG_PS, |
577 | "PS wait for CAB frames timed out\n"); | ||
569 | } | 578 | } |
570 | } | 579 | } |
571 | 580 | ||
572 | static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | 581 | static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) |
573 | { | 582 | { |
574 | struct ieee80211_hdr *hdr; | 583 | struct ieee80211_hdr *hdr; |
584 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
575 | 585 | ||
576 | hdr = (struct ieee80211_hdr *)skb->data; | 586 | hdr = (struct ieee80211_hdr *)skb->data; |
577 | 587 | ||
@@ -589,14 +599,15 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
589 | * point. | 599 | * point. |
590 | */ | 600 | */ |
591 | sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; | 601 | sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; |
592 | DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to " | 602 | ath_print(common, ATH_DBG_PS, |
593 | "sleep\n"); | 603 | "All PS CAB frames received, back to sleep\n"); |
594 | } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) && | 604 | } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) && |
595 | !is_multicast_ether_addr(hdr->addr1) && | 605 | !is_multicast_ether_addr(hdr->addr1) && |
596 | !ieee80211_has_morefrags(hdr->frame_control)) { | 606 | !ieee80211_has_morefrags(hdr->frame_control)) { |
597 | sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA; | 607 | sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA; |
598 | DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having " | 608 | ath_print(common, ATH_DBG_PS, |
599 | "received PS-Poll data (0x%x)\n", | 609 | "Going back to sleep after having received " |
610 | "PS-Poll data (0x%x)\n", | ||
600 | sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | | 611 | sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | |
601 | SC_OP_WAIT_FOR_CAB | | 612 | SC_OP_WAIT_FOR_CAB | |
602 | SC_OP_WAIT_FOR_PSPOLL_DATA | | 613 | SC_OP_WAIT_FOR_PSPOLL_DATA | |
@@ -651,6 +662,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
651 | struct sk_buff *skb = NULL, *requeue_skb; | 662 | struct sk_buff *skb = NULL, *requeue_skb; |
652 | struct ieee80211_rx_status rx_status; | 663 | struct ieee80211_rx_status rx_status; |
653 | struct ath_hw *ah = sc->sc_ah; | 664 | struct ath_hw *ah = sc->sc_ah; |
665 | struct ath_common *common = ath9k_hw_common(ah); | ||
654 | struct ieee80211_hdr *hdr; | 666 | struct ieee80211_hdr *hdr; |
655 | int hdrlen, padsize, retval; | 667 | int hdrlen, padsize, retval; |
656 | bool decrypt_error = false; | 668 | bool decrypt_error = false; |
@@ -749,7 +761,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
749 | 761 | ||
750 | /* Ensure we always have an skb to requeue once we are done | 762 | /* Ensure we always have an skb to requeue once we are done |
751 | * processing the current buffer's skb */ | 763 | * processing the current buffer's skb */ |
752 | requeue_skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_ATOMIC); | 764 | requeue_skb = ath_rxbuf_alloc(common, sc->rx.bufsize, GFP_ATOMIC); |
753 | 765 | ||
754 | /* If there is no memory we ignore the current RX'd frame, | 766 | /* If there is no memory we ignore the current RX'd frame, |
755 | * tell hardware it can give us a new frame using the old | 767 | * tell hardware it can give us a new frame using the old |
@@ -811,8 +823,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
811 | bf->bf_buf_addr))) { | 823 | bf->bf_buf_addr))) { |
812 | dev_kfree_skb_any(requeue_skb); | 824 | dev_kfree_skb_any(requeue_skb); |
813 | bf->bf_mpdu = NULL; | 825 | bf->bf_mpdu = NULL; |
814 | DPRINTF(sc, ATH_DBG_FATAL, | 826 | ath_print(common, ATH_DBG_FATAL, |
815 | "dma_mapping_error() on RX\n"); | 827 | "dma_mapping_error() on RX\n"); |
816 | ath_rx_send_to_mac80211(sc, skb, &rx_status); | 828 | ath_rx_send_to_mac80211(sc, skb, &rx_status); |
817 | break; | 829 | break; |
818 | } | 830 | } |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d83b77f821e9..ceed0095efac 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -17,6 +17,8 @@ | |||
17 | #ifndef REG_H | 17 | #ifndef REG_H |
18 | #define REG_H | 18 | #define REG_H |
19 | 19 | ||
20 | #include "../reg.h" | ||
21 | |||
20 | #define AR_CR 0x0008 | 22 | #define AR_CR 0x0008 |
21 | #define AR_CR_RXE 0x00000004 | 23 | #define AR_CR_RXE 0x00000004 |
22 | #define AR_CR_RXD 0x00000020 | 24 | #define AR_CR_RXD 0x00000020 |
@@ -1421,9 +1423,6 @@ enum { | |||
1421 | #define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000 | 1423 | #define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000 |
1422 | #define AR_SLEEP2_BEACON_TIMEOUT_S 21 | 1424 | #define AR_SLEEP2_BEACON_TIMEOUT_S 21 |
1423 | 1425 | ||
1424 | #define AR_BSSMSKL 0x80e0 | ||
1425 | #define AR_BSSMSKU 0x80e4 | ||
1426 | |||
1427 | #define AR_TPC 0x80e8 | 1426 | #define AR_TPC 0x80e8 |
1428 | #define AR_TPC_ACK 0x0000003f | 1427 | #define AR_TPC_ACK 0x0000003f |
1429 | #define AR_TPC_ACK_S 0x00 | 1428 | #define AR_TPC_ACK_S 0x00 |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 19b88f8177fd..bc7d173b6fae 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -40,6 +40,7 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw) | |||
40 | { | 40 | { |
41 | struct ath_wiphy *aphy = hw->priv; | 41 | struct ath_wiphy *aphy = hw->priv; |
42 | struct ath_softc *sc = aphy->sc; | 42 | struct ath_softc *sc = aphy->sc; |
43 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
43 | struct ath9k_vif_iter_data iter_data; | 44 | struct ath9k_vif_iter_data iter_data; |
44 | int i, j; | 45 | int i, j; |
45 | u8 mask[ETH_ALEN]; | 46 | u8 mask[ETH_ALEN]; |
@@ -51,7 +52,7 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw) | |||
51 | */ | 52 | */ |
52 | iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); | 53 | iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); |
53 | if (iter_data.addr) { | 54 | if (iter_data.addr) { |
54 | memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN); | 55 | memcpy(iter_data.addr, common->macaddr, ETH_ALEN); |
55 | iter_data.count = 1; | 56 | iter_data.count = 1; |
56 | } else | 57 | } else |
57 | iter_data.count = 0; | 58 | iter_data.count = 0; |
@@ -86,20 +87,21 @@ void ath9k_set_bssid_mask(struct ieee80211_hw *hw) | |||
86 | kfree(iter_data.addr); | 87 | kfree(iter_data.addr); |
87 | 88 | ||
88 | /* Invert the mask and configure hardware */ | 89 | /* Invert the mask and configure hardware */ |
89 | sc->bssidmask[0] = ~mask[0]; | 90 | common->bssidmask[0] = ~mask[0]; |
90 | sc->bssidmask[1] = ~mask[1]; | 91 | common->bssidmask[1] = ~mask[1]; |
91 | sc->bssidmask[2] = ~mask[2]; | 92 | common->bssidmask[2] = ~mask[2]; |
92 | sc->bssidmask[3] = ~mask[3]; | 93 | common->bssidmask[3] = ~mask[3]; |
93 | sc->bssidmask[4] = ~mask[4]; | 94 | common->bssidmask[4] = ~mask[4]; |
94 | sc->bssidmask[5] = ~mask[5]; | 95 | common->bssidmask[5] = ~mask[5]; |
95 | 96 | ||
96 | ath9k_hw_setbssidmask(sc); | 97 | ath_hw_setbssidmask(common); |
97 | } | 98 | } |
98 | 99 | ||
99 | int ath9k_wiphy_add(struct ath_softc *sc) | 100 | int ath9k_wiphy_add(struct ath_softc *sc) |
100 | { | 101 | { |
101 | int i, error; | 102 | int i, error; |
102 | struct ath_wiphy *aphy; | 103 | struct ath_wiphy *aphy; |
104 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
103 | struct ieee80211_hw *hw; | 105 | struct ieee80211_hw *hw; |
104 | u8 addr[ETH_ALEN]; | 106 | u8 addr[ETH_ALEN]; |
105 | 107 | ||
@@ -138,7 +140,7 @@ int ath9k_wiphy_add(struct ath_softc *sc) | |||
138 | sc->sec_wiphy[i] = aphy; | 140 | sc->sec_wiphy[i] = aphy; |
139 | spin_unlock_bh(&sc->wiphy_lock); | 141 | spin_unlock_bh(&sc->wiphy_lock); |
140 | 142 | ||
141 | memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN); | 143 | memcpy(addr, common->macaddr, ETH_ALEN); |
142 | addr[0] |= 0x02; /* Locally managed address */ | 144 | addr[0] |= 0x02; /* Locally managed address */ |
143 | /* | 145 | /* |
144 | * XOR virtual wiphy index into the least significant bits to generate | 146 | * XOR virtual wiphy index into the least significant bits to generate |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 42551a48c8ac..a8620b1d091b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -107,7 +107,7 @@ static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
107 | { | 107 | { |
108 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; | 108 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; |
109 | 109 | ||
110 | ASSERT(tid->paused > 0); | 110 | BUG_ON(tid->paused <= 0); |
111 | spin_lock_bh(&txq->axq_lock); | 111 | spin_lock_bh(&txq->axq_lock); |
112 | 112 | ||
113 | tid->paused--; | 113 | tid->paused--; |
@@ -131,7 +131,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
131 | struct list_head bf_head; | 131 | struct list_head bf_head; |
132 | INIT_LIST_HEAD(&bf_head); | 132 | INIT_LIST_HEAD(&bf_head); |
133 | 133 | ||
134 | ASSERT(tid->paused > 0); | 134 | BUG_ON(tid->paused <= 0); |
135 | spin_lock_bh(&txq->axq_lock); | 135 | spin_lock_bh(&txq->axq_lock); |
136 | 136 | ||
137 | tid->paused--; | 137 | tid->paused--; |
@@ -143,7 +143,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | |||
143 | 143 | ||
144 | while (!list_empty(&tid->buf_q)) { | 144 | while (!list_empty(&tid->buf_q)) { |
145 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 145 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
146 | ASSERT(!bf_isretried(bf)); | 146 | BUG_ON(bf_isretried(bf)); |
147 | list_move_tail(&bf->list, &bf_head); | 147 | list_move_tail(&bf->list, &bf_head); |
148 | ath_tx_send_ht_normal(sc, txq, tid, &bf_head); | 148 | ath_tx_send_ht_normal(sc, txq, tid, &bf_head); |
149 | } | 149 | } |
@@ -178,7 +178,7 @@ static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
178 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); | 178 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); |
179 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 179 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
180 | 180 | ||
181 | ASSERT(tid->tx_buf[cindex] == NULL); | 181 | BUG_ON(tid->tx_buf[cindex] != NULL); |
182 | tid->tx_buf[cindex] = bf; | 182 | tid->tx_buf[cindex] = bf; |
183 | 183 | ||
184 | if (index >= ((tid->baw_tail - tid->baw_head) & | 184 | if (index >= ((tid->baw_tail - tid->baw_head) & |
@@ -358,7 +358,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
358 | else | 358 | else |
359 | INIT_LIST_HEAD(&bf_head); | 359 | INIT_LIST_HEAD(&bf_head); |
360 | } else { | 360 | } else { |
361 | ASSERT(!list_empty(bf_q)); | 361 | BUG_ON(list_empty(bf_q)); |
362 | list_move_tail(&bf->list, &bf_head); | 362 | list_move_tail(&bf->list, &bf_head); |
363 | } | 363 | } |
364 | 364 | ||
@@ -815,6 +815,7 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc, | |||
815 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | 815 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) |
816 | { | 816 | { |
817 | struct ath_hw *ah = sc->sc_ah; | 817 | struct ath_hw *ah = sc->sc_ah; |
818 | struct ath_common *common = ath9k_hw_common(ah); | ||
818 | struct ath9k_tx_queue_info qi; | 819 | struct ath9k_tx_queue_info qi; |
819 | int qnum; | 820 | int qnum; |
820 | 821 | ||
@@ -854,9 +855,9 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
854 | return NULL; | 855 | return NULL; |
855 | } | 856 | } |
856 | if (qnum >= ARRAY_SIZE(sc->tx.txq)) { | 857 | if (qnum >= ARRAY_SIZE(sc->tx.txq)) { |
857 | DPRINTF(sc, ATH_DBG_FATAL, | 858 | ath_print(common, ATH_DBG_FATAL, |
858 | "qnum %u out of range, max %u!\n", | 859 | "qnum %u out of range, max %u!\n", |
859 | qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); | 860 | qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); |
860 | ath9k_hw_releasetxqueue(ah, qnum); | 861 | ath9k_hw_releasetxqueue(ah, qnum); |
861 | return NULL; | 862 | return NULL; |
862 | } | 863 | } |
@@ -884,9 +885,9 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) | |||
884 | switch (qtype) { | 885 | switch (qtype) { |
885 | case ATH9K_TX_QUEUE_DATA: | 886 | case ATH9K_TX_QUEUE_DATA: |
886 | if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { | 887 | if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { |
887 | DPRINTF(sc, ATH_DBG_FATAL, | 888 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
888 | "HAL AC %u out of range, max %zu!\n", | 889 | "HAL AC %u out of range, max %zu!\n", |
889 | haltype, ARRAY_SIZE(sc->tx.hwq_map)); | 890 | haltype, ARRAY_SIZE(sc->tx.hwq_map)); |
890 | return -1; | 891 | return -1; |
891 | } | 892 | } |
892 | qnum = sc->tx.hwq_map[haltype]; | 893 | qnum = sc->tx.hwq_map[haltype]; |
@@ -914,9 +915,9 @@ struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) | |||
914 | spin_lock_bh(&txq->axq_lock); | 915 | spin_lock_bh(&txq->axq_lock); |
915 | 916 | ||
916 | if (txq->axq_depth >= (ATH_TXBUF - 20)) { | 917 | if (txq->axq_depth >= (ATH_TXBUF - 20)) { |
917 | DPRINTF(sc, ATH_DBG_XMIT, | 918 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT, |
918 | "TX queue: %d is full, depth: %d\n", | 919 | "TX queue: %d is full, depth: %d\n", |
919 | qnum, txq->axq_depth); | 920 | qnum, txq->axq_depth); |
920 | ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); | 921 | ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); |
921 | txq->stopped = 1; | 922 | txq->stopped = 1; |
922 | spin_unlock_bh(&txq->axq_lock); | 923 | spin_unlock_bh(&txq->axq_lock); |
@@ -945,7 +946,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum, | |||
945 | return 0; | 946 | return 0; |
946 | } | 947 | } |
947 | 948 | ||
948 | ASSERT(sc->tx.txq[qnum].axq_qnum == qnum); | 949 | BUG_ON(sc->tx.txq[qnum].axq_qnum != qnum); |
949 | 950 | ||
950 | ath9k_hw_get_txq_props(ah, qnum, &qi); | 951 | ath9k_hw_get_txq_props(ah, qnum, &qi); |
951 | qi.tqi_aifs = qinfo->tqi_aifs; | 952 | qi.tqi_aifs = qinfo->tqi_aifs; |
@@ -955,8 +956,8 @@ int ath_txq_update(struct ath_softc *sc, int qnum, | |||
955 | qi.tqi_readyTime = qinfo->tqi_readyTime; | 956 | qi.tqi_readyTime = qinfo->tqi_readyTime; |
956 | 957 | ||
957 | if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { | 958 | if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { |
958 | DPRINTF(sc, ATH_DBG_FATAL, | 959 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
959 | "Unable to update hardware queue %u!\n", qnum); | 960 | "Unable to update hardware queue %u!\n", qnum); |
960 | error = -EIO; | 961 | error = -EIO; |
961 | } else { | 962 | } else { |
962 | ath9k_hw_resettxqueue(ah, qnum); | 963 | ath9k_hw_resettxqueue(ah, qnum); |
@@ -1055,6 +1056,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1055 | void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | 1056 | void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) |
1056 | { | 1057 | { |
1057 | struct ath_hw *ah = sc->sc_ah; | 1058 | struct ath_hw *ah = sc->sc_ah; |
1059 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1058 | struct ath_txq *txq; | 1060 | struct ath_txq *txq; |
1059 | int i, npend = 0; | 1061 | int i, npend = 0; |
1060 | 1062 | ||
@@ -1076,14 +1078,15 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | |||
1076 | if (npend) { | 1078 | if (npend) { |
1077 | int r; | 1079 | int r; |
1078 | 1080 | ||
1079 | DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n"); | 1081 | ath_print(common, ATH_DBG_XMIT, |
1082 | "Unable to stop TxDMA. Reset HAL!\n"); | ||
1080 | 1083 | ||
1081 | spin_lock_bh(&sc->sc_resetlock); | 1084 | spin_lock_bh(&sc->sc_resetlock); |
1082 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true); | 1085 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true); |
1083 | if (r) | 1086 | if (r) |
1084 | DPRINTF(sc, ATH_DBG_FATAL, | 1087 | ath_print(common, ATH_DBG_FATAL, |
1085 | "Unable to reset hardware; reset status %d\n", | 1088 | "Unable to reset hardware; reset status %d\n", |
1086 | r); | 1089 | r); |
1087 | spin_unlock_bh(&sc->sc_resetlock); | 1090 | spin_unlock_bh(&sc->sc_resetlock); |
1088 | } | 1091 | } |
1089 | 1092 | ||
@@ -1147,8 +1150,8 @@ int ath_tx_setup(struct ath_softc *sc, int haltype) | |||
1147 | struct ath_txq *txq; | 1150 | struct ath_txq *txq; |
1148 | 1151 | ||
1149 | if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { | 1152 | if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { |
1150 | DPRINTF(sc, ATH_DBG_FATAL, | 1153 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
1151 | "HAL AC %u out of range, max %zu!\n", | 1154 | "HAL AC %u out of range, max %zu!\n", |
1152 | haltype, ARRAY_SIZE(sc->tx.hwq_map)); | 1155 | haltype, ARRAY_SIZE(sc->tx.hwq_map)); |
1153 | return 0; | 1156 | return 0; |
1154 | } | 1157 | } |
@@ -1172,6 +1175,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1172 | struct list_head *head) | 1175 | struct list_head *head) |
1173 | { | 1176 | { |
1174 | struct ath_hw *ah = sc->sc_ah; | 1177 | struct ath_hw *ah = sc->sc_ah; |
1178 | struct ath_common *common = ath9k_hw_common(ah); | ||
1175 | struct ath_buf *bf; | 1179 | struct ath_buf *bf; |
1176 | 1180 | ||
1177 | /* | 1181 | /* |
@@ -1188,19 +1192,19 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1188 | txq->axq_depth++; | 1192 | txq->axq_depth++; |
1189 | txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); | 1193 | txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); |
1190 | 1194 | ||
1191 | DPRINTF(sc, ATH_DBG_QUEUE, | 1195 | ath_print(common, ATH_DBG_QUEUE, |
1192 | "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); | 1196 | "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); |
1193 | 1197 | ||
1194 | if (txq->axq_link == NULL) { | 1198 | if (txq->axq_link == NULL) { |
1195 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); | 1199 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); |
1196 | DPRINTF(sc, ATH_DBG_XMIT, | 1200 | ath_print(common, ATH_DBG_XMIT, |
1197 | "TXDP[%u] = %llx (%p)\n", | 1201 | "TXDP[%u] = %llx (%p)\n", |
1198 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); | 1202 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); |
1199 | } else { | 1203 | } else { |
1200 | *txq->axq_link = bf->bf_daddr; | 1204 | *txq->axq_link = bf->bf_daddr; |
1201 | DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n", | 1205 | ath_print(common, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n", |
1202 | txq->axq_qnum, txq->axq_link, | 1206 | txq->axq_qnum, txq->axq_link, |
1203 | ito64(bf->bf_daddr), bf->bf_desc); | 1207 | ito64(bf->bf_daddr), bf->bf_desc); |
1204 | } | 1208 | } |
1205 | txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); | 1209 | txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); |
1206 | ath9k_hw_txstart(ah, txq->axq_qnum); | 1210 | ath9k_hw_txstart(ah, txq->axq_qnum); |
@@ -1452,6 +1456,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, | |||
1452 | 1456 | ||
1453 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | 1457 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) |
1454 | { | 1458 | { |
1459 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1455 | const struct ath_rate_table *rt = sc->cur_rate_table; | 1460 | const struct ath_rate_table *rt = sc->cur_rate_table; |
1456 | struct ath9k_11n_rate_series series[4]; | 1461 | struct ath9k_11n_rate_series series[4]; |
1457 | struct sk_buff *skb; | 1462 | struct sk_buff *skb; |
@@ -1507,7 +1512,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
1507 | 1512 | ||
1508 | rix = rates[i].idx; | 1513 | rix = rates[i].idx; |
1509 | series[i].Tries = rates[i].count; | 1514 | series[i].Tries = rates[i].count; |
1510 | series[i].ChSel = sc->tx_chainmask; | 1515 | series[i].ChSel = common->tx_chainmask; |
1511 | 1516 | ||
1512 | if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | 1517 | if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) |
1513 | series[i].Rate = rt->info[rix].ratecode | | 1518 | series[i].Rate = rt->info[rix].ratecode | |
@@ -1587,7 +1592,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1587 | bf->bf_mpdu = NULL; | 1592 | bf->bf_mpdu = NULL; |
1588 | kfree(tx_info_priv); | 1593 | kfree(tx_info_priv); |
1589 | tx_info->rate_driver_data[0] = NULL; | 1594 | tx_info->rate_driver_data[0] = NULL; |
1590 | DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on TX\n"); | 1595 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
1596 | "dma_mapping_error() on TX\n"); | ||
1591 | return -ENOMEM; | 1597 | return -ENOMEM; |
1592 | } | 1598 | } |
1593 | 1599 | ||
@@ -1669,12 +1675,13 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1669 | { | 1675 | { |
1670 | struct ath_wiphy *aphy = hw->priv; | 1676 | struct ath_wiphy *aphy = hw->priv; |
1671 | struct ath_softc *sc = aphy->sc; | 1677 | struct ath_softc *sc = aphy->sc; |
1678 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1672 | struct ath_buf *bf; | 1679 | struct ath_buf *bf; |
1673 | int r; | 1680 | int r; |
1674 | 1681 | ||
1675 | bf = ath_tx_get_buffer(sc); | 1682 | bf = ath_tx_get_buffer(sc); |
1676 | if (!bf) { | 1683 | if (!bf) { |
1677 | DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n"); | 1684 | ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n"); |
1678 | return -1; | 1685 | return -1; |
1679 | } | 1686 | } |
1680 | 1687 | ||
@@ -1682,7 +1689,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1682 | if (unlikely(r)) { | 1689 | if (unlikely(r)) { |
1683 | struct ath_txq *txq = txctl->txq; | 1690 | struct ath_txq *txq = txctl->txq; |
1684 | 1691 | ||
1685 | DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n"); | 1692 | ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); |
1686 | 1693 | ||
1687 | /* upon ath_tx_processq() this TX queue will be resumed, we | 1694 | /* upon ath_tx_processq() this TX queue will be resumed, we |
1688 | * guarantee this will happen by knowing beforehand that | 1695 | * guarantee this will happen by knowing beforehand that |
@@ -1712,6 +1719,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1712 | { | 1719 | { |
1713 | struct ath_wiphy *aphy = hw->priv; | 1720 | struct ath_wiphy *aphy = hw->priv; |
1714 | struct ath_softc *sc = aphy->sc; | 1721 | struct ath_softc *sc = aphy->sc; |
1722 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1715 | int hdrlen, padsize; | 1723 | int hdrlen, padsize; |
1716 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1724 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1717 | struct ath_tx_control txctl; | 1725 | struct ath_tx_control txctl; |
@@ -1736,7 +1744,8 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1736 | if (hdrlen & 3) { | 1744 | if (hdrlen & 3) { |
1737 | padsize = hdrlen % 4; | 1745 | padsize = hdrlen % 4; |
1738 | if (skb_headroom(skb) < padsize) { | 1746 | if (skb_headroom(skb) < padsize) { |
1739 | DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n"); | 1747 | ath_print(common, ATH_DBG_XMIT, |
1748 | "TX CABQ padding failed\n"); | ||
1740 | dev_kfree_skb_any(skb); | 1749 | dev_kfree_skb_any(skb); |
1741 | return; | 1750 | return; |
1742 | } | 1751 | } |
@@ -1746,10 +1755,11 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1746 | 1755 | ||
1747 | txctl.txq = sc->beacon.cabq; | 1756 | txctl.txq = sc->beacon.cabq; |
1748 | 1757 | ||
1749 | DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb); | 1758 | ath_print(common, ATH_DBG_XMIT, |
1759 | "transmitting CABQ packet, skb: %p\n", skb); | ||
1750 | 1760 | ||
1751 | if (ath_tx_start(hw, skb, &txctl) != 0) { | 1761 | if (ath_tx_start(hw, skb, &txctl) != 0) { |
1752 | DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n"); | 1762 | ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n"); |
1753 | goto exit; | 1763 | goto exit; |
1754 | } | 1764 | } |
1755 | 1765 | ||
@@ -1768,10 +1778,11 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1768 | struct ieee80211_hw *hw = sc->hw; | 1778 | struct ieee80211_hw *hw = sc->hw; |
1769 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1779 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1770 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | 1780 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); |
1781 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1771 | int hdrlen, padsize; | 1782 | int hdrlen, padsize; |
1772 | int frame_type = ATH9K_NOT_INTERNAL; | 1783 | int frame_type = ATH9K_NOT_INTERNAL; |
1773 | 1784 | ||
1774 | DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 1785 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
1775 | 1786 | ||
1776 | if (tx_info_priv) { | 1787 | if (tx_info_priv) { |
1777 | hw = tx_info_priv->aphy->hw; | 1788 | hw = tx_info_priv->aphy->hw; |
@@ -1805,8 +1816,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1805 | 1816 | ||
1806 | if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) { | 1817 | if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) { |
1807 | sc->sc_flags &= ~SC_OP_WAIT_FOR_TX_ACK; | 1818 | sc->sc_flags &= ~SC_OP_WAIT_FOR_TX_ACK; |
1808 | DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having " | 1819 | ath_print(common, ATH_DBG_PS, |
1809 | "received TX status (0x%x)\n", | 1820 | "Going back to sleep after having " |
1821 | "received TX status (0x%x)\n", | ||
1810 | sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | | 1822 | sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | |
1811 | SC_OP_WAIT_FOR_CAB | | 1823 | SC_OP_WAIT_FOR_CAB | |
1812 | SC_OP_WAIT_FOR_PSPOLL_DATA | | 1824 | SC_OP_WAIT_FOR_PSPOLL_DATA | |
@@ -1936,15 +1948,16 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) | |||
1936 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | 1948 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) |
1937 | { | 1949 | { |
1938 | struct ath_hw *ah = sc->sc_ah; | 1950 | struct ath_hw *ah = sc->sc_ah; |
1951 | struct ath_common *common = ath9k_hw_common(ah); | ||
1939 | struct ath_buf *bf, *lastbf, *bf_held = NULL; | 1952 | struct ath_buf *bf, *lastbf, *bf_held = NULL; |
1940 | struct list_head bf_head; | 1953 | struct list_head bf_head; |
1941 | struct ath_desc *ds; | 1954 | struct ath_desc *ds; |
1942 | int txok; | 1955 | int txok; |
1943 | int status; | 1956 | int status; |
1944 | 1957 | ||
1945 | DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", | 1958 | ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", |
1946 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), | 1959 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), |
1947 | txq->axq_link); | 1960 | txq->axq_link); |
1948 | 1961 | ||
1949 | for (;;) { | 1962 | for (;;) { |
1950 | spin_lock_bh(&txq->axq_lock); | 1963 | spin_lock_bh(&txq->axq_lock); |
@@ -2064,7 +2077,8 @@ static void ath_tx_complete_poll_work(struct work_struct *work) | |||
2064 | } | 2077 | } |
2065 | 2078 | ||
2066 | if (needreset) { | 2079 | if (needreset) { |
2067 | DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n"); | 2080 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, |
2081 | "tx hung, resetting the chip\n"); | ||
2068 | ath_reset(sc, false); | 2082 | ath_reset(sc, false); |
2069 | } | 2083 | } |
2070 | 2084 | ||
@@ -2093,6 +2107,7 @@ void ath_tx_tasklet(struct ath_softc *sc) | |||
2093 | 2107 | ||
2094 | int ath_tx_init(struct ath_softc *sc, int nbufs) | 2108 | int ath_tx_init(struct ath_softc *sc, int nbufs) |
2095 | { | 2109 | { |
2110 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2096 | int error = 0; | 2111 | int error = 0; |
2097 | 2112 | ||
2098 | spin_lock_init(&sc->tx.txbuflock); | 2113 | spin_lock_init(&sc->tx.txbuflock); |
@@ -2100,16 +2115,16 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) | |||
2100 | error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, | 2115 | error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, |
2101 | "tx", nbufs, 1); | 2116 | "tx", nbufs, 1); |
2102 | if (error != 0) { | 2117 | if (error != 0) { |
2103 | DPRINTF(sc, ATH_DBG_FATAL, | 2118 | ath_print(common, ATH_DBG_FATAL, |
2104 | "Failed to allocate tx descriptors: %d\n", error); | 2119 | "Failed to allocate tx descriptors: %d\n", error); |
2105 | goto err; | 2120 | goto err; |
2106 | } | 2121 | } |
2107 | 2122 | ||
2108 | error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, | 2123 | error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, |
2109 | "beacon", ATH_BCBUF, 1); | 2124 | "beacon", ATH_BCBUF, 1); |
2110 | if (error != 0) { | 2125 | if (error != 0) { |
2111 | DPRINTF(sc, ATH_DBG_FATAL, | 2126 | ath_print(common, ATH_DBG_FATAL, |
2112 | "Failed to allocate beacon descriptors: %d\n", error); | 2127 | "Failed to allocate beacon descriptors: %d\n", error); |
2113 | goto err; | 2128 | goto err; |
2114 | } | 2129 | } |
2115 | 2130 | ||
diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c new file mode 100644 index 000000000000..53e77bd131b9 --- /dev/null +++ b/drivers/net/wireless/ath/debug.c | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009 Atheros Communications Inc. | ||
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 "ath.h" | ||
18 | #include "debug.h" | ||
19 | |||
20 | void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) | ||
21 | { | ||
22 | va_list args; | ||
23 | |||
24 | if (likely(!(common->debug_mask & dbg_mask))) | ||
25 | return; | ||
26 | |||
27 | va_start(args, fmt); | ||
28 | printk(KERN_DEBUG "ath: "); | ||
29 | vprintk(fmt, args); | ||
30 | va_end(args); | ||
31 | } | ||
32 | EXPORT_SYMBOL(ath_print); | ||
diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h new file mode 100644 index 000000000000..d6b685a06c5e --- /dev/null +++ b/drivers/net/wireless/ath/debug.h | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef ATH_DEBUG_H | ||
18 | #define ATH_DEBUG_H | ||
19 | |||
20 | #include "ath.h" | ||
21 | |||
22 | /** | ||
23 | * enum ath_debug_level - atheros wireless debug level | ||
24 | * | ||
25 | * @ATH_DBG_RESET: reset processing | ||
26 | * @ATH_DBG_QUEUE: hardware queue management | ||
27 | * @ATH_DBG_EEPROM: eeprom processing | ||
28 | * @ATH_DBG_CALIBRATE: periodic calibration | ||
29 | * @ATH_DBG_INTERRUPT: interrupt processing | ||
30 | * @ATH_DBG_REGULATORY: regulatory processing | ||
31 | * @ATH_DBG_ANI: adaptive noise immunitive processing | ||
32 | * @ATH_DBG_XMIT: basic xmit operation | ||
33 | * @ATH_DBG_BEACON: beacon handling | ||
34 | * @ATH_DBG_CONFIG: configuration of the hardware | ||
35 | * @ATH_DBG_FATAL: fatal errors, this is the default, DBG_DEFAULT | ||
36 | * @ATH_DBG_PS: power save processing | ||
37 | * @ATH_DBG_HWTIMER: hardware timer handling | ||
38 | * @ATH_DBG_BTCOEX: bluetooth coexistance | ||
39 | * @ATH_DBG_ANY: enable all debugging | ||
40 | * | ||
41 | * The debug level is used to control the amount and type of debugging output | ||
42 | * we want to see. Each driver has its own method for enabling debugging and | ||
43 | * modifying debug level states -- but this is typically done through a | ||
44 | * module parameter 'debug' along with a respective 'debug' debugfs file | ||
45 | * entry. | ||
46 | */ | ||
47 | enum ATH_DEBUG { | ||
48 | ATH_DBG_RESET = 0x00000001, | ||
49 | ATH_DBG_QUEUE = 0x00000002, | ||
50 | ATH_DBG_EEPROM = 0x00000004, | ||
51 | ATH_DBG_CALIBRATE = 0x00000008, | ||
52 | ATH_DBG_INTERRUPT = 0x00000010, | ||
53 | ATH_DBG_REGULATORY = 0x00000020, | ||
54 | ATH_DBG_ANI = 0x00000040, | ||
55 | ATH_DBG_XMIT = 0x00000080, | ||
56 | ATH_DBG_BEACON = 0x00000100, | ||
57 | ATH_DBG_CONFIG = 0x00000200, | ||
58 | ATH_DBG_FATAL = 0x00000400, | ||
59 | ATH_DBG_PS = 0x00000800, | ||
60 | ATH_DBG_HWTIMER = 0x00001000, | ||
61 | ATH_DBG_BTCOEX = 0x00002000, | ||
62 | ATH_DBG_ANY = 0xffffffff | ||
63 | }; | ||
64 | |||
65 | #define ATH_DBG_DEFAULT (ATH_DBG_FATAL) | ||
66 | |||
67 | #ifdef CONFIG_ATH_DEBUG | ||
68 | void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...); | ||
69 | #else | ||
70 | static inline void ath_print(struct ath_common *common, | ||
71 | int dbg_mask, | ||
72 | const char *fmt, ...) | ||
73 | { | ||
74 | } | ||
75 | #endif /* CONFIG_ATH_DEBUG */ | ||
76 | |||
77 | #endif /* ATH_DEBUG_H */ | ||
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c new file mode 100644 index 000000000000..ecc9eb01f4fa --- /dev/null +++ b/drivers/net/wireless/ath/hw.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009 Atheros Communications Inc. | ||
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 <asm/unaligned.h> | ||
18 | |||
19 | #include "ath.h" | ||
20 | #include "reg.h" | ||
21 | |||
22 | #define REG_READ common->ops->read | ||
23 | #define REG_WRITE common->ops->write | ||
24 | |||
25 | /** | ||
26 | * ath_hw_set_bssid_mask - filter out bssids we listen | ||
27 | * | ||
28 | * @common: the ath_common struct for the device. | ||
29 | * | ||
30 | * BSSID masking is a method used by AR5212 and newer hardware to inform PCU | ||
31 | * which bits of the interface's MAC address should be looked at when trying | ||
32 | * to decide which packets to ACK. In station mode and AP mode with a single | ||
33 | * BSS every bit matters since we lock to only one BSS. In AP mode with | ||
34 | * multiple BSSes (virtual interfaces) not every bit matters because hw must | ||
35 | * accept frames for all BSSes and so we tweak some bits of our mac address | ||
36 | * in order to have multiple BSSes. | ||
37 | * | ||
38 | * NOTE: This is a simple filter and does *not* filter out all | ||
39 | * relevant frames. Some frames that are not for us might get ACKed from us | ||
40 | * by PCU because they just match the mask. | ||
41 | * | ||
42 | * When handling multiple BSSes you can get the BSSID mask by computing the | ||
43 | * set of ~ ( MAC XOR BSSID ) for all bssids we handle. | ||
44 | * | ||
45 | * When you do this you are essentially computing the common bits of all your | ||
46 | * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with | ||
47 | * the MAC address to obtain the relevant bits and compare the result with | ||
48 | * (frame's BSSID & mask) to see if they match. | ||
49 | * | ||
50 | * Simple example: on your card you have have two BSSes you have created with | ||
51 | * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. | ||
52 | * There is another BSSID-03 but you are not part of it. For simplicity's sake, | ||
53 | * assuming only 4 bits for a mac address and for BSSIDs you can then have: | ||
54 | * | ||
55 | * \ | ||
56 | * MAC: 0001 | | ||
57 | * BSSID-01: 0100 | --> Belongs to us | ||
58 | * BSSID-02: 1001 | | ||
59 | * / | ||
60 | * ------------------- | ||
61 | * BSSID-03: 0110 | --> External | ||
62 | * ------------------- | ||
63 | * | ||
64 | * Our bssid_mask would then be: | ||
65 | * | ||
66 | * On loop iteration for BSSID-01: | ||
67 | * ~(0001 ^ 0100) -> ~(0101) | ||
68 | * -> 1010 | ||
69 | * bssid_mask = 1010 | ||
70 | * | ||
71 | * On loop iteration for BSSID-02: | ||
72 | * bssid_mask &= ~(0001 ^ 1001) | ||
73 | * bssid_mask = (1010) & ~(0001 ^ 1001) | ||
74 | * bssid_mask = (1010) & ~(1001) | ||
75 | * bssid_mask = (1010) & (0110) | ||
76 | * bssid_mask = 0010 | ||
77 | * | ||
78 | * A bssid_mask of 0010 means "only pay attention to the second least | ||
79 | * significant bit". This is because its the only bit common | ||
80 | * amongst the MAC and all BSSIDs we support. To findout what the real | ||
81 | * common bit is we can simply "&" the bssid_mask now with any BSSID we have | ||
82 | * or our MAC address (we assume the hardware uses the MAC address). | ||
83 | * | ||
84 | * Now, suppose there's an incoming frame for BSSID-03: | ||
85 | * | ||
86 | * IFRAME-01: 0110 | ||
87 | * | ||
88 | * An easy eye-inspeciton of this already should tell you that this frame | ||
89 | * will not pass our check. This is beacuse the bssid_mask tells the | ||
90 | * hardware to only look at the second least significant bit and the | ||
91 | * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB | ||
92 | * as 1, which does not match 0. | ||
93 | * | ||
94 | * So with IFRAME-01 we *assume* the hardware will do: | ||
95 | * | ||
96 | * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
97 | * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; | ||
98 | * --> allow = (0010) == 0000 ? 1 : 0; | ||
99 | * --> allow = 0 | ||
100 | * | ||
101 | * Lets now test a frame that should work: | ||
102 | * | ||
103 | * IFRAME-02: 0001 (we should allow) | ||
104 | * | ||
105 | * allow = (0001 & 1010) == 1010 | ||
106 | * | ||
107 | * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; | ||
108 | * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; | ||
109 | * --> allow = (0010) == (0010) | ||
110 | * --> allow = 1 | ||
111 | * | ||
112 | * Other examples: | ||
113 | * | ||
114 | * IFRAME-03: 0100 --> allowed | ||
115 | * IFRAME-04: 1001 --> allowed | ||
116 | * IFRAME-05: 1101 --> allowed but its not for us!!! | ||
117 | * | ||
118 | */ | ||
119 | void ath_hw_setbssidmask(struct ath_common *common) | ||
120 | { | ||
121 | void *ah = common->ah; | ||
122 | |||
123 | REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL); | ||
124 | REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU); | ||
125 | } | ||
126 | EXPORT_SYMBOL(ath_hw_setbssidmask); | ||
diff --git a/drivers/net/wireless/ath/reg.h b/drivers/net/wireless/ath/reg.h new file mode 100644 index 000000000000..dfe1fbec24f5 --- /dev/null +++ b/drivers/net/wireless/ath/reg.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef ATH_REGISTERS_H | ||
18 | #define ATH_REGISTERS_H | ||
19 | |||
20 | /* | ||
21 | * BSSID mask registers. See ath_hw_set_bssid_mask() | ||
22 | * for detailed documentation about these registers. | ||
23 | */ | ||
24 | #define AR_BSSMSKL 0x80e0 | ||
25 | #define AR_BSSMSKU 0x80e4 | ||
26 | |||
27 | #endif /* ATH_REGISTERS_H */ | ||
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index 1e318d815a5b..c6987b147af4 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -379,6 +379,8 @@ static void lpphy_save_dig_flt_state(struct b43_wldev *dev) | |||
379 | } | 379 | } |
380 | } | 380 | } |
381 | 381 | ||
382 | /* lpphy_restore_dig_flt_state is unused but kept as a reference */ | ||
383 | #if 0 | ||
382 | static void lpphy_restore_dig_flt_state(struct b43_wldev *dev) | 384 | static void lpphy_restore_dig_flt_state(struct b43_wldev *dev) |
383 | { | 385 | { |
384 | static const u16 addr[] = { | 386 | static const u16 addr[] = { |
@@ -399,6 +401,7 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev) | |||
399 | for (i = 0; i < ARRAY_SIZE(addr); i++) | 401 | for (i = 0; i < ARRAY_SIZE(addr); i++) |
400 | b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]); | 402 | b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]); |
401 | } | 403 | } |
404 | #endif | ||
402 | 405 | ||
403 | static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | 406 | static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) |
404 | { | 407 | { |
@@ -887,6 +890,8 @@ static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain) | |||
887 | } | 890 | } |
888 | } | 891 | } |
889 | 892 | ||
893 | /* lpphy_disable_rx_gain_override is unused but kept as a reference */ | ||
894 | #if 0 | ||
890 | static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) | 895 | static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) |
891 | { | 896 | { |
892 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE); | 897 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE); |
@@ -902,6 +907,7 @@ static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) | |||
902 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); | 907 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); |
903 | } | 908 | } |
904 | } | 909 | } |
910 | #endif | ||
905 | 911 | ||
906 | static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) | 912 | static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) |
907 | { | 913 | { |
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig index c15db2293515..08f1e989653d 100644 --- a/drivers/net/wireless/hostap/Kconfig +++ b/drivers/net/wireless/hostap/Kconfig | |||
@@ -2,6 +2,8 @@ config HOSTAP | |||
2 | tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)" | 2 | tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)" |
3 | depends on WLAN_80211 | 3 | depends on WLAN_80211 |
4 | select WIRELESS_EXT | 4 | select WIRELESS_EXT |
5 | select WEXT_SPY | ||
6 | select WEXT_PRIV | ||
5 | select CRYPTO | 7 | select CRYPTO |
6 | select CRYPTO_ARC4 | 8 | select CRYPTO_ARC4 |
7 | select CRYPTO_ECB | 9 | select CRYPTO_ECB |
diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig index a8131384c6b9..59ec9eec5024 100644 --- a/drivers/net/wireless/ipw2x00/Kconfig +++ b/drivers/net/wireless/ipw2x00/Kconfig | |||
@@ -6,6 +6,8 @@ config IPW2100 | |||
6 | tristate "Intel PRO/Wireless 2100 Network Connection" | 6 | tristate "Intel PRO/Wireless 2100 Network Connection" |
7 | depends on PCI && WLAN_80211 && CFG80211 | 7 | depends on PCI && WLAN_80211 && CFG80211 |
8 | select WIRELESS_EXT | 8 | select WIRELESS_EXT |
9 | select WEXT_SPY | ||
10 | select WEXT_PRIV | ||
9 | select FW_LOADER | 11 | select FW_LOADER |
10 | select LIB80211 | 12 | select LIB80211 |
11 | select LIBIPW | 13 | select LIBIPW |
@@ -63,8 +65,10 @@ config IPW2100_DEBUG | |||
63 | 65 | ||
64 | config IPW2200 | 66 | config IPW2200 |
65 | tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" | 67 | tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" |
66 | depends on PCI && WLAN_80211 && CFG80211 | 68 | depends on PCI && WLAN_80211 && CFG80211 && CFG80211_WEXT |
67 | select WIRELESS_EXT | 69 | select WIRELESS_EXT |
70 | select WEXT_SPY | ||
71 | select WEXT_PRIV | ||
68 | select FW_LOADER | 72 | select FW_LOADER |
69 | select LIB80211 | 73 | select LIB80211 |
70 | select LIBIPW | 74 | select LIBIPW |
@@ -152,6 +156,7 @@ config LIBIPW | |||
152 | tristate | 156 | tristate |
153 | depends on PCI && WLAN_80211 && CFG80211 | 157 | depends on PCI && WLAN_80211 && CFG80211 |
154 | select WIRELESS_EXT | 158 | select WIRELESS_EXT |
159 | select WEXT_SPY | ||
155 | select CRYPTO | 160 | select CRYPTO |
156 | select CRYPTO_ARC4 | 161 | select CRYPTO_ARC4 |
157 | select CRYPTO_ECB | 162 | select CRYPTO_ECB |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 8d58e6ed4e7d..61ef8904af97 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -11275,6 +11275,7 @@ static int ipw_up(struct ipw_priv *priv) | |||
11275 | if (!(priv->config & CFG_CUSTOM_MAC)) | 11275 | if (!(priv->config & CFG_CUSTOM_MAC)) |
11276 | eeprom_parse_mac(priv, priv->mac_addr); | 11276 | eeprom_parse_mac(priv, priv->mac_addr); |
11277 | memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); | 11277 | memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); |
11278 | memcpy(priv->net_dev->perm_addr, priv->mac_addr, ETH_ALEN); | ||
11278 | 11279 | ||
11279 | for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) { | 11280 | for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) { |
11280 | if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE], | 11281 | if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE], |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 99310c033253..c82c97be7bfa 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -1,17 +1,7 @@ | |||
1 | config IWLWIFI | 1 | config IWLWIFI |
2 | tristate "Intel Wireless Wifi" | 2 | tristate "Intel Wireless Wifi" |
3 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL | 3 | depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL |
4 | select LIB80211 | ||
5 | select FW_LOADER | 4 | select FW_LOADER |
6 | select MAC80211_LEDS if IWLWIFI_LEDS | ||
7 | select LEDS_CLASS if IWLWIFI_LEDS | ||
8 | |||
9 | config IWLWIFI_LEDS | ||
10 | bool "Enable LED support in iwlagn and iwl3945 drivers" | ||
11 | depends on IWLWIFI | ||
12 | default y | ||
13 | ---help--- | ||
14 | Select this if you want LED support. | ||
15 | 5 | ||
16 | config IWLWIFI_SPECTRUM_MEASUREMENT | 6 | config IWLWIFI_SPECTRUM_MEASUREMENT |
17 | bool "Enable Spectrum Measurement in iwlagn driver" | 7 | bool "Enable Spectrum Measurement in iwlagn driver" |
@@ -50,6 +40,24 @@ config IWLWIFI_DEBUGFS | |||
50 | ---help--- | 40 | ---help--- |
51 | Enable creation of debugfs files for the iwlwifi drivers. | 41 | Enable creation of debugfs files for the iwlwifi drivers. |
52 | 42 | ||
43 | config IWLWIFI_DEVICE_TRACING | ||
44 | bool "iwlwifi device access tracing" | ||
45 | depends on IWLWIFI | ||
46 | depends on EVENT_TRACING | ||
47 | help | ||
48 | Say Y here to trace all commands, including TX frames and IO | ||
49 | accesses, sent to the device. If you say yes, iwlwifi will | ||
50 | register with the ftrace framework for event tracing and dump | ||
51 | all this information to the ringbuffer, you may need to | ||
52 | increase the ringbuffer size. See the ftrace documentation | ||
53 | for more information. | ||
54 | |||
55 | When tracing is not enabled, this option still has some | ||
56 | (though rather small) overhead. | ||
57 | |||
58 | If unsure, say Y so we can help you better when problems | ||
59 | occur. | ||
60 | |||
53 | config IWLAGN | 61 | config IWLAGN |
54 | tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" | 62 | tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" |
55 | depends on IWLWIFI | 63 | depends on IWLWIFI |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 1d4e0a226fd4..7f82044af242 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -1,20 +1,22 @@ | |||
1 | obj-$(CONFIG_IWLWIFI) += iwlcore.o | 1 | obj-$(CONFIG_IWLWIFI) += iwlcore.o |
2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o | 2 | iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o |
3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o | 3 | iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o |
4 | iwlcore-objs += iwl-scan.o | 4 | iwlcore-objs += iwl-scan.o iwl-led.o |
5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 5 | iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
6 | iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o | ||
7 | iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o | 6 | iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o |
7 | iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | ||
8 | 8 | ||
9 | CFLAGS_iwl-devtrace.o := -I$(src) | ||
10 | |||
11 | # AGN | ||
9 | obj-$(CONFIG_IWLAGN) += iwlagn.o | 12 | obj-$(CONFIG_IWLAGN) += iwlagn.o |
10 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o | 13 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o |
11 | 14 | ||
12 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 15 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
13 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o | 16 | iwlagn-$(CONFIG_IWL5000) += iwl-5000.o |
14 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o | 17 | iwlagn-$(CONFIG_IWL5000) += iwl-6000.o |
15 | iwlagn-$(CONFIG_IWL5000) += iwl-1000.o | 18 | iwlagn-$(CONFIG_IWL5000) += iwl-1000.o |
16 | 19 | ||
20 | # 3945 | ||
17 | obj-$(CONFIG_IWL3945) += iwl3945.o | 21 | obj-$(CONFIG_IWL3945) += iwl3945.o |
18 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o | 22 | iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o |
19 | |||
20 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 2716b91ba9fa..679a67ff76eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-helpers.h" | 45 | #include "iwl-helpers.h" |
46 | #include "iwl-5000-hw.h" | 46 | #include "iwl-5000-hw.h" |
47 | #include "iwl-agn-led.h" | ||
47 | 48 | ||
48 | /* Highest firmware API version supported */ | 49 | /* Highest firmware API version supported */ |
49 | #define IWL1000_UCODE_API_MAX 3 | 50 | #define IWL1000_UCODE_API_MAX 3 |
@@ -76,7 +77,10 @@ static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | |||
76 | /* NIC configuration for 1000 series */ | 77 | /* NIC configuration for 1000 series */ |
77 | static void iwl1000_nic_config(struct iwl_priv *priv) | 78 | static void iwl1000_nic_config(struct iwl_priv *priv) |
78 | { | 79 | { |
79 | iwl5000_nic_config(priv); | 80 | /* set CSR_HW_CONFIG_REG for uCode use */ |
81 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
82 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
83 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
80 | 84 | ||
81 | /* Setting digital SVR for 1000 card to 1.32V */ | 85 | /* Setting digital SVR for 1000 card to 1.32V */ |
82 | /* locking is acquired in iwl_set_bits_mask_prph() function */ | 86 | /* locking is acquired in iwl_set_bits_mask_prph() function */ |
@@ -108,7 +112,7 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
108 | .apm_ops = { | 112 | .apm_ops = { |
109 | .init = iwl5000_apm_init, | 113 | .init = iwl5000_apm_init, |
110 | .reset = iwl5000_apm_reset, | 114 | .reset = iwl5000_apm_reset, |
111 | .stop = iwl5000_apm_stop, | 115 | .stop = iwl_apm_stop, |
112 | .config = iwl1000_nic_config, | 116 | .config = iwl1000_nic_config, |
113 | .set_pwr_src = iwl_set_pwr_src, | 117 | .set_pwr_src = iwl_set_pwr_src, |
114 | }, | 118 | }, |
@@ -142,6 +146,7 @@ static struct iwl_ops iwl1000_ops = { | |||
142 | .lib = &iwl1000_lib, | 146 | .lib = &iwl1000_lib, |
143 | .hcmd = &iwl5000_hcmd, | 147 | .hcmd = &iwl5000_hcmd, |
144 | .utils = &iwl5000_hcmd_utils, | 148 | .utils = &iwl5000_hcmd_utils, |
149 | .led = &iwlagn_led_ops, | ||
145 | }; | 150 | }; |
146 | 151 | ||
147 | struct iwl_cfg iwl1000_bgn_cfg = { | 152 | struct iwl_cfg iwl1000_bgn_cfg = { |
@@ -152,7 +157,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
152 | .sku = IWL_SKU_G|IWL_SKU_N, | 157 | .sku = IWL_SKU_G|IWL_SKU_N, |
153 | .ops = &iwl1000_ops, | 158 | .ops = &iwl1000_ops, |
154 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 159 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
155 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 160 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, |
156 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 161 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
157 | .mod_params = &iwl50_mod_params, | 162 | .mod_params = &iwl50_mod_params, |
158 | .valid_tx_ant = ANT_A, | 163 | .valid_tx_ant = ANT_A, |
@@ -161,5 +166,29 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
161 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | 166 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, |
162 | .shadow_ram_support = false, | 167 | .shadow_ram_support = false, |
163 | .ht_greenfield_support = true, | 168 | .ht_greenfield_support = true, |
169 | .led_compensation = 51, | ||
170 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
164 | }; | 171 | }; |
165 | 172 | ||
173 | struct iwl_cfg iwl1000_bg_cfg = { | ||
174 | .name = "1000 Series BG", | ||
175 | .fw_name_pre = IWL1000_FW_PRE, | ||
176 | .ucode_api_max = IWL1000_UCODE_API_MAX, | ||
177 | .ucode_api_min = IWL1000_UCODE_API_MIN, | ||
178 | .sku = IWL_SKU_G, | ||
179 | .ops = &iwl1000_ops, | ||
180 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
181 | .eeprom_ver = EEPROM_1000_EEPROM_VERSION, | ||
182 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
183 | .mod_params = &iwl50_mod_params, | ||
184 | .valid_tx_ant = ANT_A, | ||
185 | .valid_rx_ant = ANT_AB, | ||
186 | .need_pll_cfg = true, | ||
187 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | ||
188 | .shadow_ram_support = false, | ||
189 | .ht_greenfield_support = true, | ||
190 | .led_compensation = 51, | ||
191 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
192 | }; | ||
193 | |||
194 | MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX)); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 8c29ded7d02c..a871d09d598f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c | |||
@@ -24,8 +24,6 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #ifdef CONFIG_IWLWIFI_LEDS | ||
28 | |||
29 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 28 | #include <linux/module.h> |
31 | #include <linux/init.h> | 29 | #include <linux/init.h> |
@@ -43,388 +41,51 @@ | |||
43 | #include "iwl-3945.h" | 41 | #include "iwl-3945.h" |
44 | #include "iwl-core.h" | 42 | #include "iwl-core.h" |
45 | #include "iwl-dev.h" | 43 | #include "iwl-dev.h" |
44 | #include "iwl-3945-led.h" | ||
46 | 45 | ||
47 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
48 | static const char *led_type_str[] = { | ||
49 | __stringify(IWL_LED_TRG_TX), | ||
50 | __stringify(IWL_LED_TRG_RX), | ||
51 | __stringify(IWL_LED_TRG_ASSOC), | ||
52 | __stringify(IWL_LED_TRG_RADIO), | ||
53 | NULL | ||
54 | }; | ||
55 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
56 | |||
57 | static const struct { | ||
58 | u16 brightness; | ||
59 | u8 on_time; | ||
60 | u8 off_time; | ||
61 | } blink_tbl[] = | ||
62 | { | ||
63 | {300, 25, 25}, | ||
64 | {200, 40, 40}, | ||
65 | {100, 55, 55}, | ||
66 | {70, 65, 65}, | ||
67 | {50, 75, 75}, | ||
68 | {20, 85, 85}, | ||
69 | {15, 95, 95 }, | ||
70 | {10, 110, 110}, | ||
71 | {5, 130, 130}, | ||
72 | {0, 167, 167}, | ||
73 | /* SOLID_ON */ | ||
74 | {-1, IWL_LED_SOLID, 0} | ||
75 | }; | ||
76 | |||
77 | #define IWL_1MB_RATE (128 * 1024) | ||
78 | #define IWL_LED_THRESHOLD (16) | ||
79 | #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/ | ||
80 | #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) | ||
81 | |||
82 | static void iwl3945_led_cmd_callback(struct iwl_priv *priv, | ||
83 | struct iwl_device_cmd *cmd, | ||
84 | struct sk_buff *skb) | ||
85 | { | ||
86 | } | ||
87 | |||
88 | static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) | ||
89 | { | ||
90 | return fls(0x000000FF & (u32)brightness); | ||
91 | } | ||
92 | 46 | ||
93 | /* Send led command */ | 47 | /* Send led command */ |
94 | static int iwl_send_led_cmd(struct iwl_priv *priv, | 48 | static int iwl3945_send_led_cmd(struct iwl_priv *priv, |
95 | struct iwl_led_cmd *led_cmd) | 49 | struct iwl_led_cmd *led_cmd) |
96 | { | 50 | { |
97 | struct iwl_host_cmd cmd = { | 51 | struct iwl_host_cmd cmd = { |
98 | .id = REPLY_LEDS_CMD, | 52 | .id = REPLY_LEDS_CMD, |
99 | .len = sizeof(struct iwl_led_cmd), | 53 | .len = sizeof(struct iwl_led_cmd), |
100 | .data = led_cmd, | 54 | .data = led_cmd, |
101 | .flags = CMD_ASYNC, | 55 | .flags = CMD_ASYNC, |
102 | .callback = iwl3945_led_cmd_callback, | 56 | .callback = NULL, |
103 | }; | 57 | }; |
104 | 58 | ||
105 | return iwl_send_cmd(priv, &cmd); | 59 | return iwl_send_cmd(priv, &cmd); |
106 | } | 60 | } |
107 | 61 | ||
108 | |||
109 | |||
110 | /* Set led on command */ | ||
111 | static int iwl3945_led_pattern(struct iwl_priv *priv, int led_id, | ||
112 | unsigned int idx) | ||
113 | { | ||
114 | struct iwl_led_cmd led_cmd = { | ||
115 | .id = led_id, | ||
116 | .interval = IWL_DEF_LED_INTRVL | ||
117 | }; | ||
118 | |||
119 | BUG_ON(idx > IWL_MAX_BLINK_TBL); | ||
120 | |||
121 | led_cmd.on = blink_tbl[idx].on_time; | ||
122 | led_cmd.off = blink_tbl[idx].off_time; | ||
123 | |||
124 | return iwl_send_led_cmd(priv, &led_cmd); | ||
125 | } | ||
126 | |||
127 | |||
128 | /* Set led on command */ | 62 | /* Set led on command */ |
129 | static int iwl3945_led_on(struct iwl_priv *priv, int led_id) | 63 | static int iwl3945_led_on(struct iwl_priv *priv) |
130 | { | 64 | { |
131 | struct iwl_led_cmd led_cmd = { | 65 | struct iwl_led_cmd led_cmd = { |
132 | .id = led_id, | 66 | .id = IWL_LED_LINK, |
133 | .on = IWL_LED_SOLID, | 67 | .on = IWL_LED_SOLID, |
134 | .off = 0, | 68 | .off = 0, |
135 | .interval = IWL_DEF_LED_INTRVL | 69 | .interval = IWL_DEF_LED_INTRVL |
136 | }; | 70 | }; |
137 | return iwl_send_led_cmd(priv, &led_cmd); | 71 | return iwl3945_send_led_cmd(priv, &led_cmd); |
138 | } | 72 | } |
139 | 73 | ||
140 | /* Set led off command */ | 74 | /* Set led off command */ |
141 | static int iwl3945_led_off(struct iwl_priv *priv, int led_id) | 75 | static int iwl3945_led_off(struct iwl_priv *priv) |
142 | { | 76 | { |
143 | struct iwl_led_cmd led_cmd = { | 77 | struct iwl_led_cmd led_cmd = { |
144 | .id = led_id, | 78 | .id = IWL_LED_LINK, |
145 | .on = 0, | 79 | .on = 0, |
146 | .off = 0, | 80 | .off = 0, |
147 | .interval = IWL_DEF_LED_INTRVL | 81 | .interval = IWL_DEF_LED_INTRVL |
148 | }; | 82 | }; |
149 | IWL_DEBUG_LED(priv, "led off %d\n", led_id); | 83 | IWL_DEBUG_LED(priv, "led off\n"); |
150 | return iwl_send_led_cmd(priv, &led_cmd); | 84 | return iwl3945_send_led_cmd(priv, &led_cmd); |
151 | } | 85 | } |
152 | 86 | ||
153 | /* | 87 | const struct iwl_led_ops iwl3945_led_ops = { |
154 | * Set led on in case of association | 88 | .cmd = iwl3945_send_led_cmd, |
155 | * */ | 89 | .on = iwl3945_led_on, |
156 | static int iwl3945_led_associate(struct iwl_priv *priv, int led_id) | 90 | .off = iwl3945_led_off, |
157 | { | 91 | }; |
158 | IWL_DEBUG_LED(priv, "Associated\n"); | ||
159 | |||
160 | priv->allow_blinking = 1; | ||
161 | return iwl3945_led_on(priv, led_id); | ||
162 | } | ||
163 | /* Set Led off in case of disassociation */ | ||
164 | static int iwl3945_led_disassociate(struct iwl_priv *priv, int led_id) | ||
165 | { | ||
166 | IWL_DEBUG_LED(priv, "Disassociated\n"); | ||
167 | |||
168 | priv->allow_blinking = 0; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * brightness call back function for Tx/Rx LED | ||
175 | */ | ||
176 | static int iwl3945_led_associated(struct iwl_priv *priv, int led_id) | ||
177 | { | ||
178 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || | ||
179 | !test_bit(STATUS_READY, &priv->status)) | ||
180 | return 0; | ||
181 | |||
182 | |||
183 | /* start counting Tx/Rx bytes */ | ||
184 | if (!priv->last_blink_time && priv->allow_blinking) | ||
185 | priv->last_blink_time = jiffies; | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * brightness call back for association and radio | ||
191 | */ | ||
192 | static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, | ||
193 | enum led_brightness brightness) | ||
194 | { | ||
195 | struct iwl_led *led = container_of(led_cdev, | ||
196 | struct iwl_led, led_dev); | ||
197 | struct iwl_priv *priv = led->priv; | ||
198 | |||
199 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
200 | return; | ||
201 | |||
202 | IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n", | ||
203 | led_type_str[led->type], brightness); | ||
204 | |||
205 | switch (brightness) { | ||
206 | case LED_FULL: | ||
207 | if (led->led_on) | ||
208 | led->led_on(priv, IWL_LED_LINK); | ||
209 | break; | ||
210 | case LED_OFF: | ||
211 | if (led->led_off) | ||
212 | led->led_off(priv, IWL_LED_LINK); | ||
213 | break; | ||
214 | default: | ||
215 | if (led->led_pattern) { | ||
216 | int idx = iwl3945_brightness_to_idx(brightness); | ||
217 | led->led_pattern(priv, IWL_LED_LINK, idx); | ||
218 | } | ||
219 | break; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Register led class with the system | ||
225 | */ | ||
226 | static int iwl3945_led_register_led(struct iwl_priv *priv, | ||
227 | struct iwl_led *led, | ||
228 | enum led_type type, u8 set_led, | ||
229 | char *trigger) | ||
230 | { | ||
231 | struct device *device = wiphy_dev(priv->hw->wiphy); | ||
232 | int ret; | ||
233 | |||
234 | led->led_dev.name = led->name; | ||
235 | led->led_dev.brightness_set = iwl3945_led_brightness_set; | ||
236 | led->led_dev.default_trigger = trigger; | ||
237 | |||
238 | led->priv = priv; | ||
239 | led->type = type; | ||
240 | |||
241 | ret = led_classdev_register(device, &led->led_dev); | ||
242 | if (ret) { | ||
243 | IWL_ERR(priv, "Error: failed to register led handler.\n"); | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | led->registered = 1; | ||
248 | |||
249 | if (set_led && led->led_on) | ||
250 | led->led_on(priv, IWL_LED_LINK); | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | |||
255 | /* | ||
256 | * calculate blink rate according to last 2 sec Tx/Rx activities | ||
257 | */ | ||
258 | static inline u8 get_blink_rate(struct iwl_priv *priv) | ||
259 | { | ||
260 | int index; | ||
261 | s64 tpt = priv->rxtxpackets; | ||
262 | |||
263 | if (tpt < 0) | ||
264 | tpt = -tpt; | ||
265 | |||
266 | IWL_DEBUG_LED(priv, "tpt %lld \n", (long long)tpt); | ||
267 | |||
268 | if (!priv->allow_blinking) | ||
269 | index = IWL_MAX_BLINK_TBL; | ||
270 | else | ||
271 | for (index = 0; index < IWL_MAX_BLINK_TBL; index++) | ||
272 | if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE)) | ||
273 | break; | ||
274 | |||
275 | IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", index); | ||
276 | return index; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * this function called from handler. Since setting Led command can | ||
281 | * happen very frequent we postpone led command to be called from | ||
282 | * REPLY handler so we know ucode is up | ||
283 | */ | ||
284 | void iwl3945_led_background(struct iwl_priv *priv) | ||
285 | { | ||
286 | u8 blink_idx; | ||
287 | |||
288 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
289 | priv->last_blink_time = 0; | ||
290 | return; | ||
291 | } | ||
292 | if (iwl_is_rfkill(priv)) { | ||
293 | priv->last_blink_time = 0; | ||
294 | return; | ||
295 | } | ||
296 | |||
297 | if (!priv->allow_blinking) { | ||
298 | priv->last_blink_time = 0; | ||
299 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { | ||
300 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; | ||
301 | iwl3945_led_pattern(priv, IWL_LED_LINK, | ||
302 | IWL_SOLID_BLINK_IDX); | ||
303 | } | ||
304 | return; | ||
305 | } | ||
306 | if (!priv->last_blink_time || | ||
307 | !time_after(jiffies, priv->last_blink_time + | ||
308 | msecs_to_jiffies(1000))) | ||
309 | return; | ||
310 | |||
311 | blink_idx = get_blink_rate(priv); | ||
312 | |||
313 | /* call only if blink rate change */ | ||
314 | if (blink_idx != priv->last_blink_rate) | ||
315 | iwl3945_led_pattern(priv, IWL_LED_LINK, blink_idx); | ||
316 | |||
317 | priv->last_blink_time = jiffies; | ||
318 | priv->last_blink_rate = blink_idx; | ||
319 | priv->rxtxpackets = 0; | ||
320 | } | ||
321 | |||
322 | |||
323 | /* Register all led handler */ | ||
324 | int iwl3945_led_register(struct iwl_priv *priv) | ||
325 | { | ||
326 | char *trigger; | ||
327 | int ret; | ||
328 | |||
329 | priv->last_blink_rate = 0; | ||
330 | priv->rxtxpackets = 0; | ||
331 | priv->led_tpt = 0; | ||
332 | priv->last_blink_time = 0; | ||
333 | priv->allow_blinking = 0; | ||
334 | |||
335 | trigger = ieee80211_get_radio_led_name(priv->hw); | ||
336 | snprintf(priv->led[IWL_LED_TRG_RADIO].name, | ||
337 | sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", | ||
338 | wiphy_name(priv->hw->wiphy)); | ||
339 | |||
340 | priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; | ||
341 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; | ||
342 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; | ||
343 | |||
344 | ret = iwl3945_led_register_led(priv, | ||
345 | &priv->led[IWL_LED_TRG_RADIO], | ||
346 | IWL_LED_TRG_RADIO, 1, trigger); | ||
347 | |||
348 | if (ret) | ||
349 | goto exit_fail; | ||
350 | |||
351 | trigger = ieee80211_get_assoc_led_name(priv->hw); | ||
352 | snprintf(priv->led[IWL_LED_TRG_ASSOC].name, | ||
353 | sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", | ||
354 | wiphy_name(priv->hw->wiphy)); | ||
355 | |||
356 | ret = iwl3945_led_register_led(priv, | ||
357 | &priv->led[IWL_LED_TRG_ASSOC], | ||
358 | IWL_LED_TRG_ASSOC, 0, trigger); | ||
359 | |||
360 | /* for assoc always turn led on */ | ||
361 | priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_associate; | ||
362 | priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_disassociate; | ||
363 | priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; | ||
364 | |||
365 | if (ret) | ||
366 | goto exit_fail; | ||
367 | |||
368 | trigger = ieee80211_get_rx_led_name(priv->hw); | ||
369 | snprintf(priv->led[IWL_LED_TRG_RX].name, | ||
370 | sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX", | ||
371 | wiphy_name(priv->hw->wiphy)); | ||
372 | |||
373 | ret = iwl3945_led_register_led(priv, | ||
374 | &priv->led[IWL_LED_TRG_RX], | ||
375 | IWL_LED_TRG_RX, 0, trigger); | ||
376 | |||
377 | priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; | ||
378 | priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; | ||
379 | priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; | ||
380 | |||
381 | if (ret) | ||
382 | goto exit_fail; | ||
383 | |||
384 | trigger = ieee80211_get_tx_led_name(priv->hw); | ||
385 | snprintf(priv->led[IWL_LED_TRG_TX].name, | ||
386 | sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX", | ||
387 | wiphy_name(priv->hw->wiphy)); | ||
388 | |||
389 | ret = iwl3945_led_register_led(priv, | ||
390 | &priv->led[IWL_LED_TRG_TX], | ||
391 | IWL_LED_TRG_TX, 0, trigger); | ||
392 | |||
393 | priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; | ||
394 | priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; | ||
395 | priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; | ||
396 | |||
397 | if (ret) | ||
398 | goto exit_fail; | ||
399 | |||
400 | return 0; | ||
401 | |||
402 | exit_fail: | ||
403 | iwl3945_led_unregister(priv); | ||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | |||
408 | /* unregister led class */ | ||
409 | static void iwl3945_led_unregister_led(struct iwl_led *led, u8 set_led) | ||
410 | { | ||
411 | if (!led->registered) | ||
412 | return; | ||
413 | |||
414 | led_classdev_unregister(&led->led_dev); | ||
415 | |||
416 | if (set_led) | ||
417 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | ||
418 | led->registered = 0; | ||
419 | } | ||
420 | |||
421 | /* Unregister all led handlers */ | ||
422 | void iwl3945_led_unregister(struct iwl_priv *priv) | ||
423 | { | ||
424 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); | ||
425 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); | ||
426 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); | ||
427 | iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); | ||
428 | } | ||
429 | |||
430 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 3b65642258ca..5a1033ca7aaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h | |||
@@ -24,23 +24,9 @@ | |||
24 | * | 24 | * |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #ifndef IWL3945_LEDS_H | 27 | #ifndef __iwl_3945_led_h__ |
28 | #define IWL3945_LEDS_H | 28 | #define __iwl_3945_led_h__ |
29 | 29 | ||
30 | struct iwl_priv; | 30 | extern const struct iwl_led_ops iwl3945_led_ops; |
31 | 31 | ||
32 | #ifdef CONFIG_IWLWIFI_LEDS | 32 | #endif /* __iwl_3945_led_h__ */ |
33 | |||
34 | #include "iwl-led.h" | ||
35 | |||
36 | extern int iwl3945_led_register(struct iwl_priv *priv); | ||
37 | extern void iwl3945_led_unregister(struct iwl_priv *priv); | ||
38 | extern void iwl3945_led_background(struct iwl_priv *priv); | ||
39 | |||
40 | #else | ||
41 | static inline int iwl3945_led_register(struct iwl_priv *priv) { return 0; } | ||
42 | static inline void iwl3945_led_unregister(struct iwl_priv *priv) {} | ||
43 | static inline void iwl3945_led_background(struct iwl_priv *priv) {} | ||
44 | |||
45 | #endif /* IWLWIFI_LEDS*/ | ||
46 | #endif /* IWL3945_LEDS_H */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index e70c5b0af364..ced0e33e44b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -46,7 +46,8 @@ | |||
46 | #include "iwl-eeprom.h" | 46 | #include "iwl-eeprom.h" |
47 | #include "iwl-helpers.h" | 47 | #include "iwl-helpers.h" |
48 | #include "iwl-core.h" | 48 | #include "iwl-core.h" |
49 | #include "iwl-agn-rs.h" | 49 | #include "iwl-led.h" |
50 | #include "iwl-3945-led.h" | ||
50 | 51 | ||
51 | #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ | 52 | #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ |
52 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ | 53 | [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ |
@@ -359,7 +360,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv, | |||
359 | 360 | ||
360 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); | 361 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); |
361 | 362 | ||
362 | iwl3945_led_background(priv); | 363 | iwl_leds_background(priv); |
363 | 364 | ||
364 | priv->last_statistics_time = jiffies; | 365 | priv->last_statistics_time = jiffies; |
365 | } | 366 | } |
@@ -572,10 +573,6 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
572 | (struct ieee80211_hdr *)rxb->skb->data, | 573 | (struct ieee80211_hdr *)rxb->skb->data, |
573 | le32_to_cpu(rx_end->status), stats); | 574 | le32_to_cpu(rx_end->status), stats); |
574 | 575 | ||
575 | #ifdef CONFIG_IWLWIFI_LEDS | ||
576 | if (ieee80211_is_data(hdr->frame_control)) | ||
577 | priv->rxtxpackets += len; | ||
578 | #endif | ||
579 | iwl_update_stats(priv, false, hdr->frame_control, len); | 576 | iwl_update_stats(priv, false, hdr->frame_control, len); |
580 | 577 | ||
581 | memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); | 578 | memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); |
@@ -1002,8 +999,9 @@ static int iwl3945_apm_init(struct iwl_priv *priv) | |||
1002 | * D0U* --> D0A* state */ | 999 | * D0U* --> D0A* state */ |
1003 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 1000 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
1004 | 1001 | ||
1005 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | 1002 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, |
1006 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | 1003 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, |
1004 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1007 | if (ret < 0) { | 1005 | if (ret < 0) { |
1008 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | 1006 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); |
1009 | goto out; | 1007 | goto out; |
@@ -1170,48 +1168,9 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) | |||
1170 | iwl3945_hw_txq_ctx_free(priv); | 1168 | iwl3945_hw_txq_ctx_free(priv); |
1171 | } | 1169 | } |
1172 | 1170 | ||
1173 | static int iwl3945_apm_stop_master(struct iwl_priv *priv) | ||
1174 | { | ||
1175 | int ret = 0; | ||
1176 | unsigned long flags; | ||
1177 | |||
1178 | spin_lock_irqsave(&priv->lock, flags); | ||
1179 | |||
1180 | /* set stop master bit */ | ||
1181 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
1182 | |||
1183 | iwl_poll_direct_bit(priv, CSR_RESET, | ||
1184 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
1185 | |||
1186 | if (ret < 0) | ||
1187 | goto out; | ||
1188 | |||
1189 | out: | ||
1190 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1191 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
1192 | |||
1193 | return ret; | ||
1194 | } | ||
1195 | |||
1196 | static void iwl3945_apm_stop(struct iwl_priv *priv) | ||
1197 | { | ||
1198 | unsigned long flags; | ||
1199 | |||
1200 | iwl3945_apm_stop_master(priv); | ||
1201 | |||
1202 | spin_lock_irqsave(&priv->lock, flags); | ||
1203 | |||
1204 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
1205 | |||
1206 | udelay(10); | ||
1207 | /* clear "init complete" move adapter D0A* --> D0U state */ | ||
1208 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1209 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1210 | } | ||
1211 | |||
1212 | static int iwl3945_apm_reset(struct iwl_priv *priv) | 1171 | static int iwl3945_apm_reset(struct iwl_priv *priv) |
1213 | { | 1172 | { |
1214 | iwl3945_apm_stop_master(priv); | 1173 | iwl_apm_stop_master(priv); |
1215 | 1174 | ||
1216 | 1175 | ||
1217 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | 1176 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); |
@@ -1219,8 +1178,9 @@ static int iwl3945_apm_reset(struct iwl_priv *priv) | |||
1219 | 1178 | ||
1220 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 1179 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
1221 | 1180 | ||
1222 | iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | 1181 | iwl_poll_bit(priv, CSR_GP_CNTRL, |
1223 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | 1182 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, |
1183 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
1224 | 1184 | ||
1225 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, | 1185 | iwl_write_prph(priv, APMG_CLK_CTRL_REG, |
1226 | APMG_CLK_VAL_BSM_CLK_RQT); | 1186 | APMG_CLK_VAL_BSM_CLK_RQT); |
@@ -2844,7 +2804,7 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2844 | .apm_ops = { | 2804 | .apm_ops = { |
2845 | .init = iwl3945_apm_init, | 2805 | .init = iwl3945_apm_init, |
2846 | .reset = iwl3945_apm_reset, | 2806 | .reset = iwl3945_apm_reset, |
2847 | .stop = iwl3945_apm_stop, | 2807 | .stop = iwl_apm_stop, |
2848 | .config = iwl3945_nic_config, | 2808 | .config = iwl3945_nic_config, |
2849 | .set_pwr_src = iwl3945_set_pwr_src, | 2809 | .set_pwr_src = iwl3945_set_pwr_src, |
2850 | }, | 2810 | }, |
@@ -2880,6 +2840,7 @@ static struct iwl_ops iwl3945_ops = { | |||
2880 | .lib = &iwl3945_lib, | 2840 | .lib = &iwl3945_lib, |
2881 | .hcmd = &iwl3945_hcmd, | 2841 | .hcmd = &iwl3945_hcmd, |
2882 | .utils = &iwl3945_hcmd_utils, | 2842 | .utils = &iwl3945_hcmd_utils, |
2843 | .led = &iwl3945_led_ops, | ||
2883 | }; | 2844 | }; |
2884 | 2845 | ||
2885 | static struct iwl_cfg iwl3945_bg_cfg = { | 2846 | static struct iwl_cfg iwl3945_bg_cfg = { |
@@ -2894,6 +2855,7 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2894 | .mod_params = &iwl3945_mod_params, | 2855 | .mod_params = &iwl3945_mod_params, |
2895 | .use_isr_legacy = true, | 2856 | .use_isr_legacy = true, |
2896 | .ht_greenfield_support = false, | 2857 | .ht_greenfield_support = false, |
2858 | .led_compensation = 64, | ||
2897 | }; | 2859 | }; |
2898 | 2860 | ||
2899 | static struct iwl_cfg iwl3945_abg_cfg = { | 2861 | static struct iwl_cfg iwl3945_abg_cfg = { |
@@ -2908,6 +2870,7 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2908 | .mod_params = &iwl3945_mod_params, | 2870 | .mod_params = &iwl3945_mod_params, |
2909 | .use_isr_legacy = true, | 2871 | .use_isr_legacy = true, |
2910 | .ht_greenfield_support = false, | 2872 | .ht_greenfield_support = false, |
2873 | .led_compensation = 64, | ||
2911 | }; | 2874 | }; |
2912 | 2875 | ||
2913 | struct pci_device_id iwl3945_hw_card_ids[] = { | 2876 | struct pci_device_id iwl3945_hw_card_ids[] = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 21679bf3a1aa..f3907c1079f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -46,7 +46,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; | |||
46 | #include "iwl-debug.h" | 46 | #include "iwl-debug.h" |
47 | #include "iwl-power.h" | 47 | #include "iwl-power.h" |
48 | #include "iwl-dev.h" | 48 | #include "iwl-dev.h" |
49 | #include "iwl-3945-led.h" | 49 | #include "iwl-led.h" |
50 | 50 | ||
51 | /* Highest firmware API version supported */ | 51 | /* Highest firmware API version supported */ |
52 | #define IWL3945_UCODE_API_MAX 2 | 52 | #define IWL3945_UCODE_API_MAX 2 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a22a0501c190..f8eed9a4abc1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include "iwl-helpers.h" | 44 | #include "iwl-helpers.h" |
45 | #include "iwl-calib.h" | 45 | #include "iwl-calib.h" |
46 | #include "iwl-sta.h" | 46 | #include "iwl-sta.h" |
47 | #include "iwl-agn-led.h" | ||
47 | 48 | ||
48 | static int iwl4965_send_tx_power(struct iwl_priv *priv); | 49 | static int iwl4965_send_tx_power(struct iwl_priv *priv); |
49 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); | 50 | static int iwl4965_hw_get_temperature(struct iwl_priv *priv); |
@@ -334,7 +335,8 @@ static int iwl4965_apm_init(struct iwl_priv *priv) | |||
334 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 335 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
335 | 336 | ||
336 | /* wait for clock stabilization */ | 337 | /* wait for clock stabilization */ |
337 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | 338 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, |
339 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
338 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | 340 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); |
339 | if (ret < 0) { | 341 | if (ret < 0) { |
340 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | 342 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); |
@@ -395,45 +397,11 @@ static void iwl4965_nic_config(struct iwl_priv *priv) | |||
395 | spin_unlock_irqrestore(&priv->lock, flags); | 397 | spin_unlock_irqrestore(&priv->lock, flags); |
396 | } | 398 | } |
397 | 399 | ||
398 | static int iwl4965_apm_stop_master(struct iwl_priv *priv) | ||
399 | { | ||
400 | unsigned long flags; | ||
401 | |||
402 | spin_lock_irqsave(&priv->lock, flags); | ||
403 | |||
404 | /* set stop master bit */ | ||
405 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
406 | |||
407 | iwl_poll_direct_bit(priv, CSR_RESET, | ||
408 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
409 | |||
410 | spin_unlock_irqrestore(&priv->lock, flags); | ||
411 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static void iwl4965_apm_stop(struct iwl_priv *priv) | ||
417 | { | ||
418 | unsigned long flags; | ||
419 | |||
420 | iwl4965_apm_stop_master(priv); | ||
421 | |||
422 | spin_lock_irqsave(&priv->lock, flags); | ||
423 | |||
424 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
425 | |||
426 | udelay(10); | ||
427 | /* clear "init complete" move adapter D0A* --> D0U state */ | ||
428 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
429 | spin_unlock_irqrestore(&priv->lock, flags); | ||
430 | } | ||
431 | |||
432 | static int iwl4965_apm_reset(struct iwl_priv *priv) | 400 | static int iwl4965_apm_reset(struct iwl_priv *priv) |
433 | { | 401 | { |
434 | int ret = 0; | 402 | int ret = 0; |
435 | 403 | ||
436 | iwl4965_apm_stop_master(priv); | 404 | iwl_apm_stop_master(priv); |
437 | 405 | ||
438 | 406 | ||
439 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | 407 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); |
@@ -444,7 +412,8 @@ static int iwl4965_apm_reset(struct iwl_priv *priv) | |||
444 | 412 | ||
445 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 413 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
446 | 414 | ||
447 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | 415 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, |
416 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
448 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | 417 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); |
449 | if (ret < 0) | 418 | if (ret < 0) |
450 | goto out; | 419 | goto out; |
@@ -495,14 +464,15 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv) | |||
495 | static void iwl4965_gain_computation(struct iwl_priv *priv, | 464 | static void iwl4965_gain_computation(struct iwl_priv *priv, |
496 | u32 *average_noise, | 465 | u32 *average_noise, |
497 | u16 min_average_noise_antenna_i, | 466 | u16 min_average_noise_antenna_i, |
498 | u32 min_average_noise) | 467 | u32 min_average_noise, |
468 | u8 default_chain) | ||
499 | { | 469 | { |
500 | int i, ret; | 470 | int i, ret; |
501 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 471 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
502 | 472 | ||
503 | data->delta_gain_code[min_average_noise_antenna_i] = 0; | 473 | data->delta_gain_code[min_average_noise_antenna_i] = 0; |
504 | 474 | ||
505 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 475 | for (i = default_chain; i < NUM_RX_CHAINS; i++) { |
506 | s32 delta_g = 0; | 476 | s32 delta_g = 0; |
507 | 477 | ||
508 | if (!(data->disconn_array[i]) && | 478 | if (!(data->disconn_array[i]) && |
@@ -662,7 +632,8 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
662 | iwl_write_targ_mem(priv, a, 0); | 632 | iwl_write_targ_mem(priv, a, 0); |
663 | for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4) | 633 | for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4) |
664 | iwl_write_targ_mem(priv, a, 0); | 634 | iwl_write_targ_mem(priv, a, 0); |
665 | for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) | 635 | for (; a < priv->scd_base_addr + |
636 | IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
666 | iwl_write_targ_mem(priv, a, 0); | 637 | iwl_write_targ_mem(priv, a, 0); |
667 | 638 | ||
668 | /* Tel 4965 where to find Tx byte count tables */ | 639 | /* Tel 4965 where to find Tx byte count tables */ |
@@ -2303,7 +2274,7 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2303 | .apm_ops = { | 2274 | .apm_ops = { |
2304 | .init = iwl4965_apm_init, | 2275 | .init = iwl4965_apm_init, |
2305 | .reset = iwl4965_apm_reset, | 2276 | .reset = iwl4965_apm_reset, |
2306 | .stop = iwl4965_apm_stop, | 2277 | .stop = iwl_apm_stop, |
2307 | .config = iwl4965_nic_config, | 2278 | .config = iwl4965_nic_config, |
2308 | .set_pwr_src = iwl_set_pwr_src, | 2279 | .set_pwr_src = iwl_set_pwr_src, |
2309 | }, | 2280 | }, |
@@ -2339,6 +2310,7 @@ static struct iwl_ops iwl4965_ops = { | |||
2339 | .lib = &iwl4965_lib, | 2310 | .lib = &iwl4965_lib, |
2340 | .hcmd = &iwl4965_hcmd, | 2311 | .hcmd = &iwl4965_hcmd, |
2341 | .utils = &iwl4965_hcmd_utils, | 2312 | .utils = &iwl4965_hcmd_utils, |
2313 | .led = &iwlagn_led_ops, | ||
2342 | }; | 2314 | }; |
2343 | 2315 | ||
2344 | struct iwl_cfg iwl4965_agn_cfg = { | 2316 | struct iwl_cfg iwl4965_agn_cfg = { |
@@ -2355,26 +2327,29 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2355 | .use_isr_legacy = true, | 2327 | .use_isr_legacy = true, |
2356 | .ht_greenfield_support = false, | 2328 | .ht_greenfield_support = false, |
2357 | .broken_powersave = true, | 2329 | .broken_powersave = true, |
2330 | .led_compensation = 61, | ||
2331 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | ||
2358 | }; | 2332 | }; |
2359 | 2333 | ||
2360 | /* Module firmware */ | 2334 | /* Module firmware */ |
2361 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); | 2335 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); |
2362 | 2336 | ||
2363 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); | 2337 | module_param_named(antenna, iwl4965_mod_params.antenna, int, S_IRUGO); |
2364 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 2338 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |
2365 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); | 2339 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO); |
2366 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | 2340 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); |
2367 | module_param_named( | 2341 | module_param_named( |
2368 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); | 2342 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, S_IRUGO); |
2369 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 2343 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
2370 | 2344 | ||
2371 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444); | 2345 | module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO); |
2372 | MODULE_PARM_DESC(queues_num, "number of hw queues."); | 2346 | MODULE_PARM_DESC(queues_num, "number of hw queues."); |
2373 | /* 11n */ | 2347 | /* 11n */ |
2374 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, 0444); | 2348 | module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO); |
2375 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); | 2349 | MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); |
2376 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444); | 2350 | module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, |
2351 | int, S_IRUGO); | ||
2377 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | 2352 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); |
2378 | 2353 | ||
2379 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, 0444); | 2354 | module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, S_IRUGO); |
2380 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); | 2355 | MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index eb08f4411000..98baf8af6da8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "iwl-io.h" | 42 | #include "iwl-io.h" |
43 | #include "iwl-sta.h" | 43 | #include "iwl-sta.h" |
44 | #include "iwl-helpers.h" | 44 | #include "iwl-helpers.h" |
45 | #include "iwl-agn-led.h" | ||
45 | #include "iwl-5000-hw.h" | 46 | #include "iwl-5000-hw.h" |
46 | #include "iwl-6000-hw.h" | 47 | #include "iwl-6000-hw.h" |
47 | 48 | ||
@@ -71,26 +72,6 @@ static const u16 iwl5000_default_queue_to_tx_fifo[] = { | |||
71 | IWL_TX_FIFO_HCCA_2 | 72 | IWL_TX_FIFO_HCCA_2 |
72 | }; | 73 | }; |
73 | 74 | ||
74 | /* FIXME: same implementation as 4965 */ | ||
75 | static int iwl5000_apm_stop_master(struct iwl_priv *priv) | ||
76 | { | ||
77 | unsigned long flags; | ||
78 | |||
79 | spin_lock_irqsave(&priv->lock, flags); | ||
80 | |||
81 | /* set stop master bit */ | ||
82 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
83 | |||
84 | iwl_poll_direct_bit(priv, CSR_RESET, | ||
85 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
86 | |||
87 | spin_unlock_irqrestore(&priv->lock, flags); | ||
88 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | |||
94 | int iwl5000_apm_init(struct iwl_priv *priv) | 75 | int iwl5000_apm_init(struct iwl_priv *priv) |
95 | { | 76 | { |
96 | int ret = 0; | 77 | int ret = 0; |
@@ -117,7 +98,8 @@ int iwl5000_apm_init(struct iwl_priv *priv) | |||
117 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 98 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
118 | 99 | ||
119 | /* wait for clock stabilization */ | 100 | /* wait for clock stabilization */ |
120 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | 101 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, |
102 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
121 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | 103 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); |
122 | if (ret < 0) { | 104 | if (ret < 0) { |
123 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | 105 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); |
@@ -136,31 +118,11 @@ int iwl5000_apm_init(struct iwl_priv *priv) | |||
136 | return ret; | 118 | return ret; |
137 | } | 119 | } |
138 | 120 | ||
139 | /* FIXME: this is identical to 4965 */ | ||
140 | void iwl5000_apm_stop(struct iwl_priv *priv) | ||
141 | { | ||
142 | unsigned long flags; | ||
143 | |||
144 | iwl5000_apm_stop_master(priv); | ||
145 | |||
146 | spin_lock_irqsave(&priv->lock, flags); | ||
147 | |||
148 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
149 | |||
150 | udelay(10); | ||
151 | |||
152 | /* clear "init complete" move adapter D0A* --> D0U state */ | ||
153 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
154 | |||
155 | spin_unlock_irqrestore(&priv->lock, flags); | ||
156 | } | ||
157 | |||
158 | |||
159 | int iwl5000_apm_reset(struct iwl_priv *priv) | 121 | int iwl5000_apm_reset(struct iwl_priv *priv) |
160 | { | 122 | { |
161 | int ret = 0; | 123 | int ret = 0; |
162 | 124 | ||
163 | iwl5000_apm_stop_master(priv); | 125 | iwl_apm_stop_master(priv); |
164 | 126 | ||
165 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | 127 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); |
166 | 128 | ||
@@ -177,7 +139,8 @@ int iwl5000_apm_reset(struct iwl_priv *priv) | |||
177 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 139 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
178 | 140 | ||
179 | /* wait for clock stabilization */ | 141 | /* wait for clock stabilization */ |
180 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | 142 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, |
143 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
181 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | 144 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); |
182 | if (ret < 0) { | 145 | if (ret < 0) { |
183 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); | 146 | IWL_DEBUG_INFO(priv, "Failed to init the card\n"); |
@@ -198,7 +161,7 @@ out: | |||
198 | } | 161 | } |
199 | 162 | ||
200 | 163 | ||
201 | /* NIC configuration for 5000 series and up */ | 164 | /* NIC configuration for 5000 series */ |
202 | void iwl5000_nic_config(struct iwl_priv *priv) | 165 | void iwl5000_nic_config(struct iwl_priv *priv) |
203 | { | 166 | { |
204 | unsigned long flags; | 167 | unsigned long flags; |
@@ -221,7 +184,7 @@ void iwl5000_nic_config(struct iwl_priv *priv) | |||
221 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | 184 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); |
222 | 185 | ||
223 | /* write radio config values to register */ | 186 | /* write radio config values to register */ |
224 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_5000_RF_CFG_TYPE_MAX) | 187 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_RF_CONFIG_TYPE_MAX) |
225 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | 188 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, |
226 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | 189 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | |
227 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | 190 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | |
@@ -301,14 +264,17 @@ u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv) | |||
301 | static void iwl5000_gain_computation(struct iwl_priv *priv, | 264 | static void iwl5000_gain_computation(struct iwl_priv *priv, |
302 | u32 average_noise[NUM_RX_CHAINS], | 265 | u32 average_noise[NUM_RX_CHAINS], |
303 | u16 min_average_noise_antenna_i, | 266 | u16 min_average_noise_antenna_i, |
304 | u32 min_average_noise) | 267 | u32 min_average_noise, |
268 | u8 default_chain) | ||
305 | { | 269 | { |
306 | int i; | 270 | int i; |
307 | s32 delta_g; | 271 | s32 delta_g; |
308 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | 272 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; |
309 | 273 | ||
310 | /* Find Gain Code for the antennas B and C */ | 274 | /* |
311 | for (i = 1; i < NUM_RX_CHAINS; i++) { | 275 | * Find Gain Code for the chains based on "default chain" |
276 | */ | ||
277 | for (i = default_chain + 1; i < NUM_RX_CHAINS; i++) { | ||
312 | if ((data->disconn_array[i])) { | 278 | if ((data->disconn_array[i])) { |
313 | data->delta_gain_code[i] = 0; | 279 | data->delta_gain_code[i] = 0; |
314 | continue; | 280 | continue; |
@@ -745,7 +711,8 @@ int iwl5000_alive_notify(struct iwl_priv *priv) | |||
745 | for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; | 711 | for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; |
746 | a += 4) | 712 | a += 4) |
747 | iwl_write_targ_mem(priv, a, 0); | 713 | iwl_write_targ_mem(priv, a, 0); |
748 | for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) | 714 | for (; a < priv->scd_base_addr + |
715 | IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4) | ||
749 | iwl_write_targ_mem(priv, a, 0); | 716 | iwl_write_targ_mem(priv, a, 0); |
750 | 717 | ||
751 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, | 718 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, |
@@ -833,16 +800,8 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
833 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | 800 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; |
834 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | 801 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; |
835 | 802 | ||
836 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | 803 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; |
837 | case CSR_HW_REV_TYPE_6x00: | 804 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; |
838 | case CSR_HW_REV_TYPE_6x50: | ||
839 | priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; | ||
840 | priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; | ||
841 | break; | ||
842 | default: | ||
843 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | ||
844 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | ||
845 | } | ||
846 | 805 | ||
847 | priv->hw_params.max_bsm_size = 0; | 806 | priv->hw_params.max_bsm_size = 0; |
848 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | 807 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | |
@@ -1458,6 +1417,24 @@ int iwl5000_calc_rssi(struct iwl_priv *priv, | |||
1458 | return max_rssi - agc - IWL49_RSSI_OFFSET; | 1417 | return max_rssi - agc - IWL49_RSSI_OFFSET; |
1459 | } | 1418 | } |
1460 | 1419 | ||
1420 | static int iwl5000_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | ||
1421 | { | ||
1422 | struct iwl_tx_ant_config_cmd tx_ant_cmd = { | ||
1423 | .valid = cpu_to_le32(valid_tx_ant), | ||
1424 | }; | ||
1425 | |||
1426 | if (IWL_UCODE_API(priv->ucode_ver) > 1) { | ||
1427 | IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant); | ||
1428 | return iwl_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, | ||
1429 | sizeof(struct iwl_tx_ant_config_cmd), | ||
1430 | &tx_ant_cmd); | ||
1431 | } else { | ||
1432 | IWL_DEBUG_HC(priv, "TX_ANT_CONFIGURATION_CMD not supported\n"); | ||
1433 | return -EOPNOTSUPP; | ||
1434 | } | ||
1435 | } | ||
1436 | |||
1437 | |||
1461 | #define IWL5000_UCODE_GET(item) \ | 1438 | #define IWL5000_UCODE_GET(item) \ |
1462 | static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ | 1439 | static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ |
1463 | u32 api_ver) \ | 1440 | u32 api_ver) \ |
@@ -1500,6 +1477,7 @@ struct iwl_hcmd_ops iwl5000_hcmd = { | |||
1500 | .rxon_assoc = iwl5000_send_rxon_assoc, | 1477 | .rxon_assoc = iwl5000_send_rxon_assoc, |
1501 | .commit_rxon = iwl_commit_rxon, | 1478 | .commit_rxon = iwl_commit_rxon, |
1502 | .set_rxon_chain = iwl_set_rxon_chain, | 1479 | .set_rxon_chain = iwl_set_rxon_chain, |
1480 | .set_tx_ant = iwl5000_send_tx_ant_config, | ||
1503 | }; | 1481 | }; |
1504 | 1482 | ||
1505 | struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | 1483 | struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { |
@@ -1545,7 +1523,7 @@ struct iwl_lib_ops iwl5000_lib = { | |||
1545 | .apm_ops = { | 1523 | .apm_ops = { |
1546 | .init = iwl5000_apm_init, | 1524 | .init = iwl5000_apm_init, |
1547 | .reset = iwl5000_apm_reset, | 1525 | .reset = iwl5000_apm_reset, |
1548 | .stop = iwl5000_apm_stop, | 1526 | .stop = iwl_apm_stop, |
1549 | .config = iwl5000_nic_config, | 1527 | .config = iwl5000_nic_config, |
1550 | .set_pwr_src = iwl_set_pwr_src, | 1528 | .set_pwr_src = iwl_set_pwr_src, |
1551 | }, | 1529 | }, |
@@ -1597,7 +1575,7 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1597 | .apm_ops = { | 1575 | .apm_ops = { |
1598 | .init = iwl5000_apm_init, | 1576 | .init = iwl5000_apm_init, |
1599 | .reset = iwl5000_apm_reset, | 1577 | .reset = iwl5000_apm_reset, |
1600 | .stop = iwl5000_apm_stop, | 1578 | .stop = iwl_apm_stop, |
1601 | .config = iwl5000_nic_config, | 1579 | .config = iwl5000_nic_config, |
1602 | .set_pwr_src = iwl_set_pwr_src, | 1580 | .set_pwr_src = iwl_set_pwr_src, |
1603 | }, | 1581 | }, |
@@ -1626,11 +1604,12 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
1626 | }, | 1604 | }, |
1627 | }; | 1605 | }; |
1628 | 1606 | ||
1629 | struct iwl_ops iwl5000_ops = { | 1607 | static struct iwl_ops iwl5000_ops = { |
1630 | .ucode = &iwl5000_ucode, | 1608 | .ucode = &iwl5000_ucode, |
1631 | .lib = &iwl5000_lib, | 1609 | .lib = &iwl5000_lib, |
1632 | .hcmd = &iwl5000_hcmd, | 1610 | .hcmd = &iwl5000_hcmd, |
1633 | .utils = &iwl5000_hcmd_utils, | 1611 | .utils = &iwl5000_hcmd_utils, |
1612 | .led = &iwlagn_led_ops, | ||
1634 | }; | 1613 | }; |
1635 | 1614 | ||
1636 | static struct iwl_ops iwl5150_ops = { | 1615 | static struct iwl_ops iwl5150_ops = { |
@@ -1638,6 +1617,7 @@ static struct iwl_ops iwl5150_ops = { | |||
1638 | .lib = &iwl5150_lib, | 1617 | .lib = &iwl5150_lib, |
1639 | .hcmd = &iwl5000_hcmd, | 1618 | .hcmd = &iwl5000_hcmd, |
1640 | .utils = &iwl5000_hcmd_utils, | 1619 | .utils = &iwl5000_hcmd_utils, |
1620 | .led = &iwlagn_led_ops, | ||
1641 | }; | 1621 | }; |
1642 | 1622 | ||
1643 | struct iwl_mod_params iwl50_mod_params = { | 1623 | struct iwl_mod_params iwl50_mod_params = { |
@@ -1664,6 +1644,8 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1664 | .valid_rx_ant = ANT_ABC, | 1644 | .valid_rx_ant = ANT_ABC, |
1665 | .need_pll_cfg = true, | 1645 | .need_pll_cfg = true, |
1666 | .ht_greenfield_support = true, | 1646 | .ht_greenfield_support = true, |
1647 | .led_compensation = 51, | ||
1648 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1667 | }; | 1649 | }; |
1668 | 1650 | ||
1669 | struct iwl_cfg iwl5100_bg_cfg = { | 1651 | struct iwl_cfg iwl5100_bg_cfg = { |
@@ -1681,6 +1663,8 @@ struct iwl_cfg iwl5100_bg_cfg = { | |||
1681 | .valid_rx_ant = ANT_AB, | 1663 | .valid_rx_ant = ANT_AB, |
1682 | .need_pll_cfg = true, | 1664 | .need_pll_cfg = true, |
1683 | .ht_greenfield_support = true, | 1665 | .ht_greenfield_support = true, |
1666 | .led_compensation = 51, | ||
1667 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1684 | }; | 1668 | }; |
1685 | 1669 | ||
1686 | struct iwl_cfg iwl5100_abg_cfg = { | 1670 | struct iwl_cfg iwl5100_abg_cfg = { |
@@ -1698,6 +1682,8 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1698 | .valid_rx_ant = ANT_AB, | 1682 | .valid_rx_ant = ANT_AB, |
1699 | .need_pll_cfg = true, | 1683 | .need_pll_cfg = true, |
1700 | .ht_greenfield_support = true, | 1684 | .ht_greenfield_support = true, |
1685 | .led_compensation = 51, | ||
1686 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1701 | }; | 1687 | }; |
1702 | 1688 | ||
1703 | struct iwl_cfg iwl5100_agn_cfg = { | 1689 | struct iwl_cfg iwl5100_agn_cfg = { |
@@ -1715,6 +1701,8 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1715 | .valid_rx_ant = ANT_AB, | 1701 | .valid_rx_ant = ANT_AB, |
1716 | .need_pll_cfg = true, | 1702 | .need_pll_cfg = true, |
1717 | .ht_greenfield_support = true, | 1703 | .ht_greenfield_support = true, |
1704 | .led_compensation = 51, | ||
1705 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1718 | }; | 1706 | }; |
1719 | 1707 | ||
1720 | struct iwl_cfg iwl5350_agn_cfg = { | 1708 | struct iwl_cfg iwl5350_agn_cfg = { |
@@ -1732,6 +1720,8 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1732 | .valid_rx_ant = ANT_ABC, | 1720 | .valid_rx_ant = ANT_ABC, |
1733 | .need_pll_cfg = true, | 1721 | .need_pll_cfg = true, |
1734 | .ht_greenfield_support = true, | 1722 | .ht_greenfield_support = true, |
1723 | .led_compensation = 51, | ||
1724 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1735 | }; | 1725 | }; |
1736 | 1726 | ||
1737 | struct iwl_cfg iwl5150_agn_cfg = { | 1727 | struct iwl_cfg iwl5150_agn_cfg = { |
@@ -1749,19 +1739,22 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1749 | .valid_rx_ant = ANT_AB, | 1739 | .valid_rx_ant = ANT_AB, |
1750 | .need_pll_cfg = true, | 1740 | .need_pll_cfg = true, |
1751 | .ht_greenfield_support = true, | 1741 | .ht_greenfield_support = true, |
1742 | .led_compensation = 51, | ||
1743 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1752 | }; | 1744 | }; |
1753 | 1745 | ||
1754 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); | 1746 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); |
1755 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); | 1747 | MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); |
1756 | 1748 | ||
1757 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); | 1749 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, S_IRUGO); |
1758 | MODULE_PARM_DESC(swcrypto50, | 1750 | MODULE_PARM_DESC(swcrypto50, |
1759 | "using software crypto engine (default 0 [hardware])\n"); | 1751 | "using software crypto engine (default 0 [hardware])\n"); |
1760 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); | 1752 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, S_IRUGO); |
1761 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); | 1753 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); |
1762 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444); | 1754 | module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, S_IRUGO); |
1763 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); | 1755 | MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); |
1764 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444); | 1756 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, |
1757 | int, S_IRUGO); | ||
1765 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); | 1758 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); |
1766 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, 0444); | 1759 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, S_IRUGO); |
1767 | MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); | 1760 | 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 c295b8ee9228..d1f0b0b4ad0c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -44,6 +44,8 @@ | |||
44 | #include "iwl-sta.h" | 44 | #include "iwl-sta.h" |
45 | #include "iwl-helpers.h" | 45 | #include "iwl-helpers.h" |
46 | #include "iwl-5000-hw.h" | 46 | #include "iwl-5000-hw.h" |
47 | #include "iwl-6000-hw.h" | ||
48 | #include "iwl-agn-led.h" | ||
47 | 49 | ||
48 | /* Highest firmware API version supported */ | 50 | /* Highest firmware API version supported */ |
49 | #define IWL6000_UCODE_API_MAX 4 | 51 | #define IWL6000_UCODE_API_MAX 4 |
@@ -71,7 +73,21 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |||
71 | /* NIC configuration for 6000 series */ | 73 | /* NIC configuration for 6000 series */ |
72 | static void iwl6000_nic_config(struct iwl_priv *priv) | 74 | static void iwl6000_nic_config(struct iwl_priv *priv) |
73 | { | 75 | { |
74 | iwl5000_nic_config(priv); | 76 | u16 radio_cfg; |
77 | |||
78 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | ||
79 | |||
80 | /* write radio config values to register */ | ||
81 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) | ||
82 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
83 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | ||
84 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | ||
85 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | ||
86 | |||
87 | /* set CSR_HW_CONFIG_REG for uCode use */ | ||
88 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | ||
89 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | ||
90 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | ||
75 | 91 | ||
76 | /* no locking required for register write */ | 92 | /* no locking required for register write */ |
77 | if (priv->cfg->pa_type == IWL_PA_HYBRID) { | 93 | if (priv->cfg->pa_type == IWL_PA_HYBRID) { |
@@ -86,8 +102,76 @@ static void iwl6000_nic_config(struct iwl_priv *priv) | |||
86 | /* else do nothing, uCode configured */ | 102 | /* else do nothing, uCode configured */ |
87 | } | 103 | } |
88 | 104 | ||
105 | static struct iwl_sensitivity_ranges iwl6000_sensitivity = { | ||
106 | .min_nrg_cck = 97, | ||
107 | .max_nrg_cck = 0, /* not used, set to 0 */ | ||
108 | .auto_corr_min_ofdm = 80, | ||
109 | .auto_corr_min_ofdm_mrc = 128, | ||
110 | .auto_corr_min_ofdm_x1 = 105, | ||
111 | .auto_corr_min_ofdm_mrc_x1 = 192, | ||
112 | |||
113 | .auto_corr_max_ofdm = 145, | ||
114 | .auto_corr_max_ofdm_mrc = 232, | ||
115 | .auto_corr_max_ofdm_x1 = 145, | ||
116 | .auto_corr_max_ofdm_mrc_x1 = 232, | ||
117 | |||
118 | .auto_corr_min_cck = 125, | ||
119 | .auto_corr_max_cck = 175, | ||
120 | .auto_corr_min_cck_mrc = 160, | ||
121 | .auto_corr_max_cck_mrc = 310, | ||
122 | .nrg_th_cck = 97, | ||
123 | .nrg_th_ofdm = 100, | ||
124 | }; | ||
125 | |||
126 | static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) | ||
127 | { | ||
128 | if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || | ||
129 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { | ||
130 | IWL_ERR(priv, | ||
131 | "invalid queues_num, should be between %d and %d\n", | ||
132 | IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | |||
136 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; | ||
137 | priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; | ||
138 | priv->hw_params.scd_bc_tbls_size = | ||
139 | IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); | ||
140 | priv->hw_params.tfd_size = sizeof(struct iwl_tfd); | ||
141 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | ||
142 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | ||
143 | |||
144 | priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; | ||
145 | priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; | ||
146 | |||
147 | priv->hw_params.max_bsm_size = 0; | ||
148 | priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | | ||
149 | BIT(IEEE80211_BAND_5GHZ); | ||
150 | priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; | ||
151 | |||
152 | priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); | ||
153 | priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); | ||
154 | priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; | ||
155 | priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; | ||
156 | |||
157 | if (priv->cfg->ops->lib->temp_ops.set_ct_kill) | ||
158 | priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); | ||
159 | |||
160 | /* Set initial sensitivity parameters */ | ||
161 | /* Set initial calibration set */ | ||
162 | priv->hw_params.sens = &iwl6000_sensitivity; | ||
163 | priv->hw_params.calib_init_cfg = | ||
164 | BIT(IWL_CALIB_XTAL) | | ||
165 | BIT(IWL_CALIB_LO) | | ||
166 | BIT(IWL_CALIB_TX_IQ) | | ||
167 | BIT(IWL_CALIB_TX_IQ_PERD) | | ||
168 | BIT(IWL_CALIB_BASE_BAND); | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
89 | static struct iwl_lib_ops iwl6000_lib = { | 173 | static struct iwl_lib_ops iwl6000_lib = { |
90 | .set_hw_params = iwl5000_hw_set_hw_params, | 174 | .set_hw_params = iwl6000_hw_set_hw_params, |
91 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, | 175 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
92 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, | 176 | .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, |
93 | .txq_set_sched = iwl5000_txq_set_sched, | 177 | .txq_set_sched = iwl5000_txq_set_sched, |
@@ -109,7 +193,7 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
109 | .apm_ops = { | 193 | .apm_ops = { |
110 | .init = iwl5000_apm_init, | 194 | .init = iwl5000_apm_init, |
111 | .reset = iwl5000_apm_reset, | 195 | .reset = iwl5000_apm_reset, |
112 | .stop = iwl5000_apm_stop, | 196 | .stop = iwl_apm_stop, |
113 | .config = iwl6000_nic_config, | 197 | .config = iwl6000_nic_config, |
114 | .set_pwr_src = iwl_set_pwr_src, | 198 | .set_pwr_src = iwl_set_pwr_src, |
115 | }, | 199 | }, |
@@ -139,18 +223,12 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
139 | }, | 223 | }, |
140 | }; | 224 | }; |
141 | 225 | ||
142 | static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = { | ||
143 | .get_hcmd_size = iwl5000_get_hcmd_size, | ||
144 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, | ||
145 | .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, | ||
146 | .calc_rssi = iwl5000_calc_rssi, | ||
147 | }; | ||
148 | |||
149 | static struct iwl_ops iwl6000_ops = { | 226 | static struct iwl_ops iwl6000_ops = { |
150 | .ucode = &iwl5000_ucode, | 227 | .ucode = &iwl5000_ucode, |
151 | .lib = &iwl6000_lib, | 228 | .lib = &iwl6000_lib, |
152 | .hcmd = &iwl5000_hcmd, | 229 | .hcmd = &iwl5000_hcmd, |
153 | .utils = &iwl6000_hcmd_utils, | 230 | .utils = &iwl5000_hcmd_utils, |
231 | .led = &iwlagn_led_ops, | ||
154 | }; | 232 | }; |
155 | 233 | ||
156 | 234 | ||
@@ -165,7 +243,54 @@ struct iwl_cfg iwl6000h_2agn_cfg = { | |||
165 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 243 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
166 | .ops = &iwl6000_ops, | 244 | .ops = &iwl6000_ops, |
167 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 245 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
168 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 246 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
247 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
248 | .mod_params = &iwl50_mod_params, | ||
249 | .valid_tx_ant = ANT_AB, | ||
250 | .valid_rx_ant = ANT_AB, | ||
251 | .need_pll_cfg = false, | ||
252 | .pa_type = IWL_PA_HYBRID, | ||
253 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
254 | .shadow_ram_support = true, | ||
255 | .ht_greenfield_support = true, | ||
256 | .led_compensation = 51, | ||
257 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
258 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
259 | .supports_idle = true, | ||
260 | }; | ||
261 | |||
262 | struct iwl_cfg iwl6000h_2abg_cfg = { | ||
263 | .name = "6000 Series 2x2 ABG", | ||
264 | .fw_name_pre = IWL6000_FW_PRE, | ||
265 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
266 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
267 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
268 | .ops = &iwl6000_ops, | ||
269 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
270 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
271 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
272 | .mod_params = &iwl50_mod_params, | ||
273 | .valid_tx_ant = ANT_AB, | ||
274 | .valid_rx_ant = ANT_AB, | ||
275 | .need_pll_cfg = false, | ||
276 | .pa_type = IWL_PA_HYBRID, | ||
277 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
278 | .shadow_ram_support = true, | ||
279 | .ht_greenfield_support = true, | ||
280 | .led_compensation = 51, | ||
281 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
282 | .supports_idle = true, | ||
283 | }; | ||
284 | |||
285 | struct iwl_cfg iwl6000h_2bg_cfg = { | ||
286 | .name = "6000 Series 2x2 BG", | ||
287 | .fw_name_pre = IWL6000_FW_PRE, | ||
288 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
289 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
290 | .sku = IWL_SKU_G, | ||
291 | .ops = &iwl6000_ops, | ||
292 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
293 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
169 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 294 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
170 | .mod_params = &iwl50_mod_params, | 295 | .mod_params = &iwl50_mod_params, |
171 | .valid_tx_ant = ANT_AB, | 296 | .valid_tx_ant = ANT_AB, |
@@ -175,6 +300,9 @@ struct iwl_cfg iwl6000h_2agn_cfg = { | |||
175 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 300 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
176 | .shadow_ram_support = true, | 301 | .shadow_ram_support = true, |
177 | .ht_greenfield_support = true, | 302 | .ht_greenfield_support = true, |
303 | .led_compensation = 51, | ||
304 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
305 | .supports_idle = true, | ||
178 | }; | 306 | }; |
179 | 307 | ||
180 | /* | 308 | /* |
@@ -188,7 +316,54 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
188 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 316 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
189 | .ops = &iwl6000_ops, | 317 | .ops = &iwl6000_ops, |
190 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 318 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
191 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 319 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
320 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
321 | .mod_params = &iwl50_mod_params, | ||
322 | .valid_tx_ant = ANT_BC, | ||
323 | .valid_rx_ant = ANT_BC, | ||
324 | .need_pll_cfg = false, | ||
325 | .pa_type = IWL_PA_INTERNAL, | ||
326 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
327 | .shadow_ram_support = true, | ||
328 | .ht_greenfield_support = true, | ||
329 | .led_compensation = 51, | ||
330 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
331 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
332 | .supports_idle = true, | ||
333 | }; | ||
334 | |||
335 | struct iwl_cfg iwl6000i_2abg_cfg = { | ||
336 | .name = "6000 Series 2x2 ABG", | ||
337 | .fw_name_pre = IWL6000_FW_PRE, | ||
338 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
339 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
340 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
341 | .ops = &iwl6000_ops, | ||
342 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
343 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
344 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
345 | .mod_params = &iwl50_mod_params, | ||
346 | .valid_tx_ant = ANT_BC, | ||
347 | .valid_rx_ant = ANT_BC, | ||
348 | .need_pll_cfg = false, | ||
349 | .pa_type = IWL_PA_INTERNAL, | ||
350 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
351 | .shadow_ram_support = true, | ||
352 | .ht_greenfield_support = true, | ||
353 | .led_compensation = 51, | ||
354 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
355 | .supports_idle = true, | ||
356 | }; | ||
357 | |||
358 | struct iwl_cfg iwl6000i_2bg_cfg = { | ||
359 | .name = "6000 Series 2x2 BG", | ||
360 | .fw_name_pre = IWL6000_FW_PRE, | ||
361 | .ucode_api_max = IWL6000_UCODE_API_MAX, | ||
362 | .ucode_api_min = IWL6000_UCODE_API_MIN, | ||
363 | .sku = IWL_SKU_G, | ||
364 | .ops = &iwl6000_ops, | ||
365 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
366 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
192 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 367 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
193 | .mod_params = &iwl50_mod_params, | 368 | .mod_params = &iwl50_mod_params, |
194 | .valid_tx_ant = ANT_BC, | 369 | .valid_tx_ant = ANT_BC, |
@@ -198,6 +373,9 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
198 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 373 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
199 | .shadow_ram_support = true, | 374 | .shadow_ram_support = true, |
200 | .ht_greenfield_support = true, | 375 | .ht_greenfield_support = true, |
376 | .led_compensation = 51, | ||
377 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
378 | .supports_idle = true, | ||
201 | }; | 379 | }; |
202 | 380 | ||
203 | struct iwl_cfg iwl6050_2agn_cfg = { | 381 | struct iwl_cfg iwl6050_2agn_cfg = { |
@@ -208,7 +386,31 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
208 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 386 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
209 | .ops = &iwl6000_ops, | 387 | .ops = &iwl6000_ops, |
210 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 388 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
211 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 389 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
390 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
391 | .mod_params = &iwl50_mod_params, | ||
392 | .valid_tx_ant = ANT_AB, | ||
393 | .valid_rx_ant = ANT_AB, | ||
394 | .need_pll_cfg = false, | ||
395 | .pa_type = IWL_PA_SYSTEM, | ||
396 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
397 | .shadow_ram_support = true, | ||
398 | .ht_greenfield_support = true, | ||
399 | .led_compensation = 51, | ||
400 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
401 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
402 | .supports_idle = true, | ||
403 | }; | ||
404 | |||
405 | struct iwl_cfg iwl6050_2abg_cfg = { | ||
406 | .name = "6050 Series 2x2 ABG", | ||
407 | .fw_name_pre = IWL6050_FW_PRE, | ||
408 | .ucode_api_max = IWL6050_UCODE_API_MAX, | ||
409 | .ucode_api_min = IWL6050_UCODE_API_MIN, | ||
410 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
411 | .ops = &iwl6000_ops, | ||
412 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
413 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, | ||
212 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 414 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
213 | .mod_params = &iwl50_mod_params, | 415 | .mod_params = &iwl50_mod_params, |
214 | .valid_tx_ant = ANT_AB, | 416 | .valid_tx_ant = ANT_AB, |
@@ -218,6 +420,9 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
218 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 420 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
219 | .shadow_ram_support = true, | 421 | .shadow_ram_support = true, |
220 | .ht_greenfield_support = true, | 422 | .ht_greenfield_support = true, |
423 | .led_compensation = 51, | ||
424 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
425 | .supports_idle = true, | ||
221 | }; | 426 | }; |
222 | 427 | ||
223 | struct iwl_cfg iwl6000_3agn_cfg = { | 428 | struct iwl_cfg iwl6000_3agn_cfg = { |
@@ -228,7 +433,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
228 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 433 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
229 | .ops = &iwl6000_ops, | 434 | .ops = &iwl6000_ops, |
230 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 435 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
231 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 436 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
232 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 437 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
233 | .mod_params = &iwl50_mod_params, | 438 | .mod_params = &iwl50_mod_params, |
234 | .valid_tx_ant = ANT_ABC, | 439 | .valid_tx_ant = ANT_ABC, |
@@ -238,6 +443,10 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
238 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 443 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
239 | .shadow_ram_support = true, | 444 | .shadow_ram_support = true, |
240 | .ht_greenfield_support = true, | 445 | .ht_greenfield_support = true, |
446 | .led_compensation = 51, | ||
447 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
448 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
449 | .supports_idle = true, | ||
241 | }; | 450 | }; |
242 | 451 | ||
243 | struct iwl_cfg iwl6050_3agn_cfg = { | 452 | struct iwl_cfg iwl6050_3agn_cfg = { |
@@ -248,7 +457,7 @@ struct iwl_cfg iwl6050_3agn_cfg = { | |||
248 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 457 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
249 | .ops = &iwl6000_ops, | 458 | .ops = &iwl6000_ops, |
250 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | 459 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
251 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 460 | .eeprom_ver = EEPROM_6000_EEPROM_VERSION, |
252 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 461 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
253 | .mod_params = &iwl50_mod_params, | 462 | .mod_params = &iwl50_mod_params, |
254 | .valid_tx_ant = ANT_ABC, | 463 | .valid_tx_ant = ANT_ABC, |
@@ -258,6 +467,10 @@ struct iwl_cfg iwl6050_3agn_cfg = { | |||
258 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | 467 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, |
259 | .shadow_ram_support = true, | 468 | .shadow_ram_support = true, |
260 | .ht_greenfield_support = true, | 469 | .ht_greenfield_support = true, |
470 | .led_compensation = 51, | ||
471 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
472 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
473 | .supports_idle = true, | ||
261 | }; | 474 | }; |
262 | 475 | ||
263 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 476 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c new file mode 100644 index 000000000000..3bccba20f6da --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/pci.h> | ||
31 | #include <linux/dma-mapping.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/skbuff.h> | ||
34 | #include <linux/netdevice.h> | ||
35 | #include <linux/wireless.h> | ||
36 | #include <net/mac80211.h> | ||
37 | #include <linux/etherdevice.h> | ||
38 | #include <asm/unaligned.h> | ||
39 | |||
40 | #include "iwl-commands.h" | ||
41 | #include "iwl-dev.h" | ||
42 | #include "iwl-core.h" | ||
43 | #include "iwl-io.h" | ||
44 | #include "iwl-agn-led.h" | ||
45 | |||
46 | /* Send led command */ | ||
47 | static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) | ||
48 | { | ||
49 | struct iwl_host_cmd cmd = { | ||
50 | .id = REPLY_LEDS_CMD, | ||
51 | .len = sizeof(struct iwl_led_cmd), | ||
52 | .data = led_cmd, | ||
53 | .flags = CMD_ASYNC, | ||
54 | .callback = NULL, | ||
55 | }; | ||
56 | u32 reg; | ||
57 | |||
58 | reg = iwl_read32(priv, CSR_LED_REG); | ||
59 | if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) | ||
60 | iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); | ||
61 | |||
62 | return iwl_send_cmd(priv, &cmd); | ||
63 | } | ||
64 | |||
65 | /* Set led register off */ | ||
66 | static int iwl_led_on_reg(struct iwl_priv *priv) | ||
67 | { | ||
68 | IWL_DEBUG_LED(priv, "led on\n"); | ||
69 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | /* Set led register off */ | ||
74 | static int iwl_led_off_reg(struct iwl_priv *priv) | ||
75 | { | ||
76 | IWL_DEBUG_LED(priv, "LED Reg off\n"); | ||
77 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | const struct iwl_led_ops iwlagn_led_ops = { | ||
82 | .cmd = iwl_send_led_cmd, | ||
83 | .on = iwl_led_on_reg, | ||
84 | .off = iwl_led_off_reg, | ||
85 | }; | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h new file mode 100644 index 000000000000..ab55f92a161d --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
24 | * | ||
25 | *****************************************************************************/ | ||
26 | |||
27 | #ifndef __iwl_agn_led_h__ | ||
28 | #define __iwl_agn_led_h__ | ||
29 | |||
30 | extern const struct iwl_led_ops iwlagn_led_ops; | ||
31 | |||
32 | #endif /* __iwl_agn_led_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 346dc06fa7b7..a07be29cc5e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -171,6 +171,8 @@ struct iwl_lq_sta { | |||
171 | int last_txrate_idx; | 171 | int last_txrate_idx; |
172 | /* last tx rate_n_flags */ | 172 | /* last tx rate_n_flags */ |
173 | u32 last_rate_n_flags; | 173 | u32 last_rate_n_flags; |
174 | /* packets destined for this STA are aggregated */ | ||
175 | u8 is_agg; | ||
174 | }; | 176 | }; |
175 | 177 | ||
176 | static void rs_rate_scale_perform(struct iwl_priv *priv, | 178 | static void rs_rate_scale_perform(struct iwl_priv *priv, |
@@ -190,84 +192,78 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, | |||
190 | {} | 192 | {} |
191 | #endif | 193 | #endif |
192 | 194 | ||
193 | /* | 195 | /** |
194 | * Expected throughput metrics for following rates: | 196 | * The following tables contain the expected throughput metrics for all rates |
195 | * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits | 197 | * |
196 | * "G" is the only table that supports CCK (the first 4 rates). | 198 | * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits |
199 | * | ||
200 | * where invalid entries are zeros. | ||
201 | * | ||
202 | * CCK rates are only valid in legacy table and will only be used in G | ||
203 | * (2.4 GHz) band. | ||
197 | */ | 204 | */ |
198 | 205 | ||
199 | static s32 expected_tpt_A[IWL_RATE_COUNT] = { | 206 | static s32 expected_tpt_legacy[IWL_RATE_COUNT] = { |
200 | 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 | 207 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0 |
201 | }; | ||
202 | |||
203 | static s32 expected_tpt_G[IWL_RATE_COUNT] = { | ||
204 | 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 186 | ||
205 | }; | ||
206 | |||
207 | static s32 expected_tpt_siso20MHz[IWL_RATE_COUNT] = { | ||
208 | 0, 0, 0, 0, 42, 42, 76, 102, 124, 159, 183, 193, 202 | ||
209 | }; | ||
210 | |||
211 | static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = { | ||
212 | 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211 | ||
213 | }; | ||
214 | |||
215 | static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = { | ||
216 | 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251 | ||
217 | }; | 208 | }; |
218 | 209 | ||
219 | static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = { | 210 | static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = { |
220 | 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257 | 211 | {0, 0, 0, 0, 42, 0, 76, 102, 124, 158, 183, 193, 202}, /* Norm */ |
212 | {0, 0, 0, 0, 46, 0, 82, 110, 132, 167, 192, 202, 210}, /* SGI */ | ||
213 | {0, 0, 0, 0, 48, 0, 93, 135, 176, 251, 319, 351, 381}, /* AGG */ | ||
214 | {0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */ | ||
221 | }; | 215 | }; |
222 | 216 | ||
223 | static s32 expected_tpt_siso40MHz[IWL_RATE_COUNT] = { | 217 | static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = { |
224 | 0, 0, 0, 0, 77, 77, 127, 160, 184, 220, 242, 250, 257 | 218 | {0, 0, 0, 0, 77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */ |
219 | {0, 0, 0, 0, 83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */ | ||
220 | {0, 0, 0, 0, 96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */ | ||
221 | {0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */ | ||
225 | }; | 222 | }; |
226 | 223 | ||
227 | static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = { | 224 | static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = { |
228 | 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 | 225 | {0, 0, 0, 0, 74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */ |
226 | {0, 0, 0, 0, 81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */ | ||
227 | {0, 0, 0, 0, 92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */ | ||
228 | {0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/ | ||
229 | }; | 229 | }; |
230 | 230 | ||
231 | static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = { | 231 | static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = { |
232 | 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 | 232 | {0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */ |
233 | {0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */ | ||
234 | {0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */ | ||
235 | {0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */ | ||
233 | }; | 236 | }; |
234 | 237 | ||
235 | static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = { | 238 | static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = { |
236 | 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 | 239 | {0, 0, 0, 0, 99, 0, 153, 186, 208, 239, 256, 263, 268}, /* Norm */ |
240 | {0, 0, 0, 0, 106, 0, 162, 194, 215, 246, 262, 268, 273}, /* SGI */ | ||
241 | {0, 0, 0, 0, 134, 0, 249, 346, 431, 574, 685, 732, 775}, /* AGG */ | ||
242 | {0, 0, 0, 0, 148, 0, 272, 376, 465, 614, 727, 775, 818}, /* AGG+SGI */ | ||
237 | }; | 243 | }; |
238 | 244 | ||
239 | /* Expected throughput metric MIMO3 */ | 245 | static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = { |
240 | static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = { | 246 | {0, 0, 0, 0, 152, 0, 211, 239, 255, 279, 290, 294, 297}, /* Norm */ |
241 | 0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268 | 247 | {0, 0, 0, 0, 160, 0, 219, 245, 261, 284, 294, 297, 300}, /* SGI */ |
242 | }; | 248 | {0, 0, 0, 0, 254, 0, 443, 584, 695, 868, 984, 1030, 1070}, /* AGG */ |
243 | 249 | {0, 0, 0, 0, 277, 0, 478, 624, 737, 911, 1026, 1070, 1109}, /* AGG+SGI */ | |
244 | static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = { | ||
245 | 0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273 | ||
246 | }; | ||
247 | |||
248 | static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = { | ||
249 | 0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297 | ||
250 | }; | ||
251 | |||
252 | static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = { | ||
253 | 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300 | ||
254 | }; | 250 | }; |
255 | 251 | ||
256 | /* mbps, mcs */ | 252 | /* mbps, mcs */ |
257 | const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { | 253 | const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { |
258 | {"1", ""}, | 254 | { "1", "BPSK DSSS"}, |
259 | {"2", ""}, | 255 | { "2", "QPSK DSSS"}, |
260 | {"5.5", ""}, | 256 | {"5.5", "BPSK CCK"}, |
261 | {"11", ""}, | 257 | { "11", "QPSK CCK"}, |
262 | {"6", "BPSK 1/2"}, | 258 | { "6", "BPSK 1/2"}, |
263 | {"9", "BPSK 1/2"}, | 259 | { "9", "BPSK 1/2"}, |
264 | {"12", "QPSK 1/2"}, | 260 | { "12", "QPSK 1/2"}, |
265 | {"18", "QPSK 3/4"}, | 261 | { "18", "QPSK 3/4"}, |
266 | {"24", "16QAM 1/2"}, | 262 | { "24", "16QAM 1/2"}, |
267 | {"36", "16QAM 3/4"}, | 263 | { "36", "16QAM 3/4"}, |
268 | {"48", "64QAM 2/3"}, | 264 | { "48", "64QAM 2/3"}, |
269 | {"54", "64QAM 3/4"}, | 265 | { "54", "64QAM 3/4"}, |
270 | {"60", "64QAM 5/6"} | 266 | { "60", "64QAM 5/6"}, |
271 | }; | 267 | }; |
272 | 268 | ||
273 | #define MCS_INDEX_PER_STREAM (8) | 269 | #define MCS_INDEX_PER_STREAM (8) |
@@ -418,6 +414,15 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, | |||
418 | else if (tid == IWL_AGG_ALL_TID) | 414 | else if (tid == IWL_AGG_ALL_TID) |
419 | for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) | 415 | for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) |
420 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); | 416 | rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); |
417 | if (priv->cfg->use_rts_for_ht) { | ||
418 | /* | ||
419 | * switch to RTS/CTS if it is the prefer protection method | ||
420 | * for HT traffic | ||
421 | */ | ||
422 | IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); | ||
423 | priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; | ||
424 | iwlcore_commit_rxon(priv); | ||
425 | } | ||
421 | } | 426 | } |
422 | 427 | ||
423 | static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | 428 | static inline int get_num_of_ant_from_rate(u32 rate_n_flags) |
@@ -435,7 +440,7 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) | |||
435 | * packets. | 440 | * packets. |
436 | */ | 441 | */ |
437 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | 442 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, |
438 | int scale_index, s32 tpt, int retries, | 443 | int scale_index, s32 tpt, int attempts, |
439 | int successes) | 444 | int successes) |
440 | { | 445 | { |
441 | struct iwl_rate_scale_data *window = NULL; | 446 | struct iwl_rate_scale_data *window = NULL; |
@@ -445,7 +450,7 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | |||
445 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) | 450 | if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) |
446 | return -EINVAL; | 451 | return -EINVAL; |
447 | 452 | ||
448 | /* Select data for current tx bit rate */ | 453 | /* Select window for current tx bit rate */ |
449 | window = &(windows[scale_index]); | 454 | window = &(windows[scale_index]); |
450 | 455 | ||
451 | /* | 456 | /* |
@@ -456,7 +461,7 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | |||
456 | * subtract "1" from the success counter (this is the main reason | 461 | * subtract "1" from the success counter (this is the main reason |
457 | * we keep these bitmaps!). | 462 | * we keep these bitmaps!). |
458 | */ | 463 | */ |
459 | while (retries > 0) { | 464 | while (attempts > 0) { |
460 | if (window->counter >= IWL_RATE_MAX_WINDOW) { | 465 | if (window->counter >= IWL_RATE_MAX_WINDOW) { |
461 | 466 | ||
462 | /* remove earliest */ | 467 | /* remove earliest */ |
@@ -471,17 +476,17 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | |||
471 | /* Increment frames-attempted counter */ | 476 | /* Increment frames-attempted counter */ |
472 | window->counter++; | 477 | window->counter++; |
473 | 478 | ||
474 | /* Shift bitmap by one frame (throw away oldest history), | 479 | /* Shift bitmap by one frame to throw away oldest history */ |
475 | * OR in "1", and increment "success" if this | ||
476 | * frame was successful. */ | ||
477 | window->data <<= 1; | 480 | window->data <<= 1; |
481 | |||
482 | /* Mark the most recent #successes attempts as successful */ | ||
478 | if (successes > 0) { | 483 | if (successes > 0) { |
479 | window->success_counter++; | 484 | window->success_counter++; |
480 | window->data |= 0x1; | 485 | window->data |= 0x1; |
481 | successes--; | 486 | successes--; |
482 | } | 487 | } |
483 | 488 | ||
484 | retries--; | 489 | attempts--; |
485 | } | 490 | } |
486 | 491 | ||
487 | /* Calculate current success ratio, avoid divide-by-0! */ | 492 | /* Calculate current success ratio, avoid divide-by-0! */ |
@@ -662,7 +667,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
662 | * there are no non-GF stations present in the BSS. | 667 | * there are no non-GF stations present in the BSS. |
663 | */ | 668 | */ |
664 | static inline u8 rs_use_green(struct ieee80211_sta *sta, | 669 | static inline u8 rs_use_green(struct ieee80211_sta *sta, |
665 | struct iwl_ht_info *ht_conf) | 670 | struct iwl_ht_config *ht_conf) |
666 | { | 671 | { |
667 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && | 672 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && |
668 | !(ht_conf->non_GF_STA_present); | 673 | !(ht_conf->non_GF_STA_present); |
@@ -812,27 +817,45 @@ out: | |||
812 | } | 817 | } |
813 | 818 | ||
814 | /* | 819 | /* |
820 | * Simple function to compare two rate scale table types | ||
821 | */ | ||
822 | static bool table_type_matches(struct iwl_scale_tbl_info *a, | ||
823 | struct iwl_scale_tbl_info *b) | ||
824 | { | ||
825 | return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && | ||
826 | (a->is_SGI == b->is_SGI); | ||
827 | } | ||
828 | /* | ||
829 | * Static function to get the expected throughput from an iwl_scale_tbl_info | ||
830 | * that wraps a NULL pointer check | ||
831 | */ | ||
832 | static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index) | ||
833 | { | ||
834 | if (tbl->expected_tpt) | ||
835 | return tbl->expected_tpt[rs_index]; | ||
836 | return 0; | ||
837 | } | ||
838 | |||
839 | /* | ||
815 | * mac80211 sends us Tx status | 840 | * mac80211 sends us Tx status |
816 | */ | 841 | */ |
817 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | 842 | static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, |
818 | struct ieee80211_sta *sta, void *priv_sta, | 843 | struct ieee80211_sta *sta, void *priv_sta, |
819 | struct sk_buff *skb) | 844 | struct sk_buff *skb) |
820 | { | 845 | { |
821 | int status; | 846 | int legacy_success; |
822 | u8 retries; | 847 | int retries; |
823 | int rs_index, mac_index, index = 0; | 848 | int rs_index, mac_index, i; |
824 | struct iwl_lq_sta *lq_sta = priv_sta; | 849 | struct iwl_lq_sta *lq_sta = priv_sta; |
825 | struct iwl_link_quality_cmd *table; | 850 | struct iwl_link_quality_cmd *table; |
826 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 851 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
827 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 852 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
828 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 853 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
829 | struct iwl_rate_scale_data *window = NULL; | 854 | struct iwl_rate_scale_data *window = NULL; |
830 | struct iwl_rate_scale_data *search_win = NULL; | ||
831 | enum mac80211_rate_control_flags mac_flags; | 855 | enum mac80211_rate_control_flags mac_flags; |
832 | u32 tx_rate; | 856 | u32 tx_rate; |
833 | struct iwl_scale_tbl_info tbl_type; | 857 | struct iwl_scale_tbl_info tbl_type; |
834 | struct iwl_scale_tbl_info *curr_tbl, *search_tbl; | 858 | struct iwl_scale_tbl_info *curr_tbl, *other_tbl; |
835 | u8 active_index = 0; | ||
836 | s32 tpt = 0; | 859 | s32 tpt = 0; |
837 | 860 | ||
838 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); | 861 | IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); |
@@ -841,30 +864,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
841 | info->flags & IEEE80211_TX_CTL_NO_ACK) | 864 | info->flags & IEEE80211_TX_CTL_NO_ACK) |
842 | return; | 865 | return; |
843 | 866 | ||
844 | /* This packet was aggregated but doesn't carry rate scale info */ | 867 | /* This packet was aggregated but doesn't carry status info */ |
845 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 868 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
846 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 869 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
847 | return; | 870 | return; |
848 | 871 | ||
849 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | ||
850 | retries = 0; | ||
851 | else | ||
852 | retries = info->status.rates[0].count - 1; | ||
853 | |||
854 | if (retries > 15) | ||
855 | retries = 15; | ||
856 | |||
857 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 872 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
858 | !lq_sta->ibss_sta_added) | 873 | !lq_sta->ibss_sta_added) |
859 | goto out; | 874 | return; |
860 | |||
861 | table = &lq_sta->lq; | ||
862 | active_index = lq_sta->active_tbl; | ||
863 | |||
864 | curr_tbl = &(lq_sta->lq_info[active_index]); | ||
865 | search_tbl = &(lq_sta->lq_info[(1 - active_index)]); | ||
866 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); | ||
867 | search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]); | ||
868 | 875 | ||
869 | /* | 876 | /* |
870 | * Ignore this Tx frame response if its initial rate doesn't match | 877 | * Ignore this Tx frame response if its initial rate doesn't match |
@@ -874,6 +881,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
874 | * to check "search" mode, or a prior "search" mode after we've moved | 881 | * to check "search" mode, or a prior "search" mode after we've moved |
875 | * to a new "search" mode (which might become the new "active" mode). | 882 | * to a new "search" mode (which might become the new "active" mode). |
876 | */ | 883 | */ |
884 | table = &lq_sta->lq; | ||
877 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | 885 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); |
878 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); | 886 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); |
879 | if (priv->band == IEEE80211_BAND_5GHZ) | 887 | if (priv->band == IEEE80211_BAND_5GHZ) |
@@ -892,7 +900,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
892 | if (priv->band == IEEE80211_BAND_2GHZ) | 900 | if (priv->band == IEEE80211_BAND_2GHZ) |
893 | mac_index += IWL_FIRST_OFDM_RATE; | 901 | mac_index += IWL_FIRST_OFDM_RATE; |
894 | } | 902 | } |
895 | 903 | /* Here we actually compare this rate to the latest LQ command */ | |
896 | if ((mac_index < 0) || | 904 | if ((mac_index < 0) || |
897 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || | 905 | (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || |
898 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || | 906 | (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || |
@@ -902,124 +910,106 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
902 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || | 910 | (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || |
903 | (rs_index != mac_index)) { | 911 | (rs_index != mac_index)) { |
904 | IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate); | 912 | IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate); |
905 | /* the last LQ command could failed so the LQ in ucode not | 913 | /* |
906 | * the same in driver sync up | 914 | * Since rates mis-match, the last LQ command may have failed. |
915 | * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with | ||
916 | * ... driver. | ||
907 | */ | 917 | */ |
908 | lq_sta->missed_rate_counter++; | 918 | lq_sta->missed_rate_counter++; |
909 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { | 919 | if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { |
910 | lq_sta->missed_rate_counter = 0; | 920 | lq_sta->missed_rate_counter = 0; |
911 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | 921 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); |
912 | } | 922 | } |
913 | goto out; | 923 | /* Regardless, ignore this status info for outdated rate */ |
924 | return; | ||
925 | } else | ||
926 | /* Rate did match, so reset the missed_rate_counter */ | ||
927 | lq_sta->missed_rate_counter = 0; | ||
928 | |||
929 | /* Figure out if rate scale algorithm is in active or search table */ | ||
930 | if (table_type_matches(&tbl_type, | ||
931 | &(lq_sta->lq_info[lq_sta->active_tbl]))) { | ||
932 | curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | ||
933 | other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); | ||
934 | } else if (table_type_matches(&tbl_type, | ||
935 | &lq_sta->lq_info[1 - lq_sta->active_tbl])) { | ||
936 | curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); | ||
937 | other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | ||
938 | } else { | ||
939 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); | ||
940 | return; | ||
914 | } | 941 | } |
942 | window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); | ||
915 | 943 | ||
916 | lq_sta->missed_rate_counter = 0; | 944 | /* |
917 | /* Update frame history window with "failure" for each Tx retry. */ | 945 | * Updating the frame history depends on whether packets were |
918 | while (retries) { | 946 | * aggregated. |
919 | /* Look up the rate and other info used for each tx attempt. | 947 | * |
920 | * Each tx attempt steps one entry deeper in the rate table. */ | 948 | * For aggregation, all packets were transmitted at the same rate, the |
921 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 949 | * first index into rate scale table. |
922 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, | 950 | */ |
923 | &tbl_type, &rs_index); | 951 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { |
924 | 952 | tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); | |
925 | /* If type matches "search" table, | 953 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, |
926 | * add failure to "search" history */ | 954 | &rs_index); |
927 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 955 | tpt = get_expected_tpt(curr_tbl, rs_index); |
928 | (tbl_type.ant_type == search_tbl->ant_type) && | 956 | rs_collect_tx_data(window, rs_index, tpt, |
929 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | 957 | info->status.ampdu_ack_len, |
930 | if (search_tbl->expected_tpt) | 958 | info->status.ampdu_ack_map); |
931 | tpt = search_tbl->expected_tpt[rs_index]; | 959 | |
932 | else | 960 | /* Update success/fail counts if not searching for new mode */ |
933 | tpt = 0; | 961 | if (lq_sta->stay_in_tbl) { |
934 | rs_collect_tx_data(search_win, rs_index, tpt, 1, 0); | 962 | lq_sta->total_success += info->status.ampdu_ack_map; |
935 | 963 | lq_sta->total_failed += (info->status.ampdu_ack_len - | |
936 | /* Else if type matches "current/active" table, | 964 | info->status.ampdu_ack_map); |
937 | * add failure to "current/active" history */ | ||
938 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && | ||
939 | (tbl_type.ant_type == curr_tbl->ant_type) && | ||
940 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { | ||
941 | if (curr_tbl->expected_tpt) | ||
942 | tpt = curr_tbl->expected_tpt[rs_index]; | ||
943 | else | ||
944 | tpt = 0; | ||
945 | rs_collect_tx_data(window, rs_index, tpt, 1, 0); | ||
946 | } | 965 | } |
947 | 966 | } else { | |
948 | /* If not searching for a new mode, increment failed counter | ||
949 | * ... this helps determine when to start searching again */ | ||
950 | if (lq_sta->stay_in_tbl) | ||
951 | lq_sta->total_failed++; | ||
952 | --retries; | ||
953 | index++; | ||
954 | |||
955 | } | ||
956 | |||
957 | /* | 967 | /* |
958 | * Find (by rate) the history window to update with final Tx attempt; | 968 | * For legacy, update frame history with for each Tx retry. |
959 | * if Tx was successful first try, use original rate, | ||
960 | * else look up the rate that was, finally, successful. | ||
961 | */ | 969 | */ |
962 | tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); | 970 | retries = info->status.rates[0].count - 1; |
963 | lq_sta->last_rate_n_flags = tx_rate; | 971 | /* HW doesn't send more than 15 retries */ |
964 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); | 972 | retries = min(retries, 15); |
965 | 973 | ||
966 | /* Update frame history window with "success" if Tx got ACKed ... */ | 974 | /* The last transmission may have been successful */ |
967 | status = !!(info->flags & IEEE80211_TX_STAT_ACK); | 975 | legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK); |
968 | 976 | /* Collect data for each rate used during failed TX attempts */ | |
969 | /* If type matches "search" table, | 977 | for (i = 0; i <= retries; ++i) { |
970 | * add final tx status to "search" history */ | 978 | tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags); |
971 | if ((tbl_type.lq_type == search_tbl->lq_type) && | 979 | rs_get_tbl_info_from_mcs(tx_rate, priv->band, |
972 | (tbl_type.ant_type == search_tbl->ant_type) && | 980 | &tbl_type, &rs_index); |
973 | (tbl_type.is_SGI == search_tbl->is_SGI)) { | 981 | /* |
974 | if (search_tbl->expected_tpt) | 982 | * Only collect stats if retried rate is in the same RS |
975 | tpt = search_tbl->expected_tpt[rs_index]; | 983 | * table as active/search. |
976 | else | 984 | */ |
977 | tpt = 0; | 985 | if (table_type_matches(&tbl_type, curr_tbl)) |
978 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | 986 | tpt = get_expected_tpt(curr_tbl, rs_index); |
979 | rs_collect_tx_data(search_win, rs_index, tpt, | 987 | else if (table_type_matches(&tbl_type, other_tbl)) |
980 | info->status.ampdu_ack_len, | 988 | tpt = get_expected_tpt(other_tbl, rs_index); |
981 | info->status.ampdu_ack_map); | 989 | else |
982 | else | 990 | continue; |
983 | rs_collect_tx_data(search_win, rs_index, tpt, | ||
984 | 1, status); | ||
985 | /* Else if type matches "current/active" table, | ||
986 | * add final tx status to "current/active" history */ | ||
987 | } else if ((tbl_type.lq_type == curr_tbl->lq_type) && | ||
988 | (tbl_type.ant_type == curr_tbl->ant_type) && | ||
989 | (tbl_type.is_SGI == curr_tbl->is_SGI)) { | ||
990 | if (curr_tbl->expected_tpt) | ||
991 | tpt = curr_tbl->expected_tpt[rs_index]; | ||
992 | else | ||
993 | tpt = 0; | ||
994 | if (info->flags & IEEE80211_TX_STAT_AMPDU) | ||
995 | rs_collect_tx_data(window, rs_index, tpt, | ||
996 | info->status.ampdu_ack_len, | ||
997 | info->status.ampdu_ack_map); | ||
998 | else | ||
999 | rs_collect_tx_data(window, rs_index, tpt, | ||
1000 | 1, status); | ||
1001 | } | ||
1002 | 991 | ||
1003 | /* If not searching for new mode, increment success/failed counter | 992 | /* Constants mean 1 transmission, 0 successes */ |
1004 | * ... these help determine when to start searching again */ | 993 | if (i < retries) |
1005 | if (lq_sta->stay_in_tbl) { | 994 | rs_collect_tx_data(window, rs_index, tpt, 1, |
1006 | if (info->flags & IEEE80211_TX_STAT_AMPDU) { | 995 | 0); |
1007 | lq_sta->total_success += info->status.ampdu_ack_map; | ||
1008 | lq_sta->total_failed += | ||
1009 | (info->status.ampdu_ack_len - info->status.ampdu_ack_map); | ||
1010 | } else { | ||
1011 | if (status) | ||
1012 | lq_sta->total_success++; | ||
1013 | else | 996 | else |
1014 | lq_sta->total_failed++; | 997 | rs_collect_tx_data(window, rs_index, tpt, 1, |
998 | legacy_success); | ||
999 | } | ||
1000 | |||
1001 | /* Update success/fail counts if not searching for new mode */ | ||
1002 | if (lq_sta->stay_in_tbl) { | ||
1003 | lq_sta->total_success += legacy_success; | ||
1004 | lq_sta->total_failed += retries + (1 - legacy_success); | ||
1015 | } | 1005 | } |
1016 | } | 1006 | } |
1007 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ | ||
1008 | lq_sta->last_rate_n_flags = tx_rate; | ||
1017 | 1009 | ||
1018 | /* See if there's a better rate or modulation mode to try. */ | 1010 | /* See if there's a better rate or modulation mode to try. */ |
1019 | if (sta && sta->supp_rates[sband->band]) | 1011 | if (sta && sta->supp_rates[sband->band]) |
1020 | rs_rate_scale_perform(priv, skb, sta, lq_sta); | 1012 | rs_rate_scale_perform(priv, skb, sta, lq_sta); |
1021 | out: | ||
1022 | return; | ||
1023 | } | 1013 | } |
1024 | 1014 | ||
1025 | /* | 1015 | /* |
@@ -1057,43 +1047,45 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, | |||
1057 | static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, | 1047 | static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, |
1058 | struct iwl_scale_tbl_info *tbl) | 1048 | struct iwl_scale_tbl_info *tbl) |
1059 | { | 1049 | { |
1050 | /* Used to choose among HT tables */ | ||
1051 | s32 (*ht_tbl_pointer)[IWL_RATE_COUNT]; | ||
1052 | |||
1053 | /* Check for invalid LQ type */ | ||
1054 | if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) { | ||
1055 | tbl->expected_tpt = expected_tpt_legacy; | ||
1056 | return; | ||
1057 | } | ||
1058 | |||
1059 | /* Legacy rates have only one table */ | ||
1060 | if (is_legacy(tbl->lq_type)) { | 1060 | if (is_legacy(tbl->lq_type)) { |
1061 | if (!is_a_band(tbl->lq_type)) | 1061 | tbl->expected_tpt = expected_tpt_legacy; |
1062 | tbl->expected_tpt = expected_tpt_G; | 1062 | return; |
1063 | else | 1063 | } |
1064 | tbl->expected_tpt = expected_tpt_A; | 1064 | |
1065 | } else if (is_siso(tbl->lq_type)) { | 1065 | /* Choose among many HT tables depending on number of streams |
1066 | if (tbl->is_ht40 && !lq_sta->is_dup) | 1066 | * (SISO/MIMO2/MIMO3), channel width (20/40), SGI, and aggregation |
1067 | if (tbl->is_SGI) | 1067 | * status */ |
1068 | tbl->expected_tpt = expected_tpt_siso40MHzSGI; | 1068 | if (is_siso(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup)) |
1069 | else | 1069 | ht_tbl_pointer = expected_tpt_siso20MHz; |
1070 | tbl->expected_tpt = expected_tpt_siso40MHz; | 1070 | else if (is_siso(tbl->lq_type)) |
1071 | else if (tbl->is_SGI) | 1071 | ht_tbl_pointer = expected_tpt_siso40MHz; |
1072 | tbl->expected_tpt = expected_tpt_siso20MHzSGI; | 1072 | else if (is_mimo2(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup)) |
1073 | else | 1073 | ht_tbl_pointer = expected_tpt_mimo2_20MHz; |
1074 | tbl->expected_tpt = expected_tpt_siso20MHz; | 1074 | else if (is_mimo2(tbl->lq_type)) |
1075 | } else if (is_mimo2(tbl->lq_type)) { | 1075 | ht_tbl_pointer = expected_tpt_mimo2_40MHz; |
1076 | if (tbl->is_ht40 && !lq_sta->is_dup) | 1076 | else if (is_mimo3(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup)) |
1077 | if (tbl->is_SGI) | 1077 | ht_tbl_pointer = expected_tpt_mimo3_20MHz; |
1078 | tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI; | 1078 | else /* if (is_mimo3(tbl->lq_type)) <-- must be true */ |
1079 | else | 1079 | ht_tbl_pointer = expected_tpt_mimo3_40MHz; |
1080 | tbl->expected_tpt = expected_tpt_mimo2_40MHz; | 1080 | |
1081 | else if (tbl->is_SGI) | 1081 | if (!tbl->is_SGI && !lq_sta->is_agg) /* Normal */ |
1082 | tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI; | 1082 | tbl->expected_tpt = ht_tbl_pointer[0]; |
1083 | else | 1083 | else if (tbl->is_SGI && !lq_sta->is_agg) /* SGI */ |
1084 | tbl->expected_tpt = expected_tpt_mimo2_20MHz; | 1084 | tbl->expected_tpt = ht_tbl_pointer[1]; |
1085 | } else if (is_mimo3(tbl->lq_type)) { | 1085 | else if (!tbl->is_SGI && lq_sta->is_agg) /* AGG */ |
1086 | if (tbl->is_ht40 && !lq_sta->is_dup) | 1086 | tbl->expected_tpt = ht_tbl_pointer[2]; |
1087 | if (tbl->is_SGI) | 1087 | else /* AGG+SGI */ |
1088 | tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI; | 1088 | tbl->expected_tpt = ht_tbl_pointer[3]; |
1089 | else | ||
1090 | tbl->expected_tpt = expected_tpt_mimo3_40MHz; | ||
1091 | else if (tbl->is_SGI) | ||
1092 | tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI; | ||
1093 | else | ||
1094 | tbl->expected_tpt = expected_tpt_mimo3_20MHz; | ||
1095 | } else | ||
1096 | tbl->expected_tpt = expected_tpt_G; | ||
1097 | } | 1089 | } |
1098 | 1090 | ||
1099 | /* | 1091 | /* |
@@ -2068,6 +2060,14 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2068 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; | 2060 | lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; |
2069 | 2061 | ||
2070 | tid = rs_tl_add_packet(lq_sta, hdr); | 2062 | tid = rs_tl_add_packet(lq_sta, hdr); |
2063 | if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) { | ||
2064 | tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid]; | ||
2065 | if (tid_data->agg.state == IWL_AGG_OFF) | ||
2066 | lq_sta->is_agg = 0; | ||
2067 | else | ||
2068 | lq_sta->is_agg = 1; | ||
2069 | } else | ||
2070 | lq_sta->is_agg = 0; | ||
2071 | 2071 | ||
2072 | /* | 2072 | /* |
2073 | * Select rate-scale / modulation-mode table to work with in | 2073 | * Select rate-scale / modulation-mode table to work with in |
@@ -2168,10 +2168,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2168 | 2168 | ||
2169 | goto out; | 2169 | goto out; |
2170 | } | 2170 | } |
2171 | |||
2172 | /* Else we have enough samples; calculate estimate of | 2171 | /* Else we have enough samples; calculate estimate of |
2173 | * actual average throughput */ | 2172 | * actual average throughput */ |
2174 | 2173 | ||
2174 | /* Sanity-check TPT calculations */ | ||
2175 | BUG_ON(window->average_tpt != ((window->success_ratio * | 2175 | BUG_ON(window->average_tpt != ((window->success_ratio * |
2176 | tbl->expected_tpt[index] + 64) / 128)); | 2176 | tbl->expected_tpt[index] + 64) / 128)); |
2177 | 2177 | ||
@@ -2681,6 +2681,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2681 | lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); | 2681 | lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); |
2682 | if (sband->band == IEEE80211_BAND_5GHZ) | 2682 | if (sband->band == IEEE80211_BAND_5GHZ) |
2683 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | 2683 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; |
2684 | lq_sta->is_agg = 0; | ||
2684 | 2685 | ||
2685 | rs_initialize_lq(priv, conf, sta, lq_sta); | 2686 | rs_initialize_lq(priv, conf, sta, lq_sta); |
2686 | } | 2687 | } |
@@ -2799,7 +2800,7 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2799 | repeat_rate--; | 2800 | repeat_rate--; |
2800 | } | 2801 | } |
2801 | 2802 | ||
2802 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_MAX; | 2803 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
2803 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | 2804 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; |
2804 | lq_cmd->agg_params.agg_time_limit = | 2805 | lq_cmd->agg_params.agg_time_limit = |
2805 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | 2806 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); |
@@ -2933,8 +2934,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, | |||
2933 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); | 2934 | ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); |
2934 | desc += sprintf(buff+desc, " %s", | 2935 | desc += sprintf(buff+desc, " %s", |
2935 | (tbl->is_ht40) ? "40MHz" : "20MHz"); | 2936 | (tbl->is_ht40) ? "40MHz" : "20MHz"); |
2936 | desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "", | 2937 | desc += sprintf(buff+desc, " %s %s %s\n", (tbl->is_SGI) ? "SGI" : "", |
2937 | (lq_sta->is_green) ? "GF enabled" : ""); | 2938 | (lq_sta->is_green) ? "GF enabled" : "", |
2939 | (lq_sta->is_agg) ? "AGG on" : ""); | ||
2938 | } | 2940 | } |
2939 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", | 2941 | desc += sprintf(buff+desc, "last tx rate=0x%X\n", |
2940 | lq_sta->last_rate_n_flags); | 2942 | lq_sta->last_rate_n_flags); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index cdc07c477457..046b571fd9ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -115,9 +115,6 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
115 | 115 | ||
116 | /* always get timestamp with Rx frame */ | 116 | /* always get timestamp with Rx frame */ |
117 | priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; | 117 | priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; |
118 | /* allow CTS-to-self if possible. this is relevant only for | ||
119 | * 5000, but will not damage 4965 */ | ||
120 | priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; | ||
121 | 118 | ||
122 | ret = iwl_check_rxon_cmd(priv); | 119 | ret = iwl_check_rxon_cmd(priv); |
123 | if (ret) { | 120 | if (ret) { |
@@ -217,6 +214,13 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
217 | "Could not send WEP static key.\n"); | 214 | "Could not send WEP static key.\n"); |
218 | } | 215 | } |
219 | 216 | ||
217 | /* | ||
218 | * allow CTS-to-self if possible for new association. | ||
219 | * this is relevant only for 5000 series and up, | ||
220 | * but will not damage 4965 | ||
221 | */ | ||
222 | priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; | ||
223 | |||
220 | /* Apply the new configuration | 224 | /* Apply the new configuration |
221 | * RXON assoc doesn't clear the station table in uCode, | 225 | * RXON assoc doesn't clear the station table in uCode, |
222 | */ | 226 | */ |
@@ -787,6 +791,9 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
787 | PCI_DMA_FROMDEVICE); | 791 | PCI_DMA_FROMDEVICE); |
788 | pkt = (struct iwl_rx_packet *)rxb->skb->data; | 792 | pkt = (struct iwl_rx_packet *)rxb->skb->data; |
789 | 793 | ||
794 | trace_iwlwifi_dev_rx(priv, pkt, | ||
795 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
796 | |||
790 | /* Reclaim a command buffer only if this packet is a response | 797 | /* Reclaim a command buffer only if this packet is a response |
791 | * to a (driver-originated) command. | 798 | * to a (driver-originated) command. |
792 | * If the packet (e.g. Rx frame) originated from uCode, | 799 | * If the packet (e.g. Rx frame) originated from uCode, |
@@ -1606,6 +1613,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv) | |||
1606 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); | 1613 | line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); |
1607 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); | 1614 | time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); |
1608 | 1615 | ||
1616 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line, | ||
1617 | blink1, blink2, ilink1, ilink2); | ||
1618 | |||
1609 | IWL_ERR(priv, "Desc Time " | 1619 | IWL_ERR(priv, "Desc Time " |
1610 | "data1 data2 line\n"); | 1620 | "data1 data2 line\n"); |
1611 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", | 1621 | IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", |
@@ -1654,12 +1664,14 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1654 | ptr += sizeof(u32); | 1664 | ptr += sizeof(u32); |
1655 | if (mode == 0) { | 1665 | if (mode == 0) { |
1656 | /* data, ev */ | 1666 | /* data, ev */ |
1667 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); | ||
1657 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); | 1668 | IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); |
1658 | } else { | 1669 | } else { |
1659 | data = iwl_read_targ_mem(priv, ptr); | 1670 | data = iwl_read_targ_mem(priv, ptr); |
1660 | ptr += sizeof(u32); | 1671 | ptr += sizeof(u32); |
1661 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", | 1672 | IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", |
1662 | time, data, ev); | 1673 | time, data, ev); |
1674 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); | ||
1663 | } | 1675 | } |
1664 | } | 1676 | } |
1665 | } | 1677 | } |
@@ -1758,6 +1770,10 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
1758 | priv->active_rate = priv->rates_mask; | 1770 | priv->active_rate = priv->rates_mask; |
1759 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; | 1771 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; |
1760 | 1772 | ||
1773 | /* Configure Tx antenna selection based on H/W config */ | ||
1774 | if (priv->cfg->ops->hcmd->set_tx_ant) | ||
1775 | priv->cfg->ops->hcmd->set_tx_ant(priv, priv->cfg->valid_tx_ant); | ||
1776 | |||
1761 | if (iwl_is_associated(priv)) { | 1777 | if (iwl_is_associated(priv)) { |
1762 | struct iwl_rxon_cmd *active_rxon = | 1778 | struct iwl_rxon_cmd *active_rxon = |
1763 | (struct iwl_rxon_cmd *)&priv->active_rxon; | 1779 | (struct iwl_rxon_cmd *)&priv->active_rxon; |
@@ -1785,7 +1801,7 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
1785 | /* At this point, the NIC is initialized and operational */ | 1801 | /* At this point, the NIC is initialized and operational */ |
1786 | iwl_rf_kill_ct_config(priv); | 1802 | iwl_rf_kill_ct_config(priv); |
1787 | 1803 | ||
1788 | iwl_leds_register(priv); | 1804 | iwl_leds_init(priv); |
1789 | 1805 | ||
1790 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | 1806 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); |
1791 | set_bit(STATUS_READY, &priv->status); | 1807 | set_bit(STATUS_READY, &priv->status); |
@@ -1823,8 +1839,6 @@ static void __iwl_down(struct iwl_priv *priv) | |||
1823 | if (!exit_pending) | 1839 | if (!exit_pending) |
1824 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 1840 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
1825 | 1841 | ||
1826 | iwl_leds_unregister(priv); | ||
1827 | |||
1828 | iwl_clear_stations_table(priv); | 1842 | iwl_clear_stations_table(priv); |
1829 | 1843 | ||
1830 | /* Unblock any waiting calls */ | 1844 | /* Unblock any waiting calls */ |
@@ -2323,6 +2337,8 @@ static int iwl_mac_start(struct ieee80211_hw *hw) | |||
2323 | } | 2337 | } |
2324 | } | 2338 | } |
2325 | 2339 | ||
2340 | iwl_led_start(priv); | ||
2341 | |||
2326 | out: | 2342 | out: |
2327 | priv->is_open = 1; | 2343 | priv->is_open = 1; |
2328 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2344 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -2794,6 +2810,40 @@ static ssize_t show_statistics(struct device *d, | |||
2794 | 2810 | ||
2795 | static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); | 2811 | static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); |
2796 | 2812 | ||
2813 | static ssize_t show_rts_ht_protection(struct device *d, | ||
2814 | struct device_attribute *attr, char *buf) | ||
2815 | { | ||
2816 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
2817 | |||
2818 | return sprintf(buf, "%s\n", | ||
2819 | priv->cfg->use_rts_for_ht ? "RTS/CTS" : "CTS-to-self"); | ||
2820 | } | ||
2821 | |||
2822 | static ssize_t store_rts_ht_protection(struct device *d, | ||
2823 | struct device_attribute *attr, | ||
2824 | const char *buf, size_t count) | ||
2825 | { | ||
2826 | struct iwl_priv *priv = dev_get_drvdata(d); | ||
2827 | unsigned long val; | ||
2828 | int ret; | ||
2829 | |||
2830 | ret = strict_strtoul(buf, 10, &val); | ||
2831 | if (ret) | ||
2832 | IWL_INFO(priv, "Input is not in decimal form.\n"); | ||
2833 | else { | ||
2834 | if (!iwl_is_associated(priv)) | ||
2835 | priv->cfg->use_rts_for_ht = val ? true : false; | ||
2836 | else | ||
2837 | IWL_ERR(priv, "Sta associated with AP - " | ||
2838 | "Change protection mechanism is not allowed\n"); | ||
2839 | ret = count; | ||
2840 | } | ||
2841 | return ret; | ||
2842 | } | ||
2843 | |||
2844 | static DEVICE_ATTR(rts_ht_protection, S_IWUSR | S_IRUGO, | ||
2845 | show_rts_ht_protection, store_rts_ht_protection); | ||
2846 | |||
2797 | 2847 | ||
2798 | /***************************************************************************** | 2848 | /***************************************************************************** |
2799 | * | 2849 | * |
@@ -2850,6 +2900,7 @@ static struct attribute *iwl_sysfs_entries[] = { | |||
2850 | &dev_attr_statistics.attr, | 2900 | &dev_attr_statistics.attr, |
2851 | &dev_attr_temperature.attr, | 2901 | &dev_attr_temperature.attr, |
2852 | &dev_attr_tx_power.attr, | 2902 | &dev_attr_tx_power.attr, |
2903 | &dev_attr_rts_ht_protection.attr, | ||
2853 | #ifdef CONFIG_IWLWIFI_DEBUG | 2904 | #ifdef CONFIG_IWLWIFI_DEBUG |
2854 | &dev_attr_debug_level.attr, | 2905 | &dev_attr_debug_level.attr, |
2855 | #endif | 2906 | #endif |
@@ -3215,20 +3266,51 @@ static struct pci_device_id iwl_hw_card_ids[] = { | |||
3215 | /* 5150 Wifi/WiMax */ | 3266 | /* 5150 Wifi/WiMax */ |
3216 | {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3267 | {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)}, |
3217 | {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3268 | {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, |
3218 | /* 6000/6050 Series */ | 3269 | |
3219 | {IWL_PCI_DEVICE(0x008D, PCI_ANY_ID, iwl6000h_2agn_cfg)}, | 3270 | /* 6x00 Series */ |
3220 | {IWL_PCI_DEVICE(0x008E, PCI_ANY_ID, iwl6000h_2agn_cfg)}, | 3271 | {IWL_PCI_DEVICE(0x008D, 0x1301, iwl6000h_2agn_cfg)}, |
3221 | {IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)}, | 3272 | {IWL_PCI_DEVICE(0x008D, 0x1321, iwl6000h_2agn_cfg)}, |
3222 | {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000i_2agn_cfg)}, | 3273 | {IWL_PCI_DEVICE(0x008D, 0x1326, iwl6000h_2abg_cfg)}, |
3223 | {IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)}, | 3274 | {IWL_PCI_DEVICE(0x008D, 0x1306, iwl6000h_2abg_cfg)}, |
3224 | {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000i_2agn_cfg)}, | 3275 | {IWL_PCI_DEVICE(0x008D, 0x1307, iwl6000h_2bg_cfg)}, |
3225 | {IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)}, | 3276 | {IWL_PCI_DEVICE(0x008E, 0x1311, iwl6000h_2agn_cfg)}, |
3226 | {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, | 3277 | {IWL_PCI_DEVICE(0x008E, 0x1316, iwl6000h_2abg_cfg)}, |
3227 | {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, | 3278 | |
3228 | {IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)}, | 3279 | {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, |
3280 | {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)}, | ||
3281 | {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)}, | ||
3282 | {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)}, | ||
3283 | {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)}, | ||
3284 | {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)}, | ||
3285 | {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)}, | ||
3286 | {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)}, | ||
3287 | {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)}, | ||
3288 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, | ||
3289 | |||
3290 | /* 6x50 WiFi/WiMax Series */ | ||
3291 | {IWL_PCI_DEVICE(0x0086, 0x1101, iwl6050_3agn_cfg)}, | ||
3292 | {IWL_PCI_DEVICE(0x0086, 0x1121, iwl6050_3agn_cfg)}, | ||
3293 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | ||
3294 | {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, | ||
3295 | {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)}, | ||
3296 | {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)}, | ||
3297 | {IWL_PCI_DEVICE(0x0088, 0x1111, iwl6050_3agn_cfg)}, | ||
3298 | {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, | ||
3299 | {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, | ||
3300 | |||
3229 | /* 1000 Series WiFi */ | 3301 | /* 1000 Series WiFi */ |
3230 | {IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl1000_bgn_cfg)}, | 3302 | {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)}, |
3231 | {IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl1000_bgn_cfg)}, | 3303 | {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)}, |
3304 | {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)}, | ||
3305 | {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)}, | ||
3306 | {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)}, | ||
3307 | {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)}, | ||
3308 | {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)}, | ||
3309 | {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)}, | ||
3310 | {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)}, | ||
3311 | {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)}, | ||
3312 | {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)}, | ||
3313 | {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)}, | ||
3232 | #endif /* CONFIG_IWL5000 */ | 3314 | #endif /* CONFIG_IWL5000 */ |
3233 | 3315 | ||
3234 | {0} | 3316 | {0} |
@@ -3283,9 +3365,9 @@ module_exit(iwl_exit); | |||
3283 | module_init(iwl_init); | 3365 | module_init(iwl_init); |
3284 | 3366 | ||
3285 | #ifdef CONFIG_IWLWIFI_DEBUG | 3367 | #ifdef CONFIG_IWLWIFI_DEBUG |
3286 | module_param_named(debug50, iwl_debug_level, uint, 0444); | 3368 | module_param_named(debug50, iwl_debug_level, uint, S_IRUGO); |
3287 | MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); | 3369 | MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); |
3288 | module_param_named(debug, iwl_debug_level, uint, 0644); | 3370 | module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); |
3289 | MODULE_PARM_DESC(debug, "debug output mask"); | 3371 | MODULE_PARM_DESC(debug, "debug output mask"); |
3290 | #endif | 3372 | #endif |
3291 | 3373 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index c4b565a2de94..69a80d7c2e44 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -516,7 +516,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) | |||
516 | for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) | 516 | for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) |
517 | data->nrg_silence_rssi[i] = 0; | 517 | data->nrg_silence_rssi[i] = 0; |
518 | 518 | ||
519 | data->auto_corr_ofdm = 90; | 519 | data->auto_corr_ofdm = ranges->auto_corr_min_ofdm; |
520 | data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc; | 520 | data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc; |
521 | data->auto_corr_ofdm_x1 = ranges->auto_corr_min_ofdm_x1; | 521 | data->auto_corr_ofdm_x1 = ranges->auto_corr_min_ofdm_x1; |
522 | data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1; | 522 | data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1; |
@@ -643,6 +643,15 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, | |||
643 | } | 643 | } |
644 | EXPORT_SYMBOL(iwl_sensitivity_calibration); | 644 | EXPORT_SYMBOL(iwl_sensitivity_calibration); |
645 | 645 | ||
646 | static inline u8 find_first_chain(u8 mask) | ||
647 | { | ||
648 | if (mask & ANT_A) | ||
649 | return CHAIN_A; | ||
650 | if (mask & ANT_B) | ||
651 | return CHAIN_B; | ||
652 | return CHAIN_C; | ||
653 | } | ||
654 | |||
646 | /* | 655 | /* |
647 | * Accumulate 20 beacons of signal and noise statistics for each of | 656 | * Accumulate 20 beacons of signal and noise statistics for each of |
648 | * 3 receivers/antennas/rx-chains, then figure out: | 657 | * 3 receivers/antennas/rx-chains, then figure out: |
@@ -675,14 +684,17 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
675 | u8 num_tx_chains; | 684 | u8 num_tx_chains; |
676 | unsigned long flags; | 685 | unsigned long flags; |
677 | struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general); | 686 | struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general); |
687 | u8 first_chain; | ||
678 | 688 | ||
679 | if (priv->disable_chain_noise_cal) | 689 | if (priv->disable_chain_noise_cal) |
680 | return; | 690 | return; |
681 | 691 | ||
682 | data = &(priv->chain_noise_data); | 692 | data = &(priv->chain_noise_data); |
683 | 693 | ||
684 | /* Accumulate just the first 20 beacons after the first association, | 694 | /* |
685 | * then we're done forever. */ | 695 | * Accumulate just the first "chain_noise_num_beacons" after |
696 | * the first association, then we're done forever. | ||
697 | */ | ||
686 | if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) { | 698 | if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) { |
687 | if (data->state == IWL_CHAIN_NOISE_ALIVE) | 699 | if (data->state == IWL_CHAIN_NOISE_ALIVE) |
688 | IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n"); | 700 | IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n"); |
@@ -710,7 +722,10 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
710 | return; | 722 | return; |
711 | } | 723 | } |
712 | 724 | ||
713 | /* Accumulate beacon statistics values across 20 beacons */ | 725 | /* |
726 | * Accumulate beacon statistics values across | ||
727 | * "chain_noise_num_beacons" | ||
728 | */ | ||
714 | chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & | 729 | chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & |
715 | IN_BAND_FILTER; | 730 | IN_BAND_FILTER; |
716 | chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) & | 731 | chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) & |
@@ -741,16 +756,19 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
741 | IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n", | 756 | IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n", |
742 | chain_noise_a, chain_noise_b, chain_noise_c); | 757 | chain_noise_a, chain_noise_b, chain_noise_c); |
743 | 758 | ||
744 | /* If this is the 20th beacon, determine: | 759 | /* If this is the "chain_noise_num_beacons", determine: |
745 | * 1) Disconnected antennas (using signal strengths) | 760 | * 1) Disconnected antennas (using signal strengths) |
746 | * 2) Differential gain (using silence noise) to balance receivers */ | 761 | * 2) Differential gain (using silence noise) to balance receivers */ |
747 | if (data->beacon_count != CAL_NUM_OF_BEACONS) | 762 | if (data->beacon_count != priv->cfg->chain_noise_num_beacons) |
748 | return; | 763 | return; |
749 | 764 | ||
750 | /* Analyze signal for disconnected antenna */ | 765 | /* Analyze signal for disconnected antenna */ |
751 | average_sig[0] = (data->chain_signal_a) / CAL_NUM_OF_BEACONS; | 766 | average_sig[0] = |
752 | average_sig[1] = (data->chain_signal_b) / CAL_NUM_OF_BEACONS; | 767 | (data->chain_signal_a) / priv->cfg->chain_noise_num_beacons; |
753 | average_sig[2] = (data->chain_signal_c) / CAL_NUM_OF_BEACONS; | 768 | average_sig[1] = |
769 | (data->chain_signal_b) / priv->cfg->chain_noise_num_beacons; | ||
770 | average_sig[2] = | ||
771 | (data->chain_signal_c) / priv->cfg->chain_noise_num_beacons; | ||
754 | 772 | ||
755 | if (average_sig[0] >= average_sig[1]) { | 773 | if (average_sig[0] >= average_sig[1]) { |
756 | max_average_sig = average_sig[0]; | 774 | max_average_sig = average_sig[0]; |
@@ -803,13 +821,17 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
803 | /* there is a Tx antenna connected */ | 821 | /* there is a Tx antenna connected */ |
804 | break; | 822 | break; |
805 | if (num_tx_chains == priv->hw_params.tx_chains_num && | 823 | if (num_tx_chains == priv->hw_params.tx_chains_num && |
806 | data->disconn_array[i]) { | 824 | data->disconn_array[i]) { |
807 | /* This is the last TX antenna and is also | 825 | /* |
808 | * disconnected connect it anyway */ | 826 | * If all chains are disconnected |
809 | data->disconn_array[i] = 0; | 827 | * connect the first valid tx chain |
810 | active_chains |= ant_msk; | 828 | */ |
811 | IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - " | 829 | first_chain = |
812 | "declare %d as connected\n", i); | 830 | find_first_chain(priv->cfg->valid_tx_ant); |
831 | data->disconn_array[first_chain] = 0; | ||
832 | active_chains |= BIT(first_chain); | ||
833 | IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n", | ||
834 | first_chain); | ||
813 | break; | 835 | break; |
814 | } | 836 | } |
815 | } | 837 | } |
@@ -820,9 +842,12 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
820 | active_chains); | 842 | active_chains); |
821 | 843 | ||
822 | /* Analyze noise for rx balance */ | 844 | /* Analyze noise for rx balance */ |
823 | average_noise[0] = ((data->chain_noise_a)/CAL_NUM_OF_BEACONS); | 845 | average_noise[0] = |
824 | average_noise[1] = ((data->chain_noise_b)/CAL_NUM_OF_BEACONS); | 846 | ((data->chain_noise_a) / priv->cfg->chain_noise_num_beacons); |
825 | average_noise[2] = ((data->chain_noise_c)/CAL_NUM_OF_BEACONS); | 847 | average_noise[1] = |
848 | ((data->chain_noise_b) / priv->cfg->chain_noise_num_beacons); | ||
849 | average_noise[2] = | ||
850 | ((data->chain_noise_c) / priv->cfg->chain_noise_num_beacons); | ||
826 | 851 | ||
827 | for (i = 0; i < NUM_RX_CHAINS; i++) { | 852 | for (i = 0; i < NUM_RX_CHAINS; i++) { |
828 | if (!(data->disconn_array[i]) && | 853 | if (!(data->disconn_array[i]) && |
@@ -843,7 +868,8 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, | |||
843 | 868 | ||
844 | if (priv->cfg->ops->utils->gain_computation) | 869 | if (priv->cfg->ops->utils->gain_computation) |
845 | priv->cfg->ops->utils->gain_computation(priv, average_noise, | 870 | priv->cfg->ops->utils->gain_computation(priv, average_noise, |
846 | min_average_noise_antenna_i, min_average_noise); | 871 | min_average_noise_antenna_i, min_average_noise, |
872 | find_first_chain(priv->cfg->valid_rx_ant)); | ||
847 | 873 | ||
848 | /* Some power changes may have been made during the calibration. | 874 | /* Some power changes may have been made during the calibration. |
849 | * Update and commit the RXON | 875 | * Update and commit the RXON |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 2c5c88fc38f5..e5f40f35dc3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -148,7 +148,7 @@ enum { | |||
148 | QUIET_NOTIFICATION = 0x96, /* not used */ | 148 | QUIET_NOTIFICATION = 0x96, /* not used */ |
149 | REPLY_TX_PWR_TABLE_CMD = 0x97, | 149 | REPLY_TX_PWR_TABLE_CMD = 0x97, |
150 | REPLY_TX_POWER_DBM_CMD_V1 = 0x98, /* old version of API */ | 150 | REPLY_TX_POWER_DBM_CMD_V1 = 0x98, /* old version of API */ |
151 | TX_ANT_CONFIGURATION_CMD = 0x98, /* not used */ | 151 | TX_ANT_CONFIGURATION_CMD = 0x98, |
152 | MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ | 152 | MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ |
153 | 153 | ||
154 | /* Bluetooth device coexistence config command */ | 154 | /* Bluetooth device coexistence config command */ |
@@ -411,6 +411,16 @@ struct iwl5000_tx_power_dbm_cmd { | |||
411 | u8 reserved; | 411 | u8 reserved; |
412 | } __attribute__ ((packed)); | 412 | } __attribute__ ((packed)); |
413 | 413 | ||
414 | /** | ||
415 | * Command TX_ANT_CONFIGURATION_CMD = 0x98 | ||
416 | * This command is used to configure valid Tx antenna. | ||
417 | * By default uCode concludes the valid antenna according to the radio flavor. | ||
418 | * This command enables the driver to override/modify this conclusion. | ||
419 | */ | ||
420 | struct iwl_tx_ant_config_cmd { | ||
421 | __le32 valid; | ||
422 | } __attribute__ ((packed)); | ||
423 | |||
414 | /****************************************************************************** | 424 | /****************************************************************************** |
415 | * (0a) | 425 | * (0a) |
416 | * Alive and Error Commands & Responses: | 426 | * Alive and Error Commands & Responses: |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 484d5c1a7312..dc7fd87bed98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -607,8 +607,7 @@ EXPORT_SYMBOL(iwlcore_free_geos); | |||
607 | static bool is_single_rx_stream(struct iwl_priv *priv) | 607 | static bool is_single_rx_stream(struct iwl_priv *priv) |
608 | { | 608 | { |
609 | return !priv->current_ht_config.is_ht || | 609 | return !priv->current_ht_config.is_ht || |
610 | ((priv->current_ht_config.mcs.rx_mask[1] == 0) && | 610 | priv->current_ht_config.single_chain_sufficient; |
611 | (priv->current_ht_config.mcs.rx_mask[2] == 0)); | ||
612 | } | 611 | } |
613 | 612 | ||
614 | static u8 iwl_is_channel_extension(struct iwl_priv *priv, | 613 | static u8 iwl_is_channel_extension(struct iwl_priv *priv, |
@@ -634,10 +633,9 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv, | |||
634 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 633 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
635 | struct ieee80211_sta_ht_cap *sta_ht_inf) | 634 | struct ieee80211_sta_ht_cap *sta_ht_inf) |
636 | { | 635 | { |
637 | struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config; | 636 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
638 | 637 | ||
639 | if ((!iwl_ht_conf->is_ht) || | 638 | if (!ht_conf->is_ht || !ht_conf->is_40mhz) |
640 | (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ)) | ||
641 | return 0; | 639 | return 0; |
642 | 640 | ||
643 | /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 641 | /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
@@ -653,7 +651,7 @@ u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | |||
653 | #endif | 651 | #endif |
654 | return iwl_is_channel_extension(priv, priv->band, | 652 | return iwl_is_channel_extension(priv, priv->band, |
655 | le16_to_cpu(priv->staging_rxon.channel), | 653 | le16_to_cpu(priv->staging_rxon.channel), |
656 | iwl_ht_conf->extension_chan_offset); | 654 | ht_conf->extension_chan_offset); |
657 | } | 655 | } |
658 | EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); | 656 | EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); |
659 | 657 | ||
@@ -877,11 +875,11 @@ u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) | |||
877 | } | 875 | } |
878 | EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); | 876 | EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); |
879 | 877 | ||
880 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | 878 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) |
881 | { | 879 | { |
882 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 880 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; |
883 | 881 | ||
884 | if (!ht_info->is_ht) { | 882 | if (!ht_conf->is_ht) { |
885 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | 883 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | |
886 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | 884 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | |
887 | RXON_FLG_HT40_PROT_MSK | | 885 | RXON_FLG_HT40_PROT_MSK | |
@@ -892,7 +890,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
892 | /* FIXME: if the definition of ht_protection changed, the "translation" | 890 | /* FIXME: if the definition of ht_protection changed, the "translation" |
893 | * will be needed for rxon->flags | 891 | * will be needed for rxon->flags |
894 | */ | 892 | */ |
895 | rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS); | 893 | rxon->flags |= cpu_to_le32(ht_conf->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS); |
896 | 894 | ||
897 | /* Set up channel bandwidth: | 895 | /* Set up channel bandwidth: |
898 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ | 896 | * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ |
@@ -901,10 +899,10 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
901 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | 899 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); |
902 | if (iwl_is_ht40_tx_allowed(priv, NULL)) { | 900 | if (iwl_is_ht40_tx_allowed(priv, NULL)) { |
903 | /* pure ht40 */ | 901 | /* pure ht40 */ |
904 | if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { | 902 | if (ht_conf->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { |
905 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; | 903 | rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; |
906 | /* Note: control channel is opposite of extension channel */ | 904 | /* Note: control channel is opposite of extension channel */ |
907 | switch (ht_info->extension_chan_offset) { | 905 | switch (ht_conf->extension_chan_offset) { |
908 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 906 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
909 | rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; | 907 | rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; |
910 | break; | 908 | break; |
@@ -914,7 +912,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
914 | } | 912 | } |
915 | } else { | 913 | } else { |
916 | /* Note: control channel is opposite of extension channel */ | 914 | /* Note: control channel is opposite of extension channel */ |
917 | switch (ht_info->extension_chan_offset) { | 915 | switch (ht_conf->extension_chan_offset) { |
918 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 916 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
919 | rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); | 917 | rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); |
920 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; | 918 | rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; |
@@ -937,14 +935,10 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) | |||
937 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 935 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
938 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 936 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
939 | 937 | ||
940 | IWL_DEBUG_ASSOC(priv, "supported HT rate 0x%X 0x%X 0x%X " | 938 | IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X " |
941 | "rxon flags 0x%X operation mode :0x%X " | ||
942 | "extension channel offset 0x%x\n", | 939 | "extension channel offset 0x%x\n", |
943 | ht_info->mcs.rx_mask[0], | 940 | le32_to_cpu(rxon->flags), ht_conf->ht_protection, |
944 | ht_info->mcs.rx_mask[1], | 941 | ht_conf->extension_chan_offset); |
945 | ht_info->mcs.rx_mask[2], | ||
946 | le32_to_cpu(rxon->flags), ht_info->ht_protection, | ||
947 | ht_info->extension_chan_offset); | ||
948 | return; | 942 | return; |
949 | } | 943 | } |
950 | EXPORT_SYMBOL(iwl_set_rxon_ht); | 944 | EXPORT_SYMBOL(iwl_set_rxon_ht); |
@@ -954,47 +948,37 @@ EXPORT_SYMBOL(iwl_set_rxon_ht); | |||
954 | #define IWL_NUM_IDLE_CHAINS_DUAL 2 | 948 | #define IWL_NUM_IDLE_CHAINS_DUAL 2 |
955 | #define IWL_NUM_IDLE_CHAINS_SINGLE 1 | 949 | #define IWL_NUM_IDLE_CHAINS_SINGLE 1 |
956 | 950 | ||
957 | /* Determine how many receiver/antenna chains to use. | 951 | /* |
958 | * More provides better reception via diversity. Fewer saves power. | 952 | * Determine how many receiver/antenna chains to use. |
953 | * | ||
954 | * More provides better reception via diversity. Fewer saves power | ||
955 | * at the expense of throughput, but only when not in powersave to | ||
956 | * start with. | ||
957 | * | ||
959 | * MIMO (dual stream) requires at least 2, but works better with 3. | 958 | * MIMO (dual stream) requires at least 2, but works better with 3. |
960 | * This does not determine *which* chains to use, just how many. | 959 | * This does not determine *which* chains to use, just how many. |
961 | */ | 960 | */ |
962 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) | 961 | static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) |
963 | { | 962 | { |
964 | bool is_single = is_single_rx_stream(priv); | ||
965 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); | ||
966 | |||
967 | /* # of Rx chains to use when expecting MIMO. */ | 963 | /* # of Rx chains to use when expecting MIMO. */ |
968 | if (is_single || (!is_cam && (priv->current_ht_config.sm_ps == | 964 | if (is_single_rx_stream(priv)) |
969 | WLAN_HT_CAP_SM_PS_STATIC))) | ||
970 | return IWL_NUM_RX_CHAINS_SINGLE; | 965 | return IWL_NUM_RX_CHAINS_SINGLE; |
971 | else | 966 | else |
972 | return IWL_NUM_RX_CHAINS_MULTIPLE; | 967 | return IWL_NUM_RX_CHAINS_MULTIPLE; |
973 | } | 968 | } |
974 | 969 | ||
970 | /* | ||
971 | * When we are in power saving, there's no difference between | ||
972 | * using multiple chains or just a single chain, but due to the | ||
973 | * lack of SM PS we lose a lot of throughput if we use just a | ||
974 | * single chain. | ||
975 | * | ||
976 | * Therefore, use the active count here (which will use multiple | ||
977 | * chains unless connected to a legacy AP). | ||
978 | */ | ||
975 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) | 979 | static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) |
976 | { | 980 | { |
977 | int idle_cnt; | 981 | return active_cnt; |
978 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); | ||
979 | /* # Rx chains when idling and maybe trying to save power */ | ||
980 | switch (priv->current_ht_config.sm_ps) { | ||
981 | case WLAN_HT_CAP_SM_PS_STATIC: | ||
982 | case WLAN_HT_CAP_SM_PS_DYNAMIC: | ||
983 | idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : | ||
984 | IWL_NUM_IDLE_CHAINS_SINGLE; | ||
985 | break; | ||
986 | case WLAN_HT_CAP_SM_PS_DISABLED: | ||
987 | idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; | ||
988 | break; | ||
989 | case WLAN_HT_CAP_SM_PS_INVALID: | ||
990 | default: | ||
991 | IWL_ERR(priv, "invalid mimo ps mode %d\n", | ||
992 | priv->current_ht_config.sm_ps); | ||
993 | WARN_ON(1); | ||
994 | idle_cnt = -1; | ||
995 | break; | ||
996 | } | ||
997 | return idle_cnt; | ||
998 | } | 982 | } |
999 | 983 | ||
1000 | /* up to 4 chains */ | 984 | /* up to 4 chains */ |
@@ -1004,7 +988,7 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap) | |||
1004 | res = (chain_bitmap & BIT(0)) >> 0; | 988 | res = (chain_bitmap & BIT(0)) >> 0; |
1005 | res += (chain_bitmap & BIT(1)) >> 1; | 989 | res += (chain_bitmap & BIT(1)) >> 1; |
1006 | res += (chain_bitmap & BIT(2)) >> 2; | 990 | res += (chain_bitmap & BIT(2)) >> 2; |
1007 | res += (chain_bitmap & BIT(4)) >> 4; | 991 | res += (chain_bitmap & BIT(3)) >> 3; |
1008 | return res; | 992 | return res; |
1009 | } | 993 | } |
1010 | 994 | ||
@@ -1345,6 +1329,42 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1345 | } | 1329 | } |
1346 | EXPORT_SYMBOL(iwl_irq_handle_error); | 1330 | EXPORT_SYMBOL(iwl_irq_handle_error); |
1347 | 1331 | ||
1332 | int iwl_apm_stop_master(struct iwl_priv *priv) | ||
1333 | { | ||
1334 | unsigned long flags; | ||
1335 | |||
1336 | spin_lock_irqsave(&priv->lock, flags); | ||
1337 | |||
1338 | /* set stop master bit */ | ||
1339 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | ||
1340 | |||
1341 | iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, | ||
1342 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | ||
1343 | |||
1344 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1345 | IWL_DEBUG_INFO(priv, "stop master\n"); | ||
1346 | |||
1347 | return 0; | ||
1348 | } | ||
1349 | EXPORT_SYMBOL(iwl_apm_stop_master); | ||
1350 | |||
1351 | void iwl_apm_stop(struct iwl_priv *priv) | ||
1352 | { | ||
1353 | unsigned long flags; | ||
1354 | |||
1355 | iwl_apm_stop_master(priv); | ||
1356 | |||
1357 | spin_lock_irqsave(&priv->lock, flags); | ||
1358 | |||
1359 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); | ||
1360 | |||
1361 | udelay(10); | ||
1362 | /* clear "init complete" move adapter D0A* --> D0U state */ | ||
1363 | iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
1364 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1365 | } | ||
1366 | EXPORT_SYMBOL(iwl_apm_stop); | ||
1367 | |||
1348 | void iwl_configure_filter(struct ieee80211_hw *hw, | 1368 | void iwl_configure_filter(struct ieee80211_hw *hw, |
1349 | unsigned int changed_flags, | 1369 | unsigned int changed_flags, |
1350 | unsigned int *total_flags, | 1370 | unsigned int *total_flags, |
@@ -1494,8 +1514,6 @@ int iwl_init_drv(struct iwl_priv *priv) | |||
1494 | 1514 | ||
1495 | priv->iw_mode = NL80211_IFTYPE_STATION; | 1515 | priv->iw_mode = NL80211_IFTYPE_STATION; |
1496 | 1516 | ||
1497 | priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; | ||
1498 | |||
1499 | /* Choose which receivers/antennas to use */ | 1517 | /* Choose which receivers/antennas to use */ |
1500 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 1518 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
1501 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 1519 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
@@ -2227,42 +2245,58 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2227 | EXPORT_SYMBOL(iwl_mac_conf_tx); | 2245 | EXPORT_SYMBOL(iwl_mac_conf_tx); |
2228 | 2246 | ||
2229 | static void iwl_ht_conf(struct iwl_priv *priv, | 2247 | static void iwl_ht_conf(struct iwl_priv *priv, |
2230 | struct ieee80211_bss_conf *bss_conf) | 2248 | struct ieee80211_bss_conf *bss_conf) |
2231 | { | 2249 | { |
2232 | struct ieee80211_sta_ht_cap *ht_conf; | 2250 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2233 | struct iwl_ht_info *iwl_conf = &priv->current_ht_config; | ||
2234 | struct ieee80211_sta *sta; | 2251 | struct ieee80211_sta *sta; |
2235 | 2252 | ||
2236 | IWL_DEBUG_MAC80211(priv, "enter: \n"); | 2253 | IWL_DEBUG_MAC80211(priv, "enter: \n"); |
2237 | 2254 | ||
2238 | if (!iwl_conf->is_ht) | 2255 | if (!ht_conf->is_ht) |
2239 | return; | 2256 | return; |
2240 | 2257 | ||
2258 | ht_conf->ht_protection = | ||
2259 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | ||
2260 | ht_conf->non_GF_STA_present = | ||
2261 | !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
2241 | 2262 | ||
2242 | /* | 2263 | ht_conf->single_chain_sufficient = false; |
2243 | * It is totally wrong to base global information on something | ||
2244 | * that is valid only when associated, alas, this driver works | ||
2245 | * that way and I don't know how to fix it. | ||
2246 | */ | ||
2247 | 2264 | ||
2248 | rcu_read_lock(); | 2265 | switch (priv->iw_mode) { |
2249 | sta = ieee80211_find_sta(priv->hw, priv->bssid); | 2266 | case NL80211_IFTYPE_STATION: |
2250 | if (!sta) { | 2267 | rcu_read_lock(); |
2268 | sta = ieee80211_find_sta(priv->hw, priv->bssid); | ||
2269 | if (sta) { | ||
2270 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
2271 | int maxstreams; | ||
2272 | |||
2273 | maxstreams = (ht_cap->mcs.tx_params & | ||
2274 | IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) | ||
2275 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; | ||
2276 | maxstreams += 1; | ||
2277 | |||
2278 | if ((ht_cap->mcs.rx_mask[1] == 0) && | ||
2279 | (ht_cap->mcs.rx_mask[2] == 0)) | ||
2280 | ht_conf->single_chain_sufficient = true; | ||
2281 | if (maxstreams <= 1) | ||
2282 | ht_conf->single_chain_sufficient = true; | ||
2283 | } else { | ||
2284 | /* | ||
2285 | * If at all, this can only happen through a race | ||
2286 | * when the AP disconnects us while we're still | ||
2287 | * setting up the connection, in that case mac80211 | ||
2288 | * will soon tell us about that. | ||
2289 | */ | ||
2290 | ht_conf->single_chain_sufficient = true; | ||
2291 | } | ||
2251 | rcu_read_unlock(); | 2292 | rcu_read_unlock(); |
2252 | return; | 2293 | break; |
2294 | case NL80211_IFTYPE_ADHOC: | ||
2295 | ht_conf->single_chain_sufficient = true; | ||
2296 | break; | ||
2297 | default: | ||
2298 | break; | ||
2253 | } | 2299 | } |
2254 | ht_conf = &sta->ht_cap; | ||
2255 | |||
2256 | iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); | ||
2257 | |||
2258 | memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); | ||
2259 | |||
2260 | iwl_conf->ht_protection = | ||
2261 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | ||
2262 | iwl_conf->non_GF_STA_present = | ||
2263 | !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
2264 | |||
2265 | rcu_read_unlock(); | ||
2266 | 2300 | ||
2267 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2301 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2268 | } | 2302 | } |
@@ -2386,6 +2420,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2386 | priv->timestamp = bss_conf->timestamp; | 2420 | priv->timestamp = bss_conf->timestamp; |
2387 | priv->assoc_capability = bss_conf->assoc_capability; | 2421 | priv->assoc_capability = bss_conf->assoc_capability; |
2388 | 2422 | ||
2423 | iwl_led_associate(priv); | ||
2424 | |||
2389 | /* | 2425 | /* |
2390 | * We have just associated, don't start scan too early | 2426 | * We have just associated, don't start scan too early |
2391 | * leave time for EAPOL exchange to complete. | 2427 | * leave time for EAPOL exchange to complete. |
@@ -2396,9 +2432,10 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2396 | IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; | 2432 | IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; |
2397 | if (!iwl_is_rfkill(priv)) | 2433 | if (!iwl_is_rfkill(priv)) |
2398 | priv->cfg->ops->lib->post_associate(priv); | 2434 | priv->cfg->ops->lib->post_associate(priv); |
2399 | } else | 2435 | } else { |
2400 | priv->assoc_id = 0; | 2436 | priv->assoc_id = 0; |
2401 | 2437 | iwl_led_disassociate(priv); | |
2438 | } | ||
2402 | } | 2439 | } |
2403 | 2440 | ||
2404 | if (changes && iwl_is_associated(priv) && priv->assoc_id) { | 2441 | if (changes && iwl_is_associated(priv) && priv->assoc_id) { |
@@ -2569,7 +2606,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2569 | struct iwl_priv *priv = hw->priv; | 2606 | struct iwl_priv *priv = hw->priv; |
2570 | const struct iwl_channel_info *ch_info; | 2607 | const struct iwl_channel_info *ch_info; |
2571 | struct ieee80211_conf *conf = &hw->conf; | 2608 | struct ieee80211_conf *conf = &hw->conf; |
2572 | struct iwl_ht_info *ht_conf = &priv->current_ht_config; | 2609 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2573 | unsigned long flags = 0; | 2610 | unsigned long flags = 0; |
2574 | int ret = 0; | 2611 | int ret = 0; |
2575 | u16 ch; | 2612 | u16 ch; |
@@ -2619,21 +2656,18 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2619 | if (conf_is_ht40_minus(conf)) { | 2656 | if (conf_is_ht40_minus(conf)) { |
2620 | ht_conf->extension_chan_offset = | 2657 | ht_conf->extension_chan_offset = |
2621 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | 2658 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; |
2622 | ht_conf->supported_chan_width = | 2659 | ht_conf->is_40mhz = true; |
2623 | IWL_CHANNEL_WIDTH_40MHZ; | ||
2624 | } else if (conf_is_ht40_plus(conf)) { | 2660 | } else if (conf_is_ht40_plus(conf)) { |
2625 | ht_conf->extension_chan_offset = | 2661 | ht_conf->extension_chan_offset = |
2626 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | 2662 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; |
2627 | ht_conf->supported_chan_width = | 2663 | ht_conf->is_40mhz = true; |
2628 | IWL_CHANNEL_WIDTH_40MHZ; | ||
2629 | } else { | 2664 | } else { |
2630 | ht_conf->extension_chan_offset = | 2665 | ht_conf->extension_chan_offset = |
2631 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | 2666 | IEEE80211_HT_PARAM_CHA_SEC_NONE; |
2632 | ht_conf->supported_chan_width = | 2667 | ht_conf->is_40mhz = false; |
2633 | IWL_CHANNEL_WIDTH_20MHZ; | ||
2634 | } | 2668 | } |
2635 | } else | 2669 | } else |
2636 | ht_conf->supported_chan_width = IWL_CHANNEL_WIDTH_20MHZ; | 2670 | ht_conf->is_40mhz = false; |
2637 | /* Default to no protection. Protection mode will later be set | 2671 | /* Default to no protection. Protection mode will later be set |
2638 | * from BSS config in iwl_ht_conf */ | 2672 | * from BSS config in iwl_ht_conf */ |
2639 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 2673 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
@@ -2655,7 +2689,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2655 | iwl_set_rate(priv); | 2689 | iwl_set_rate(priv); |
2656 | } | 2690 | } |
2657 | 2691 | ||
2658 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 2692 | if (changed & (IEEE80211_CONF_CHANGE_PS | |
2693 | IEEE80211_CONF_CHANGE_IDLE)) { | ||
2659 | ret = iwl_power_update_mode(priv, false); | 2694 | ret = iwl_power_update_mode(priv, false); |
2660 | if (ret) | 2695 | if (ret) |
2661 | IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); | 2696 | IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); |
@@ -2739,7 +2774,7 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) | |||
2739 | IWL_DEBUG_MAC80211(priv, "enter\n"); | 2774 | IWL_DEBUG_MAC80211(priv, "enter\n"); |
2740 | 2775 | ||
2741 | spin_lock_irqsave(&priv->lock, flags); | 2776 | spin_lock_irqsave(&priv->lock, flags); |
2742 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); | 2777 | memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config)); |
2743 | spin_unlock_irqrestore(&priv->lock, flags); | 2778 | spin_unlock_irqrestore(&priv->lock, flags); |
2744 | 2779 | ||
2745 | iwl_reset_qos(priv); | 2780 | iwl_reset_qos(priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e50103a956b1..6688b6944200 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -89,6 +89,7 @@ struct iwl_hcmd_ops { | |||
89 | int (*rxon_assoc)(struct iwl_priv *priv); | 89 | int (*rxon_assoc)(struct iwl_priv *priv); |
90 | int (*commit_rxon)(struct iwl_priv *priv); | 90 | int (*commit_rxon)(struct iwl_priv *priv); |
91 | void (*set_rxon_chain)(struct iwl_priv *priv); | 91 | void (*set_rxon_chain)(struct iwl_priv *priv); |
92 | int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant); | ||
92 | }; | 93 | }; |
93 | 94 | ||
94 | struct iwl_hcmd_utils_ops { | 95 | struct iwl_hcmd_utils_ops { |
@@ -97,7 +98,8 @@ struct iwl_hcmd_utils_ops { | |||
97 | void (*gain_computation)(struct iwl_priv *priv, | 98 | void (*gain_computation)(struct iwl_priv *priv, |
98 | u32 *average_noise, | 99 | u32 *average_noise, |
99 | u16 min_average_noise_antennat_i, | 100 | u16 min_average_noise_antennat_i, |
100 | u32 min_average_noise); | 101 | u32 min_average_noise, |
102 | u8 default_chain); | ||
101 | void (*chain_noise_reset)(struct iwl_priv *priv); | 103 | void (*chain_noise_reset)(struct iwl_priv *priv); |
102 | void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, | 104 | void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, |
103 | __le32 *tx_flags); | 105 | __le32 *tx_flags); |
@@ -185,11 +187,18 @@ struct iwl_lib_ops { | |||
185 | struct iwl_temp_ops temp_ops; | 187 | struct iwl_temp_ops temp_ops; |
186 | }; | 188 | }; |
187 | 189 | ||
190 | struct iwl_led_ops { | ||
191 | int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd); | ||
192 | int (*on)(struct iwl_priv *priv); | ||
193 | int (*off)(struct iwl_priv *priv); | ||
194 | }; | ||
195 | |||
188 | struct iwl_ops { | 196 | struct iwl_ops { |
189 | const struct iwl_ucode_ops *ucode; | 197 | const struct iwl_ucode_ops *ucode; |
190 | const struct iwl_lib_ops *lib; | 198 | const struct iwl_lib_ops *lib; |
191 | const struct iwl_hcmd_ops *hcmd; | 199 | const struct iwl_hcmd_ops *hcmd; |
192 | const struct iwl_hcmd_utils_ops *utils; | 200 | const struct iwl_hcmd_utils_ops *utils; |
201 | const struct iwl_led_ops *led; | ||
193 | }; | 202 | }; |
194 | 203 | ||
195 | struct iwl_mod_params { | 204 | struct iwl_mod_params { |
@@ -213,6 +222,11 @@ struct iwl_mod_params { | |||
213 | * @pa_type: used by 6000 series only to identify the type of Power Amplifier | 222 | * @pa_type: used by 6000 series only to identify the type of Power Amplifier |
214 | * @max_ll_items: max number of OTP blocks | 223 | * @max_ll_items: max number of OTP blocks |
215 | * @shadow_ram_support: shadow support for OTP memory | 224 | * @shadow_ram_support: shadow support for OTP memory |
225 | * @led_compensation: compensate on the led on/off time per HW according | ||
226 | * to the deviation to achieve the desired led frequency. | ||
227 | * The detail algorithm is described in iwl-led.c | ||
228 | * @use_rts_for_ht: use rts/cts protection for HT traffic | ||
229 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | ||
216 | * | 230 | * |
217 | * We enable the driver to be backward compatible wrt API version. The | 231 | * We enable the driver to be backward compatible wrt API version. The |
218 | * driver specifies which APIs it supports (with @ucode_api_max being the | 232 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -254,7 +268,11 @@ struct iwl_cfg { | |||
254 | const u16 max_ll_items; | 268 | const u16 max_ll_items; |
255 | const bool shadow_ram_support; | 269 | const bool shadow_ram_support; |
256 | const bool ht_greenfield_support; | 270 | const bool ht_greenfield_support; |
271 | u16 led_compensation; | ||
257 | const bool broken_powersave; | 272 | const bool broken_powersave; |
273 | bool use_rts_for_ht; | ||
274 | int chain_noise_num_beacons; | ||
275 | const bool supports_idle; | ||
258 | }; | 276 | }; |
259 | 277 | ||
260 | /*************************** | 278 | /*************************** |
@@ -273,7 +291,7 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv); | |||
273 | int iwl_full_rxon_required(struct iwl_priv *priv); | 291 | int iwl_full_rxon_required(struct iwl_priv *priv); |
274 | void iwl_set_rxon_chain(struct iwl_priv *priv); | 292 | void iwl_set_rxon_chain(struct iwl_priv *priv); |
275 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); | 293 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); |
276 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); | 294 | void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf); |
277 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, | 295 | u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, |
278 | struct ieee80211_sta_ht_cap *sta_ht_inf); | 296 | struct ieee80211_sta_ht_cap *sta_ht_inf); |
279 | void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band); | 297 | void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band); |
@@ -569,6 +587,7 @@ void iwlcore_free_geos(struct iwl_priv *priv); | |||
569 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ | 587 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ |
570 | #define STATUS_INT_ENABLED 2 | 588 | #define STATUS_INT_ENABLED 2 |
571 | #define STATUS_RF_KILL_HW 3 | 589 | #define STATUS_RF_KILL_HW 3 |
590 | #define STATUS_CT_KILL 4 | ||
572 | #define STATUS_INIT 5 | 591 | #define STATUS_INIT 5 |
573 | #define STATUS_ALIVE 6 | 592 | #define STATUS_ALIVE 6 |
574 | #define STATUS_READY 7 | 593 | #define STATUS_READY 7 |
@@ -613,6 +632,11 @@ static inline int iwl_is_rfkill(struct iwl_priv *priv) | |||
613 | return iwl_is_rfkill_hw(priv); | 632 | return iwl_is_rfkill_hw(priv); |
614 | } | 633 | } |
615 | 634 | ||
635 | static inline int iwl_is_ctkill(struct iwl_priv *priv) | ||
636 | { | ||
637 | return test_bit(STATUS_CT_KILL, &priv->status); | ||
638 | } | ||
639 | |||
616 | static inline int iwl_is_ready_rf(struct iwl_priv *priv) | 640 | static inline int iwl_is_ready_rf(struct iwl_priv *priv) |
617 | { | 641 | { |
618 | 642 | ||
@@ -634,6 +658,8 @@ extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, | |||
634 | struct iwl_rx_mem_buffer *rxb); | 658 | struct iwl_rx_mem_buffer *rxb); |
635 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, | 659 | void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, |
636 | struct iwl_rx_mem_buffer *rxb); | 660 | struct iwl_rx_mem_buffer *rxb); |
661 | void iwl_apm_stop(struct iwl_priv *priv); | ||
662 | int iwl_apm_stop_master(struct iwl_priv *priv); | ||
637 | 663 | ||
638 | void iwl_setup_rxon_timing(struct iwl_priv *priv); | 664 | void iwl_setup_rxon_timing(struct iwl_priv *priv); |
639 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) | 665 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) |
@@ -653,5 +679,4 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode( | |||
653 | { | 679 | { |
654 | return priv->hw->wiphy->bands[band]; | 680 | return priv->hw->wiphy->bands[band]; |
655 | } | 681 | } |
656 | |||
657 | #endif /* __iwl_core_h__ */ | 682 | #endif /* __iwl_core_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 06437d13e73e..8f183e0fa512 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -230,13 +230,18 @@ | |||
230 | 230 | ||
231 | /* EEPROM GP */ | 231 | /* EEPROM GP */ |
232 | #define CSR_EEPROM_GP_VALID_MSK (0x00000007) | 232 | #define CSR_EEPROM_GP_VALID_MSK (0x00000007) |
233 | #define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) | ||
234 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) | 233 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) |
235 | #define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */ | 234 | #define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */ |
236 | #define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ | 235 | #define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ |
237 | #define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ | 236 | #define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ |
238 | #define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ | 237 | #define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ |
239 | 238 | ||
239 | /* EEPROM signature */ | ||
240 | #define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000) | ||
241 | #define CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP (0x00000001) | ||
242 | #define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K (0x00000002) | ||
243 | #define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K (0x00000004) | ||
244 | |||
240 | /* CSR GIO */ | 245 | /* CSR GIO */ |
241 | #define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) | 246 | #define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) |
242 | 247 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index cbc62904655d..b9ca475cc61c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -84,9 +84,7 @@ struct iwl_debugfs { | |||
84 | struct dentry *file_interrupt; | 84 | struct dentry *file_interrupt; |
85 | struct dentry *file_qos; | 85 | struct dentry *file_qos; |
86 | struct dentry *file_thermal_throttling; | 86 | struct dentry *file_thermal_throttling; |
87 | #ifdef CONFIG_IWLWIFI_LEDS | ||
88 | struct dentry *file_led; | 87 | struct dentry *file_led; |
89 | #endif | ||
90 | struct dentry *file_disable_ht40; | 88 | struct dentry *file_disable_ht40; |
91 | struct dentry *file_sleep_level_override; | 89 | struct dentry *file_sleep_level_override; |
92 | struct dentry *file_current_sleep_command; | 90 | struct dentry *file_current_sleep_command; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index a198bcf61022..1794b9c4e6ac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -383,6 +383,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
383 | int pos = 0, ofs = 0, buf_size = 0; | 383 | int pos = 0, ofs = 0, buf_size = 0; |
384 | const u8 *ptr; | 384 | const u8 *ptr; |
385 | char *buf; | 385 | char *buf; |
386 | u16 eeprom_ver; | ||
386 | size_t eeprom_len = priv->cfg->eeprom_size; | 387 | size_t eeprom_len = priv->cfg->eeprom_size; |
387 | buf_size = 4 * eeprom_len + 256; | 388 | buf_size = 4 * eeprom_len + 256; |
388 | 389 | ||
@@ -403,9 +404,11 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file, | |||
403 | IWL_ERR(priv, "Can not allocate Buffer\n"); | 404 | IWL_ERR(priv, "Can not allocate Buffer\n"); |
404 | return -ENOMEM; | 405 | return -ENOMEM; |
405 | } | 406 | } |
406 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n", | 407 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); |
408 | pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s, " | ||
409 | "version: 0x%x\n", | ||
407 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 410 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) |
408 | ? "OTP" : "EEPROM"); | 411 | ? "OTP" : "EEPROM", eeprom_ver); |
409 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { | 412 | for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { |
410 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); | 413 | pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); |
411 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, | 414 | hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, |
@@ -532,6 +535,8 @@ static ssize_t iwl_dbgfs_status_read(struct file *file, | |||
532 | test_bit(STATUS_INT_ENABLED, &priv->status)); | 535 | test_bit(STATUS_INT_ENABLED, &priv->status)); |
533 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", | 536 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", |
534 | test_bit(STATUS_RF_KILL_HW, &priv->status)); | 537 | test_bit(STATUS_RF_KILL_HW, &priv->status)); |
538 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n", | ||
539 | test_bit(STATUS_CT_KILL, &priv->status)); | ||
535 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", | 540 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", |
536 | test_bit(STATUS_INIT, &priv->status)); | 541 | test_bit(STATUS_INIT, &priv->status)); |
537 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", | 542 | pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", |
@@ -672,7 +677,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, | |||
672 | return ret; | 677 | return ret; |
673 | } | 678 | } |
674 | 679 | ||
675 | #ifdef CONFIG_IWLWIFI_LEDS | ||
676 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | 680 | static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, |
677 | size_t count, loff_t *ppos) | 681 | size_t count, loff_t *ppos) |
678 | { | 682 | { |
@@ -697,7 +701,6 @@ static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, | |||
697 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 701 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
698 | return ret; | 702 | return ret; |
699 | } | 703 | } |
700 | #endif | ||
701 | 704 | ||
702 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, | 705 | static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, |
703 | char __user *user_buf, | 706 | char __user *user_buf, |
@@ -861,9 +864,7 @@ DEBUGFS_READ_FILE_OPS(channels); | |||
861 | DEBUGFS_READ_FILE_OPS(status); | 864 | DEBUGFS_READ_FILE_OPS(status); |
862 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); | 865 | DEBUGFS_READ_WRITE_FILE_OPS(interrupt); |
863 | DEBUGFS_READ_FILE_OPS(qos); | 866 | DEBUGFS_READ_FILE_OPS(qos); |
864 | #ifdef CONFIG_IWLWIFI_LEDS | ||
865 | DEBUGFS_READ_FILE_OPS(led); | 867 | DEBUGFS_READ_FILE_OPS(led); |
866 | #endif | ||
867 | DEBUGFS_READ_FILE_OPS(thermal_throttling); | 868 | DEBUGFS_READ_FILE_OPS(thermal_throttling); |
868 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); | 869 | DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); |
869 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); | 870 | DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); |
@@ -1661,9 +1662,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1661 | DEBUGFS_ADD_FILE(status, data); | 1662 | DEBUGFS_ADD_FILE(status, data); |
1662 | DEBUGFS_ADD_FILE(interrupt, data); | 1663 | DEBUGFS_ADD_FILE(interrupt, data); |
1663 | DEBUGFS_ADD_FILE(qos, data); | 1664 | DEBUGFS_ADD_FILE(qos, data); |
1664 | #ifdef CONFIG_IWLWIFI_LEDS | ||
1665 | DEBUGFS_ADD_FILE(led, data); | 1665 | DEBUGFS_ADD_FILE(led, data); |
1666 | #endif | ||
1667 | DEBUGFS_ADD_FILE(sleep_level_override, data); | 1666 | DEBUGFS_ADD_FILE(sleep_level_override, data); |
1668 | DEBUGFS_ADD_FILE(current_sleep_command, data); | 1667 | DEBUGFS_ADD_FILE(current_sleep_command, data); |
1669 | DEBUGFS_ADD_FILE(thermal_throttling, data); | 1668 | DEBUGFS_ADD_FILE(thermal_throttling, data); |
@@ -1716,9 +1715,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
1716 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); | 1715 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); |
1717 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); | 1716 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); |
1718 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos); | 1717 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos); |
1719 | #ifdef CONFIG_IWLWIFI_LEDS | ||
1720 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led); | 1718 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led); |
1721 | #endif | ||
1722 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling); | 1719 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling); |
1723 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40); | 1720 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40); |
1724 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); | 1721 | DEBUGFS_REMOVE(priv->dbgfs->dir_data); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 028d50599550..72946c144be7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -43,7 +43,6 @@ | |||
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-3945-led.h" | ||
47 | #include "iwl-led.h" | 46 | #include "iwl-led.h" |
48 | #include "iwl-power.h" | 47 | #include "iwl-power.h" |
49 | #include "iwl-agn-rs.h" | 48 | #include "iwl-agn-rs.h" |
@@ -57,17 +56,22 @@ extern struct iwl_cfg iwl5100_bg_cfg; | |||
57 | extern struct iwl_cfg iwl5100_abg_cfg; | 56 | extern struct iwl_cfg iwl5100_abg_cfg; |
58 | extern struct iwl_cfg iwl5150_agn_cfg; | 57 | extern struct iwl_cfg iwl5150_agn_cfg; |
59 | extern struct iwl_cfg iwl6000h_2agn_cfg; | 58 | extern struct iwl_cfg iwl6000h_2agn_cfg; |
59 | extern struct iwl_cfg iwl6000h_2abg_cfg; | ||
60 | extern struct iwl_cfg iwl6000h_2bg_cfg; | ||
60 | extern struct iwl_cfg iwl6000i_2agn_cfg; | 61 | extern struct iwl_cfg iwl6000i_2agn_cfg; |
62 | extern struct iwl_cfg iwl6000i_2abg_cfg; | ||
63 | extern struct iwl_cfg iwl6000i_2bg_cfg; | ||
61 | extern struct iwl_cfg iwl6000_3agn_cfg; | 64 | extern struct iwl_cfg iwl6000_3agn_cfg; |
62 | extern struct iwl_cfg iwl6050_2agn_cfg; | 65 | extern struct iwl_cfg iwl6050_2agn_cfg; |
66 | extern struct iwl_cfg iwl6050_2abg_cfg; | ||
63 | extern struct iwl_cfg iwl6050_3agn_cfg; | 67 | extern struct iwl_cfg iwl6050_3agn_cfg; |
64 | extern struct iwl_cfg iwl1000_bgn_cfg; | 68 | extern struct iwl_cfg iwl1000_bgn_cfg; |
69 | extern struct iwl_cfg iwl1000_bg_cfg; | ||
65 | 70 | ||
66 | struct iwl_tx_queue; | 71 | struct iwl_tx_queue; |
67 | 72 | ||
68 | /* shared structures from iwl-5000.c */ | 73 | /* shared structures from iwl-5000.c */ |
69 | extern struct iwl_mod_params iwl50_mod_params; | 74 | extern struct iwl_mod_params iwl50_mod_params; |
70 | extern struct iwl_ops iwl5000_ops; | ||
71 | extern struct iwl_ucode_ops iwl5000_ucode; | 75 | extern struct iwl_ucode_ops iwl5000_ucode; |
72 | extern struct iwl_lib_ops iwl5000_lib; | 76 | extern struct iwl_lib_ops iwl5000_lib; |
73 | extern struct iwl_hcmd_ops iwl5000_hcmd; | 77 | extern struct iwl_hcmd_ops iwl5000_hcmd; |
@@ -82,7 +86,6 @@ extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, | |||
82 | extern int iwl5000_calc_rssi(struct iwl_priv *priv, | 86 | extern int iwl5000_calc_rssi(struct iwl_priv *priv, |
83 | struct iwl_rx_phy_res *rx_resp); | 87 | struct iwl_rx_phy_res *rx_resp); |
84 | extern int iwl5000_apm_init(struct iwl_priv *priv); | 88 | extern int iwl5000_apm_init(struct iwl_priv *priv); |
85 | extern void iwl5000_apm_stop(struct iwl_priv *priv); | ||
86 | extern int iwl5000_apm_reset(struct iwl_priv *priv); | 89 | extern int iwl5000_apm_reset(struct iwl_priv *priv); |
87 | extern void iwl5000_nic_config(struct iwl_priv *priv); | 90 | extern void iwl5000_nic_config(struct iwl_priv *priv); |
88 | extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); | 91 | extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); |
@@ -502,12 +505,11 @@ union iwl_ht_rate_supp { | |||
502 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) | 505 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) |
503 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC | 506 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC |
504 | 507 | ||
505 | struct iwl_ht_info { | 508 | struct iwl_ht_config { |
506 | /* self configuration data */ | 509 | /* self configuration data */ |
507 | u8 is_ht; | 510 | bool is_ht; |
508 | u8 supported_chan_width; | 511 | bool is_40mhz; |
509 | u8 sm_ps; | 512 | bool single_chain_sufficient; |
510 | struct ieee80211_mcs_info mcs; | ||
511 | /* BSS related data */ | 513 | /* BSS related data */ |
512 | u8 extension_chan_offset; | 514 | u8 extension_chan_offset; |
513 | u8 ht_protection; | 515 | u8 ht_protection; |
@@ -726,9 +728,6 @@ struct iwl_dma_ptr { | |||
726 | size_t size; | 728 | size_t size; |
727 | }; | 729 | }; |
728 | 730 | ||
729 | #define IWL_CHANNEL_WIDTH_20MHZ 0 | ||
730 | #define IWL_CHANNEL_WIDTH_40MHZ 1 | ||
731 | |||
732 | #define IWL_OPERATION_MODE_AUTO 0 | 731 | #define IWL_OPERATION_MODE_AUTO 0 |
733 | #define IWL_OPERATION_MODE_HT_ONLY 1 | 732 | #define IWL_OPERATION_MODE_HT_ONLY 1 |
734 | #define IWL_OPERATION_MODE_MIXED 2 | 733 | #define IWL_OPERATION_MODE_MIXED 2 |
@@ -741,7 +740,8 @@ struct iwl_dma_ptr { | |||
741 | 740 | ||
742 | /* Sensitivity and chain noise calibration */ | 741 | /* Sensitivity and chain noise calibration */ |
743 | #define INITIALIZATION_VALUE 0xFFFF | 742 | #define INITIALIZATION_VALUE 0xFFFF |
744 | #define CAL_NUM_OF_BEACONS 20 | 743 | #define IWL4965_CAL_NUM_BEACONS 20 |
744 | #define IWL_CAL_NUM_BEACONS 16 | ||
745 | #define MAXIMUM_ALLOWED_PATHLOSS 15 | 745 | #define MAXIMUM_ALLOWED_PATHLOSS 15 |
746 | 746 | ||
747 | #define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3 | 747 | #define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3 |
@@ -1063,14 +1063,11 @@ struct iwl_priv { | |||
1063 | struct iwl_init_alive_resp card_alive_init; | 1063 | struct iwl_init_alive_resp card_alive_init; |
1064 | struct iwl_alive_resp card_alive; | 1064 | struct iwl_alive_resp card_alive; |
1065 | 1065 | ||
1066 | #ifdef CONFIG_IWLWIFI_LEDS | ||
1067 | unsigned long last_blink_time; | 1066 | unsigned long last_blink_time; |
1068 | u8 last_blink_rate; | 1067 | u8 last_blink_rate; |
1069 | u8 allow_blinking; | 1068 | u8 allow_blinking; |
1070 | u64 led_tpt; | 1069 | u64 led_tpt; |
1071 | struct iwl_led led[IWL_LED_TRG_MAX]; | 1070 | |
1072 | unsigned int rxtxpackets; | ||
1073 | #endif | ||
1074 | u16 active_rate; | 1071 | u16 active_rate; |
1075 | u16 active_rate_basic; | 1072 | u16 active_rate_basic; |
1076 | 1073 | ||
@@ -1080,7 +1077,7 @@ struct iwl_priv { | |||
1080 | struct iwl_chain_noise_data chain_noise_data; | 1077 | struct iwl_chain_noise_data chain_noise_data; |
1081 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; | 1078 | __le16 sensitivity_tbl[HD_TABLE_SIZE]; |
1082 | 1079 | ||
1083 | struct iwl_ht_info current_ht_config; | 1080 | struct iwl_ht_config current_ht_config; |
1084 | u8 last_phy_res[100]; | 1081 | u8 last_phy_res[100]; |
1085 | 1082 | ||
1086 | /* Rate scaling data */ | 1083 | /* Rate scaling data */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c new file mode 100644 index 000000000000..4ef5acaa556d --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
@@ -0,0 +1,13 @@ | |||
1 | #include <linux/module.h> | ||
2 | |||
3 | /* sparse doesn't like tracepoint macros */ | ||
4 | #ifndef __CHECKER__ | ||
5 | #define CREATE_TRACE_POINTS | ||
6 | #include "iwl-devtrace.h" | ||
7 | |||
8 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); | ||
9 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); | ||
10 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); | ||
11 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_event); | ||
12 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ucode_error); | ||
13 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h new file mode 100644 index 000000000000..8c7159208da1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -0,0 +1,178 @@ | |||
1 | #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | #define __IWLWIFI_DEVICE_TRACE | ||
3 | |||
4 | #include <linux/tracepoint.h> | ||
5 | #include "iwl-dev.h" | ||
6 | |||
7 | #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__) | ||
8 | #undef TRACE_EVENT | ||
9 | #define TRACE_EVENT(name, proto, ...) \ | ||
10 | static inline void trace_ ## name(proto) {} | ||
11 | #endif | ||
12 | |||
13 | #define PRIV_ENTRY __field(struct iwl_priv *, priv) | ||
14 | #define PRIV_ASSIGN __entry->priv = priv | ||
15 | |||
16 | #undef TRACE_SYSTEM | ||
17 | #define TRACE_SYSTEM iwlwifi | ||
18 | |||
19 | TRACE_EVENT(iwlwifi_dev_ioread32, | ||
20 | TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val), | ||
21 | TP_ARGS(priv, offs, val), | ||
22 | TP_STRUCT__entry( | ||
23 | PRIV_ENTRY | ||
24 | __field(u32, offs) | ||
25 | __field(u32, val) | ||
26 | ), | ||
27 | TP_fast_assign( | ||
28 | PRIV_ASSIGN; | ||
29 | __entry->offs = offs; | ||
30 | __entry->val = val; | ||
31 | ), | ||
32 | TP_printk("[%p] read io[%#x] = %#x", __entry->priv, __entry->offs, __entry->val) | ||
33 | ); | ||
34 | |||
35 | TRACE_EVENT(iwlwifi_dev_iowrite32, | ||
36 | TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val), | ||
37 | TP_ARGS(priv, offs, val), | ||
38 | TP_STRUCT__entry( | ||
39 | PRIV_ENTRY | ||
40 | __field(u32, offs) | ||
41 | __field(u32, val) | ||
42 | ), | ||
43 | TP_fast_assign( | ||
44 | PRIV_ASSIGN; | ||
45 | __entry->offs = offs; | ||
46 | __entry->val = val; | ||
47 | ), | ||
48 | TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) | ||
49 | ); | ||
50 | |||
51 | TRACE_EVENT(iwlwifi_dev_hcmd, | ||
52 | TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags), | ||
53 | TP_ARGS(priv, hcmd, len, flags), | ||
54 | TP_STRUCT__entry( | ||
55 | PRIV_ENTRY | ||
56 | __dynamic_array(u8, hcmd, len) | ||
57 | __field(u32, flags) | ||
58 | ), | ||
59 | TP_fast_assign( | ||
60 | PRIV_ASSIGN; | ||
61 | memcpy(__get_dynamic_array(hcmd), hcmd, len); | ||
62 | __entry->flags = flags; | ||
63 | ), | ||
64 | TP_printk("[%p] hcmd %#.2x (%ssync)", | ||
65 | __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0], | ||
66 | __entry->flags & CMD_ASYNC ? "a" : "") | ||
67 | ); | ||
68 | |||
69 | TRACE_EVENT(iwlwifi_dev_rx, | ||
70 | TP_PROTO(struct iwl_priv *priv, void *rxbuf, size_t len), | ||
71 | TP_ARGS(priv, rxbuf, len), | ||
72 | TP_STRUCT__entry( | ||
73 | PRIV_ENTRY | ||
74 | __dynamic_array(u8, rxbuf, len) | ||
75 | ), | ||
76 | TP_fast_assign( | ||
77 | PRIV_ASSIGN; | ||
78 | memcpy(__get_dynamic_array(rxbuf), rxbuf, len); | ||
79 | ), | ||
80 | TP_printk("[%p] RX cmd %#.2x", | ||
81 | __entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4]) | ||
82 | ); | ||
83 | |||
84 | TRACE_EVENT(iwlwifi_dev_tx, | ||
85 | TP_PROTO(struct iwl_priv *priv, void *tfd, size_t tfdlen, | ||
86 | void *buf0, size_t buf0_len, | ||
87 | void *buf1, size_t buf1_len), | ||
88 | TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len), | ||
89 | TP_STRUCT__entry( | ||
90 | PRIV_ENTRY | ||
91 | |||
92 | __field(size_t, framelen) | ||
93 | __dynamic_array(u8, tfd, tfdlen) | ||
94 | |||
95 | /* | ||
96 | * Do not insert between or below these items, | ||
97 | * we want to keep the frame together (except | ||
98 | * for the possible padding). | ||
99 | */ | ||
100 | __dynamic_array(u8, buf0, buf0_len) | ||
101 | __dynamic_array(u8, buf1, buf1_len) | ||
102 | ), | ||
103 | TP_fast_assign( | ||
104 | PRIV_ASSIGN; | ||
105 | __entry->framelen = buf0_len + buf1_len; | ||
106 | memcpy(__get_dynamic_array(tfd), tfd, tfdlen); | ||
107 | memcpy(__get_dynamic_array(buf0), buf0, buf0_len); | ||
108 | memcpy(__get_dynamic_array(buf1), buf1, buf0_len); | ||
109 | ), | ||
110 | TP_printk("[%p] TX %.2x (%zu bytes)", | ||
111 | __entry->priv, | ||
112 | ((u8 *)__get_dynamic_array(buf0))[0], | ||
113 | __entry->framelen) | ||
114 | ); | ||
115 | |||
116 | TRACE_EVENT(iwlwifi_dev_ucode_error, | ||
117 | TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time, | ||
118 | u32 data1, u32 data2, u32 line, u32 blink1, | ||
119 | u32 blink2, u32 ilink1, u32 ilink2), | ||
120 | TP_ARGS(priv, desc, time, data1, data2, line, | ||
121 | blink1, blink2, ilink1, ilink2), | ||
122 | TP_STRUCT__entry( | ||
123 | PRIV_ENTRY | ||
124 | __field(u32, desc) | ||
125 | __field(u32, time) | ||
126 | __field(u32, data1) | ||
127 | __field(u32, data2) | ||
128 | __field(u32, line) | ||
129 | __field(u32, blink1) | ||
130 | __field(u32, blink2) | ||
131 | __field(u32, ilink1) | ||
132 | __field(u32, ilink2) | ||
133 | ), | ||
134 | TP_fast_assign( | ||
135 | PRIV_ASSIGN; | ||
136 | __entry->desc = desc; | ||
137 | __entry->time = time; | ||
138 | __entry->data1 = data1; | ||
139 | __entry->data2 = data2; | ||
140 | __entry->line = line; | ||
141 | __entry->blink1 = blink1; | ||
142 | __entry->blink2 = blink2; | ||
143 | __entry->ilink1 = ilink1; | ||
144 | __entry->ilink2 = ilink2; | ||
145 | ), | ||
146 | TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, " | ||
147 | "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X", | ||
148 | __entry->priv, __entry->desc, __entry->time, __entry->data1, | ||
149 | __entry->data2, __entry->line, __entry->blink1, | ||
150 | __entry->blink2, __entry->ilink1, __entry->ilink2) | ||
151 | ); | ||
152 | |||
153 | TRACE_EVENT(iwlwifi_dev_ucode_event, | ||
154 | TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev), | ||
155 | TP_ARGS(priv, time, data, ev), | ||
156 | TP_STRUCT__entry( | ||
157 | PRIV_ENTRY | ||
158 | |||
159 | __field(u32, time) | ||
160 | __field(u32, data) | ||
161 | __field(u32, ev) | ||
162 | ), | ||
163 | TP_fast_assign( | ||
164 | PRIV_ASSIGN; | ||
165 | __entry->time = time; | ||
166 | __entry->data = data; | ||
167 | __entry->ev = ev; | ||
168 | ), | ||
169 | TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", | ||
170 | __entry->priv, __entry->time, __entry->data, __entry->ev) | ||
171 | ); | ||
172 | #endif /* __IWLWIFI_DEVICE_TRACE */ | ||
173 | |||
174 | #undef TRACE_INCLUDE_PATH | ||
175 | #define TRACE_INCLUDE_PATH . | ||
176 | #undef TRACE_INCLUDE_FILE | ||
177 | #define TRACE_INCLUDE_FILE iwl-devtrace | ||
178 | #include <trace/define_trace.h> | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 3d2b93a61e62..e3dbd79cd13e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -215,12 +215,35 @@ static const struct iwl_txpwr_section enhinfo[] = { | |||
215 | 215 | ||
216 | int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) | 216 | int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) |
217 | { | 217 | { |
218 | u32 gp = iwl_read32(priv, CSR_EEPROM_GP); | 218 | u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; |
219 | if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { | 219 | int ret = 0; |
220 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | 220 | |
221 | return -ENOENT; | 221 | IWL_DEBUG_INFO(priv, "EEPROM signature=0x%08x\n", gp); |
222 | switch (gp) { | ||
223 | case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP: | ||
224 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) { | ||
225 | IWL_ERR(priv, "EEPROM with bad signature: 0x%08x\n", | ||
226 | gp); | ||
227 | ret = -ENOENT; | ||
228 | } | ||
229 | break; | ||
230 | case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K: | ||
231 | case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K: | ||
232 | if (priv->nvm_device_type != NVM_DEVICE_TYPE_EEPROM) { | ||
233 | IWL_ERR(priv, "OTP with bad signature: 0x%08x\n", gp); | ||
234 | ret = -ENOENT; | ||
235 | } | ||
236 | break; | ||
237 | case CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP: | ||
238 | default: | ||
239 | IWL_ERR(priv, "bad EEPROM/OTP signature, type=%s, " | ||
240 | "EEPROM_GP=0x%08x\n", | ||
241 | (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | ||
242 | ? "OTP" : "EEPROM", gp); | ||
243 | ret = -ENOENT; | ||
244 | break; | ||
222 | } | 245 | } |
223 | return 0; | 246 | return ret; |
224 | } | 247 | } |
225 | EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); | 248 | EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); |
226 | 249 | ||
@@ -283,7 +306,8 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) | |||
283 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); | 306 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); |
284 | 307 | ||
285 | /* See if we got it */ | 308 | /* See if we got it */ |
286 | ret = iwl_poll_direct_bit(priv, CSR_HW_IF_CONFIG_REG, | 309 | ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, |
310 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | ||
287 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, | 311 | CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, |
288 | EEPROM_SEM_TIMEOUT); | 312 | EEPROM_SEM_TIMEOUT); |
289 | if (ret >= 0) { | 313 | if (ret >= 0) { |
@@ -322,7 +346,8 @@ static int iwl_init_otp_access(struct iwl_priv *priv) | |||
322 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | 346 | CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
323 | 347 | ||
324 | /* wait for clock to be ready */ | 348 | /* wait for clock to be ready */ |
325 | ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, | 349 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, |
350 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
326 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | 351 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, |
327 | 25000); | 352 | 25000); |
328 | if (ret < 0) | 353 | if (ret < 0) |
@@ -345,7 +370,8 @@ static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) | |||
345 | 370 | ||
346 | _iwl_write32(priv, CSR_EEPROM_REG, | 371 | _iwl_write32(priv, CSR_EEPROM_REG, |
347 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | 372 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); |
348 | ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, | 373 | ret = iwl_poll_bit(priv, CSR_EEPROM_REG, |
374 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
349 | CSR_EEPROM_REG_READ_VALID_MSK, | 375 | CSR_EEPROM_REG_READ_VALID_MSK, |
350 | IWL_EEPROM_ACCESS_TIMEOUT); | 376 | IWL_EEPROM_ACCESS_TIMEOUT); |
351 | if (ret < 0) { | 377 | if (ret < 0) { |
@@ -538,7 +564,8 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
538 | _iwl_write32(priv, CSR_EEPROM_REG, | 564 | _iwl_write32(priv, CSR_EEPROM_REG, |
539 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | 565 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); |
540 | 566 | ||
541 | ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, | 567 | ret = iwl_poll_bit(priv, CSR_EEPROM_REG, |
568 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
542 | CSR_EEPROM_REG_READ_VALID_MSK, | 569 | CSR_EEPROM_REG_READ_VALID_MSK, |
543 | IWL_EEPROM_ACCESS_TIMEOUT); | 570 | IWL_EEPROM_ACCESS_TIMEOUT); |
544 | if (ret < 0) { | 571 | if (ret < 0) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 6b68db7b1b81..fee6f0c7503e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -63,6 +63,8 @@ | |||
63 | #ifndef __iwl_eeprom_h__ | 63 | #ifndef __iwl_eeprom_h__ |
64 | #define __iwl_eeprom_h__ | 64 | #define __iwl_eeprom_h__ |
65 | 65 | ||
66 | #include <net/mac80211.h> | ||
67 | |||
66 | struct iwl_priv; | 68 | struct iwl_priv; |
67 | 69 | ||
68 | /* | 70 | /* |
@@ -256,6 +258,12 @@ struct iwl_eeprom_enhanced_txpwr { | |||
256 | #define EEPROM_5050_TX_POWER_VERSION (4) | 258 | #define EEPROM_5050_TX_POWER_VERSION (4) |
257 | #define EEPROM_5050_EEPROM_VERSION (0x21E) | 259 | #define EEPROM_5050_EEPROM_VERSION (0x21E) |
258 | 260 | ||
261 | /* 1000 Specific */ | ||
262 | #define EEPROM_1000_EEPROM_VERSION (0x15C) | ||
263 | |||
264 | /* 60x0 Specific */ | ||
265 | #define EEPROM_6000_EEPROM_VERSION (0x434) | ||
266 | |||
259 | /* OTP */ | 267 | /* OTP */ |
260 | /* lower blocks contain EEPROM image and calibration data */ | 268 | /* lower blocks contain EEPROM image and calibration data */ |
261 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ | 269 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ |
@@ -370,12 +378,10 @@ struct iwl_eeprom_calib_info { | |||
370 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ | 378 | #define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ |
371 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ | 379 | #define EEPROM_VERSION (2*0x44) /* 2 bytes */ |
372 | #define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ | 380 | #define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ |
373 | #define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */ | ||
374 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ | 381 | #define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ |
375 | #define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ | 382 | #define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ |
376 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ | 383 | #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ |
377 | #define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */ | 384 | #define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */ |
378 | #define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */ | ||
379 | 385 | ||
380 | /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ | 386 | /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ |
381 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ | 387 | #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ |
@@ -387,7 +393,12 @@ struct iwl_eeprom_calib_info { | |||
387 | 393 | ||
388 | #define EEPROM_3945_RF_CFG_TYPE_MAX 0x0 | 394 | #define EEPROM_3945_RF_CFG_TYPE_MAX 0x0 |
389 | #define EEPROM_4965_RF_CFG_TYPE_MAX 0x1 | 395 | #define EEPROM_4965_RF_CFG_TYPE_MAX 0x1 |
390 | #define EEPROM_5000_RF_CFG_TYPE_MAX 0x3 | 396 | |
397 | /* Radio Config for 5000 and up */ | ||
398 | #define EEPROM_RF_CONFIG_TYPE_R3x3 0x0 | ||
399 | #define EEPROM_RF_CONFIG_TYPE_R2x2 0x1 | ||
400 | #define EEPROM_RF_CONFIG_TYPE_R1x2 0x2 | ||
401 | #define EEPROM_RF_CONFIG_TYPE_MAX 0x3 | ||
391 | 402 | ||
392 | /* | 403 | /* |
393 | * Per-channel regulatory data. | 404 | * Per-channel regulatory data. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index d30cb0275d19..0a078b082833 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
33 | 33 | ||
34 | #include "iwl-debug.h" | 34 | #include "iwl-debug.h" |
35 | #include "iwl-devtrace.h" | ||
35 | 36 | ||
36 | /* | 37 | /* |
37 | * IO, register, and NIC memory access functions | 38 | * IO, register, and NIC memory access functions |
@@ -61,7 +62,12 @@ | |||
61 | * | 62 | * |
62 | */ | 63 | */ |
63 | 64 | ||
64 | #define _iwl_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs)) | 65 | static inline void _iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) |
66 | { | ||
67 | trace_iwlwifi_dev_iowrite32(priv, ofs, val); | ||
68 | iowrite32(val, priv->hw_base + ofs); | ||
69 | } | ||
70 | |||
65 | #ifdef CONFIG_IWLWIFI_DEBUG | 71 | #ifdef CONFIG_IWLWIFI_DEBUG |
66 | static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, | 72 | static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, |
67 | u32 ofs, u32 val) | 73 | u32 ofs, u32 val) |
@@ -75,7 +81,13 @@ static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, | |||
75 | #define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) | 81 | #define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) |
76 | #endif | 82 | #endif |
77 | 83 | ||
78 | #define _iwl_read32(priv, ofs) ioread32((priv)->hw_base + (ofs)) | 84 | static inline u32 _iwl_read32(struct iwl_priv *priv, u32 ofs) |
85 | { | ||
86 | u32 val = ioread32(priv->hw_base + ofs); | ||
87 | trace_iwlwifi_dev_ioread32(priv, ofs, val); | ||
88 | return val; | ||
89 | } | ||
90 | |||
79 | #ifdef CONFIG_IWLWIFI_DEBUG | 91 | #ifdef CONFIG_IWLWIFI_DEBUG |
80 | static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) | 92 | static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) |
81 | { | 93 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index f420c99e7240..478c90511ebf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -42,15 +42,11 @@ | |||
42 | #include "iwl-core.h" | 42 | #include "iwl-core.h" |
43 | #include "iwl-io.h" | 43 | #include "iwl-io.h" |
44 | 44 | ||
45 | #ifdef CONFIG_IWLWIFI_DEBUG | 45 | /* default: IWL_LED_BLINK(0) using blinking index table */ |
46 | static const char *led_type_str[] = { | 46 | static int led_mode; |
47 | __stringify(IWL_LED_TRG_TX), | 47 | module_param(led_mode, int, S_IRUGO); |
48 | __stringify(IWL_LED_TRG_RX), | 48 | MODULE_PARM_DESC(led_mode, "led mode: 0=blinking, 1=On(RF On)/Off(RF Off), " |
49 | __stringify(IWL_LED_TRG_ASSOC), | 49 | "(default 0)\n"); |
50 | __stringify(IWL_LED_TRG_RADIO), | ||
51 | NULL | ||
52 | }; | ||
53 | #endif /* CONFIG_IWLWIFI_DEBUG */ | ||
54 | 50 | ||
55 | 51 | ||
56 | static const struct { | 52 | static const struct { |
@@ -65,11 +61,11 @@ static const struct { | |||
65 | {70, 65, 65}, | 61 | {70, 65, 65}, |
66 | {50, 75, 75}, | 62 | {50, 75, 75}, |
67 | {20, 85, 85}, | 63 | {20, 85, 85}, |
68 | {15, 95, 95 }, | 64 | {10, 95, 95}, |
69 | {10, 110, 110}, | 65 | {5, 110, 110}, |
70 | {5, 130, 130}, | 66 | {1, 130, 130}, |
71 | {0, 167, 167}, | 67 | {0, 167, 167}, |
72 | /* SOLID_ON */ | 68 | /* SOLID_ON */ |
73 | {-1, IWL_LED_SOLID, 0} | 69 | {-1, IWL_LED_SOLID, 0} |
74 | }; | 70 | }; |
75 | 71 | ||
@@ -78,191 +74,74 @@ static const struct { | |||
78 | #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */ | 74 | #define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */ |
79 | #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) | 75 | #define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) |
80 | 76 | ||
81 | /* [0-256] -> [0..8] FIXME: we need [0..10] */ | 77 | /* |
82 | static inline int iwl_brightness_to_idx(enum led_brightness brightness) | 78 | * Adjust led blink rate to compensate on a MAC Clock difference on every HW |
83 | { | 79 | * Led blink rate analysis showed an average deviation of 0% on 3945, |
84 | return fls(0x000000FF & (u32)brightness); | 80 | * 5% on 4965 HW and 20% on 5000 series and up. |
85 | } | 81 | * Need to compensate on the led on/off time per HW according to the deviation |
86 | 82 | * to achieve the desired led frequency | |
87 | /* Send led command */ | 83 | * The calculation is: (100-averageDeviation)/100 * blinkTime |
88 | static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) | 84 | * For code efficiency the calculation will be: |
85 | * compensation = (100 - averageDeviation) * 64 / 100 | ||
86 | * NewBlinkTime = (compensation * BlinkTime) / 64 | ||
87 | */ | ||
88 | static inline u8 iwl_blink_compensation(struct iwl_priv *priv, | ||
89 | u8 time, u16 compensation) | ||
89 | { | 90 | { |
90 | struct iwl_host_cmd cmd = { | 91 | if (!compensation) { |
91 | .id = REPLY_LEDS_CMD, | 92 | IWL_ERR(priv, "undefined blink compensation: " |
92 | .len = sizeof(struct iwl_led_cmd), | 93 | "use pre-defined blinking time\n"); |
93 | .data = led_cmd, | 94 | return time; |
94 | .flags = CMD_ASYNC, | 95 | } |
95 | .callback = NULL, | ||
96 | }; | ||
97 | u32 reg; | ||
98 | |||
99 | reg = iwl_read32(priv, CSR_LED_REG); | ||
100 | if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) | ||
101 | iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); | ||
102 | 96 | ||
103 | return iwl_send_cmd(priv, &cmd); | 97 | return (u8)((time * compensation) >> 6); |
104 | } | 98 | } |
105 | 99 | ||
106 | /* Set led pattern command */ | 100 | /* Set led pattern command */ |
107 | static int iwl_led_pattern(struct iwl_priv *priv, int led_id, | 101 | static int iwl_led_pattern(struct iwl_priv *priv, unsigned int idx) |
108 | unsigned int idx) | ||
109 | { | 102 | { |
110 | struct iwl_led_cmd led_cmd = { | 103 | struct iwl_led_cmd led_cmd = { |
111 | .id = led_id, | 104 | .id = IWL_LED_LINK, |
112 | .interval = IWL_DEF_LED_INTRVL | 105 | .interval = IWL_DEF_LED_INTRVL |
113 | }; | 106 | }; |
114 | 107 | ||
115 | BUG_ON(idx > IWL_MAX_BLINK_TBL); | 108 | BUG_ON(idx > IWL_MAX_BLINK_TBL); |
116 | 109 | ||
117 | led_cmd.on = blink_tbl[idx].on_time; | 110 | IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n", |
118 | led_cmd.off = blink_tbl[idx].off_time; | 111 | priv->cfg->led_compensation); |
119 | 112 | led_cmd.on = | |
120 | return iwl_send_led_cmd(priv, &led_cmd); | 113 | iwl_blink_compensation(priv, blink_tbl[idx].on_time, |
121 | } | 114 | priv->cfg->led_compensation); |
122 | 115 | led_cmd.off = | |
123 | /* Set led register off */ | 116 | iwl_blink_compensation(priv, blink_tbl[idx].off_time, |
124 | static int iwl_led_on_reg(struct iwl_priv *priv, int led_id) | 117 | priv->cfg->led_compensation); |
125 | { | ||
126 | IWL_DEBUG_LED(priv, "led on %d\n", led_id); | ||
127 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); | ||
128 | return 0; | ||
129 | } | ||
130 | 118 | ||
131 | #if 0 | 119 | return priv->cfg->ops->led->cmd(priv, &led_cmd); |
132 | /* Set led on command */ | ||
133 | static int iwl_led_on(struct iwl_priv *priv, int led_id) | ||
134 | { | ||
135 | struct iwl_led_cmd led_cmd = { | ||
136 | .id = led_id, | ||
137 | .on = IWL_LED_SOLID, | ||
138 | .off = 0, | ||
139 | .interval = IWL_DEF_LED_INTRVL | ||
140 | }; | ||
141 | return iwl_send_led_cmd(priv, &led_cmd); | ||
142 | } | 120 | } |
143 | 121 | ||
144 | /* Set led off command */ | 122 | int iwl_led_start(struct iwl_priv *priv) |
145 | int iwl_led_off(struct iwl_priv *priv, int led_id) | ||
146 | { | 123 | { |
147 | struct iwl_led_cmd led_cmd = { | 124 | return priv->cfg->ops->led->on(priv); |
148 | .id = led_id, | ||
149 | .on = 0, | ||
150 | .off = 0, | ||
151 | .interval = IWL_DEF_LED_INTRVL | ||
152 | }; | ||
153 | IWL_DEBUG_LED(priv, "led off %d\n", led_id); | ||
154 | return iwl_send_led_cmd(priv, &led_cmd); | ||
155 | } | 125 | } |
156 | #endif | 126 | EXPORT_SYMBOL(iwl_led_start); |
157 | |||
158 | 127 | ||
159 | /* Set led register off */ | 128 | int iwl_led_associate(struct iwl_priv *priv) |
160 | static int iwl_led_off_reg(struct iwl_priv *priv, int led_id) | ||
161 | { | ||
162 | IWL_DEBUG_LED(priv, "LED Reg off\n"); | ||
163 | iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * Set led register in case of disassociation according to rfkill state | ||
169 | */ | ||
170 | static int iwl_led_associate(struct iwl_priv *priv, int led_id) | ||
171 | { | 129 | { |
172 | IWL_DEBUG_LED(priv, "Associated\n"); | 130 | IWL_DEBUG_LED(priv, "Associated\n"); |
173 | priv->allow_blinking = 1; | 131 | if (led_mode == IWL_LED_BLINK) |
174 | return iwl_led_on_reg(priv, led_id); | 132 | priv->allow_blinking = 1; |
175 | } | 133 | priv->last_blink_time = jiffies; |
176 | static int iwl_led_disassociate(struct iwl_priv *priv, int led_id) | ||
177 | { | ||
178 | priv->allow_blinking = 0; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * brightness call back function for Tx/Rx LED | ||
185 | */ | ||
186 | static int iwl_led_associated(struct iwl_priv *priv, int led_id) | ||
187 | { | ||
188 | if (test_bit(STATUS_EXIT_PENDING, &priv->status) || | ||
189 | !test_bit(STATUS_READY, &priv->status)) | ||
190 | return 0; | ||
191 | |||
192 | 134 | ||
193 | /* start counting Tx/Rx bytes */ | ||
194 | if (!priv->last_blink_time && priv->allow_blinking) | ||
195 | priv->last_blink_time = jiffies; | ||
196 | return 0; | 135 | return 0; |
197 | } | 136 | } |
198 | 137 | ||
199 | /* | 138 | int iwl_led_disassociate(struct iwl_priv *priv) |
200 | * brightness call back for association and radio | ||
201 | */ | ||
202 | static void iwl_led_brightness_set(struct led_classdev *led_cdev, | ||
203 | enum led_brightness brightness) | ||
204 | { | 139 | { |
205 | struct iwl_led *led = container_of(led_cdev, struct iwl_led, led_dev); | 140 | priv->allow_blinking = 0; |
206 | struct iwl_priv *priv = led->priv; | ||
207 | |||
208 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
209 | return; | ||
210 | |||
211 | |||
212 | IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n", | ||
213 | led_type_str[led->type], brightness); | ||
214 | switch (brightness) { | ||
215 | case LED_FULL: | ||
216 | if (led->led_on) | ||
217 | led->led_on(priv, IWL_LED_LINK); | ||
218 | break; | ||
219 | case LED_OFF: | ||
220 | if (led->led_off) | ||
221 | led->led_off(priv, IWL_LED_LINK); | ||
222 | break; | ||
223 | default: | ||
224 | if (led->led_pattern) { | ||
225 | int idx = iwl_brightness_to_idx(brightness); | ||
226 | led->led_pattern(priv, IWL_LED_LINK, idx); | ||
227 | } | ||
228 | break; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | |||
233 | |||
234 | /* | ||
235 | * Register led class with the system | ||
236 | */ | ||
237 | static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, | ||
238 | enum led_type type, u8 set_led, | ||
239 | char *trigger) | ||
240 | { | ||
241 | struct device *device = wiphy_dev(priv->hw->wiphy); | ||
242 | int ret; | ||
243 | |||
244 | led->led_dev.name = led->name; | ||
245 | led->led_dev.brightness_set = iwl_led_brightness_set; | ||
246 | led->led_dev.default_trigger = trigger; | ||
247 | |||
248 | led->priv = priv; | ||
249 | led->type = type; | ||
250 | |||
251 | ret = led_classdev_register(device, &led->led_dev); | ||
252 | if (ret) { | ||
253 | IWL_ERR(priv, "Error: failed to register led handler.\n"); | ||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | led->registered = 1; | ||
258 | |||
259 | if (set_led && led->led_on) | ||
260 | led->led_on(priv, IWL_LED_LINK); | ||
261 | 141 | ||
262 | return 0; | 142 | return 0; |
263 | } | 143 | } |
264 | 144 | ||
265 | |||
266 | /* | 145 | /* |
267 | * calculate blink rate according to last second Tx/Rx activities | 146 | * calculate blink rate according to last second Tx/Rx activities |
268 | */ | 147 | */ |
@@ -288,7 +167,7 @@ static int iwl_get_blink_rate(struct iwl_priv *priv) | |||
288 | i = IWL_MAX_BLINK_TBL; | 167 | i = IWL_MAX_BLINK_TBL; |
289 | else | 168 | else |
290 | for (i = 0; i < IWL_MAX_BLINK_TBL; i++) | 169 | for (i = 0; i < IWL_MAX_BLINK_TBL; i++) |
291 | if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) | 170 | if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) |
292 | break; | 171 | break; |
293 | 172 | ||
294 | IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i); | 173 | IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i); |
@@ -317,8 +196,7 @@ void iwl_leds_background(struct iwl_priv *priv) | |||
317 | priv->last_blink_time = 0; | 196 | priv->last_blink_time = 0; |
318 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { | 197 | if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { |
319 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; | 198 | priv->last_blink_rate = IWL_SOLID_BLINK_IDX; |
320 | iwl_led_pattern(priv, IWL_LED_LINK, | 199 | iwl_led_pattern(priv, IWL_SOLID_BLINK_IDX); |
321 | IWL_SOLID_BLINK_IDX); | ||
322 | } | 200 | } |
323 | return; | 201 | return; |
324 | } | 202 | } |
@@ -331,111 +209,18 @@ void iwl_leds_background(struct iwl_priv *priv) | |||
331 | 209 | ||
332 | /* call only if blink rate change */ | 210 | /* call only if blink rate change */ |
333 | if (blink_idx != priv->last_blink_rate) | 211 | if (blink_idx != priv->last_blink_rate) |
334 | iwl_led_pattern(priv, IWL_LED_LINK, blink_idx); | 212 | iwl_led_pattern(priv, blink_idx); |
335 | 213 | ||
336 | priv->last_blink_time = jiffies; | 214 | priv->last_blink_time = jiffies; |
337 | priv->last_blink_rate = blink_idx; | 215 | priv->last_blink_rate = blink_idx; |
338 | } | 216 | } |
217 | EXPORT_SYMBOL(iwl_leds_background); | ||
339 | 218 | ||
340 | /* Register all led handler */ | 219 | void iwl_leds_init(struct iwl_priv *priv) |
341 | int iwl_leds_register(struct iwl_priv *priv) | ||
342 | { | 220 | { |
343 | char *trigger; | ||
344 | int ret; | ||
345 | |||
346 | priv->last_blink_rate = 0; | 221 | priv->last_blink_rate = 0; |
347 | priv->led_tpt = 0; | 222 | priv->led_tpt = 0; |
348 | priv->last_blink_time = 0; | 223 | priv->last_blink_time = 0; |
349 | priv->allow_blinking = 0; | 224 | priv->allow_blinking = 0; |
350 | |||
351 | trigger = ieee80211_get_radio_led_name(priv->hw); | ||
352 | snprintf(priv->led[IWL_LED_TRG_RADIO].name, | ||
353 | sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", | ||
354 | wiphy_name(priv->hw->wiphy)); | ||
355 | |||
356 | priv->led[IWL_LED_TRG_RADIO].led_on = iwl_led_on_reg; | ||
357 | priv->led[IWL_LED_TRG_RADIO].led_off = iwl_led_off_reg; | ||
358 | priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; | ||
359 | |||
360 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], | ||
361 | IWL_LED_TRG_RADIO, 1, trigger); | ||
362 | if (ret) | ||
363 | goto exit_fail; | ||
364 | |||
365 | trigger = ieee80211_get_assoc_led_name(priv->hw); | ||
366 | snprintf(priv->led[IWL_LED_TRG_ASSOC].name, | ||
367 | sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", | ||
368 | wiphy_name(priv->hw->wiphy)); | ||
369 | |||
370 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], | ||
371 | IWL_LED_TRG_ASSOC, 0, trigger); | ||
372 | |||
373 | /* for assoc always turn led on */ | ||
374 | priv->led[IWL_LED_TRG_ASSOC].led_on = iwl_led_associate; | ||
375 | priv->led[IWL_LED_TRG_ASSOC].led_off = iwl_led_disassociate; | ||
376 | priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; | ||
377 | |||
378 | if (ret) | ||
379 | goto exit_fail; | ||
380 | |||
381 | trigger = ieee80211_get_rx_led_name(priv->hw); | ||
382 | snprintf(priv->led[IWL_LED_TRG_RX].name, | ||
383 | sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX", | ||
384 | wiphy_name(priv->hw->wiphy)); | ||
385 | |||
386 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], | ||
387 | IWL_LED_TRG_RX, 0, trigger); | ||
388 | |||
389 | priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; | ||
390 | priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; | ||
391 | priv->led[IWL_LED_TRG_RX].led_pattern = iwl_led_pattern; | ||
392 | |||
393 | if (ret) | ||
394 | goto exit_fail; | ||
395 | |||
396 | trigger = ieee80211_get_tx_led_name(priv->hw); | ||
397 | snprintf(priv->led[IWL_LED_TRG_TX].name, | ||
398 | sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX", | ||
399 | wiphy_name(priv->hw->wiphy)); | ||
400 | |||
401 | ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], | ||
402 | IWL_LED_TRG_TX, 0, trigger); | ||
403 | |||
404 | priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; | ||
405 | priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; | ||
406 | priv->led[IWL_LED_TRG_TX].led_pattern = iwl_led_pattern; | ||
407 | |||
408 | if (ret) | ||
409 | goto exit_fail; | ||
410 | |||
411 | return 0; | ||
412 | |||
413 | exit_fail: | ||
414 | iwl_leds_unregister(priv); | ||
415 | return ret; | ||
416 | } | 225 | } |
417 | EXPORT_SYMBOL(iwl_leds_register); | 226 | EXPORT_SYMBOL(iwl_leds_init); |
418 | |||
419 | /* unregister led class */ | ||
420 | static void iwl_leds_unregister_led(struct iwl_led *led, u8 set_led) | ||
421 | { | ||
422 | if (!led->registered) | ||
423 | return; | ||
424 | |||
425 | led_classdev_unregister(&led->led_dev); | ||
426 | |||
427 | if (set_led) | ||
428 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | ||
429 | led->registered = 0; | ||
430 | } | ||
431 | |||
432 | /* Unregister all led handlers */ | ||
433 | void iwl_leds_unregister(struct iwl_priv *priv) | ||
434 | { | ||
435 | iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); | ||
436 | iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); | ||
437 | iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); | ||
438 | iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); | ||
439 | } | ||
440 | EXPORT_SYMBOL(iwl_leds_unregister); | ||
441 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index ef9b174c37ff..f47f053f02ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h | |||
@@ -30,9 +30,6 @@ | |||
30 | 30 | ||
31 | struct iwl_priv; | 31 | struct iwl_priv; |
32 | 32 | ||
33 | #ifdef CONFIG_IWLWIFI_LEDS | ||
34 | #include <linux/leds.h> | ||
35 | |||
36 | #define IWL_LED_SOLID 11 | 33 | #define IWL_LED_SOLID 11 |
37 | #define IWL_LED_NAME_LEN 31 | 34 | #define IWL_LED_NAME_LEN 31 |
38 | #define IWL_DEF_LED_INTRVL cpu_to_le32(1000) | 35 | #define IWL_DEF_LED_INTRVL cpu_to_le32(1000) |
@@ -47,38 +44,23 @@ enum led_type { | |||
47 | IWL_LED_TRG_RADIO, | 44 | IWL_LED_TRG_RADIO, |
48 | IWL_LED_TRG_MAX, | 45 | IWL_LED_TRG_MAX, |
49 | }; | 46 | }; |
50 | #endif | ||
51 | |||
52 | #ifdef CONFIG_IWLWIFI_LEDS | ||
53 | |||
54 | struct iwl_led { | ||
55 | struct iwl_priv *priv; | ||
56 | struct led_classdev led_dev; | ||
57 | char name[32]; | ||
58 | 47 | ||
59 | int (*led_on) (struct iwl_priv *priv, int led_id); | 48 | /* |
60 | int (*led_off) (struct iwl_priv *priv, int led_id); | 49 | * LED mode |
61 | int (*led_pattern) (struct iwl_priv *priv, int led_id, unsigned int idx); | 50 | * IWL_LED_BLINK: adjust led blink rate based on blink table |
62 | 51 | * IWL_LED_RF_STATE: turn LED on/off based on RF state | |
63 | enum led_type type; | 52 | * LED ON = RF ON |
64 | unsigned int registered; | 53 | * LED OFF = RF OFF |
54 | */ | ||
55 | enum iwl_led_mode { | ||
56 | IWL_LED_BLINK, | ||
57 | IWL_LED_RF_STATE, | ||
65 | }; | 58 | }; |
66 | 59 | ||
67 | int iwl_leds_register(struct iwl_priv *priv); | 60 | void iwl_leds_init(struct iwl_priv *priv); |
68 | void iwl_leds_unregister(struct iwl_priv *priv); | ||
69 | void iwl_leds_background(struct iwl_priv *priv); | 61 | void iwl_leds_background(struct iwl_priv *priv); |
62 | int iwl_led_start(struct iwl_priv *priv); | ||
63 | int iwl_led_associate(struct iwl_priv *priv); | ||
64 | int iwl_led_disassociate(struct iwl_priv *priv); | ||
70 | 65 | ||
71 | #else | ||
72 | static inline int iwl_leds_register(struct iwl_priv *priv) | ||
73 | { | ||
74 | return 0; | ||
75 | } | ||
76 | static inline void iwl_leds_unregister(struct iwl_priv *priv) | ||
77 | { | ||
78 | } | ||
79 | static inline void iwl_leds_background(struct iwl_priv *priv) | ||
80 | { | ||
81 | } | ||
82 | |||
83 | #endif /* CONFIG_IWLWIFI_LEDS */ | ||
84 | #endif /* __iwl_leds_h__ */ | 66 | #endif /* __iwl_leds_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 60be976afff8..9c6b14952061 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -165,26 +165,26 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
165 | *============================================================================= | 165 | *============================================================================= |
166 | * Condition Nxt State Condition Nxt State Condition Nxt State | 166 | * Condition Nxt State Condition Nxt State Condition Nxt State |
167 | *----------------------------------------------------------------------------- | 167 | *----------------------------------------------------------------------------- |
168 | * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A | 168 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A |
169 | * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0 | 169 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 |
170 | * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1 | 170 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 |
171 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | 171 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 |
172 | *============================================================================= | 172 | *============================================================================= |
173 | */ | 173 | */ |
174 | static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { | 174 | static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { |
175 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, | 175 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, |
176 | {IWL_TI_1, 105, CT_KILL_THRESHOLD}, | 176 | {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, |
177 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | 177 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} |
178 | }; | 178 | }; |
179 | static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { | 179 | static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { |
180 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, | 180 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, |
181 | {IWL_TI_2, 110, CT_KILL_THRESHOLD}, | 181 | {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, |
182 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | 182 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} |
183 | }; | 183 | }; |
184 | static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { | 184 | static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { |
185 | {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, | 185 | {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, |
186 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, | 186 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, |
187 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | 187 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} |
188 | }; | 188 | }; |
189 | static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { | 189 | static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { |
190 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, | 190 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, |
@@ -294,6 +294,9 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
294 | 294 | ||
295 | if (priv->cfg->broken_powersave) | 295 | if (priv->cfg->broken_powersave) |
296 | iwl_power_sleep_cam_cmd(priv, &cmd); | 296 | iwl_power_sleep_cam_cmd(priv, &cmd); |
297 | else if (priv->cfg->supports_idle && | ||
298 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) | ||
299 | iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); | ||
297 | else if (tt->state >= IWL_TI_1) | 300 | else if (tt->state >= IWL_TI_1) |
298 | iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); | 301 | iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); |
299 | else if (!enabled) | 302 | else if (!enabled) |
@@ -348,6 +351,23 @@ bool iwl_ht_enabled(struct iwl_priv *priv) | |||
348 | } | 351 | } |
349 | EXPORT_SYMBOL(iwl_ht_enabled); | 352 | EXPORT_SYMBOL(iwl_ht_enabled); |
350 | 353 | ||
354 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | ||
355 | { | ||
356 | s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ | ||
357 | bool within_margin = false; | ||
358 | |||
359 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | ||
360 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
361 | |||
362 | if (!priv->thermal_throttle.advanced_tt) | ||
363 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
364 | CT_KILL_THRESHOLD_LEGACY) ? true : false; | ||
365 | else | ||
366 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
367 | CT_KILL_THRESHOLD) ? true : false; | ||
368 | return within_margin; | ||
369 | } | ||
370 | |||
351 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) | 371 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) |
352 | { | 372 | { |
353 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 373 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; |
@@ -372,6 +392,7 @@ enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) | |||
372 | } | 392 | } |
373 | 393 | ||
374 | #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ | 394 | #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ |
395 | #define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ | ||
375 | 396 | ||
376 | /* | 397 | /* |
377 | * toggle the bit to wake up uCode and check the temperature | 398 | * toggle the bit to wake up uCode and check the temperature |
@@ -409,6 +430,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data) | |||
409 | /* Reschedule the ct_kill timer to occur in | 430 | /* Reschedule the ct_kill timer to occur in |
410 | * CT_KILL_EXIT_DURATION seconds to ensure we get a | 431 | * CT_KILL_EXIT_DURATION seconds to ensure we get a |
411 | * thermal update */ | 432 | * thermal update */ |
433 | IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); | ||
412 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + | 434 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + |
413 | CT_KILL_EXIT_DURATION * HZ); | 435 | CT_KILL_EXIT_DURATION * HZ); |
414 | } | 436 | } |
@@ -432,6 +454,33 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | |||
432 | } | 454 | } |
433 | } | 455 | } |
434 | 456 | ||
457 | static void iwl_tt_ready_for_ct_kill(unsigned long data) | ||
458 | { | ||
459 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
460 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
461 | |||
462 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
463 | return; | ||
464 | |||
465 | /* temperature timer expired, ready to go into CT_KILL state */ | ||
466 | if (tt->state != IWL_TI_CT_KILL) { | ||
467 | IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n"); | ||
468 | tt->state = IWL_TI_CT_KILL; | ||
469 | set_bit(STATUS_CT_KILL, &priv->status); | ||
470 | iwl_perform_ct_kill_task(priv, true); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) | ||
475 | { | ||
476 | IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); | ||
477 | /* make request to retrieve statistics information */ | ||
478 | iwl_send_statistics_request(priv, 0); | ||
479 | /* Reschedule the ct_kill wait timer */ | ||
480 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, | ||
481 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); | ||
482 | } | ||
483 | |||
435 | #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) | 484 | #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) |
436 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) | 485 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) |
437 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) | 486 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) |
@@ -445,7 +494,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | |||
445 | * Throttle early enough to lower the power consumption before | 494 | * Throttle early enough to lower the power consumption before |
446 | * drastic steps are needed | 495 | * drastic steps are needed |
447 | */ | 496 | */ |
448 | static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) | 497 | static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) |
449 | { | 498 | { |
450 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 499 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; |
451 | enum iwl_tt_state old_state; | 500 | enum iwl_tt_state old_state; |
@@ -474,6 +523,8 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) | |||
474 | #ifdef CONFIG_IWLWIFI_DEBUG | 523 | #ifdef CONFIG_IWLWIFI_DEBUG |
475 | tt->tt_previous_temp = temp; | 524 | tt->tt_previous_temp = temp; |
476 | #endif | 525 | #endif |
526 | /* stop ct_kill_waiting_tm timer */ | ||
527 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
477 | if (tt->state != old_state) { | 528 | if (tt->state != old_state) { |
478 | switch (tt->state) { | 529 | switch (tt->state) { |
479 | case IWL_TI_0: | 530 | case IWL_TI_0: |
@@ -494,17 +545,28 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) | |||
494 | break; | 545 | break; |
495 | } | 546 | } |
496 | mutex_lock(&priv->mutex); | 547 | mutex_lock(&priv->mutex); |
497 | if (iwl_power_update_mode(priv, true)) { | 548 | if (old_state == IWL_TI_CT_KILL) |
549 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
550 | if (tt->state != IWL_TI_CT_KILL && | ||
551 | iwl_power_update_mode(priv, true)) { | ||
498 | /* TT state not updated | 552 | /* TT state not updated |
499 | * try again during next temperature read | 553 | * try again during next temperature read |
500 | */ | 554 | */ |
555 | if (old_state == IWL_TI_CT_KILL) | ||
556 | set_bit(STATUS_CT_KILL, &priv->status); | ||
501 | tt->state = old_state; | 557 | tt->state = old_state; |
502 | IWL_ERR(priv, "Cannot update power mode, " | 558 | IWL_ERR(priv, "Cannot update power mode, " |
503 | "TT state not updated\n"); | 559 | "TT state not updated\n"); |
504 | } else { | 560 | } else { |
505 | if (tt->state == IWL_TI_CT_KILL) | 561 | if (tt->state == IWL_TI_CT_KILL) { |
506 | iwl_perform_ct_kill_task(priv, true); | 562 | if (force) { |
507 | else if (old_state == IWL_TI_CT_KILL && | 563 | set_bit(STATUS_CT_KILL, &priv->status); |
564 | iwl_perform_ct_kill_task(priv, true); | ||
565 | } else { | ||
566 | iwl_prepare_ct_kill_task(priv); | ||
567 | tt->state = old_state; | ||
568 | } | ||
569 | } else if (old_state == IWL_TI_CT_KILL && | ||
508 | tt->state != IWL_TI_CT_KILL) | 570 | tt->state != IWL_TI_CT_KILL) |
509 | iwl_perform_ct_kill_task(priv, false); | 571 | iwl_perform_ct_kill_task(priv, false); |
510 | IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", | 572 | IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", |
@@ -531,13 +593,13 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) | |||
531 | *============================================================================= | 593 | *============================================================================= |
532 | * Condition Nxt State Condition Nxt State Condition Nxt State | 594 | * Condition Nxt State Condition Nxt State Condition Nxt State |
533 | *----------------------------------------------------------------------------- | 595 | *----------------------------------------------------------------------------- |
534 | * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A | 596 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A |
535 | * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0 | 597 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 |
536 | * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1 | 598 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 |
537 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | 599 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 |
538 | *============================================================================= | 600 | *============================================================================= |
539 | */ | 601 | */ |
540 | static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) | 602 | static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) |
541 | { | 603 | { |
542 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | 604 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; |
543 | int i; | 605 | int i; |
@@ -582,6 +644,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) | |||
582 | break; | 644 | break; |
583 | } | 645 | } |
584 | } | 646 | } |
647 | /* stop ct_kill_waiting_tm timer */ | ||
648 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
585 | if (changed) { | 649 | if (changed) { |
586 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | 650 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; |
587 | 651 | ||
@@ -613,12 +677,17 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) | |||
613 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | 677 | iwl_set_rxon_ht(priv, &priv->current_ht_config); |
614 | } | 678 | } |
615 | mutex_lock(&priv->mutex); | 679 | mutex_lock(&priv->mutex); |
616 | if (iwl_power_update_mode(priv, true)) { | 680 | if (old_state == IWL_TI_CT_KILL) |
681 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
682 | if (tt->state != IWL_TI_CT_KILL && | ||
683 | iwl_power_update_mode(priv, true)) { | ||
617 | /* TT state not updated | 684 | /* TT state not updated |
618 | * try again during next temperature read | 685 | * try again during next temperature read |
619 | */ | 686 | */ |
620 | IWL_ERR(priv, "Cannot update power mode, " | 687 | IWL_ERR(priv, "Cannot update power mode, " |
621 | "TT state not updated\n"); | 688 | "TT state not updated\n"); |
689 | if (old_state == IWL_TI_CT_KILL) | ||
690 | set_bit(STATUS_CT_KILL, &priv->status); | ||
622 | tt->state = old_state; | 691 | tt->state = old_state; |
623 | } else { | 692 | } else { |
624 | IWL_DEBUG_POWER(priv, | 693 | IWL_DEBUG_POWER(priv, |
@@ -626,9 +695,15 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) | |||
626 | tt->state); | 695 | tt->state); |
627 | if (old_state != IWL_TI_CT_KILL && | 696 | if (old_state != IWL_TI_CT_KILL && |
628 | tt->state == IWL_TI_CT_KILL) { | 697 | tt->state == IWL_TI_CT_KILL) { |
629 | IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n"); | 698 | if (force) { |
630 | iwl_perform_ct_kill_task(priv, true); | 699 | IWL_DEBUG_POWER(priv, |
631 | 700 | "Enter IWL_TI_CT_KILL\n"); | |
701 | set_bit(STATUS_CT_KILL, &priv->status); | ||
702 | iwl_perform_ct_kill_task(priv, true); | ||
703 | } else { | ||
704 | iwl_prepare_ct_kill_task(priv); | ||
705 | tt->state = old_state; | ||
706 | } | ||
632 | } else if (old_state == IWL_TI_CT_KILL && | 707 | } else if (old_state == IWL_TI_CT_KILL && |
633 | tt->state != IWL_TI_CT_KILL) { | 708 | tt->state != IWL_TI_CT_KILL) { |
634 | IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); | 709 | IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); |
@@ -665,10 +740,11 @@ static void iwl_bg_ct_enter(struct work_struct *work) | |||
665 | "- ucode going to sleep!\n"); | 740 | "- ucode going to sleep!\n"); |
666 | if (!priv->thermal_throttle.advanced_tt) | 741 | if (!priv->thermal_throttle.advanced_tt) |
667 | iwl_legacy_tt_handler(priv, | 742 | iwl_legacy_tt_handler(priv, |
668 | IWL_MINIMAL_POWER_THRESHOLD); | 743 | IWL_MINIMAL_POWER_THRESHOLD, |
744 | true); | ||
669 | else | 745 | else |
670 | iwl_advance_tt_handler(priv, | 746 | iwl_advance_tt_handler(priv, |
671 | CT_KILL_THRESHOLD + 1); | 747 | CT_KILL_THRESHOLD + 1, true); |
672 | } | 748 | } |
673 | } | 749 | } |
674 | 750 | ||
@@ -695,11 +771,18 @@ static void iwl_bg_ct_exit(struct work_struct *work) | |||
695 | IWL_ERR(priv, | 771 | IWL_ERR(priv, |
696 | "Device temperature below critical" | 772 | "Device temperature below critical" |
697 | "- ucode awake!\n"); | 773 | "- ucode awake!\n"); |
774 | /* | ||
775 | * exit from CT_KILL state | ||
776 | * reset the current temperature reading | ||
777 | */ | ||
778 | priv->temperature = 0; | ||
698 | if (!priv->thermal_throttle.advanced_tt) | 779 | if (!priv->thermal_throttle.advanced_tt) |
699 | iwl_legacy_tt_handler(priv, | 780 | iwl_legacy_tt_handler(priv, |
700 | IWL_REDUCED_PERFORMANCE_THRESHOLD_2); | 781 | IWL_REDUCED_PERFORMANCE_THRESHOLD_2, |
782 | true); | ||
701 | else | 783 | else |
702 | iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD); | 784 | iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, |
785 | true); | ||
703 | } | 786 | } |
704 | } | 787 | } |
705 | 788 | ||
@@ -735,9 +818,9 @@ static void iwl_bg_tt_work(struct work_struct *work) | |||
735 | temp = KELVIN_TO_CELSIUS(priv->temperature); | 818 | temp = KELVIN_TO_CELSIUS(priv->temperature); |
736 | 819 | ||
737 | if (!priv->thermal_throttle.advanced_tt) | 820 | if (!priv->thermal_throttle.advanced_tt) |
738 | iwl_legacy_tt_handler(priv, temp); | 821 | iwl_legacy_tt_handler(priv, temp, false); |
739 | else | 822 | else |
740 | iwl_advance_tt_handler(priv, temp); | 823 | iwl_advance_tt_handler(priv, temp, false); |
741 | } | 824 | } |
742 | 825 | ||
743 | void iwl_tt_handler(struct iwl_priv *priv) | 826 | void iwl_tt_handler(struct iwl_priv *priv) |
@@ -768,8 +851,12 @@ void iwl_tt_initialize(struct iwl_priv *priv) | |||
768 | tt->state = IWL_TI_0; | 851 | tt->state = IWL_TI_0; |
769 | init_timer(&priv->thermal_throttle.ct_kill_exit_tm); | 852 | init_timer(&priv->thermal_throttle.ct_kill_exit_tm); |
770 | priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; | 853 | priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; |
771 | priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill; | 854 | priv->thermal_throttle.ct_kill_exit_tm.function = |
772 | 855 | iwl_tt_check_exit_ct_kill; | |
856 | init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
857 | priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv; | ||
858 | priv->thermal_throttle.ct_kill_waiting_tm.function = | ||
859 | iwl_tt_ready_for_ct_kill; | ||
773 | /* setup deferred ct kill work */ | 860 | /* setup deferred ct kill work */ |
774 | INIT_WORK(&priv->tt_work, iwl_bg_tt_work); | 861 | INIT_WORK(&priv->tt_work, iwl_bg_tt_work); |
775 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); | 862 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); |
@@ -826,6 +913,8 @@ void iwl_tt_exit(struct iwl_priv *priv) | |||
826 | 913 | ||
827 | /* stop ct_kill_exit_tm timer if activated */ | 914 | /* stop ct_kill_exit_tm timer if activated */ |
828 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | 915 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); |
916 | /* stop ct_kill_waiting_tm timer if activated */ | ||
917 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
829 | cancel_work_sync(&priv->tt_work); | 918 | cancel_work_sync(&priv->tt_work); |
830 | cancel_work_sync(&priv->ct_enter); | 919 | cancel_work_sync(&priv->ct_enter); |
831 | cancel_work_sync(&priv->ct_exit); | 920 | cancel_work_sync(&priv->ct_exit); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index df6f6a49712b..310c32e8f698 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #define IWL_ABSOLUTE_ZERO 0 | 33 | #define IWL_ABSOLUTE_ZERO 0 |
34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF | 34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF |
35 | #define IWL_TT_INCREASE_MARGIN 5 | 35 | #define IWL_TT_INCREASE_MARGIN 5 |
36 | #define IWL_TT_CT_KILL_MARGIN 3 | ||
36 | 37 | ||
37 | enum iwl_antenna_ok { | 38 | enum iwl_antenna_ok { |
38 | IWL_ANT_OK_NONE, | 39 | IWL_ANT_OK_NONE, |
@@ -110,6 +111,7 @@ struct iwl_tt_mgmt { | |||
110 | struct iwl_tt_restriction *restriction; | 111 | struct iwl_tt_restriction *restriction; |
111 | struct iwl_tt_trans *transaction; | 112 | struct iwl_tt_trans *transaction; |
112 | struct timer_list ct_kill_exit_tm; | 113 | struct timer_list ct_kill_exit_tm; |
114 | struct timer_list ct_kill_waiting_tm; | ||
113 | }; | 115 | }; |
114 | 116 | ||
115 | enum iwl_power_level { | 117 | enum iwl_power_level { |
@@ -129,6 +131,7 @@ struct iwl_power_mgr { | |||
129 | 131 | ||
130 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); | 132 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); |
131 | bool iwl_ht_enabled(struct iwl_priv *priv); | 133 | bool iwl_ht_enabled(struct iwl_priv *priv); |
134 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv); | ||
132 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); | 135 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); |
133 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); | 136 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); |
134 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv); | 137 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 4f3a108fa990..41f9a0621250 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -27,7 +27,6 @@ | |||
27 | *****************************************************************************/ | 27 | *****************************************************************************/ |
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/etherdevice.h> | 29 | #include <linux/etherdevice.h> |
30 | #include <net/lib80211.h> | ||
31 | #include <net/mac80211.h> | 30 | #include <net/mac80211.h> |
32 | 31 | ||
33 | #include "iwl-eeprom.h" | 32 | #include "iwl-eeprom.h" |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index c18907544701..c832ba085dba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -709,7 +709,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
709 | dma_addr_t phys_addr; | 709 | dma_addr_t phys_addr; |
710 | dma_addr_t txcmd_phys; | 710 | dma_addr_t txcmd_phys; |
711 | dma_addr_t scratch_phys; | 711 | dma_addr_t scratch_phys; |
712 | u16 len, len_org; | 712 | u16 len, len_org, firstlen, secondlen; |
713 | u16 seq_number = 0; | 713 | u16 seq_number = 0; |
714 | __le16 fc; | 714 | __le16 fc; |
715 | u8 hdr_len; | 715 | u8 hdr_len; |
@@ -842,7 +842,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
842 | sizeof(struct iwl_cmd_header) + hdr_len; | 842 | sizeof(struct iwl_cmd_header) + hdr_len; |
843 | 843 | ||
844 | len_org = len; | 844 | len_org = len; |
845 | len = (len + 3) & ~3; | 845 | firstlen = len = (len + 3) & ~3; |
846 | 846 | ||
847 | if (len_org != len) | 847 | if (len_org != len) |
848 | len_org = 1; | 848 | len_org = 1; |
@@ -876,7 +876,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
876 | 876 | ||
877 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 877 | /* Set up TFD's 2nd entry to point directly to remainder of skb, |
878 | * if any (802.11 null frames have no payload). */ | 878 | * if any (802.11 null frames have no payload). */ |
879 | len = skb->len - hdr_len; | 879 | secondlen = len = skb->len - hdr_len; |
880 | if (len) { | 880 | if (len) { |
881 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | 881 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, |
882 | len, PCI_DMA_TODEVICE); | 882 | len, PCI_DMA_TODEVICE); |
@@ -910,6 +910,12 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
910 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, | 910 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, |
911 | len, PCI_DMA_BIDIRECTIONAL); | 911 | len, PCI_DMA_BIDIRECTIONAL); |
912 | 912 | ||
913 | trace_iwlwifi_dev_tx(priv, | ||
914 | &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr], | ||
915 | sizeof(struct iwl_tfd), | ||
916 | &out_cmd->hdr, firstlen, | ||
917 | skb->data + hdr_len, secondlen); | ||
918 | |||
913 | /* Tell device the write index *just past* this latest filled TFD */ | 919 | /* Tell device the write index *just past* this latest filled TFD */ |
914 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 920 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
915 | ret = iwl_txq_update_write_ptr(priv, txq); | 921 | ret = iwl_txq_update_write_ptr(priv, txq); |
@@ -969,13 +975,19 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
969 | BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && | 975 | BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && |
970 | !(cmd->flags & CMD_SIZE_HUGE)); | 976 | !(cmd->flags & CMD_SIZE_HUGE)); |
971 | 977 | ||
972 | if (iwl_is_rfkill(priv)) { | 978 | if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) { |
973 | IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n"); | 979 | IWL_DEBUG_INFO(priv, "Not sending command - RF/CT KILL\n"); |
974 | return -EIO; | 980 | return -EIO; |
975 | } | 981 | } |
976 | 982 | ||
977 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { | 983 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { |
978 | IWL_ERR(priv, "No space for Tx\n"); | 984 | IWL_ERR(priv, "No space for Tx\n"); |
985 | if (iwl_within_ct_kill_margin(priv)) | ||
986 | iwl_tt_enter_ct_kill(priv); | ||
987 | else { | ||
988 | IWL_ERR(priv, "Restarting adapter due to queue full\n"); | ||
989 | queue_work(priv->workqueue, &priv->restart); | ||
990 | } | ||
979 | return -ENOSPC; | 991 | return -ENOSPC; |
980 | } | 992 | } |
981 | 993 | ||
@@ -1038,6 +1050,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1038 | pci_unmap_addr_set(out_meta, mapping, phys_addr); | 1050 | pci_unmap_addr_set(out_meta, mapping, phys_addr); |
1039 | pci_unmap_len_set(out_meta, len, fix_size); | 1051 | pci_unmap_len_set(out_meta, len, fix_size); |
1040 | 1052 | ||
1053 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); | ||
1054 | |||
1041 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 1055 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, |
1042 | phys_addr, fix_size, 1, | 1056 | phys_addr, fix_size, 1, |
1043 | U32_PAD(cmd->len)); | 1057 | U32_PAD(cmd->len)); |
@@ -1400,7 +1414,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1400 | 1414 | ||
1401 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); | 1415 | info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); |
1402 | memset(&info->status, 0, sizeof(info->status)); | 1416 | memset(&info->status, 0, sizeof(info->status)); |
1403 | info->flags = IEEE80211_TX_STAT_ACK; | 1417 | info->flags |= IEEE80211_TX_STAT_ACK; |
1404 | info->flags |= IEEE80211_TX_STAT_AMPDU; | 1418 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
1405 | info->status.ampdu_ack_map = successes; | 1419 | info->status.ampdu_ack_map = successes; |
1406 | info->status.ampdu_ack_len = agg->frame_count; | 1420 | info->status.ampdu_ack_len = agg->frame_count; |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c390dbd877e4..ecbe036ecb63 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/if_arp.h> | 41 | #include <linux/if_arp.h> |
42 | 42 | ||
43 | #include <net/ieee80211_radiotap.h> | 43 | #include <net/ieee80211_radiotap.h> |
44 | #include <net/lib80211.h> | ||
45 | #include <net/mac80211.h> | 44 | #include <net/mac80211.h> |
46 | 45 | ||
47 | #include <asm/div64.h> | 46 | #include <asm/div64.h> |
@@ -456,9 +455,6 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, | |||
456 | tx->timeout.pm_frame_timeout = cpu_to_le16(2); | 455 | tx->timeout.pm_frame_timeout = cpu_to_le16(2); |
457 | } else { | 456 | } else { |
458 | tx->timeout.pm_frame_timeout = 0; | 457 | tx->timeout.pm_frame_timeout = 0; |
459 | #ifdef CONFIG_IWLWIFI_LEDS | ||
460 | priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len); | ||
461 | #endif | ||
462 | } | 458 | } |
463 | 459 | ||
464 | tx->driver_txop = 0; | 460 | tx->driver_txop = 0; |
@@ -1405,6 +1401,9 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1405 | PCI_DMA_FROMDEVICE); | 1401 | PCI_DMA_FROMDEVICE); |
1406 | pkt = (struct iwl_rx_packet *)rxb->skb->data; | 1402 | pkt = (struct iwl_rx_packet *)rxb->skb->data; |
1407 | 1403 | ||
1404 | trace_iwlwifi_dev_rx(priv, pkt, | ||
1405 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
1406 | |||
1408 | /* Reclaim a command buffer only if this packet is a response | 1407 | /* Reclaim a command buffer only if this packet is a response |
1409 | * to a (driver-originated) command. | 1408 | * to a (driver-originated) command. |
1410 | * If the packet (e.g. Rx frame) originated from uCode, | 1409 | * If the packet (e.g. Rx frame) originated from uCode, |
@@ -1550,8 +1549,9 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | |||
1550 | "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", | 1549 | "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", |
1551 | desc_lookup(desc), desc, time, blink1, blink2, | 1550 | desc_lookup(desc), desc, time, blink1, blink2, |
1552 | ilink1, ilink2, data1); | 1551 | ilink1, ilink2, data1); |
1552 | trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0, | ||
1553 | 0, blink1, blink2, ilink1, ilink2); | ||
1553 | } | 1554 | } |
1554 | |||
1555 | } | 1555 | } |
1556 | 1556 | ||
1557 | #define EVENT_START_OFFSET (6 * sizeof(u32)) | 1557 | #define EVENT_START_OFFSET (6 * sizeof(u32)) |
@@ -1591,10 +1591,12 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1591 | if (mode == 0) { | 1591 | if (mode == 0) { |
1592 | /* data, ev */ | 1592 | /* data, ev */ |
1593 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); | 1593 | IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); |
1594 | trace_iwlwifi_dev_ucode_event(priv, 0, time, ev); | ||
1594 | } else { | 1595 | } else { |
1595 | data = iwl_read_targ_mem(priv, ptr); | 1596 | data = iwl_read_targ_mem(priv, ptr); |
1596 | ptr += sizeof(u32); | 1597 | ptr += sizeof(u32); |
1597 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); | 1598 | IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); |
1599 | trace_iwlwifi_dev_ucode_event(priv, time, data, ev); | ||
1598 | } | 1600 | } |
1599 | } | 1601 | } |
1600 | } | 1602 | } |
@@ -2478,7 +2480,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2478 | 2480 | ||
2479 | iwl3945_reg_txpower_periodic(priv); | 2481 | iwl3945_reg_txpower_periodic(priv); |
2480 | 2482 | ||
2481 | iwl3945_led_register(priv); | 2483 | iwl_leds_init(priv); |
2482 | 2484 | ||
2483 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); | 2485 | IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); |
2484 | set_bit(STATUS_READY, &priv->status); | 2486 | set_bit(STATUS_READY, &priv->status); |
@@ -2516,7 +2518,6 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2516 | if (!exit_pending) | 2518 | if (!exit_pending) |
2517 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2519 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2518 | 2520 | ||
2519 | iwl3945_led_unregister(priv); | ||
2520 | iwl_clear_stations_table(priv); | 2521 | iwl_clear_stations_table(priv); |
2521 | 2522 | ||
2522 | /* Unblock any waiting calls */ | 2523 | /* Unblock any waiting calls */ |
@@ -3151,6 +3152,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) | |||
3151 | * no need to poll the killswitch state anymore */ | 3152 | * no need to poll the killswitch state anymore */ |
3152 | cancel_delayed_work(&priv->rfkill_poll); | 3153 | cancel_delayed_work(&priv->rfkill_poll); |
3153 | 3154 | ||
3155 | iwl_led_start(priv); | ||
3156 | |||
3154 | priv->is_open = 1; | 3157 | priv->is_open = 1; |
3155 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 3158 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
3156 | return 0; | 3159 | return 0; |
@@ -4225,18 +4228,19 @@ static void __exit iwl3945_exit(void) | |||
4225 | 4228 | ||
4226 | MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); | 4229 | MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); |
4227 | 4230 | ||
4228 | module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444); | 4231 | module_param_named(antenna, iwl3945_mod_params.antenna, int, S_IRUGO); |
4229 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 4232 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |
4230 | module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444); | 4233 | module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, S_IRUGO); |
4231 | MODULE_PARM_DESC(swcrypto, | 4234 | MODULE_PARM_DESC(swcrypto, |
4232 | "using software crypto (default 1 [software])\n"); | 4235 | "using software crypto (default 1 [software])\n"); |
4233 | #ifdef CONFIG_IWLWIFI_DEBUG | 4236 | #ifdef CONFIG_IWLWIFI_DEBUG |
4234 | module_param_named(debug, iwl_debug_level, uint, 0644); | 4237 | module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR); |
4235 | MODULE_PARM_DESC(debug, "debug output mask"); | 4238 | MODULE_PARM_DESC(debug, "debug output mask"); |
4236 | #endif | 4239 | #endif |
4237 | module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444); | 4240 | module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, |
4241 | int, S_IRUGO); | ||
4238 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 4242 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
4239 | module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444); | 4243 | module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO); |
4240 | MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); | 4244 | MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); |
4241 | 4245 | ||
4242 | module_exit(iwl3945_exit); | 4246 | module_exit(iwl3945_exit); |
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index d668e4756324..170f33706490 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c | |||
@@ -637,6 +637,8 @@ static int __iwm_up(struct iwm_priv *iwm) | |||
637 | IWM_ERR(iwm, "MAC reading failed\n"); | 637 | IWM_ERR(iwm, "MAC reading failed\n"); |
638 | goto err_disable; | 638 | goto err_disable; |
639 | } | 639 | } |
640 | memcpy(iwm_to_ndev(iwm)->perm_addr, iwm_to_ndev(iwm)->dev_addr, | ||
641 | ETH_ALEN); | ||
640 | 642 | ||
641 | /* We can load the FWs */ | 643 | /* We can load the FWs */ |
642 | ret = iwm_load_fw(iwm); | 644 | ret = iwm_load_fw(iwm); |
diff --git a/drivers/net/wireless/libertas/Kconfig b/drivers/net/wireless/libertas/Kconfig new file mode 100644 index 000000000000..8f8d75b61ea9 --- /dev/null +++ b/drivers/net/wireless/libertas/Kconfig | |||
@@ -0,0 +1,39 @@ | |||
1 | config LIBERTAS | ||
2 | tristate "Marvell 8xxx Libertas WLAN driver support" | ||
3 | depends on WLAN_80211 && CFG80211 | ||
4 | select WIRELESS_EXT | ||
5 | select WEXT_SPY | ||
6 | select LIB80211 | ||
7 | select FW_LOADER | ||
8 | ---help--- | ||
9 | A library for Marvell Libertas 8xxx devices. | ||
10 | |||
11 | config LIBERTAS_USB | ||
12 | tristate "Marvell Libertas 8388 USB 802.11b/g cards" | ||
13 | depends on LIBERTAS && USB | ||
14 | ---help--- | ||
15 | A driver for Marvell Libertas 8388 USB devices. | ||
16 | |||
17 | config LIBERTAS_CS | ||
18 | tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards" | ||
19 | depends on LIBERTAS && PCMCIA | ||
20 | ---help--- | ||
21 | A driver for Marvell Libertas 8385 CompactFlash devices. | ||
22 | |||
23 | config LIBERTAS_SDIO | ||
24 | tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards" | ||
25 | depends on LIBERTAS && MMC | ||
26 | ---help--- | ||
27 | A driver for Marvell Libertas 8385/8686/8688 SDIO devices. | ||
28 | |||
29 | config LIBERTAS_SPI | ||
30 | tristate "Marvell Libertas 8686 SPI 802.11b/g cards" | ||
31 | depends on LIBERTAS && SPI | ||
32 | ---help--- | ||
33 | A driver for Marvell Libertas 8686 SPI devices. | ||
34 | |||
35 | config LIBERTAS_DEBUG | ||
36 | bool "Enable full debugging output in the Libertas module." | ||
37 | depends on LIBERTAS | ||
38 | ---help--- | ||
39 | Debugging support. | ||
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index 0b6918584503..e5584dd1c79a 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile | |||
@@ -1,5 +1,16 @@ | |||
1 | libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \ | 1 | libertas-y += 11d.o |
2 | debugfs.o persistcfg.o ethtool.o assoc.o | 2 | libertas-y += assoc.o |
3 | libertas-y += cfg.o | ||
4 | libertas-y += cmd.o | ||
5 | libertas-y += cmdresp.o | ||
6 | libertas-y += debugfs.o | ||
7 | libertas-y += ethtool.o | ||
8 | libertas-y += main.o | ||
9 | libertas-y += persistcfg.o | ||
10 | libertas-y += rx.o | ||
11 | libertas-y += scan.o | ||
12 | libertas-y += tx.o | ||
13 | libertas-y += wext.o | ||
3 | 14 | ||
4 | usb8xxx-objs += if_usb.o | 15 | usb8xxx-objs += if_usb.o |
5 | libertas_cs-objs += if_cs.o | 16 | libertas_cs-objs += if_cs.o |
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index ab6a2d518af0..2726c044430f 100644 --- a/drivers/net/wireless/libertas/README +++ b/drivers/net/wireless/libertas/README | |||
@@ -1,5 +1,5 @@ | |||
1 | ================================================================================ | 1 | ================================================================================ |
2 | README for USB8388 | 2 | README for Libertas |
3 | 3 | ||
4 | (c) Copyright © 2003-2006, Marvell International Ltd. | 4 | (c) Copyright © 2003-2006, Marvell International Ltd. |
5 | All Rights Reserved | 5 | All Rights Reserved |
@@ -226,4 +226,28 @@ setuserscan | |||
226 | All entries in the scan table (not just the new scan data when keep=1) | 226 | All entries in the scan table (not just the new scan data when keep=1) |
227 | will be displayed upon completion by use of the getscantable ioctl. | 227 | will be displayed upon completion by use of the getscantable ioctl. |
228 | 228 | ||
229 | ======================== | ||
230 | IWCONFIG COMMANDS | ||
231 | ======================== | ||
232 | power period | ||
233 | |||
234 | This command is used to configure the station in deep sleep mode / | ||
235 | auto deep sleep mode. | ||
236 | |||
237 | The timer is implemented to monitor the activities (command, event, | ||
238 | etc.). When an activity is detected station will exit from deep | ||
239 | sleep mode automatically and restart the timer. At timer expiry | ||
240 | (no activity for defined time period) the deep sleep mode is entered | ||
241 | automatically. | ||
242 | |||
243 | Note: this command is for SDIO interface only. | ||
244 | |||
245 | Usage: | ||
246 | To enable deep sleep mode do: | ||
247 | iwconfig wlan0 power period 0 | ||
248 | To enable auto deep sleep mode with idle time period 5 seconds do: | ||
249 | iwconfig wlan0 power period 5 | ||
250 | To disable deep sleep/auto deep sleep mode do: | ||
251 | iwconfig wlan0 power period -1 | ||
252 | |||
229 | ============================================================================== | 253 | ============================================================================== |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c new file mode 100644 index 000000000000..4396dccd12ac --- /dev/null +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | * Implement cfg80211 ("iw") support. | ||
3 | * | ||
4 | * Copyright (C) 2009 M&N Solutions GmbH, 61191 Rosbach, Germany | ||
5 | * Holger Schurig <hs4233@mail.mn-solutions.de> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <net/cfg80211.h> | ||
10 | |||
11 | #include "cfg.h" | ||
12 | #include "cmd.h" | ||
13 | |||
14 | |||
15 | #define CHAN2G(_channel, _freq, _flags) { \ | ||
16 | .band = IEEE80211_BAND_2GHZ, \ | ||
17 | .center_freq = (_freq), \ | ||
18 | .hw_value = (_channel), \ | ||
19 | .flags = (_flags), \ | ||
20 | .max_antenna_gain = 0, \ | ||
21 | .max_power = 30, \ | ||
22 | } | ||
23 | |||
24 | static struct ieee80211_channel lbs_2ghz_channels[] = { | ||
25 | CHAN2G(1, 2412, 0), | ||
26 | CHAN2G(2, 2417, 0), | ||
27 | CHAN2G(3, 2422, 0), | ||
28 | CHAN2G(4, 2427, 0), | ||
29 | CHAN2G(5, 2432, 0), | ||
30 | CHAN2G(6, 2437, 0), | ||
31 | CHAN2G(7, 2442, 0), | ||
32 | CHAN2G(8, 2447, 0), | ||
33 | CHAN2G(9, 2452, 0), | ||
34 | CHAN2G(10, 2457, 0), | ||
35 | CHAN2G(11, 2462, 0), | ||
36 | CHAN2G(12, 2467, 0), | ||
37 | CHAN2G(13, 2472, 0), | ||
38 | CHAN2G(14, 2484, 0), | ||
39 | }; | ||
40 | |||
41 | #define RATETAB_ENT(_rate, _rateid, _flags) { \ | ||
42 | .bitrate = (_rate), \ | ||
43 | .hw_value = (_rateid), \ | ||
44 | .flags = (_flags), \ | ||
45 | } | ||
46 | |||
47 | |||
48 | static struct ieee80211_rate lbs_rates[] = { | ||
49 | RATETAB_ENT(10, 0x1, 0), | ||
50 | RATETAB_ENT(20, 0x2, 0), | ||
51 | RATETAB_ENT(55, 0x4, 0), | ||
52 | RATETAB_ENT(110, 0x8, 0), | ||
53 | RATETAB_ENT(60, 0x10, 0), | ||
54 | RATETAB_ENT(90, 0x20, 0), | ||
55 | RATETAB_ENT(120, 0x40, 0), | ||
56 | RATETAB_ENT(180, 0x80, 0), | ||
57 | RATETAB_ENT(240, 0x100, 0), | ||
58 | RATETAB_ENT(360, 0x200, 0), | ||
59 | RATETAB_ENT(480, 0x400, 0), | ||
60 | RATETAB_ENT(540, 0x800, 0), | ||
61 | }; | ||
62 | |||
63 | static struct ieee80211_supported_band lbs_band_2ghz = { | ||
64 | .channels = lbs_2ghz_channels, | ||
65 | .n_channels = ARRAY_SIZE(lbs_2ghz_channels), | ||
66 | .bitrates = lbs_rates, | ||
67 | .n_bitrates = ARRAY_SIZE(lbs_rates), | ||
68 | }; | ||
69 | |||
70 | |||
71 | static const u32 cipher_suites[] = { | ||
72 | WLAN_CIPHER_SUITE_WEP40, | ||
73 | WLAN_CIPHER_SUITE_WEP104, | ||
74 | WLAN_CIPHER_SUITE_TKIP, | ||
75 | WLAN_CIPHER_SUITE_CCMP, | ||
76 | }; | ||
77 | |||
78 | |||
79 | |||
80 | static int lbs_cfg_set_channel(struct wiphy *wiphy, | ||
81 | struct ieee80211_channel *chan, | ||
82 | enum nl80211_channel_type channel_type) | ||
83 | { | ||
84 | struct lbs_private *priv = wiphy_priv(wiphy); | ||
85 | int ret = -ENOTSUPP; | ||
86 | |||
87 | lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type); | ||
88 | |||
89 | if (channel_type != NL80211_CHAN_NO_HT) | ||
90 | goto out; | ||
91 | |||
92 | ret = lbs_set_channel(priv, chan->hw_value); | ||
93 | |||
94 | out: | ||
95 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | |||
100 | |||
101 | |||
102 | static struct cfg80211_ops lbs_cfg80211_ops = { | ||
103 | .set_channel = lbs_cfg_set_channel, | ||
104 | }; | ||
105 | |||
106 | |||
107 | /* | ||
108 | * At this time lbs_private *priv doesn't even exist, so we just allocate | ||
109 | * memory and don't initialize the wiphy further. This is postponed until we | ||
110 | * can talk to the firmware and happens at registration time in | ||
111 | * lbs_cfg_wiphy_register(). | ||
112 | */ | ||
113 | struct wireless_dev *lbs_cfg_alloc(struct device *dev) | ||
114 | { | ||
115 | int ret = 0; | ||
116 | struct wireless_dev *wdev; | ||
117 | |||
118 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
119 | |||
120 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
121 | if (!wdev) { | ||
122 | dev_err(dev, "cannot allocate wireless device\n"); | ||
123 | return ERR_PTR(-ENOMEM); | ||
124 | } | ||
125 | |||
126 | wdev->wiphy = wiphy_new(&lbs_cfg80211_ops, sizeof(struct lbs_private)); | ||
127 | if (!wdev->wiphy) { | ||
128 | dev_err(dev, "cannot allocate wiphy\n"); | ||
129 | ret = -ENOMEM; | ||
130 | goto err_wiphy_new; | ||
131 | } | ||
132 | |||
133 | lbs_deb_leave(LBS_DEB_CFG80211); | ||
134 | return wdev; | ||
135 | |||
136 | err_wiphy_new: | ||
137 | kfree(wdev); | ||
138 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
139 | return ERR_PTR(ret); | ||
140 | } | ||
141 | |||
142 | |||
143 | /* | ||
144 | * This function get's called after lbs_setup_firmware() determined the | ||
145 | * firmware capabities. So we can setup the wiphy according to our | ||
146 | * hardware/firmware. | ||
147 | */ | ||
148 | int lbs_cfg_register(struct lbs_private *priv) | ||
149 | { | ||
150 | struct wireless_dev *wdev = priv->wdev; | ||
151 | int ret; | ||
152 | |||
153 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
154 | |||
155 | wdev->wiphy->max_scan_ssids = 1; | ||
156 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
157 | |||
158 | /* TODO: BIT(NL80211_IFTYPE_ADHOC); */ | ||
159 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
160 | |||
161 | /* TODO: honor priv->regioncode */ | ||
162 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz; | ||
163 | |||
164 | /* | ||
165 | * We could check priv->fwcapinfo && FW_CAPINFO_WPA, but I have | ||
166 | * never seen a firmware without WPA | ||
167 | */ | ||
168 | wdev->wiphy->cipher_suites = cipher_suites; | ||
169 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | ||
170 | |||
171 | ret = wiphy_register(wdev->wiphy); | ||
172 | if (ret < 0) | ||
173 | lbs_pr_err("cannot register wiphy device\n"); | ||
174 | |||
175 | ret = register_netdev(priv->dev); | ||
176 | if (ret) | ||
177 | lbs_pr_err("cannot register network device\n"); | ||
178 | |||
179 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | ||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | |||
184 | void lbs_cfg_free(struct lbs_private *priv) | ||
185 | { | ||
186 | struct wireless_dev *wdev = priv->wdev; | ||
187 | |||
188 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
189 | |||
190 | if (!wdev) | ||
191 | return; | ||
192 | |||
193 | if (wdev->wiphy) { | ||
194 | wiphy_unregister(wdev->wiphy); | ||
195 | wiphy_free(wdev->wiphy); | ||
196 | } | ||
197 | kfree(wdev); | ||
198 | } | ||
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h new file mode 100644 index 000000000000..e09a193a34d6 --- /dev/null +++ b/drivers/net/wireless/libertas/cfg.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef __LBS_CFG80211_H__ | ||
2 | #define __LBS_CFG80211_H__ | ||
3 | |||
4 | #include "dev.h" | ||
5 | |||
6 | struct wireless_dev *lbs_cfg_alloc(struct device *dev); | ||
7 | int lbs_cfg_register(struct lbs_private *priv); | ||
8 | void lbs_cfg_free(struct lbs_private *priv); | ||
9 | |||
10 | int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, | ||
11 | u8 ssid_len); | ||
12 | int lbs_scan_networks(struct lbs_private *priv, int full_scan); | ||
13 | void lbs_cfg_scan_worker(struct work_struct *work); | ||
14 | |||
15 | |||
16 | #endif | ||
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 685098148e10..0fb312576b8d 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -17,7 +17,6 @@ | |||
17 | 17 | ||
18 | static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); | 18 | static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); |
19 | 19 | ||
20 | |||
21 | /** | 20 | /** |
22 | * @brief Simple callback that copies response back into command | 21 | * @brief Simple callback that copies response back into command |
23 | * | 22 | * |
@@ -76,6 +75,30 @@ static u8 is_command_allowed_in_ps(u16 cmd) | |||
76 | } | 75 | } |
77 | 76 | ||
78 | /** | 77 | /** |
78 | * @brief This function checks if the command is allowed. | ||
79 | * | ||
80 | * @param priv A pointer to lbs_private structure | ||
81 | * @return allowed or not allowed. | ||
82 | */ | ||
83 | |||
84 | static int lbs_is_cmd_allowed(struct lbs_private *priv) | ||
85 | { | ||
86 | int ret = 1; | ||
87 | |||
88 | lbs_deb_enter(LBS_DEB_CMD); | ||
89 | |||
90 | if (!priv->is_auto_deep_sleep_enabled) { | ||
91 | if (priv->is_deep_sleep) { | ||
92 | lbs_deb_cmd("command not allowed in deep sleep\n"); | ||
93 | ret = 0; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | lbs_deb_leave(LBS_DEB_CMD); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | /** | ||
79 | * @brief Updates the hardware details like MAC address and regulatory region | 102 | * @brief Updates the hardware details like MAC address and regulatory region |
80 | * | 103 | * |
81 | * @param priv A pointer to struct lbs_private structure | 104 | * @param priv A pointer to struct lbs_private structure |
@@ -319,6 +342,60 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, | |||
319 | return 0; | 342 | return 0; |
320 | } | 343 | } |
321 | 344 | ||
345 | static int lbs_wait_for_ds_awake(struct lbs_private *priv) | ||
346 | { | ||
347 | int ret = 0; | ||
348 | |||
349 | lbs_deb_enter(LBS_DEB_CMD); | ||
350 | |||
351 | if (priv->is_deep_sleep) { | ||
352 | if (!wait_event_interruptible_timeout(priv->ds_awake_q, | ||
353 | !priv->is_deep_sleep, (10 * HZ))) { | ||
354 | lbs_pr_err("ds_awake_q: timer expired\n"); | ||
355 | ret = -1; | ||
356 | } | ||
357 | } | ||
358 | |||
359 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
360 | return ret; | ||
361 | } | ||
362 | |||
363 | int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) | ||
364 | { | ||
365 | int ret = 0; | ||
366 | |||
367 | lbs_deb_enter(LBS_DEB_CMD); | ||
368 | |||
369 | if (deep_sleep) { | ||
370 | if (priv->is_deep_sleep != 1) { | ||
371 | lbs_deb_cmd("deep sleep: sleep\n"); | ||
372 | BUG_ON(!priv->enter_deep_sleep); | ||
373 | ret = priv->enter_deep_sleep(priv); | ||
374 | if (!ret) { | ||
375 | netif_stop_queue(priv->dev); | ||
376 | netif_carrier_off(priv->dev); | ||
377 | } | ||
378 | } else { | ||
379 | lbs_pr_err("deep sleep: already enabled\n"); | ||
380 | } | ||
381 | } else { | ||
382 | if (priv->is_deep_sleep) { | ||
383 | lbs_deb_cmd("deep sleep: wakeup\n"); | ||
384 | BUG_ON(!priv->exit_deep_sleep); | ||
385 | ret = priv->exit_deep_sleep(priv); | ||
386 | if (!ret) { | ||
387 | ret = lbs_wait_for_ds_awake(priv); | ||
388 | if (ret) | ||
389 | lbs_pr_err("deep sleep: wakeup" | ||
390 | "failed\n"); | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | |||
395 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
396 | return ret; | ||
397 | } | ||
398 | |||
322 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | 399 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, |
323 | struct assoc_request *assoc) | 400 | struct assoc_request *assoc) |
324 | { | 401 | { |
@@ -1242,8 +1319,17 @@ static void lbs_submit_command(struct lbs_private *priv, | |||
1242 | timeo = HZ/4; | 1319 | timeo = HZ/4; |
1243 | } | 1320 | } |
1244 | 1321 | ||
1245 | /* Setup the timer after transmit command */ | 1322 | if (command == CMD_802_11_DEEP_SLEEP) { |
1246 | mod_timer(&priv->command_timer, jiffies + timeo); | 1323 | if (priv->is_auto_deep_sleep_enabled) { |
1324 | priv->wakeup_dev_required = 1; | ||
1325 | priv->dnld_sent = 0; | ||
1326 | } | ||
1327 | priv->is_deep_sleep = 1; | ||
1328 | lbs_complete_command(priv, cmdnode, 0); | ||
1329 | } else { | ||
1330 | /* Setup the timer after transmit command */ | ||
1331 | mod_timer(&priv->command_timer, jiffies + timeo); | ||
1332 | } | ||
1247 | 1333 | ||
1248 | lbs_deb_leave(LBS_DEB_HOST); | 1334 | lbs_deb_leave(LBS_DEB_HOST); |
1249 | } | 1335 | } |
@@ -1390,6 +1476,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1390 | goto done; | 1476 | goto done; |
1391 | } | 1477 | } |
1392 | 1478 | ||
1479 | if (!lbs_is_cmd_allowed(priv)) { | ||
1480 | ret = -EBUSY; | ||
1481 | goto done; | ||
1482 | } | ||
1483 | |||
1393 | cmdnode = lbs_get_cmd_ctrl_node(priv); | 1484 | cmdnode = lbs_get_cmd_ctrl_node(priv); |
1394 | 1485 | ||
1395 | if (cmdnode == NULL) { | 1486 | if (cmdnode == NULL) { |
@@ -1505,6 +1596,10 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1505 | case CMD_802_11_BEACON_CTRL: | 1596 | case CMD_802_11_BEACON_CTRL: |
1506 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); | 1597 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); |
1507 | break; | 1598 | break; |
1599 | case CMD_802_11_DEEP_SLEEP: | ||
1600 | cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP); | ||
1601 | cmdptr->size = cpu_to_le16(S_DS_GEN); | ||
1602 | break; | ||
1508 | default: | 1603 | default: |
1509 | lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); | 1604 | lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); |
1510 | ret = -1; | 1605 | ret = -1; |
@@ -2038,6 +2133,11 @@ static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, | |||
2038 | goto done; | 2133 | goto done; |
2039 | } | 2134 | } |
2040 | 2135 | ||
2136 | if (!lbs_is_cmd_allowed(priv)) { | ||
2137 | cmdnode = ERR_PTR(-EBUSY); | ||
2138 | goto done; | ||
2139 | } | ||
2140 | |||
2041 | cmdnode = lbs_get_cmd_ctrl_node(priv); | 2141 | cmdnode = lbs_get_cmd_ctrl_node(priv); |
2042 | if (cmdnode == NULL) { | 2142 | if (cmdnode == NULL) { |
2043 | lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); | 2143 | lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index c42d3faa2660..47d2b1909d69 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -504,9 +504,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event) | |||
504 | 504 | ||
505 | case MACREG_INT_CODE_HOST_AWAKE: | 505 | case MACREG_INT_CODE_HOST_AWAKE: |
506 | lbs_deb_cmd("EVENT: host awake\n"); | 506 | lbs_deb_cmd("EVENT: host awake\n"); |
507 | if (priv->reset_deep_sleep_wakeup) | ||
508 | priv->reset_deep_sleep_wakeup(priv); | ||
509 | priv->is_deep_sleep = 0; | ||
507 | lbs_send_confirmwake(priv); | 510 | lbs_send_confirmwake(priv); |
508 | break; | 511 | break; |
509 | 512 | ||
513 | case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: | ||
514 | if (priv->reset_deep_sleep_wakeup) | ||
515 | priv->reset_deep_sleep_wakeup(priv); | ||
516 | lbs_deb_cmd("EVENT: ds awake\n"); | ||
517 | priv->is_deep_sleep = 0; | ||
518 | priv->wakeup_dev_required = 0; | ||
519 | wake_up_interruptible(&priv->ds_awake_q); | ||
520 | break; | ||
521 | |||
510 | case MACREG_INT_CODE_PS_AWAKE: | 522 | case MACREG_INT_CODE_PS_AWAKE: |
511 | lbs_deb_cmd("EVENT: ps awake\n"); | 523 | lbs_deb_cmd("EVENT: ps awake\n"); |
512 | /* handle unexpected PS AWAKE event */ | 524 | /* handle unexpected PS AWAKE event */ |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 8b15380ae6e1..fb91c3639fc1 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -33,6 +33,9 @@ int lbs_execute_next_command(struct lbs_private *priv); | |||
33 | int lbs_process_event(struct lbs_private *priv, u32 event); | 33 | int lbs_process_event(struct lbs_private *priv, u32 event); |
34 | void lbs_queue_event(struct lbs_private *priv, u32 event); | 34 | void lbs_queue_event(struct lbs_private *priv, u32 event); |
35 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); | 35 | void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); |
36 | int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep); | ||
37 | int lbs_enter_auto_deep_sleep(struct lbs_private *priv); | ||
38 | int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | ||
36 | 39 | ||
37 | u32 lbs_fw_index_to_data_rate(u8 index); | 40 | u32 lbs_fw_index_to_data_rate(u8 index); |
38 | u8 lbs_data_rate_to_fw_index(u32 rate); | 41 | u8 lbs_data_rate_to_fw_index(u32 rate); |
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 72f3479a4d70..1cf5d5985dac 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define LBS_DEB_SDIO 0x00400000 | 42 | #define LBS_DEB_SDIO 0x00400000 |
43 | #define LBS_DEB_SYSFS 0x00800000 | 43 | #define LBS_DEB_SYSFS 0x00800000 |
44 | #define LBS_DEB_SPI 0x01000000 | 44 | #define LBS_DEB_SPI 0x01000000 |
45 | #define LBS_DEB_CFG80211 0x02000000 | ||
45 | 46 | ||
46 | extern unsigned int lbs_debug; | 47 | extern unsigned int lbs_debug; |
47 | 48 | ||
@@ -86,6 +87,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \ | |||
86 | #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) | 87 | #define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) |
87 | #define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) | 88 | #define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) |
88 | #define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) | 89 | #define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) |
90 | #define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args) | ||
89 | 91 | ||
90 | #define lbs_pr_info(format, args...) \ | 92 | #define lbs_pr_info(format, args...) \ |
91 | printk(KERN_INFO DRV_NAME": " format, ## args) | 93 | printk(KERN_INFO DRV_NAME": " format, ## args) |
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index d3b69a4b4b5e..8abb28af5afa 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -100,6 +100,7 @@ struct lbs_mesh_stats { | |||
100 | 100 | ||
101 | /** Private structure for the MV device */ | 101 | /** Private structure for the MV device */ |
102 | struct lbs_private { | 102 | struct lbs_private { |
103 | struct wireless_dev *wdev; | ||
103 | int mesh_open; | 104 | int mesh_open; |
104 | int mesh_fw_ver; | 105 | int mesh_fw_ver; |
105 | int infra_open; | 106 | int infra_open; |
@@ -129,6 +130,20 @@ struct lbs_private { | |||
129 | u32 bbp_offset; | 130 | u32 bbp_offset; |
130 | u32 rf_offset; | 131 | u32 rf_offset; |
131 | 132 | ||
133 | /** Deep sleep flag */ | ||
134 | int is_deep_sleep; | ||
135 | /** Auto deep sleep enabled flag */ | ||
136 | int is_auto_deep_sleep_enabled; | ||
137 | /** Device wakeup required flag */ | ||
138 | int wakeup_dev_required; | ||
139 | /** Auto deep sleep flag*/ | ||
140 | int is_activity_detected; | ||
141 | /** Auto deep sleep timeout (in miliseconds) */ | ||
142 | int auto_deep_sleep_timeout; | ||
143 | |||
144 | /** Deep sleep wait queue */ | ||
145 | wait_queue_head_t ds_awake_q; | ||
146 | |||
132 | /* Download sent: | 147 | /* Download sent: |
133 | bit0 1/0=data_sent/data_tx_done, | 148 | bit0 1/0=data_sent/data_tx_done, |
134 | bit1 1/0=cmd_sent/cmd_tx_done, | 149 | bit1 1/0=cmd_sent/cmd_tx_done, |
@@ -154,6 +169,9 @@ struct lbs_private { | |||
154 | /** Hardware access */ | 169 | /** Hardware access */ |
155 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); | 170 | int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); |
156 | void (*reset_card) (struct lbs_private *priv); | 171 | void (*reset_card) (struct lbs_private *priv); |
172 | int (*enter_deep_sleep) (struct lbs_private *priv); | ||
173 | int (*exit_deep_sleep) (struct lbs_private *priv); | ||
174 | int (*reset_deep_sleep_wakeup) (struct lbs_private *priv); | ||
157 | 175 | ||
158 | /* Wake On LAN */ | 176 | /* Wake On LAN */ |
159 | uint32_t wol_criteria; | 177 | uint32_t wol_criteria; |
@@ -204,6 +222,7 @@ struct lbs_private { | |||
204 | 222 | ||
205 | /** Timers */ | 223 | /** Timers */ |
206 | struct timer_list command_timer; | 224 | struct timer_list command_timer; |
225 | struct timer_list auto_deepsleep_timer; | ||
207 | int nr_retries; | 226 | int nr_retries; |
208 | int cmd_timed_out; | 227 | int cmd_timed_out; |
209 | 228 | ||
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index fe8f0cb737bc..c055daabea13 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h | |||
@@ -57,6 +57,7 @@ | |||
57 | #define CMD_802_11_ENABLE_RSN 0x002f | 57 | #define CMD_802_11_ENABLE_RSN 0x002f |
58 | #define CMD_802_11_SET_AFC 0x003c | 58 | #define CMD_802_11_SET_AFC 0x003c |
59 | #define CMD_802_11_GET_AFC 0x003d | 59 | #define CMD_802_11_GET_AFC 0x003d |
60 | #define CMD_802_11_DEEP_SLEEP 0x003e | ||
60 | #define CMD_802_11_AD_HOC_STOP 0x0040 | 61 | #define CMD_802_11_AD_HOC_STOP 0x0040 |
61 | #define CMD_802_11_HOST_SLEEP_CFG 0x0043 | 62 | #define CMD_802_11_HOST_SLEEP_CFG 0x0043 |
62 | #define CMD_802_11_WAKEUP_CONFIRM 0x0044 | 63 | #define CMD_802_11_WAKEUP_CONFIRM 0x0044 |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 62381768f2d5..465742f19ecb 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -946,6 +946,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
946 | card->priv = priv; | 946 | card->priv = priv; |
947 | priv->card = card; | 947 | priv->card = card; |
948 | priv->hw_host_to_card = if_cs_host_to_card; | 948 | priv->hw_host_to_card = if_cs_host_to_card; |
949 | priv->enter_deep_sleep = NULL; | ||
950 | priv->exit_deep_sleep = NULL; | ||
951 | priv->reset_deep_sleep_wakeup = NULL; | ||
949 | priv->fw_ready = 1; | 952 | priv->fw_ready = 1; |
950 | 953 | ||
951 | /* Now actually get the IRQ */ | 954 | /* Now actually get the IRQ */ |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 485a8d406525..9716728a33cb 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -831,6 +831,58 @@ out: | |||
831 | return ret; | 831 | return ret; |
832 | } | 832 | } |
833 | 833 | ||
834 | static int if_sdio_enter_deep_sleep(struct lbs_private *priv) | ||
835 | { | ||
836 | int ret = -1; | ||
837 | struct cmd_header cmd; | ||
838 | |||
839 | memset(&cmd, 0, sizeof(cmd)); | ||
840 | |||
841 | lbs_deb_sdio("send DEEP_SLEEP command\n"); | ||
842 | ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd), | ||
843 | lbs_cmd_copyback, (unsigned long) &cmd); | ||
844 | if (ret) | ||
845 | lbs_pr_err("DEEP_SLEEP cmd failed\n"); | ||
846 | |||
847 | mdelay(200); | ||
848 | return ret; | ||
849 | } | ||
850 | |||
851 | static int if_sdio_exit_deep_sleep(struct lbs_private *priv) | ||
852 | { | ||
853 | struct if_sdio_card *card = priv->card; | ||
854 | int ret = -1; | ||
855 | |||
856 | lbs_deb_enter(LBS_DEB_SDIO); | ||
857 | sdio_claim_host(card->func); | ||
858 | |||
859 | sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); | ||
860 | if (ret) | ||
861 | lbs_pr_err("sdio_writeb failed!\n"); | ||
862 | |||
863 | sdio_release_host(card->func); | ||
864 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
865 | return ret; | ||
866 | } | ||
867 | |||
868 | static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) | ||
869 | { | ||
870 | struct if_sdio_card *card = priv->card; | ||
871 | int ret = -1; | ||
872 | |||
873 | lbs_deb_enter(LBS_DEB_SDIO); | ||
874 | sdio_claim_host(card->func); | ||
875 | |||
876 | sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret); | ||
877 | if (ret) | ||
878 | lbs_pr_err("sdio_writeb failed!\n"); | ||
879 | |||
880 | sdio_release_host(card->func); | ||
881 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
882 | return ret; | ||
883 | |||
884 | } | ||
885 | |||
834 | /*******************************************************************/ | 886 | /*******************************************************************/ |
835 | /* SDIO callbacks */ | 887 | /* SDIO callbacks */ |
836 | /*******************************************************************/ | 888 | /*******************************************************************/ |
@@ -859,6 +911,7 @@ static void if_sdio_interrupt(struct sdio_func *func) | |||
859 | * Ignore the define name, this really means the card has | 911 | * Ignore the define name, this really means the card has |
860 | * successfully received the command. | 912 | * successfully received the command. |
861 | */ | 913 | */ |
914 | card->priv->is_activity_detected = 1; | ||
862 | if (cause & IF_SDIO_H_INT_DNLD) | 915 | if (cause & IF_SDIO_H_INT_DNLD) |
863 | lbs_host_to_card_done(card->priv); | 916 | lbs_host_to_card_done(card->priv); |
864 | 917 | ||
@@ -998,6 +1051,9 @@ static int if_sdio_probe(struct sdio_func *func, | |||
998 | 1051 | ||
999 | priv->card = card; | 1052 | priv->card = card; |
1000 | priv->hw_host_to_card = if_sdio_host_to_card; | 1053 | priv->hw_host_to_card = if_sdio_host_to_card; |
1054 | priv->enter_deep_sleep = if_sdio_enter_deep_sleep; | ||
1055 | priv->exit_deep_sleep = if_sdio_exit_deep_sleep; | ||
1056 | priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; | ||
1001 | 1057 | ||
1002 | priv->fw_ready = 1; | 1058 | priv->fw_ready = 1; |
1003 | 1059 | ||
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 60c9b2fcef03..12179c1dc9c9 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h | |||
@@ -51,5 +51,6 @@ | |||
51 | #define IF_SDIO_EVENT 0x80fc | 51 | #define IF_SDIO_EVENT 0x80fc |
52 | 52 | ||
53 | #define IF_SDIO_BLOCK_SIZE 256 | 53 | #define IF_SDIO_BLOCK_SIZE 256 |
54 | 54 | #define CONFIGURATION_REG 0x03 | |
55 | #define HOST_POWER_UP (0x1U << 1) | ||
55 | #endif | 56 | #endif |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index cb8be8d7abc1..06df2e174b50 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -1117,6 +1117,9 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
1117 | card->priv = priv; | 1117 | card->priv = priv; |
1118 | priv->card = card; | 1118 | priv->card = card; |
1119 | priv->hw_host_to_card = if_spi_host_to_card; | 1119 | priv->hw_host_to_card = if_spi_host_to_card; |
1120 | priv->enter_deep_sleep = NULL; | ||
1121 | priv->exit_deep_sleep = NULL; | ||
1122 | priv->reset_deep_sleep_wakeup = NULL; | ||
1120 | priv->fw_ready = 1; | 1123 | priv->fw_ready = 1; |
1121 | 1124 | ||
1122 | /* Initialize interrupt handling stuff. */ | 1125 | /* Initialize interrupt handling stuff. */ |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 92bc8c5f1ca2..a8262dea9b1f 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -300,6 +300,9 @@ static int if_usb_probe(struct usb_interface *intf, | |||
300 | cardp->priv->fw_ready = 1; | 300 | cardp->priv->fw_ready = 1; |
301 | 301 | ||
302 | priv->hw_host_to_card = if_usb_host_to_card; | 302 | priv->hw_host_to_card = if_usb_host_to_card; |
303 | priv->enter_deep_sleep = NULL; | ||
304 | priv->exit_deep_sleep = NULL; | ||
305 | priv->reset_deep_sleep_wakeup = NULL; | ||
303 | #ifdef CONFIG_OLPC | 306 | #ifdef CONFIG_OLPC |
304 | if (machine_is_olpc()) | 307 | if (machine_is_olpc()) |
305 | priv->reset_card = if_usb_reset_olpc_card; | 308 | priv->reset_card = if_usb_reset_olpc_card; |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 87b4e497faa2..87bfd17b9c8c 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -14,11 +14,13 @@ | |||
14 | #include <linux/stddef.h> | 14 | #include <linux/stddef.h> |
15 | #include <linux/ieee80211.h> | 15 | #include <linux/ieee80211.h> |
16 | #include <net/iw_handler.h> | 16 | #include <net/iw_handler.h> |
17 | #include <net/cfg80211.h> | ||
17 | 18 | ||
18 | #include "host.h" | 19 | #include "host.h" |
19 | #include "decl.h" | 20 | #include "decl.h" |
20 | #include "dev.h" | 21 | #include "dev.h" |
21 | #include "wext.h" | 22 | #include "wext.h" |
23 | #include "cfg.h" | ||
22 | #include "debugfs.h" | 24 | #include "debugfs.h" |
23 | #include "scan.h" | 25 | #include "scan.h" |
24 | #include "assoc.h" | 26 | #include "assoc.h" |
@@ -574,8 +576,10 @@ void lbs_host_to_card_done(struct lbs_private *priv) | |||
574 | priv->dnld_sent = DNLD_RES_RECEIVED; | 576 | priv->dnld_sent = DNLD_RES_RECEIVED; |
575 | 577 | ||
576 | /* Wake main thread if commands are pending */ | 578 | /* Wake main thread if commands are pending */ |
577 | if (!priv->cur_cmd || priv->tx_pending_len > 0) | 579 | if (!priv->cur_cmd || priv->tx_pending_len > 0) { |
578 | wake_up_interruptible(&priv->waitq); | 580 | if (!priv->wakeup_dev_required) |
581 | wake_up_interruptible(&priv->waitq); | ||
582 | } | ||
579 | 583 | ||
580 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 584 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
581 | lbs_deb_leave(LBS_DEB_THREAD); | 585 | lbs_deb_leave(LBS_DEB_THREAD); |
@@ -770,7 +774,8 @@ static int lbs_thread(void *data) | |||
770 | shouldsleep = 0; /* We have a command response */ | 774 | shouldsleep = 0; /* We have a command response */ |
771 | else if (priv->cur_cmd) | 775 | else if (priv->cur_cmd) |
772 | shouldsleep = 1; /* Can't send a command; one already running */ | 776 | shouldsleep = 1; /* Can't send a command; one already running */ |
773 | else if (!list_empty(&priv->cmdpendingq)) | 777 | else if (!list_empty(&priv->cmdpendingq) && |
778 | !(priv->wakeup_dev_required)) | ||
774 | shouldsleep = 0; /* We have a command to send */ | 779 | shouldsleep = 0; /* We have a command to send */ |
775 | else if (__kfifo_len(priv->event_fifo)) | 780 | else if (__kfifo_len(priv->event_fifo)) |
776 | shouldsleep = 0; /* We have an event to process */ | 781 | shouldsleep = 0; /* We have an event to process */ |
@@ -822,6 +827,26 @@ static int lbs_thread(void *data) | |||
822 | } | 827 | } |
823 | spin_unlock_irq(&priv->driver_lock); | 828 | spin_unlock_irq(&priv->driver_lock); |
824 | 829 | ||
830 | /* Process hardware events, e.g. card removed, link lost */ | ||
831 | spin_lock_irq(&priv->driver_lock); | ||
832 | while (__kfifo_len(priv->event_fifo)) { | ||
833 | u32 event; | ||
834 | __kfifo_get(priv->event_fifo, (unsigned char *) &event, | ||
835 | sizeof(event)); | ||
836 | spin_unlock_irq(&priv->driver_lock); | ||
837 | lbs_process_event(priv, event); | ||
838 | spin_lock_irq(&priv->driver_lock); | ||
839 | } | ||
840 | spin_unlock_irq(&priv->driver_lock); | ||
841 | |||
842 | if (priv->wakeup_dev_required) { | ||
843 | lbs_deb_thread("Waking up device...\n"); | ||
844 | /* Wake up device */ | ||
845 | if (priv->exit_deep_sleep(priv)) | ||
846 | lbs_deb_thread("Wakeup device failed\n"); | ||
847 | continue; | ||
848 | } | ||
849 | |||
825 | /* command timeout stuff */ | 850 | /* command timeout stuff */ |
826 | if (priv->cmd_timed_out && priv->cur_cmd) { | 851 | if (priv->cmd_timed_out && priv->cur_cmd) { |
827 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | 852 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; |
@@ -849,18 +874,7 @@ static int lbs_thread(void *data) | |||
849 | } | 874 | } |
850 | priv->cmd_timed_out = 0; | 875 | priv->cmd_timed_out = 0; |
851 | 876 | ||
852 | /* Process hardware events, e.g. card removed, link lost */ | ||
853 | spin_lock_irq(&priv->driver_lock); | ||
854 | while (__kfifo_len(priv->event_fifo)) { | ||
855 | u32 event; | ||
856 | 877 | ||
857 | __kfifo_get(priv->event_fifo, (unsigned char *) &event, | ||
858 | sizeof(event)); | ||
859 | spin_unlock_irq(&priv->driver_lock); | ||
860 | lbs_process_event(priv, event); | ||
861 | spin_lock_irq(&priv->driver_lock); | ||
862 | } | ||
863 | spin_unlock_irq(&priv->driver_lock); | ||
864 | 878 | ||
865 | if (!priv->fw_ready) | 879 | if (!priv->fw_ready) |
866 | continue; | 880 | continue; |
@@ -894,6 +908,9 @@ static int lbs_thread(void *data) | |||
894 | (priv->psstate == PS_STATE_PRE_SLEEP)) | 908 | (priv->psstate == PS_STATE_PRE_SLEEP)) |
895 | continue; | 909 | continue; |
896 | 910 | ||
911 | if (priv->is_deep_sleep) | ||
912 | continue; | ||
913 | |||
897 | /* Execute the next command */ | 914 | /* Execute the next command */ |
898 | if (!priv->dnld_sent && !priv->cur_cmd) | 915 | if (!priv->dnld_sent && !priv->cur_cmd) |
899 | lbs_execute_next_command(priv); | 916 | lbs_execute_next_command(priv); |
@@ -928,6 +945,7 @@ static int lbs_thread(void *data) | |||
928 | } | 945 | } |
929 | 946 | ||
930 | del_timer(&priv->command_timer); | 947 | del_timer(&priv->command_timer); |
948 | del_timer(&priv->auto_deepsleep_timer); | ||
931 | wake_up_all(&priv->cmd_pending); | 949 | wake_up_all(&priv->cmd_pending); |
932 | 950 | ||
933 | lbs_deb_leave(LBS_DEB_THREAD); | 951 | lbs_deb_leave(LBS_DEB_THREAD); |
@@ -1050,6 +1068,60 @@ out: | |||
1050 | lbs_deb_leave(LBS_DEB_CMD); | 1068 | lbs_deb_leave(LBS_DEB_CMD); |
1051 | } | 1069 | } |
1052 | 1070 | ||
1071 | /** | ||
1072 | * This function put the device back to deep sleep mode when timer expires | ||
1073 | * and no activity (command, event, data etc.) is detected. | ||
1074 | */ | ||
1075 | static void auto_deepsleep_timer_fn(unsigned long data) | ||
1076 | { | ||
1077 | struct lbs_private *priv = (struct lbs_private *)data; | ||
1078 | int ret; | ||
1079 | |||
1080 | lbs_deb_enter(LBS_DEB_CMD); | ||
1081 | |||
1082 | if (priv->is_activity_detected) { | ||
1083 | priv->is_activity_detected = 0; | ||
1084 | } else { | ||
1085 | if (priv->is_auto_deep_sleep_enabled && | ||
1086 | (!priv->wakeup_dev_required) && | ||
1087 | (priv->connect_status != LBS_CONNECTED)) { | ||
1088 | lbs_deb_main("Entering auto deep sleep mode...\n"); | ||
1089 | ret = lbs_prepare_and_send_command(priv, | ||
1090 | CMD_802_11_DEEP_SLEEP, 0, | ||
1091 | 0, 0, NULL); | ||
1092 | } | ||
1093 | } | ||
1094 | mod_timer(&priv->auto_deepsleep_timer , jiffies + | ||
1095 | (priv->auto_deep_sleep_timeout * HZ)/1000); | ||
1096 | lbs_deb_leave(LBS_DEB_CMD); | ||
1097 | } | ||
1098 | |||
1099 | int lbs_enter_auto_deep_sleep(struct lbs_private *priv) | ||
1100 | { | ||
1101 | lbs_deb_enter(LBS_DEB_SDIO); | ||
1102 | |||
1103 | priv->is_auto_deep_sleep_enabled = 1; | ||
1104 | if (priv->is_deep_sleep) | ||
1105 | priv->wakeup_dev_required = 1; | ||
1106 | mod_timer(&priv->auto_deepsleep_timer , | ||
1107 | jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000); | ||
1108 | |||
1109 | lbs_deb_leave(LBS_DEB_SDIO); | ||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | int lbs_exit_auto_deep_sleep(struct lbs_private *priv) | ||
1114 | { | ||
1115 | lbs_deb_enter(LBS_DEB_SDIO); | ||
1116 | |||
1117 | priv->is_auto_deep_sleep_enabled = 0; | ||
1118 | priv->auto_deep_sleep_timeout = 0; | ||
1119 | del_timer(&priv->auto_deepsleep_timer); | ||
1120 | |||
1121 | lbs_deb_leave(LBS_DEB_SDIO); | ||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1053 | static void lbs_sync_channel_worker(struct work_struct *work) | 1125 | static void lbs_sync_channel_worker(struct work_struct *work) |
1054 | { | 1126 | { |
1055 | struct lbs_private *priv = container_of(work, struct lbs_private, | 1127 | struct lbs_private *priv = container_of(work, struct lbs_private, |
@@ -1099,11 +1171,17 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
1099 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; | 1171 | priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; |
1100 | priv->psmode = LBS802_11POWERMODECAM; | 1172 | priv->psmode = LBS802_11POWERMODECAM; |
1101 | priv->psstate = PS_STATE_FULL_POWER; | 1173 | priv->psstate = PS_STATE_FULL_POWER; |
1174 | priv->is_deep_sleep = 0; | ||
1175 | priv->is_auto_deep_sleep_enabled = 0; | ||
1176 | priv->wakeup_dev_required = 0; | ||
1177 | init_waitqueue_head(&priv->ds_awake_q); | ||
1102 | 1178 | ||
1103 | mutex_init(&priv->lock); | 1179 | mutex_init(&priv->lock); |
1104 | 1180 | ||
1105 | setup_timer(&priv->command_timer, command_timer_fn, | 1181 | setup_timer(&priv->command_timer, command_timer_fn, |
1106 | (unsigned long)priv); | 1182 | (unsigned long)priv); |
1183 | setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn, | ||
1184 | (unsigned long)priv); | ||
1107 | 1185 | ||
1108 | INIT_LIST_HEAD(&priv->cmdfreeq); | 1186 | INIT_LIST_HEAD(&priv->cmdfreeq); |
1109 | INIT_LIST_HEAD(&priv->cmdpendingq); | 1187 | INIT_LIST_HEAD(&priv->cmdpendingq); |
@@ -1142,6 +1220,7 @@ static void lbs_free_adapter(struct lbs_private *priv) | |||
1142 | if (priv->event_fifo) | 1220 | if (priv->event_fifo) |
1143 | kfifo_free(priv->event_fifo); | 1221 | kfifo_free(priv->event_fifo); |
1144 | del_timer(&priv->command_timer); | 1222 | del_timer(&priv->command_timer); |
1223 | del_timer(&priv->auto_deepsleep_timer); | ||
1145 | kfree(priv->networks); | 1224 | kfree(priv->networks); |
1146 | priv->networks = NULL; | 1225 | priv->networks = NULL; |
1147 | 1226 | ||
@@ -1168,31 +1247,41 @@ static const struct net_device_ops lbs_netdev_ops = { | |||
1168 | */ | 1247 | */ |
1169 | struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | 1248 | struct lbs_private *lbs_add_card(void *card, struct device *dmdev) |
1170 | { | 1249 | { |
1171 | struct net_device *dev = NULL; | 1250 | struct net_device *dev; |
1251 | struct wireless_dev *wdev; | ||
1172 | struct lbs_private *priv = NULL; | 1252 | struct lbs_private *priv = NULL; |
1173 | 1253 | ||
1174 | lbs_deb_enter(LBS_DEB_MAIN); | 1254 | lbs_deb_enter(LBS_DEB_MAIN); |
1175 | 1255 | ||
1176 | /* Allocate an Ethernet device and register it */ | 1256 | /* Allocate an Ethernet device and register it */ |
1177 | dev = alloc_etherdev(sizeof(struct lbs_private)); | 1257 | wdev = lbs_cfg_alloc(dmdev); |
1178 | if (!dev) { | 1258 | if (IS_ERR(wdev)) { |
1179 | lbs_pr_err("init wlanX device failed\n"); | 1259 | lbs_pr_err("cfg80211 init failed\n"); |
1180 | goto done; | 1260 | goto done; |
1181 | } | 1261 | } |
1182 | priv = netdev_priv(dev); | 1262 | /* TODO? */ |
1183 | dev->ml_priv = priv; | 1263 | wdev->iftype = NL80211_IFTYPE_STATION; |
1264 | priv = wdev_priv(wdev); | ||
1265 | priv->wdev = wdev; | ||
1184 | 1266 | ||
1185 | if (lbs_init_adapter(priv)) { | 1267 | if (lbs_init_adapter(priv)) { |
1186 | lbs_pr_err("failed to initialize adapter structure.\n"); | 1268 | lbs_pr_err("failed to initialize adapter structure.\n"); |
1187 | goto err_init_adapter; | 1269 | goto err_wdev; |
1270 | } | ||
1271 | |||
1272 | //TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES); | ||
1273 | dev = alloc_netdev(0, "wlan%d", ether_setup); | ||
1274 | if (!dev) { | ||
1275 | dev_err(dmdev, "no memory for network device instance\n"); | ||
1276 | goto err_adapter; | ||
1188 | } | 1277 | } |
1189 | 1278 | ||
1279 | dev->ieee80211_ptr = wdev; | ||
1280 | dev->ml_priv = priv; | ||
1281 | SET_NETDEV_DEV(dev, dmdev); | ||
1282 | wdev->netdev = dev; | ||
1190 | priv->dev = dev; | 1283 | priv->dev = dev; |
1191 | priv->card = card; | ||
1192 | priv->mesh_open = 0; | ||
1193 | priv->infra_open = 0; | ||
1194 | 1284 | ||
1195 | /* Setup the OS Interface to our functions */ | ||
1196 | dev->netdev_ops = &lbs_netdev_ops; | 1285 | dev->netdev_ops = &lbs_netdev_ops; |
1197 | dev->watchdog_timeo = 5 * HZ; | 1286 | dev->watchdog_timeo = 5 * HZ; |
1198 | dev->ethtool_ops = &lbs_ethtool_ops; | 1287 | dev->ethtool_ops = &lbs_ethtool_ops; |
@@ -1201,7 +1290,14 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1201 | #endif | 1290 | #endif |
1202 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; | 1291 | dev->flags |= IFF_BROADCAST | IFF_MULTICAST; |
1203 | 1292 | ||
1204 | SET_NETDEV_DEV(dev, dmdev); | 1293 | |
1294 | // TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ?? | ||
1295 | |||
1296 | |||
1297 | priv->card = card; | ||
1298 | priv->mesh_open = 0; | ||
1299 | priv->infra_open = 0; | ||
1300 | |||
1205 | 1301 | ||
1206 | priv->rtap_net_dev = NULL; | 1302 | priv->rtap_net_dev = NULL; |
1207 | strcpy(dev->name, "wlan%d"); | 1303 | strcpy(dev->name, "wlan%d"); |
@@ -1211,7 +1307,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1211 | priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main"); | 1307 | priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main"); |
1212 | if (IS_ERR(priv->main_thread)) { | 1308 | if (IS_ERR(priv->main_thread)) { |
1213 | lbs_deb_thread("Error creating main thread.\n"); | 1309 | lbs_deb_thread("Error creating main thread.\n"); |
1214 | goto err_init_adapter; | 1310 | goto err_ndev; |
1215 | } | 1311 | } |
1216 | 1312 | ||
1217 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); | 1313 | priv->work_thread = create_singlethread_workqueue("lbs_worker"); |
@@ -1228,9 +1324,15 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1228 | 1324 | ||
1229 | goto done; | 1325 | goto done; |
1230 | 1326 | ||
1231 | err_init_adapter: | 1327 | err_ndev: |
1232 | lbs_free_adapter(priv); | ||
1233 | free_netdev(dev); | 1328 | free_netdev(dev); |
1329 | |||
1330 | err_adapter: | ||
1331 | lbs_free_adapter(priv); | ||
1332 | |||
1333 | err_wdev: | ||
1334 | lbs_cfg_free(priv); | ||
1335 | |||
1234 | priv = NULL; | 1336 | priv = NULL; |
1235 | 1337 | ||
1236 | done: | 1338 | done: |
@@ -1272,11 +1374,17 @@ void lbs_remove_card(struct lbs_private *priv) | |||
1272 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 1374 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
1273 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | 1375 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); |
1274 | 1376 | ||
1377 | if (priv->is_deep_sleep) { | ||
1378 | priv->is_deep_sleep = 0; | ||
1379 | wake_up_interruptible(&priv->ds_awake_q); | ||
1380 | } | ||
1381 | |||
1275 | /* Stop the thread servicing the interrupts */ | 1382 | /* Stop the thread servicing the interrupts */ |
1276 | priv->surpriseremoved = 1; | 1383 | priv->surpriseremoved = 1; |
1277 | kthread_stop(priv->main_thread); | 1384 | kthread_stop(priv->main_thread); |
1278 | 1385 | ||
1279 | lbs_free_adapter(priv); | 1386 | lbs_free_adapter(priv); |
1387 | lbs_cfg_free(priv); | ||
1280 | 1388 | ||
1281 | priv->dev = NULL; | 1389 | priv->dev = NULL; |
1282 | free_netdev(dev); | 1390 | free_netdev(dev); |
@@ -1301,8 +1409,8 @@ int lbs_start_card(struct lbs_private *priv) | |||
1301 | /* init 802.11d */ | 1409 | /* init 802.11d */ |
1302 | lbs_init_11d(priv); | 1410 | lbs_init_11d(priv); |
1303 | 1411 | ||
1304 | if (register_netdev(dev)) { | 1412 | if (lbs_cfg_register(priv)) { |
1305 | lbs_pr_err("cannot register ethX device\n"); | 1413 | lbs_pr_err("cannot register device\n"); |
1306 | goto done; | 1414 | goto done; |
1307 | } | 1415 | } |
1308 | 1416 | ||
@@ -1392,6 +1500,7 @@ void lbs_stop_card(struct lbs_private *priv) | |||
1392 | 1500 | ||
1393 | /* Delete the timeout of the currently processing command */ | 1501 | /* Delete the timeout of the currently processing command */ |
1394 | del_timer_sync(&priv->command_timer); | 1502 | del_timer_sync(&priv->command_timer); |
1503 | del_timer_sync(&priv->auto_deepsleep_timer); | ||
1395 | 1504 | ||
1396 | /* Flush pending command nodes */ | 1505 | /* Flush pending command nodes */ |
1397 | spin_lock_irqsave(&priv->driver_lock, flags); | 1506 | spin_lock_irqsave(&priv->driver_lock, flags); |
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index be837a0d2517..69dd19bf9558 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c | |||
@@ -45,7 +45,6 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv) | |||
45 | priv->pending_assoc_req = NULL; | 45 | priv->pending_assoc_req = NULL; |
46 | } | 46 | } |
47 | 47 | ||
48 | |||
49 | /** | 48 | /** |
50 | * @brief Find the channel frequency power info with specific channel | 49 | * @brief Find the channel frequency power info with specific channel |
51 | * | 50 | * |
@@ -709,6 +708,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | |||
709 | struct iw_param *vwrq, char *extra) | 708 | struct iw_param *vwrq, char *extra) |
710 | { | 709 | { |
711 | struct lbs_private *priv = dev->ml_priv; | 710 | struct lbs_private *priv = dev->ml_priv; |
711 | int ret = 0; | ||
712 | 712 | ||
713 | lbs_deb_enter(LBS_DEB_WEXT); | 713 | lbs_deb_enter(LBS_DEB_WEXT); |
714 | 714 | ||
@@ -737,8 +737,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | |||
737 | "setting power timeout is not supported\n"); | 737 | "setting power timeout is not supported\n"); |
738 | return -EINVAL; | 738 | return -EINVAL; |
739 | } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { | 739 | } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { |
740 | lbs_deb_wext("setting power period not supported\n"); | 740 | vwrq->value = vwrq->value / 1000; |
741 | return -EINVAL; | 741 | if (!priv->enter_deep_sleep) { |
742 | lbs_pr_err("deep sleep feature is not implemented " | ||
743 | "for this interface driver\n"); | ||
744 | return -EINVAL; | ||
745 | } | ||
746 | |||
747 | if (priv->connect_status == LBS_CONNECTED) { | ||
748 | if ((priv->is_auto_deep_sleep_enabled) && | ||
749 | (vwrq->value == -1000)) { | ||
750 | lbs_exit_auto_deep_sleep(priv); | ||
751 | return 0; | ||
752 | } else { | ||
753 | lbs_pr_err("can't use deep sleep cmd in " | ||
754 | "connected state\n"); | ||
755 | return -EINVAL; | ||
756 | } | ||
757 | } | ||
758 | |||
759 | if ((vwrq->value < 0) && (vwrq->value != -1000)) { | ||
760 | lbs_pr_err("unknown option\n"); | ||
761 | return -EINVAL; | ||
762 | } | ||
763 | |||
764 | if (vwrq->value > 0) { | ||
765 | if (!priv->is_auto_deep_sleep_enabled) { | ||
766 | priv->is_activity_detected = 0; | ||
767 | priv->auto_deep_sleep_timeout = vwrq->value; | ||
768 | lbs_enter_auto_deep_sleep(priv); | ||
769 | } else { | ||
770 | priv->auto_deep_sleep_timeout = vwrq->value; | ||
771 | lbs_deb_debugfs("auto deep sleep: " | ||
772 | "already enabled\n"); | ||
773 | } | ||
774 | return 0; | ||
775 | } else { | ||
776 | if (priv->is_auto_deep_sleep_enabled) { | ||
777 | lbs_exit_auto_deep_sleep(priv); | ||
778 | /* Try to exit deep sleep if auto */ | ||
779 | /*deep sleep disabled */ | ||
780 | ret = lbs_set_deep_sleep(priv, 0); | ||
781 | } | ||
782 | if (vwrq->value == 0) | ||
783 | ret = lbs_set_deep_sleep(priv, 1); | ||
784 | else if (vwrq->value == -1000) | ||
785 | ret = lbs_set_deep_sleep(priv, 0); | ||
786 | return ret; | ||
787 | } | ||
742 | } | 788 | } |
743 | 789 | ||
744 | if (priv->psmode != LBS802_11POWERMODECAM) { | 790 | if (priv->psmode != LBS802_11POWERMODECAM) { |
@@ -752,6 +798,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, | |||
752 | } | 798 | } |
753 | 799 | ||
754 | lbs_deb_leave(LBS_DEB_WEXT); | 800 | lbs_deb_leave(LBS_DEB_WEXT); |
801 | |||
755 | return 0; | 802 | return 0; |
756 | } | 803 | } |
757 | 804 | ||
@@ -1000,6 +1047,7 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, | |||
1000 | u8 rates[MAX_RATES + 1]; | 1047 | u8 rates[MAX_RATES + 1]; |
1001 | 1048 | ||
1002 | lbs_deb_enter(LBS_DEB_WEXT); | 1049 | lbs_deb_enter(LBS_DEB_WEXT); |
1050 | |||
1003 | lbs_deb_wext("vwrq->value %d\n", vwrq->value); | 1051 | lbs_deb_wext("vwrq->value %d\n", vwrq->value); |
1004 | lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); | 1052 | lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); |
1005 | 1053 | ||
diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig index 83b635fd7784..dce652054afd 100644 --- a/drivers/net/wireless/orinoco/Kconfig +++ b/drivers/net/wireless/orinoco/Kconfig | |||
@@ -1,8 +1,10 @@ | |||
1 | config HERMES | 1 | config HERMES |
2 | tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" | 2 | tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" |
3 | depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 | 3 | depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 |
4 | depends on CFG80211 | 4 | depends on CFG80211 && CFG80211_WEXT |
5 | select WIRELESS_EXT | 5 | select WIRELESS_EXT |
6 | select WEXT_SPY | ||
7 | select WEXT_PRIV | ||
6 | select FW_LOADER | 8 | select FW_LOADER |
7 | select CRYPTO | 9 | select CRYPTO |
8 | select CRYPTO_MICHAEL_MIC | 10 | select CRYPTO_MICHAEL_MIC |
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index 7a32bcb0c037..5fdc59c594f2 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c | |||
@@ -2225,6 +2225,7 @@ int orinoco_if_add(struct orinoco_private *priv, | |||
2225 | netif_carrier_off(dev); | 2225 | netif_carrier_off(dev); |
2226 | 2226 | ||
2227 | memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); | 2227 | memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); |
2228 | memcpy(dev->perm_addr, wiphy->perm_addr, ETH_ALEN); | ||
2228 | 2229 | ||
2229 | dev->base_addr = base_addr; | 2230 | dev->base_addr = base_addr; |
2230 | dev->irq = irq; | 2231 | dev->irq = irq; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_netlink.h b/drivers/net/wireless/wl12xx/wl1251_netlink.h deleted file mode 100644 index ee36695e134e..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_netlink.h +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | /* | ||
2 | * This file is part of wl1251 | ||
3 | * | ||
4 | * Copyright (C) 2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Kalle Valo <kalle.valo@nokia.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef __WL1251_NETLINK_H__ | ||
25 | #define __WL1251_NETLINK_H__ | ||
26 | |||
27 | int wl1251_nl_register(void); | ||
28 | void wl1251_nl_unregister(void); | ||
29 | |||
30 | #endif /* __WL1251_NETLINK_H__ */ | ||
diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig index 236e42725447..faf6c6087414 100644 --- a/drivers/staging/rtl8187se/Kconfig +++ b/drivers/staging/rtl8187se/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config RTL8187SE | 1 | config RTL8187SE |
2 | tristate "RealTek RTL8187SE Wireless LAN NIC driver" | 2 | tristate "RealTek RTL8187SE Wireless LAN NIC driver" |
3 | depends on PCI | 3 | depends on PCI |
4 | depends on WIRELESS_EXT | 4 | select WIRELESS_EXT |
5 | select WEXT_PRIV | ||
5 | default N | 6 | default N |
6 | ---help--- | 7 | ---help--- |
diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig index 3100aa58c940..5c077b9fdc77 100644 --- a/drivers/staging/rtl8192e/Kconfig +++ b/drivers/staging/rtl8192e/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config RTL8192E | 1 | config RTL8192E |
2 | tristate "RealTek RTL8192E Wireless LAN NIC driver" | 2 | tristate "RealTek RTL8192E Wireless LAN NIC driver" |
3 | depends on PCI | 3 | depends on PCI |
4 | depends on WIRELESS_EXT | 4 | select WIRELESS_EXT |
5 | select WEXT_PRIV | ||
5 | default N | 6 | default N |
6 | ---help--- | 7 | ---help--- |
diff --git a/drivers/staging/vt6655/Kconfig b/drivers/staging/vt6655/Kconfig index 9bec95adcce2..825bbc4fc3fa 100644 --- a/drivers/staging/vt6655/Kconfig +++ b/drivers/staging/vt6655/Kconfig | |||
@@ -1,6 +1,8 @@ | |||
1 | config VT6655 | 1 | config VT6655 |
2 | tristate "VIA Technologies VT6655 support" | 2 | tristate "VIA Technologies VT6655 support" |
3 | depends on WIRELESS_EXT && PCI | 3 | depends on PCI |
4 | select WIRELESS_EXT | ||
5 | select WEXT_PRIV | ||
4 | ---help--- | 6 | ---help--- |
5 | This is a vendor-written driver for VIA VT6655. | 7 | This is a vendor-written driver for VIA VT6655. |
6 | 8 | ||
diff --git a/drivers/staging/vt6656/Kconfig b/drivers/staging/vt6656/Kconfig index 3165f2c42079..87bcd269310c 100644 --- a/drivers/staging/vt6656/Kconfig +++ b/drivers/staging/vt6656/Kconfig | |||
@@ -1,6 +1,8 @@ | |||
1 | config VT6656 | 1 | config VT6656 |
2 | tristate "VIA Technologies VT6656 support" | 2 | tristate "VIA Technologies VT6656 support" |
3 | depends on WIRELESS_EXT && USB | 3 | depends on USB |
4 | select WIRELESS_EXT | ||
5 | select WEXT_PRIV | ||
4 | ---help--- | 6 | ---help--- |
5 | This is a vendor-written driver for VIA VT6656. | 7 | This is a vendor-written driver for VIA VT6656. |
6 | 8 | ||
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index a8d71ed43a0e..50afca3dcff1 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -1277,6 +1277,7 @@ enum nl80211_channel_type { | |||
1277 | * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon | 1277 | * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon |
1278 | * in unspecified units, scaled to 0..100 (u8) | 1278 | * in unspecified units, scaled to 0..100 (u8) |
1279 | * @NL80211_BSS_STATUS: status, if this BSS is "used" | 1279 | * @NL80211_BSS_STATUS: status, if this BSS is "used" |
1280 | * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms | ||
1280 | * @__NL80211_BSS_AFTER_LAST: internal | 1281 | * @__NL80211_BSS_AFTER_LAST: internal |
1281 | * @NL80211_BSS_MAX: highest BSS attribute | 1282 | * @NL80211_BSS_MAX: highest BSS attribute |
1282 | */ | 1283 | */ |
@@ -1291,6 +1292,7 @@ enum nl80211_bss { | |||
1291 | NL80211_BSS_SIGNAL_MBM, | 1292 | NL80211_BSS_SIGNAL_MBM, |
1292 | NL80211_BSS_SIGNAL_UNSPEC, | 1293 | NL80211_BSS_SIGNAL_UNSPEC, |
1293 | NL80211_BSS_STATUS, | 1294 | NL80211_BSS_STATUS, |
1295 | NL80211_BSS_SEEN_MS_AGO, | ||
1294 | 1296 | ||
1295 | /* keep last */ | 1297 | /* keep last */ |
1296 | __NL80211_BSS_AFTER_LAST, | 1298 | __NL80211_BSS_AFTER_LAST, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3d874c620219..6f4862b3ec2c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1142,6 +1142,9 @@ struct wiphy { | |||
1142 | u32 frag_threshold; | 1142 | u32 frag_threshold; |
1143 | u32 rts_threshold; | 1143 | u32 rts_threshold; |
1144 | 1144 | ||
1145 | char fw_version[ETHTOOL_BUSINFO_LEN]; | ||
1146 | u32 hw_version; | ||
1147 | |||
1145 | /* If multiple wiphys are registered and you're handed e.g. | 1148 | /* If multiple wiphys are registered and you're handed e.g. |
1146 | * a regular netdev with assigned ieee80211_ptr, you won't | 1149 | * a regular netdev with assigned ieee80211_ptr, you won't |
1147 | * know whether it points to a wiphy your driver has registered | 1150 | * know whether it points to a wiphy your driver has registered |
@@ -1171,6 +1174,10 @@ struct wiphy { | |||
1171 | struct net *_net; | 1174 | struct net *_net; |
1172 | #endif | 1175 | #endif |
1173 | 1176 | ||
1177 | #ifdef CONFIG_CFG80211_WEXT | ||
1178 | const struct iw_handler_def *wext; | ||
1179 | #endif | ||
1180 | |||
1174 | char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); | 1181 | char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); |
1175 | }; | 1182 | }; |
1176 | 1183 | ||
@@ -1345,7 +1352,7 @@ struct wireless_dev { | |||
1345 | struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES]; | 1352 | struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES]; |
1346 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ | 1353 | struct cfg80211_internal_bss *current_bss; /* associated / joined */ |
1347 | 1354 | ||
1348 | #ifdef CONFIG_WIRELESS_EXT | 1355 | #ifdef CONFIG_CFG80211_WEXT |
1349 | /* wext data */ | 1356 | /* wext data */ |
1350 | struct { | 1357 | struct { |
1351 | struct cfg80211_ibss_params ibss; | 1358 | struct cfg80211_ibss_params ibss; |
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h index e9054a283fde..d5d337170a56 100644 --- a/include/net/iw_handler.h +++ b/include/net/iw_handler.h | |||
@@ -323,18 +323,19 @@ typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info, | |||
323 | */ | 323 | */ |
324 | struct iw_handler_def | 324 | struct iw_handler_def |
325 | { | 325 | { |
326 | /* Number of handlers defined (more precisely, index of the | ||
327 | * last defined handler + 1) */ | ||
328 | __u16 num_standard; | ||
329 | __u16 num_private; | ||
330 | /* Number of private arg description */ | ||
331 | __u16 num_private_args; | ||
332 | 326 | ||
333 | /* Array of handlers for standard ioctls | 327 | /* Array of handlers for standard ioctls |
334 | * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT] | 328 | * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWCOMMIT] |
335 | */ | 329 | */ |
336 | const iw_handler * standard; | 330 | const iw_handler * standard; |
331 | /* Number of handlers defined (more precisely, index of the | ||
332 | * last defined handler + 1) */ | ||
333 | __u16 num_standard; | ||
337 | 334 | ||
335 | #ifdef CONFIG_WEXT_PRIV | ||
336 | __u16 num_private; | ||
337 | /* Number of private arg description */ | ||
338 | __u16 num_private_args; | ||
338 | /* Array of handlers for private ioctls | 339 | /* Array of handlers for private ioctls |
339 | * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV] | 340 | * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV] |
340 | */ | 341 | */ |
@@ -344,6 +345,7 @@ struct iw_handler_def | |||
344 | * can put it in any order you want and should not leave holes... | 345 | * can put it in any order you want and should not leave holes... |
345 | * We will automatically export that to user space... */ | 346 | * We will automatically export that to user space... */ |
346 | const struct iw_priv_args * private_args; | 347 | const struct iw_priv_args * private_args; |
348 | #endif | ||
347 | 349 | ||
348 | /* New location of get_wireless_stats, to de-bloat struct net_device. | 350 | /* New location of get_wireless_stats, to de-bloat struct net_device. |
349 | * The old pointer in struct net_device will be gradually phased | 351 | * The old pointer in struct net_device will be gradually phased |
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index a1202841aadd..699410142bfa 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h | |||
@@ -80,7 +80,7 @@ struct net { | |||
80 | #ifdef CONFIG_XFRM | 80 | #ifdef CONFIG_XFRM |
81 | struct netns_xfrm xfrm; | 81 | struct netns_xfrm xfrm; |
82 | #endif | 82 | #endif |
83 | #ifdef CONFIG_WIRELESS_EXT | 83 | #ifdef CONFIG_WEXT_CORE |
84 | struct sk_buff_head wext_nlevents; | 84 | struct sk_buff_head wext_nlevents; |
85 | #endif | 85 | #endif |
86 | struct net_generic *gen; | 86 | struct net_generic *gen; |
diff --git a/include/net/wext.h b/include/net/wext.h index 3f2b94de2cfa..4f6e7423174c 100644 --- a/include/net/wext.h +++ b/include/net/wext.h | |||
@@ -1,29 +1,19 @@ | |||
1 | #ifndef __NET_WEXT_H | 1 | #ifndef __NET_WEXT_H |
2 | #define __NET_WEXT_H | 2 | #define __NET_WEXT_H |
3 | 3 | ||
4 | /* | 4 | #include <net/iw_handler.h> |
5 | * wireless extensions interface to the core code | ||
6 | */ | ||
7 | 5 | ||
8 | struct net; | 6 | struct net; |
9 | 7 | ||
10 | #ifdef CONFIG_WIRELESS_EXT | 8 | #ifdef CONFIG_WEXT_CORE |
11 | extern int wext_proc_init(struct net *net); | ||
12 | extern void wext_proc_exit(struct net *net); | ||
13 | extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | 9 | extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, |
14 | void __user *arg); | 10 | void __user *arg); |
15 | extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | 11 | extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, |
16 | unsigned long arg); | 12 | unsigned long arg); |
13 | |||
17 | extern struct iw_statistics *get_wireless_stats(struct net_device *dev); | 14 | extern struct iw_statistics *get_wireless_stats(struct net_device *dev); |
15 | extern int call_commit_handler(struct net_device *dev); | ||
18 | #else | 16 | #else |
19 | static inline int wext_proc_init(struct net *net) | ||
20 | { | ||
21 | return 0; | ||
22 | } | ||
23 | static inline void wext_proc_exit(struct net *net) | ||
24 | { | ||
25 | return; | ||
26 | } | ||
27 | static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | 17 | static inline int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, |
28 | void __user *arg) | 18 | void __user *arg) |
29 | { | 19 | { |
@@ -36,4 +26,35 @@ static inline int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | |||
36 | } | 26 | } |
37 | #endif | 27 | #endif |
38 | 28 | ||
29 | #ifdef CONFIG_WEXT_PROC | ||
30 | extern int wext_proc_init(struct net *net); | ||
31 | extern void wext_proc_exit(struct net *net); | ||
32 | #else | ||
33 | static inline int wext_proc_init(struct net *net) | ||
34 | { | ||
35 | return 0; | ||
36 | } | ||
37 | static inline void wext_proc_exit(struct net *net) | ||
38 | { | ||
39 | return; | ||
40 | } | ||
41 | #endif | ||
42 | |||
43 | #ifdef CONFIG_WEXT_PRIV | ||
44 | int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, | ||
45 | unsigned int cmd, struct iw_request_info *info, | ||
46 | iw_handler handler); | ||
47 | int compat_private_call(struct net_device *dev, struct iwreq *iwr, | ||
48 | unsigned int cmd, struct iw_request_info *info, | ||
49 | iw_handler handler); | ||
50 | int iw_handler_get_private(struct net_device * dev, | ||
51 | struct iw_request_info * info, | ||
52 | union iwreq_data * wrqu, | ||
53 | char * extra); | ||
54 | #else | ||
55 | #define ioctl_private_call NULL | ||
56 | #define compat_private_call NULL | ||
57 | #endif | ||
58 | |||
59 | |||
39 | #endif /* __NET_WEXT_H */ | 60 | #endif /* __NET_WEXT_H */ |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 4242e94ff1a5..753c420060df 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -543,8 +543,12 @@ int netdev_register_kobject(struct net_device *net) | |||
543 | *groups++ = &netstat_group; | 543 | *groups++ = &netstat_group; |
544 | 544 | ||
545 | #ifdef CONFIG_WIRELESS_EXT_SYSFS | 545 | #ifdef CONFIG_WIRELESS_EXT_SYSFS |
546 | if (net->wireless_handlers || net->ieee80211_ptr) | 546 | if (net->ieee80211_ptr) |
547 | *groups++ = &wireless_group; | 547 | *groups++ = &wireless_group; |
548 | #ifdef CONFIG_WIRELESS_EXT | ||
549 | else if (net->wireless_handlers) | ||
550 | *groups++ = &wireless_group; | ||
551 | #endif | ||
548 | #endif | 552 | #endif |
549 | #endif /* CONFIG_SYSFS */ | 553 | #endif /* CONFIG_SYSFS */ |
550 | 554 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index f6005adcbf90..87aff1d923ba 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -184,10 +184,12 @@ static int ieee80211_open(struct net_device *dev) | |||
184 | * No need to check netif_running since we do not allow | 184 | * No need to check netif_running since we do not allow |
185 | * it to start up with this invalid address. | 185 | * it to start up with this invalid address. |
186 | */ | 186 | */ |
187 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) | 187 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { |
188 | memcpy(ndev->dev_addr, | 188 | memcpy(ndev->dev_addr, |
189 | local->hw.wiphy->perm_addr, | 189 | local->hw.wiphy->perm_addr, |
190 | ETH_ALEN); | 190 | ETH_ALEN); |
191 | memcpy(ndev->perm_addr, ndev->dev_addr, ETH_ALEN); | ||
192 | } | ||
191 | } | 193 | } |
192 | 194 | ||
193 | /* | 195 | /* |
@@ -784,6 +786,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
784 | goto fail; | 786 | goto fail; |
785 | 787 | ||
786 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | 788 | memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); |
789 | memcpy(ndev->perm_addr, ndev->dev_addr, ETH_ALEN); | ||
787 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | 790 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); |
788 | 791 | ||
789 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 792 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ |
diff --git a/net/socket.c b/net/socket.c index d53ad11558c3..954f3381cc8a 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -905,11 +905,11 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
905 | if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { | 905 | if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) { |
906 | err = dev_ioctl(net, cmd, argp); | 906 | err = dev_ioctl(net, cmd, argp); |
907 | } else | 907 | } else |
908 | #ifdef CONFIG_WIRELESS_EXT | 908 | #ifdef CONFIG_WEXT_CORE |
909 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { | 909 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { |
910 | err = dev_ioctl(net, cmd, argp); | 910 | err = dev_ioctl(net, cmd, argp); |
911 | } else | 911 | } else |
912 | #endif /* CONFIG_WIRELESS_EXT */ | 912 | #endif |
913 | switch (cmd) { | 913 | switch (cmd) { |
914 | case FIOSETOWN: | 914 | case FIOSETOWN: |
915 | case SIOCSPGRP: | 915 | case SIOCSPGRP: |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index abf7ca3f9ff9..614bdcec1c80 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -1,3 +1,21 @@ | |||
1 | config WIRELESS_EXT | ||
2 | bool | ||
3 | |||
4 | config WEXT_CORE | ||
5 | def_bool y | ||
6 | depends on CFG80211_WEXT || WIRELESS_EXT | ||
7 | |||
8 | config WEXT_PROC | ||
9 | def_bool y | ||
10 | depends on PROC_FS | ||
11 | depends on WEXT_CORE | ||
12 | |||
13 | config WEXT_SPY | ||
14 | bool | ||
15 | |||
16 | config WEXT_PRIV | ||
17 | bool | ||
18 | |||
1 | config CFG80211 | 19 | config CFG80211 |
2 | tristate "cfg80211 - wireless configuration API" | 20 | tristate "cfg80211 - wireless configuration API" |
3 | depends on RFKILL || !RFKILL | 21 | depends on RFKILL || !RFKILL |
@@ -56,6 +74,12 @@ config CFG80211_REG_DEBUG | |||
56 | 74 | ||
57 | If unsure, say N. | 75 | If unsure, say N. |
58 | 76 | ||
77 | config CFG80211_DEFAULT_PS_VALUE | ||
78 | int | ||
79 | default 1 if CFG80211_DEFAULT_PS | ||
80 | default 0 | ||
81 | depends on CFG80211 | ||
82 | |||
59 | config CFG80211_DEFAULT_PS | 83 | config CFG80211_DEFAULT_PS |
60 | bool "enable powersave by default" | 84 | bool "enable powersave by default" |
61 | depends on CFG80211 | 85 | depends on CFG80211 |
@@ -67,14 +91,10 @@ config CFG80211_DEFAULT_PS | |||
67 | applications instead -- they need to register their network | 91 | applications instead -- they need to register their network |
68 | latency requirement, see Documentation/power/pm_qos_interface.txt. | 92 | latency requirement, see Documentation/power/pm_qos_interface.txt. |
69 | 93 | ||
70 | config CFG80211_DEFAULT_PS_VALUE | ||
71 | int | ||
72 | default 1 if CFG80211_DEFAULT_PS | ||
73 | default 0 | ||
74 | |||
75 | config CFG80211_DEBUGFS | 94 | config CFG80211_DEBUGFS |
76 | bool "cfg80211 DebugFS entries" | 95 | bool "cfg80211 DebugFS entries" |
77 | depends on CFG80211 && DEBUG_FS | 96 | depends on CFG80211 |
97 | depends on DEBUG_FS | ||
78 | ---help--- | 98 | ---help--- |
79 | You can enable this if you want to debugfs entries for cfg80211. | 99 | You can enable this if you want to debugfs entries for cfg80211. |
80 | 100 | ||
@@ -83,6 +103,7 @@ config CFG80211_DEBUGFS | |||
83 | config WIRELESS_OLD_REGULATORY | 103 | config WIRELESS_OLD_REGULATORY |
84 | bool "Old wireless static regulatory definitions" | 104 | bool "Old wireless static regulatory definitions" |
85 | default n | 105 | default n |
106 | depends on CFG80211 | ||
86 | ---help--- | 107 | ---help--- |
87 | This option enables the old static regulatory information | 108 | This option enables the old static regulatory information |
88 | and uses it within the new framework. This option is available | 109 | and uses it within the new framework. This option is available |
@@ -94,20 +115,19 @@ config WIRELESS_OLD_REGULATORY | |||
94 | 115 | ||
95 | Say N and if you say Y, please tell us why. The default is N. | 116 | Say N and if you say Y, please tell us why. The default is N. |
96 | 117 | ||
97 | config WIRELESS_EXT | 118 | config CFG80211_WEXT |
98 | bool "Wireless extensions" | 119 | bool "cfg80211 wireless extensions compatibility" |
120 | depends on CFG80211 | ||
121 | select WEXT_CORE | ||
99 | default y | 122 | default y |
100 | ---help--- | 123 | help |
101 | This option enables the legacy wireless extensions | 124 | Enable this option if you need old userspace for wireless |
102 | (wireless network interface configuration via ioctls.) | 125 | extensions with cfg80211-based drivers. |
103 | |||
104 | Say Y unless you've upgraded all your userspace to use | ||
105 | nl80211 instead of wireless extensions. | ||
106 | 126 | ||
107 | config WIRELESS_EXT_SYSFS | 127 | config WIRELESS_EXT_SYSFS |
108 | bool "Wireless extensions sysfs files" | 128 | bool "Wireless extensions sysfs files" |
109 | default y | 129 | default y |
110 | depends on WIRELESS_EXT && SYSFS | 130 | depends on WEXT_CORE && SYSFS |
111 | help | 131 | help |
112 | This option enables the deprecated wireless statistics | 132 | This option enables the deprecated wireless statistics |
113 | files in /sys/class/net/*/wireless/. The same information | 133 | files in /sys/class/net/*/wireless/. The same information |
diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 3ecaa9179977..f07c8dc7aab2 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile | |||
@@ -1,13 +1,17 @@ | |||
1 | obj-$(CONFIG_WIRELESS_EXT) += wext.o | ||
2 | obj-$(CONFIG_CFG80211) += cfg80211.o | 1 | obj-$(CONFIG_CFG80211) += cfg80211.o |
3 | obj-$(CONFIG_LIB80211) += lib80211.o | 2 | obj-$(CONFIG_LIB80211) += lib80211.o |
4 | obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o | 3 | obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o |
5 | obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o | 4 | obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o |
6 | obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o | 5 | obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o |
7 | 6 | ||
7 | obj-$(CONFIG_WEXT_CORE) += wext-core.o | ||
8 | obj-$(CONFIG_WEXT_PROC) += wext-proc.o | ||
9 | obj-$(CONFIG_WEXT_SPY) += wext-spy.o | ||
10 | obj-$(CONFIG_WEXT_PRIV) += wext-priv.o | ||
11 | |||
8 | cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o | 12 | cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o |
9 | cfg80211-y += mlme.o ibss.o sme.o chan.o | 13 | cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o |
10 | cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o | 14 | cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o |
11 | cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o | 15 | cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o |
12 | 16 | ||
13 | ccflags-y += -D__CHECK_ENDIAN__ | 17 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/net/wireless/core.c b/net/wireless/core.c index e6f02e98e5fd..07252967be9c 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "sysfs.h" | 21 | #include "sysfs.h" |
22 | #include "debugfs.h" | 22 | #include "debugfs.h" |
23 | #include "wext-compat.h" | 23 | #include "wext-compat.h" |
24 | #include "ethtool.h" | ||
24 | 25 | ||
25 | /* name for sysfs, %d is appended */ | 26 | /* name for sysfs, %d is appended */ |
26 | #define PHY_NAME "phy" | 27 | #define PHY_NAME "phy" |
@@ -358,6 +359,10 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
358 | INIT_LIST_HEAD(&rdev->bss_list); | 359 | INIT_LIST_HEAD(&rdev->bss_list); |
359 | INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); | 360 | INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); |
360 | 361 | ||
362 | #ifdef CONFIG_CFG80211_WEXT | ||
363 | rdev->wiphy.wext = &cfg80211_wext_handler; | ||
364 | #endif | ||
365 | |||
361 | device_initialize(&rdev->wiphy.dev); | 366 | device_initialize(&rdev->wiphy.dev); |
362 | rdev->wiphy.dev.class = &ieee80211_class; | 367 | rdev->wiphy.dev.class = &ieee80211_class; |
363 | rdev->wiphy.dev.platform_data = rdev; | 368 | rdev->wiphy.dev.platform_data = rdev; |
@@ -672,9 +677,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
672 | wdev->netdev = dev; | 677 | wdev->netdev = dev; |
673 | wdev->sme_state = CFG80211_SME_IDLE; | 678 | wdev->sme_state = CFG80211_SME_IDLE; |
674 | mutex_unlock(&rdev->devlist_mtx); | 679 | mutex_unlock(&rdev->devlist_mtx); |
675 | #ifdef CONFIG_WIRELESS_EXT | 680 | #ifdef CONFIG_CFG80211_WEXT |
676 | if (!dev->wireless_handlers) | ||
677 | dev->wireless_handlers = &cfg80211_wext_handler; | ||
678 | wdev->wext.default_key = -1; | 681 | wdev->wext.default_key = -1; |
679 | wdev->wext.default_mgmt_key = -1; | 682 | wdev->wext.default_mgmt_key = -1; |
680 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 683 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
@@ -688,6 +691,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
688 | wdev->wext.ps = false; | 691 | wdev->wext.ps = false; |
689 | } | 692 | } |
690 | #endif | 693 | #endif |
694 | if (!dev->ethtool_ops) | ||
695 | dev->ethtool_ops = &cfg80211_ethtool_ops; | ||
691 | break; | 696 | break; |
692 | case NETDEV_GOING_DOWN: | 697 | case NETDEV_GOING_DOWN: |
693 | switch (wdev->iftype) { | 698 | switch (wdev->iftype) { |
@@ -696,7 +701,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
696 | break; | 701 | break; |
697 | case NL80211_IFTYPE_STATION: | 702 | case NL80211_IFTYPE_STATION: |
698 | wdev_lock(wdev); | 703 | wdev_lock(wdev); |
699 | #ifdef CONFIG_WIRELESS_EXT | 704 | #ifdef CONFIG_CFG80211_WEXT |
700 | kfree(wdev->wext.ie); | 705 | kfree(wdev->wext.ie); |
701 | wdev->wext.ie = NULL; | 706 | wdev->wext.ie = NULL; |
702 | wdev->wext.ie_len = 0; | 707 | wdev->wext.ie_len = 0; |
@@ -728,7 +733,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
728 | mutex_unlock(&rdev->devlist_mtx); | 733 | mutex_unlock(&rdev->devlist_mtx); |
729 | dev_put(dev); | 734 | dev_put(dev); |
730 | } | 735 | } |
731 | #ifdef CONFIG_WIRELESS_EXT | 736 | #ifdef CONFIG_CFG80211_WEXT |
732 | cfg80211_lock_rdev(rdev); | 737 | cfg80211_lock_rdev(rdev); |
733 | mutex_lock(&rdev->devlist_mtx); | 738 | mutex_lock(&rdev->devlist_mtx); |
734 | wdev_lock(wdev); | 739 | wdev_lock(wdev); |
@@ -766,7 +771,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
766 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); | 771 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); |
767 | list_del_init(&wdev->list); | 772 | list_del_init(&wdev->list); |
768 | rdev->devlist_generation++; | 773 | rdev->devlist_generation++; |
769 | #ifdef CONFIG_WIRELESS_EXT | 774 | #ifdef CONFIG_CFG80211_WEXT |
770 | kfree(wdev->wext.keys); | 775 | kfree(wdev->wext.keys); |
771 | #endif | 776 | #endif |
772 | } | 777 | } |
diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c new file mode 100644 index 000000000000..ca4c825be93d --- /dev/null +++ b/net/wireless/ethtool.c | |||
@@ -0,0 +1,45 @@ | |||
1 | #include <linux/utsname.h> | ||
2 | #include <net/cfg80211.h> | ||
3 | #include "ethtool.h" | ||
4 | |||
5 | static void cfg80211_get_drvinfo(struct net_device *dev, | ||
6 | struct ethtool_drvinfo *info) | ||
7 | { | ||
8 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
9 | |||
10 | strlcpy(info->driver, wiphy_dev(wdev->wiphy)->driver->name, | ||
11 | sizeof(info->driver)); | ||
12 | |||
13 | strlcpy(info->version, init_utsname()->release, sizeof(info->version)); | ||
14 | |||
15 | if (wdev->wiphy->fw_version[0]) | ||
16 | strncpy(info->fw_version, wdev->wiphy->fw_version, | ||
17 | sizeof(info->fw_version)); | ||
18 | else | ||
19 | strncpy(info->fw_version, "N/A", sizeof(info->fw_version)); | ||
20 | |||
21 | strlcpy(info->bus_info, dev_name(wiphy_dev(wdev->wiphy)), | ||
22 | sizeof(info->bus_info)); | ||
23 | } | ||
24 | |||
25 | static int cfg80211_get_regs_len(struct net_device *dev) | ||
26 | { | ||
27 | /* For now, return 0... */ | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | static void cfg80211_get_regs(struct net_device *dev, struct ethtool_regs *regs, | ||
32 | void *data) | ||
33 | { | ||
34 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
35 | |||
36 | regs->version = wdev->wiphy->hw_version; | ||
37 | regs->len = 0; | ||
38 | } | ||
39 | |||
40 | const struct ethtool_ops cfg80211_ethtool_ops = { | ||
41 | .get_drvinfo = cfg80211_get_drvinfo, | ||
42 | .get_regs_len = cfg80211_get_regs_len, | ||
43 | .get_regs = cfg80211_get_regs, | ||
44 | .get_link = ethtool_op_get_link, | ||
45 | }; | ||
diff --git a/net/wireless/ethtool.h b/net/wireless/ethtool.h new file mode 100644 index 000000000000..695ecad20bd6 --- /dev/null +++ b/net/wireless/ethtool.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __CFG80211_ETHTOOL__ | ||
2 | #define __CFG80211_ETHTOOL__ | ||
3 | |||
4 | extern const struct ethtool_ops cfg80211_ethtool_ops; | ||
5 | |||
6 | #endif /* __CFG80211_ETHTOOL__ */ | ||
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index c88338911979..39b6d92e2828 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -15,7 +15,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | |||
15 | { | 15 | { |
16 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 16 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
17 | struct cfg80211_bss *bss; | 17 | struct cfg80211_bss *bss; |
18 | #ifdef CONFIG_WIRELESS_EXT | 18 | #ifdef CONFIG_CFG80211_WEXT |
19 | union iwreq_data wrqu; | 19 | union iwreq_data wrqu; |
20 | #endif | 20 | #endif |
21 | 21 | ||
@@ -44,7 +44,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | |||
44 | 44 | ||
45 | nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, | 45 | nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, |
46 | GFP_KERNEL); | 46 | GFP_KERNEL); |
47 | #ifdef CONFIG_WIRELESS_EXT | 47 | #ifdef CONFIG_CFG80211_WEXT |
48 | memset(&wrqu, 0, sizeof(wrqu)); | 48 | memset(&wrqu, 0, sizeof(wrqu)); |
49 | memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); | 49 | memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); |
50 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | 50 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); |
@@ -96,7 +96,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
96 | kfree(wdev->connect_keys); | 96 | kfree(wdev->connect_keys); |
97 | wdev->connect_keys = connkeys; | 97 | wdev->connect_keys = connkeys; |
98 | 98 | ||
99 | #ifdef CONFIG_WIRELESS_EXT | 99 | #ifdef CONFIG_CFG80211_WEXT |
100 | wdev->wext.ibss.channel = params->channel; | 100 | wdev->wext.ibss.channel = params->channel; |
101 | #endif | 101 | #endif |
102 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); | 102 | err = rdev->ops->join_ibss(&rdev->wiphy, dev, params); |
@@ -154,7 +154,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | |||
154 | 154 | ||
155 | wdev->current_bss = NULL; | 155 | wdev->current_bss = NULL; |
156 | wdev->ssid_len = 0; | 156 | wdev->ssid_len = 0; |
157 | #ifdef CONFIG_WIRELESS_EXT | 157 | #ifdef CONFIG_CFG80211_WEXT |
158 | if (!nowext) | 158 | if (!nowext) |
159 | wdev->wext.ibss.ssid_len = 0; | 159 | wdev->wext.ibss.ssid_len = 0; |
160 | #endif | 160 | #endif |
@@ -203,7 +203,7 @@ int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | |||
203 | return err; | 203 | return err; |
204 | } | 204 | } |
205 | 205 | ||
206 | #ifdef CONFIG_WIRELESS_EXT | 206 | #ifdef CONFIG_CFG80211_WEXT |
207 | int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | 207 | int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, |
208 | struct wireless_dev *wdev) | 208 | struct wireless_dev *wdev) |
209 | { | 209 | { |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 79d2eec54cec..ceb2c14c8f47 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -331,7 +331,7 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, | |||
331 | { | 331 | { |
332 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | 332 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; |
333 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 333 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
334 | #ifdef CONFIG_WIRELESS_EXT | 334 | #ifdef CONFIG_CFG80211_WEXT |
335 | union iwreq_data wrqu; | 335 | union iwreq_data wrqu; |
336 | char *buf = kmalloc(128, gfp); | 336 | char *buf = kmalloc(128, gfp); |
337 | 337 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index eddab097435c..14004e2ebd62 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1264,7 +1264,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1264 | if (!err) | 1264 | if (!err) |
1265 | err = func(&rdev->wiphy, dev, key.idx); | 1265 | err = func(&rdev->wiphy, dev, key.idx); |
1266 | 1266 | ||
1267 | #ifdef CONFIG_WIRELESS_EXT | 1267 | #ifdef CONFIG_CFG80211_WEXT |
1268 | if (!err) { | 1268 | if (!err) { |
1269 | if (func == rdev->ops->set_default_key) | 1269 | if (func == rdev->ops->set_default_key) |
1270 | dev->ieee80211_ptr->wext.default_key = key.idx; | 1270 | dev->ieee80211_ptr->wext.default_key = key.idx; |
@@ -1365,7 +1365,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
1365 | if (!err) | 1365 | if (!err) |
1366 | err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); | 1366 | err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); |
1367 | 1367 | ||
1368 | #ifdef CONFIG_WIRELESS_EXT | 1368 | #ifdef CONFIG_CFG80211_WEXT |
1369 | if (!err) { | 1369 | if (!err) { |
1370 | if (key.idx == dev->ieee80211_ptr->wext.default_key) | 1370 | if (key.idx == dev->ieee80211_ptr->wext.default_key) |
1371 | dev->ieee80211_ptr->wext.default_key = -1; | 1371 | dev->ieee80211_ptr->wext.default_key = -1; |
@@ -3105,6 +3105,8 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
3105 | NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval); | 3105 | NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval); |
3106 | NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability); | 3106 | NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability); |
3107 | NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq); | 3107 | NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq); |
3108 | NLA_PUT_U32(msg, NL80211_BSS_SEEN_MS_AGO, | ||
3109 | jiffies_to_msecs(jiffies - intbss->ts)); | ||
3108 | 3110 | ||
3109 | switch (rdev->wiphy.signal_type) { | 3111 | switch (rdev->wiphy.signal_type) { |
3110 | case CFG80211_SIGNAL_TYPE_MBM: | 3112 | case CFG80211_SIGNAL_TYPE_MBM: |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e5f92ee758f4..2e8c515f3c5c 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -22,7 +22,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) | |||
22 | { | 22 | { |
23 | struct cfg80211_scan_request *request; | 23 | struct cfg80211_scan_request *request; |
24 | struct net_device *dev; | 24 | struct net_device *dev; |
25 | #ifdef CONFIG_WIRELESS_EXT | 25 | #ifdef CONFIG_CFG80211_WEXT |
26 | union iwreq_data wrqu; | 26 | union iwreq_data wrqu; |
27 | #endif | 27 | #endif |
28 | 28 | ||
@@ -47,7 +47,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) | |||
47 | else | 47 | else |
48 | nl80211_send_scan_done(rdev, dev); | 48 | nl80211_send_scan_done(rdev, dev); |
49 | 49 | ||
50 | #ifdef CONFIG_WIRELESS_EXT | 50 | #ifdef CONFIG_CFG80211_WEXT |
51 | if (!request->aborted) { | 51 | if (!request->aborted) { |
52 | memset(&wrqu, 0, sizeof(wrqu)); | 52 | memset(&wrqu, 0, sizeof(wrqu)); |
53 | 53 | ||
@@ -592,7 +592,7 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) | |||
592 | } | 592 | } |
593 | EXPORT_SYMBOL(cfg80211_unlink_bss); | 593 | EXPORT_SYMBOL(cfg80211_unlink_bss); |
594 | 594 | ||
595 | #ifdef CONFIG_WIRELESS_EXT | 595 | #ifdef CONFIG_CFG80211_WEXT |
596 | int cfg80211_wext_siwscan(struct net_device *dev, | 596 | int cfg80211_wext_siwscan(struct net_device *dev, |
597 | struct iw_request_info *info, | 597 | struct iw_request_info *info, |
598 | union iwreq_data *wrqu, char *extra) | 598 | union iwreq_data *wrqu, char *extra) |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 93c3ed329204..d3624152f7f7 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -345,7 +345,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
345 | { | 345 | { |
346 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 346 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
347 | u8 *country_ie; | 347 | u8 *country_ie; |
348 | #ifdef CONFIG_WIRELESS_EXT | 348 | #ifdef CONFIG_CFG80211_WEXT |
349 | union iwreq_data wrqu; | 349 | union iwreq_data wrqu; |
350 | #endif | 350 | #endif |
351 | 351 | ||
@@ -362,7 +362,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
362 | resp_ie, resp_ie_len, | 362 | resp_ie, resp_ie_len, |
363 | status, GFP_KERNEL); | 363 | status, GFP_KERNEL); |
364 | 364 | ||
365 | #ifdef CONFIG_WIRELESS_EXT | 365 | #ifdef CONFIG_CFG80211_WEXT |
366 | if (wextev) { | 366 | if (wextev) { |
367 | if (req_ie && status == WLAN_STATUS_SUCCESS) { | 367 | if (req_ie && status == WLAN_STATUS_SUCCESS) { |
368 | memset(&wrqu, 0, sizeof(wrqu)); | 368 | memset(&wrqu, 0, sizeof(wrqu)); |
@@ -477,7 +477,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, | |||
477 | const u8 *resp_ie, size_t resp_ie_len) | 477 | const u8 *resp_ie, size_t resp_ie_len) |
478 | { | 478 | { |
479 | struct cfg80211_bss *bss; | 479 | struct cfg80211_bss *bss; |
480 | #ifdef CONFIG_WIRELESS_EXT | 480 | #ifdef CONFIG_CFG80211_WEXT |
481 | union iwreq_data wrqu; | 481 | union iwreq_data wrqu; |
482 | #endif | 482 | #endif |
483 | 483 | ||
@@ -512,7 +512,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, | |||
512 | req_ie, req_ie_len, resp_ie, resp_ie_len, | 512 | req_ie, req_ie_len, resp_ie, resp_ie_len, |
513 | GFP_KERNEL); | 513 | GFP_KERNEL); |
514 | 514 | ||
515 | #ifdef CONFIG_WIRELESS_EXT | 515 | #ifdef CONFIG_CFG80211_WEXT |
516 | if (req_ie) { | 516 | if (req_ie) { |
517 | memset(&wrqu, 0, sizeof(wrqu)); | 517 | memset(&wrqu, 0, sizeof(wrqu)); |
518 | wrqu.data.length = req_ie_len; | 518 | wrqu.data.length = req_ie_len; |
@@ -573,7 +573,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
573 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 573 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
574 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 574 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
575 | int i; | 575 | int i; |
576 | #ifdef CONFIG_WIRELESS_EXT | 576 | #ifdef CONFIG_CFG80211_WEXT |
577 | union iwreq_data wrqu; | 577 | union iwreq_data wrqu; |
578 | #endif | 578 | #endif |
579 | 579 | ||
@@ -631,7 +631,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | |||
631 | for (i = 0; i < 6; i++) | 631 | for (i = 0; i < 6; i++) |
632 | rdev->ops->del_key(wdev->wiphy, dev, i, NULL); | 632 | rdev->ops->del_key(wdev->wiphy, dev, i, NULL); |
633 | 633 | ||
634 | #ifdef CONFIG_WIRELESS_EXT | 634 | #ifdef CONFIG_CFG80211_WEXT |
635 | memset(&wrqu, 0, sizeof(wrqu)); | 635 | memset(&wrqu, 0, sizeof(wrqu)); |
636 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 636 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
637 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | 637 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); |
diff --git a/net/wireless/wext.c b/net/wireless/wext-core.c index 60fe57761ca9..a4e5ddc8d4f5 100644 --- a/net/wireless/wext.c +++ b/net/wireless/wext-core.c | |||
@@ -1,112 +1,28 @@ | |||
1 | /* | 1 | /* |
2 | * This file implement the Wireless Extensions APIs. | 2 | * This file implement the Wireless Extensions core API. |
3 | * | 3 | * |
4 | * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> | 4 | * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> |
5 | * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. | 5 | * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. |
6 | * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> | ||
6 | * | 7 | * |
7 | * (As all part of the Linux kernel, this file is GPL) | 8 | * (As all part of the Linux kernel, this file is GPL) |
8 | */ | 9 | */ |
9 | 10 | #include <linux/kernel.h> | |
10 | /************************** DOCUMENTATION **************************/ | 11 | #include <linux/netdevice.h> |
11 | /* | 12 | #include <linux/rtnetlink.h> |
12 | * API definition : | 13 | #include <linux/wireless.h> |
13 | * -------------- | 14 | #include <linux/uaccess.h> |
14 | * See <linux/wireless.h> for details of the APIs and the rest. | 15 | #include <net/cfg80211.h> |
15 | * | 16 | #include <net/iw_handler.h> |
16 | * History : | ||
17 | * ------- | ||
18 | * | ||
19 | * v1 - 5.12.01 - Jean II | ||
20 | * o Created this file. | ||
21 | * | ||
22 | * v2 - 13.12.01 - Jean II | ||
23 | * o Move /proc/net/wireless stuff from net/core/dev.c to here | ||
24 | * o Make Wireless Extension IOCTLs go through here | ||
25 | * o Added iw_handler handling ;-) | ||
26 | * o Added standard ioctl description | ||
27 | * o Initial dumb commit strategy based on orinoco.c | ||
28 | * | ||
29 | * v3 - 19.12.01 - Jean II | ||
30 | * o Make sure we don't go out of standard_ioctl[] in ioctl_standard_call | ||
31 | * o Add event dispatcher function | ||
32 | * o Add event description | ||
33 | * o Propagate events as rtnetlink IFLA_WIRELESS option | ||
34 | * o Generate event on selected SET requests | ||
35 | * | ||
36 | * v4 - 18.04.02 - Jean II | ||
37 | * o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1 | ||
38 | * | ||
39 | * v5 - 21.06.02 - Jean II | ||
40 | * o Add IW_PRIV_TYPE_ADDR in priv_type_size (+cleanup) | ||
41 | * o Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes | ||
42 | * o Add IWEVCUSTOM for driver specific event/scanning token | ||
43 | * o Turn on WE_STRICT_WRITE by default + kernel warning | ||
44 | * o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num) | ||
45 | * o Fix off-by-one in test (extra_size <= IFNAMSIZ) | ||
46 | * | ||
47 | * v6 - 9.01.03 - Jean II | ||
48 | * o Add common spy support : iw_handler_set_spy(), wireless_spy_update() | ||
49 | * o Add enhanced spy support : iw_handler_set_thrspy() and event. | ||
50 | * o Add WIRELESS_EXT version display in /proc/net/wireless | ||
51 | * | ||
52 | * v6 - 18.06.04 - Jean II | ||
53 | * o Change get_spydata() method for added safety | ||
54 | * o Remove spy #ifdef, they are always on -> cleaner code | ||
55 | * o Allow any size GET request if user specifies length > max | ||
56 | * and if request has IW_DESCR_FLAG_NOMAX flag or is SIOCGIWPRIV | ||
57 | * o Start migrating get_wireless_stats to struct iw_handler_def | ||
58 | * o Add wmb() in iw_handler_set_spy() for non-coherent archs/cpus | ||
59 | * Based on patch from Pavel Roskin <proski@gnu.org> : | ||
60 | * o Fix kernel data leak to user space in private handler handling | ||
61 | * | ||
62 | * v7 - 18.3.05 - Jean II | ||
63 | * o Remove (struct iw_point *)->pointer from events and streams | ||
64 | * o Remove spy_offset from struct iw_handler_def | ||
65 | * o Start deprecating dev->get_wireless_stats, output a warning | ||
66 | * o If IW_QUAL_DBM is set, show dBm values in /proc/net/wireless | ||
67 | * o Don't lose INVALID/DBM flags when clearing UPDATED flags (iwstats) | ||
68 | * | ||
69 | * v8 - 17.02.06 - Jean II | ||
70 | * o RtNetlink requests support (SET/GET) | ||
71 | * | ||
72 | * v8b - 03.08.06 - Herbert Xu | ||
73 | * o Fix Wireless Event locking issues. | ||
74 | * | ||
75 | * v9 - 14.3.06 - Jean II | ||
76 | * o Change length in ESSID and NICK to strlen() instead of strlen()+1 | ||
77 | * o Make standard_ioctl_num and standard_event_num unsigned | ||
78 | * o Remove (struct net_device *)->get_wireless_stats() | ||
79 | * | ||
80 | * v10 - 16.3.07 - Jean II | ||
81 | * o Prevent leaking of kernel space in stream on 64 bits. | ||
82 | */ | ||
83 | |||
84 | /***************************** INCLUDES *****************************/ | ||
85 | |||
86 | #include <linux/module.h> | ||
87 | #include <linux/types.h> /* off_t */ | ||
88 | #include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */ | ||
89 | #include <linux/proc_fs.h> | ||
90 | #include <linux/rtnetlink.h> /* rtnetlink stuff */ | ||
91 | #include <linux/seq_file.h> | ||
92 | #include <linux/init.h> /* for __init */ | ||
93 | #include <linux/if_arp.h> /* ARPHRD_ETHER */ | ||
94 | #include <linux/etherdevice.h> /* compare_ether_addr */ | ||
95 | #include <linux/interrupt.h> | ||
96 | #include <net/net_namespace.h> | ||
97 | |||
98 | #include <linux/wireless.h> /* Pretty obvious */ | ||
99 | #include <net/iw_handler.h> /* New driver API */ | ||
100 | #include <net/netlink.h> | 17 | #include <net/netlink.h> |
101 | #include <net/wext.h> | 18 | #include <net/wext.h> |
19 | #include <net/net_namespace.h> | ||
20 | |||
21 | typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, | ||
22 | unsigned int, struct iw_request_info *, | ||
23 | iw_handler); | ||
102 | 24 | ||
103 | #include <asm/uaccess.h> /* copy_to_user() */ | ||
104 | 25 | ||
105 | /************************* GLOBAL VARIABLES *************************/ | ||
106 | /* | ||
107 | * You should not use global variables, because of re-entrancy. | ||
108 | * On our case, it's only const, so it's OK... | ||
109 | */ | ||
110 | /* | 26 | /* |
111 | * Meta-data about all the standard Wireless Extension request we | 27 | * Meta-data about all the standard Wireless Extension request we |
112 | * know about. | 28 | * know about. |
@@ -390,18 +306,6 @@ static const struct iw_ioctl_description standard_event[] = { | |||
390 | }; | 306 | }; |
391 | static const unsigned standard_event_num = ARRAY_SIZE(standard_event); | 307 | static const unsigned standard_event_num = ARRAY_SIZE(standard_event); |
392 | 308 | ||
393 | /* Size (in bytes) of the various private data types */ | ||
394 | static const char iw_priv_type_size[] = { | ||
395 | 0, /* IW_PRIV_TYPE_NONE */ | ||
396 | 1, /* IW_PRIV_TYPE_BYTE */ | ||
397 | 1, /* IW_PRIV_TYPE_CHAR */ | ||
398 | 0, /* Not defined */ | ||
399 | sizeof(__u32), /* IW_PRIV_TYPE_INT */ | ||
400 | sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ | ||
401 | sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ | ||
402 | 0, /* Not defined */ | ||
403 | }; | ||
404 | |||
405 | /* Size (in bytes) of various events */ | 309 | /* Size (in bytes) of various events */ |
406 | static const int event_type_size[] = { | 310 | static const int event_type_size[] = { |
407 | IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */ | 311 | IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */ |
@@ -433,323 +337,346 @@ static const int compat_event_type_size[] = { | |||
433 | }; | 337 | }; |
434 | #endif | 338 | #endif |
435 | 339 | ||
436 | /************************ COMMON SUBROUTINES ************************/ | ||
437 | /* | ||
438 | * Stuff that may be used in various place or doesn't fit in one | ||
439 | * of the section below. | ||
440 | */ | ||
441 | |||
442 | /* ---------------------------------------------------------------- */ | ||
443 | /* | ||
444 | * Return the driver handler associated with a specific Wireless Extension. | ||
445 | */ | ||
446 | static iw_handler get_handler(struct net_device *dev, unsigned int cmd) | ||
447 | { | ||
448 | /* Don't "optimise" the following variable, it will crash */ | ||
449 | unsigned int index; /* *MUST* be unsigned */ | ||
450 | 340 | ||
451 | /* Check if we have some wireless handlers defined */ | 341 | /* IW event code */ |
452 | if (dev->wireless_handlers == NULL) | ||
453 | return NULL; | ||
454 | |||
455 | /* Try as a standard command */ | ||
456 | index = cmd - SIOCIWFIRST; | ||
457 | if (index < dev->wireless_handlers->num_standard) | ||
458 | return dev->wireless_handlers->standard[index]; | ||
459 | |||
460 | /* Try as a private command */ | ||
461 | index = cmd - SIOCIWFIRSTPRIV; | ||
462 | if (index < dev->wireless_handlers->num_private) | ||
463 | return dev->wireless_handlers->private[index]; | ||
464 | 342 | ||
465 | /* Not found */ | 343 | static int __net_init wext_pernet_init(struct net *net) |
466 | return NULL; | ||
467 | } | ||
468 | |||
469 | /* ---------------------------------------------------------------- */ | ||
470 | /* | ||
471 | * Get statistics out of the driver | ||
472 | */ | ||
473 | struct iw_statistics *get_wireless_stats(struct net_device *dev) | ||
474 | { | 344 | { |
475 | /* New location */ | 345 | skb_queue_head_init(&net->wext_nlevents); |
476 | if ((dev->wireless_handlers != NULL) && | 346 | return 0; |
477 | (dev->wireless_handlers->get_wireless_stats != NULL)) | ||
478 | return dev->wireless_handlers->get_wireless_stats(dev); | ||
479 | |||
480 | /* Not found */ | ||
481 | return NULL; | ||
482 | } | 347 | } |
483 | 348 | ||
484 | /* ---------------------------------------------------------------- */ | 349 | static void __net_exit wext_pernet_exit(struct net *net) |
485 | /* | ||
486 | * Call the commit handler in the driver | ||
487 | * (if exist and if conditions are right) | ||
488 | * | ||
489 | * Note : our current commit strategy is currently pretty dumb, | ||
490 | * but we will be able to improve on that... | ||
491 | * The goal is to try to agreagate as many changes as possible | ||
492 | * before doing the commit. Drivers that will define a commit handler | ||
493 | * are usually those that need a reset after changing parameters, so | ||
494 | * we want to minimise the number of reset. | ||
495 | * A cool idea is to use a timer : at each "set" command, we re-set the | ||
496 | * timer, when the timer eventually fires, we call the driver. | ||
497 | * Hopefully, more on that later. | ||
498 | * | ||
499 | * Also, I'm waiting to see how many people will complain about the | ||
500 | * netif_running(dev) test. I'm open on that one... | ||
501 | * Hopefully, the driver will remember to do a commit in "open()" ;-) | ||
502 | */ | ||
503 | static int call_commit_handler(struct net_device *dev) | ||
504 | { | 350 | { |
505 | if ((netif_running(dev)) && | 351 | skb_queue_purge(&net->wext_nlevents); |
506 | (dev->wireless_handlers->standard[0] != NULL)) | ||
507 | /* Call the commit handler on the driver */ | ||
508 | return dev->wireless_handlers->standard[0](dev, NULL, | ||
509 | NULL, NULL); | ||
510 | else | ||
511 | return 0; /* Command completed successfully */ | ||
512 | } | 352 | } |
513 | 353 | ||
514 | /* ---------------------------------------------------------------- */ | 354 | static struct pernet_operations wext_pernet_ops = { |
515 | /* | 355 | .init = wext_pernet_init, |
516 | * Calculate size of private arguments | 356 | .exit = wext_pernet_exit, |
517 | */ | 357 | }; |
518 | static int get_priv_size(__u16 args) | ||
519 | { | ||
520 | int num = args & IW_PRIV_SIZE_MASK; | ||
521 | int type = (args & IW_PRIV_TYPE_MASK) >> 12; | ||
522 | 358 | ||
523 | return num * iw_priv_type_size[type]; | 359 | static int __init wireless_nlevent_init(void) |
360 | { | ||
361 | return register_pernet_subsys(&wext_pernet_ops); | ||
524 | } | 362 | } |
525 | 363 | ||
526 | /* ---------------------------------------------------------------- */ | 364 | subsys_initcall(wireless_nlevent_init); |
527 | /* | 365 | |
528 | * Re-calculate the size of private arguments | 366 | /* Process events generated by the wireless layer or the driver. */ |
529 | */ | 367 | static void wireless_nlevent_process(struct work_struct *work) |
530 | static int adjust_priv_size(__u16 args, struct iw_point *iwp) | ||
531 | { | 368 | { |
532 | int num = iwp->length; | 369 | struct sk_buff *skb; |
533 | int max = args & IW_PRIV_SIZE_MASK; | 370 | struct net *net; |
534 | int type = (args & IW_PRIV_TYPE_MASK) >> 12; | ||
535 | 371 | ||
536 | /* Make sure the driver doesn't goof up */ | 372 | rtnl_lock(); |
537 | if (max < num) | 373 | |
538 | num = max; | 374 | for_each_net(net) { |
375 | while ((skb = skb_dequeue(&net->wext_nlevents))) | ||
376 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, | ||
377 | GFP_KERNEL); | ||
378 | } | ||
539 | 379 | ||
540 | return num * iw_priv_type_size[type]; | 380 | rtnl_unlock(); |
541 | } | 381 | } |
542 | 382 | ||
543 | /* ---------------------------------------------------------------- */ | 383 | static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process); |
544 | /* | 384 | |
545 | * Standard Wireless Handler : get wireless stats | 385 | static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev, |
546 | * Allow programatic access to /proc/net/wireless even if /proc | 386 | struct sk_buff *skb) |
547 | * doesn't exist... Also more efficient... | ||
548 | */ | ||
549 | static int iw_handler_get_iwstats(struct net_device * dev, | ||
550 | struct iw_request_info * info, | ||
551 | union iwreq_data * wrqu, | ||
552 | char * extra) | ||
553 | { | 387 | { |
554 | /* Get stats from the driver */ | 388 | struct ifinfomsg *r; |
555 | struct iw_statistics *stats; | 389 | struct nlmsghdr *nlh; |
556 | 390 | ||
557 | stats = get_wireless_stats(dev); | 391 | nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0); |
558 | if (stats) { | 392 | if (!nlh) |
559 | /* Copy statistics to extra */ | 393 | return NULL; |
560 | memcpy(extra, stats, sizeof(struct iw_statistics)); | ||
561 | wrqu->data.length = sizeof(struct iw_statistics); | ||
562 | 394 | ||
563 | /* Check if we need to clear the updated flag */ | 395 | r = nlmsg_data(nlh); |
564 | if (wrqu->data.flags != 0) | 396 | r->ifi_family = AF_UNSPEC; |
565 | stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; | 397 | r->__ifi_pad = 0; |
566 | return 0; | 398 | r->ifi_type = dev->type; |
567 | } else | 399 | r->ifi_index = dev->ifindex; |
568 | return -EOPNOTSUPP; | 400 | r->ifi_flags = dev_get_flags(dev); |
401 | r->ifi_change = 0; /* Wireless changes don't affect those flags */ | ||
402 | |||
403 | NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); | ||
404 | |||
405 | return nlh; | ||
406 | nla_put_failure: | ||
407 | nlmsg_cancel(skb, nlh); | ||
408 | return NULL; | ||
569 | } | 409 | } |
570 | 410 | ||
571 | /* ---------------------------------------------------------------- */ | 411 | |
572 | /* | 412 | /* |
573 | * Standard Wireless Handler : get iwpriv definitions | 413 | * Main event dispatcher. Called from other parts and drivers. |
574 | * Export the driver private handler definition | 414 | * Send the event on the appropriate channels. |
575 | * They will be picked up by tools like iwpriv... | 415 | * May be called from interrupt context. |
576 | */ | 416 | */ |
577 | static int iw_handler_get_private(struct net_device * dev, | 417 | void wireless_send_event(struct net_device * dev, |
578 | struct iw_request_info * info, | 418 | unsigned int cmd, |
579 | union iwreq_data * wrqu, | 419 | union iwreq_data * wrqu, |
580 | char * extra) | 420 | const char * extra) |
581 | { | 421 | { |
582 | /* Check if the driver has something to export */ | 422 | const struct iw_ioctl_description * descr = NULL; |
583 | if ((dev->wireless_handlers->num_private_args == 0) || | 423 | int extra_len = 0; |
584 | (dev->wireless_handlers->private_args == NULL)) | 424 | struct iw_event *event; /* Mallocated whole event */ |
585 | return -EOPNOTSUPP; | 425 | int event_len; /* Its size */ |
426 | int hdr_len; /* Size of the event header */ | ||
427 | int wrqu_off = 0; /* Offset in wrqu */ | ||
428 | /* Don't "optimise" the following variable, it will crash */ | ||
429 | unsigned cmd_index; /* *MUST* be unsigned */ | ||
430 | struct sk_buff *skb; | ||
431 | struct nlmsghdr *nlh; | ||
432 | struct nlattr *nla; | ||
433 | #ifdef CONFIG_COMPAT | ||
434 | struct __compat_iw_event *compat_event; | ||
435 | struct compat_iw_point compat_wrqu; | ||
436 | struct sk_buff *compskb; | ||
437 | #endif | ||
586 | 438 | ||
587 | /* Check if there is enough buffer up there */ | 439 | /* |
588 | if (wrqu->data.length < dev->wireless_handlers->num_private_args) { | 440 | * Nothing in the kernel sends scan events with data, be safe. |
589 | /* User space can't know in advance how large the buffer | 441 | * This is necessary because we cannot fix up scan event data |
590 | * needs to be. Give it a hint, so that we can support | 442 | * for compat, due to being contained in 'extra', but normally |
591 | * any size buffer we want somewhat efficiently... */ | 443 | * applications are required to retrieve the scan data anyway |
592 | wrqu->data.length = dev->wireless_handlers->num_private_args; | 444 | * and no data is included in the event, this codifies that |
593 | return -E2BIG; | 445 | * practice. |
446 | */ | ||
447 | if (WARN_ON(cmd == SIOCGIWSCAN && extra)) | ||
448 | extra = NULL; | ||
449 | |||
450 | /* Get the description of the Event */ | ||
451 | if (cmd <= SIOCIWLAST) { | ||
452 | cmd_index = cmd - SIOCIWFIRST; | ||
453 | if (cmd_index < standard_ioctl_num) | ||
454 | descr = &(standard_ioctl[cmd_index]); | ||
455 | } else { | ||
456 | cmd_index = cmd - IWEVFIRST; | ||
457 | if (cmd_index < standard_event_num) | ||
458 | descr = &(standard_event[cmd_index]); | ||
459 | } | ||
460 | /* Don't accept unknown events */ | ||
461 | if (descr == NULL) { | ||
462 | /* Note : we don't return an error to the driver, because | ||
463 | * the driver would not know what to do about it. It can't | ||
464 | * return an error to the user, because the event is not | ||
465 | * initiated by a user request. | ||
466 | * The best the driver could do is to log an error message. | ||
467 | * We will do it ourselves instead... | ||
468 | */ | ||
469 | printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n", | ||
470 | dev->name, cmd); | ||
471 | return; | ||
594 | } | 472 | } |
595 | 473 | ||
596 | /* Set the number of available ioctls. */ | 474 | /* Check extra parameters and set extra_len */ |
597 | wrqu->data.length = dev->wireless_handlers->num_private_args; | 475 | if (descr->header_type == IW_HEADER_TYPE_POINT) { |
476 | /* Check if number of token fits within bounds */ | ||
477 | if (wrqu->data.length > descr->max_tokens) { | ||
478 | printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length); | ||
479 | return; | ||
480 | } | ||
481 | if (wrqu->data.length < descr->min_tokens) { | ||
482 | printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length); | ||
483 | return; | ||
484 | } | ||
485 | /* Calculate extra_len - extra is NULL for restricted events */ | ||
486 | if (extra != NULL) | ||
487 | extra_len = wrqu->data.length * descr->token_size; | ||
488 | /* Always at an offset in wrqu */ | ||
489 | wrqu_off = IW_EV_POINT_OFF; | ||
490 | } | ||
598 | 491 | ||
599 | /* Copy structure to the user buffer. */ | 492 | /* Total length of the event */ |
600 | memcpy(extra, dev->wireless_handlers->private_args, | 493 | hdr_len = event_type_size[descr->header_type]; |
601 | sizeof(struct iw_priv_args) * wrqu->data.length); | 494 | event_len = hdr_len + extra_len; |
602 | 495 | ||
603 | return 0; | 496 | /* |
604 | } | 497 | * The problem for 64/32 bit. |
498 | * | ||
499 | * On 64-bit, a regular event is laid out as follows: | ||
500 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | ||
501 | * | event.len | event.cmd | p a d d i n g | | ||
502 | * | wrqu data ... (with the correct size) | | ||
503 | * | ||
504 | * This padding exists because we manipulate event->u, | ||
505 | * and 'event' is not packed. | ||
506 | * | ||
507 | * An iw_point event is laid out like this instead: | ||
508 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | ||
509 | * | event.len | event.cmd | p a d d i n g | | ||
510 | * | iwpnt.len | iwpnt.flg | p a d d i n g | | ||
511 | * | extra data ... | ||
512 | * | ||
513 | * The second padding exists because struct iw_point is extended, | ||
514 | * but this depends on the platform... | ||
515 | * | ||
516 | * On 32-bit, all the padding shouldn't be there. | ||
517 | */ | ||
605 | 518 | ||
519 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); | ||
520 | if (!skb) | ||
521 | return; | ||
606 | 522 | ||
607 | /******************** /proc/net/wireless SUPPORT ********************/ | 523 | /* Send via the RtNetlink event channel */ |
608 | /* | 524 | nlh = rtnetlink_ifinfo_prep(dev, skb); |
609 | * The /proc/net/wireless file is a human readable user-space interface | 525 | if (WARN_ON(!nlh)) { |
610 | * exporting various wireless specific statistics from the wireless devices. | 526 | kfree_skb(skb); |
611 | * This is the most popular part of the Wireless Extensions ;-) | 527 | return; |
612 | * | 528 | } |
613 | * This interface is a pure clone of /proc/net/dev (in net/core/dev.c). | ||
614 | * The content of the file is basically the content of "struct iw_statistics". | ||
615 | */ | ||
616 | 529 | ||
617 | #ifdef CONFIG_PROC_FS | 530 | /* Add the wireless events in the netlink packet */ |
531 | nla = nla_reserve(skb, IFLA_WIRELESS, event_len); | ||
532 | if (!nla) { | ||
533 | kfree_skb(skb); | ||
534 | return; | ||
535 | } | ||
536 | event = nla_data(nla); | ||
618 | 537 | ||
619 | /* ---------------------------------------------------------------- */ | 538 | /* Fill event - first clear to avoid data leaking */ |
620 | /* | 539 | memset(event, 0, hdr_len); |
621 | * Print one entry (line) of /proc/net/wireless | 540 | event->len = event_len; |
622 | */ | 541 | event->cmd = cmd; |
623 | static void wireless_seq_printf_stats(struct seq_file *seq, | 542 | memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN); |
624 | struct net_device *dev) | 543 | if (extra_len) |
625 | { | 544 | memcpy(((char *) event) + hdr_len, extra, extra_len); |
626 | /* Get stats from the driver */ | ||
627 | struct iw_statistics *stats = get_wireless_stats(dev); | ||
628 | static struct iw_statistics nullstats = {}; | ||
629 | 545 | ||
630 | /* show device if it's wireless regardless of current stats */ | 546 | nlmsg_end(skb, nlh); |
631 | if (!stats && dev->wireless_handlers) | 547 | #ifdef CONFIG_COMPAT |
632 | stats = &nullstats; | 548 | hdr_len = compat_event_type_size[descr->header_type]; |
549 | event_len = hdr_len + extra_len; | ||
633 | 550 | ||
634 | if (stats) { | 551 | compskb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
635 | seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d " | 552 | if (!compskb) { |
636 | "%6d %6d %6d\n", | 553 | kfree_skb(skb); |
637 | dev->name, stats->status, stats->qual.qual, | 554 | return; |
638 | stats->qual.updated & IW_QUAL_QUAL_UPDATED | ||
639 | ? '.' : ' ', | ||
640 | ((__s32) stats->qual.level) - | ||
641 | ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0), | ||
642 | stats->qual.updated & IW_QUAL_LEVEL_UPDATED | ||
643 | ? '.' : ' ', | ||
644 | ((__s32) stats->qual.noise) - | ||
645 | ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0), | ||
646 | stats->qual.updated & IW_QUAL_NOISE_UPDATED | ||
647 | ? '.' : ' ', | ||
648 | stats->discard.nwid, stats->discard.code, | ||
649 | stats->discard.fragment, stats->discard.retries, | ||
650 | stats->discard.misc, stats->miss.beacon); | ||
651 | |||
652 | if (stats != &nullstats) | ||
653 | stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; | ||
654 | } | 555 | } |
655 | } | ||
656 | 556 | ||
657 | /* ---------------------------------------------------------------- */ | 557 | /* Send via the RtNetlink event channel */ |
658 | /* | 558 | nlh = rtnetlink_ifinfo_prep(dev, compskb); |
659 | * Print info for /proc/net/wireless (print all entries) | 559 | if (WARN_ON(!nlh)) { |
660 | */ | 560 | kfree_skb(skb); |
661 | static int wireless_dev_seq_show(struct seq_file *seq, void *v) | 561 | kfree_skb(compskb); |
662 | { | 562 | return; |
663 | might_sleep(); | 563 | } |
664 | 564 | ||
665 | if (v == SEQ_START_TOKEN) | 565 | /* Add the wireless events in the netlink packet */ |
666 | seq_printf(seq, "Inter-| sta-| Quality | Discarded " | 566 | nla = nla_reserve(compskb, IFLA_WIRELESS, event_len); |
667 | "packets | Missed | WE\n" | 567 | if (!nla) { |
668 | " face | tus | link level noise | nwid " | 568 | kfree_skb(skb); |
669 | "crypt frag retry misc | beacon | %d\n", | 569 | kfree_skb(compskb); |
670 | WIRELESS_EXT); | 570 | return; |
671 | else | 571 | } |
672 | wireless_seq_printf_stats(seq, v); | 572 | compat_event = nla_data(nla); |
673 | return 0; | 573 | |
574 | compat_event->len = event_len; | ||
575 | compat_event->cmd = cmd; | ||
576 | if (descr->header_type == IW_HEADER_TYPE_POINT) { | ||
577 | compat_wrqu.length = wrqu->data.length; | ||
578 | compat_wrqu.flags = wrqu->data.flags; | ||
579 | memcpy(&compat_event->pointer, | ||
580 | ((char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF, | ||
581 | hdr_len - IW_EV_COMPAT_LCP_LEN); | ||
582 | if (extra_len) | ||
583 | memcpy(((char *) compat_event) + hdr_len, | ||
584 | extra, extra_len); | ||
585 | } else { | ||
586 | /* extra_len must be zero, so no if (extra) needed */ | ||
587 | memcpy(&compat_event->pointer, wrqu, | ||
588 | hdr_len - IW_EV_COMPAT_LCP_LEN); | ||
589 | } | ||
590 | |||
591 | nlmsg_end(compskb, nlh); | ||
592 | |||
593 | skb_shinfo(skb)->frag_list = compskb; | ||
594 | #endif | ||
595 | skb_queue_tail(&dev_net(dev)->wext_nlevents, skb); | ||
596 | schedule_work(&wireless_nlevent_work); | ||
674 | } | 597 | } |
598 | EXPORT_SYMBOL(wireless_send_event); | ||
599 | |||
600 | |||
601 | |||
602 | /* IW handlers */ | ||
675 | 603 | ||
676 | static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos) | 604 | struct iw_statistics *get_wireless_stats(struct net_device *dev) |
677 | { | 605 | { |
678 | struct net *net = seq_file_net(seq); | 606 | #ifdef CONFIG_WIRELESS_EXT |
679 | loff_t off; | 607 | if ((dev->wireless_handlers != NULL) && |
680 | struct net_device *dev; | 608 | (dev->wireless_handlers->get_wireless_stats != NULL)) |
609 | return dev->wireless_handlers->get_wireless_stats(dev); | ||
610 | #endif | ||
681 | 611 | ||
682 | rtnl_lock(); | 612 | #ifdef CONFIG_CFG80211_WEXT |
683 | if (!*pos) | 613 | if (dev->ieee80211_ptr && dev->ieee80211_ptr && |
684 | return SEQ_START_TOKEN; | 614 | dev->ieee80211_ptr->wiphy && |
615 | dev->ieee80211_ptr->wiphy->wext && | ||
616 | dev->ieee80211_ptr->wiphy->wext->get_wireless_stats) | ||
617 | return dev->ieee80211_ptr->wiphy->wext->get_wireless_stats(dev); | ||
618 | #endif | ||
685 | 619 | ||
686 | off = 1; | 620 | /* not found */ |
687 | for_each_netdev(net, dev) | ||
688 | if (off++ == *pos) | ||
689 | return dev; | ||
690 | return NULL; | 621 | return NULL; |
691 | } | 622 | } |
692 | 623 | ||
693 | static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 624 | static int iw_handler_get_iwstats(struct net_device * dev, |
625 | struct iw_request_info * info, | ||
626 | union iwreq_data * wrqu, | ||
627 | char * extra) | ||
694 | { | 628 | { |
695 | struct net *net = seq_file_net(seq); | 629 | /* Get stats from the driver */ |
630 | struct iw_statistics *stats; | ||
696 | 631 | ||
697 | ++*pos; | 632 | stats = get_wireless_stats(dev); |
633 | if (stats) { | ||
634 | /* Copy statistics to extra */ | ||
635 | memcpy(extra, stats, sizeof(struct iw_statistics)); | ||
636 | wrqu->data.length = sizeof(struct iw_statistics); | ||
698 | 637 | ||
699 | return v == SEQ_START_TOKEN ? | 638 | /* Check if we need to clear the updated flag */ |
700 | first_net_device(net) : next_net_device(v); | 639 | if (wrqu->data.flags != 0) |
640 | stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; | ||
641 | return 0; | ||
642 | } else | ||
643 | return -EOPNOTSUPP; | ||
701 | } | 644 | } |
702 | 645 | ||
703 | static void wireless_dev_seq_stop(struct seq_file *seq, void *v) | 646 | static iw_handler get_handler(struct net_device *dev, unsigned int cmd) |
704 | { | 647 | { |
705 | rtnl_unlock(); | 648 | /* Don't "optimise" the following variable, it will crash */ |
706 | } | 649 | unsigned int index; /* *MUST* be unsigned */ |
707 | 650 | const struct iw_handler_def *handlers = NULL; | |
708 | static const struct seq_operations wireless_seq_ops = { | ||
709 | .start = wireless_dev_seq_start, | ||
710 | .next = wireless_dev_seq_next, | ||
711 | .stop = wireless_dev_seq_stop, | ||
712 | .show = wireless_dev_seq_show, | ||
713 | }; | ||
714 | 651 | ||
715 | static int seq_open_wireless(struct inode *inode, struct file *file) | 652 | #ifdef CONFIG_CFG80211_WEXT |
716 | { | 653 | if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy) |
717 | return seq_open_net(inode, file, &wireless_seq_ops, | 654 | handlers = dev->ieee80211_ptr->wiphy->wext; |
718 | sizeof(struct seq_net_private)); | 655 | #endif |
719 | } | 656 | #ifdef CONFIG_WIRELESS_EXT |
657 | if (dev->wireless_handlers) | ||
658 | handlers = dev->wireless_handlers; | ||
659 | #endif | ||
720 | 660 | ||
721 | static const struct file_operations wireless_seq_fops = { | 661 | if (!handlers) |
722 | .owner = THIS_MODULE, | 662 | return NULL; |
723 | .open = seq_open_wireless, | ||
724 | .read = seq_read, | ||
725 | .llseek = seq_lseek, | ||
726 | .release = seq_release_net, | ||
727 | }; | ||
728 | 663 | ||
729 | int wext_proc_init(struct net *net) | 664 | /* Try as a standard command */ |
730 | { | 665 | index = cmd - SIOCIWFIRST; |
731 | /* Create /proc/net/wireless entry */ | 666 | if (index < handlers->num_standard) |
732 | if (!proc_net_fops_create(net, "wireless", S_IRUGO, &wireless_seq_fops)) | 667 | return handlers->standard[index]; |
733 | return -ENOMEM; | ||
734 | 668 | ||
735 | return 0; | 669 | #ifdef CONFIG_WEXT_PRIV |
736 | } | 670 | /* Try as a private command */ |
671 | index = cmd - SIOCIWFIRSTPRIV; | ||
672 | if (index < handlers->num_private) | ||
673 | return handlers->private[index]; | ||
674 | #endif | ||
737 | 675 | ||
738 | void wext_proc_exit(struct net *net) | 676 | /* Not found */ |
739 | { | 677 | return NULL; |
740 | proc_net_remove(net, "wireless"); | ||
741 | } | 678 | } |
742 | #endif /* CONFIG_PROC_FS */ | ||
743 | 679 | ||
744 | /************************** IOCTL SUPPORT **************************/ | ||
745 | /* | ||
746 | * The original user space API to configure all those Wireless Extensions | ||
747 | * is through IOCTLs. | ||
748 | * In there, we check if we need to call the new driver API (iw_handler) | ||
749 | * or just call the driver ioctl handler. | ||
750 | */ | ||
751 | |||
752 | /* ---------------------------------------------------------------- */ | ||
753 | static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, | 680 | static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, |
754 | const struct iw_ioctl_description *descr, | 681 | const struct iw_ioctl_description *descr, |
755 | iw_handler handler, struct net_device *dev, | 682 | iw_handler handler, struct net_device *dev, |
@@ -893,188 +820,39 @@ out: | |||
893 | } | 820 | } |
894 | 821 | ||
895 | /* | 822 | /* |
896 | * Wrapper to call a standard Wireless Extension handler. | 823 | * Call the commit handler in the driver |
897 | * We do various checks and also take care of moving data between | 824 | * (if exist and if conditions are right) |
898 | * user space and kernel space. | 825 | * |
899 | */ | 826 | * Note : our current commit strategy is currently pretty dumb, |
900 | static int ioctl_standard_call(struct net_device * dev, | 827 | * but we will be able to improve on that... |
901 | struct iwreq *iwr, | 828 | * The goal is to try to agreagate as many changes as possible |
902 | unsigned int cmd, | 829 | * before doing the commit. Drivers that will define a commit handler |
903 | struct iw_request_info *info, | 830 | * are usually those that need a reset after changing parameters, so |
904 | iw_handler handler) | 831 | * we want to minimise the number of reset. |
905 | { | 832 | * A cool idea is to use a timer : at each "set" command, we re-set the |
906 | const struct iw_ioctl_description * descr; | 833 | * timer, when the timer eventually fires, we call the driver. |
907 | int ret = -EINVAL; | 834 | * Hopefully, more on that later. |
908 | |||
909 | /* Get the description of the IOCTL */ | ||
910 | if ((cmd - SIOCIWFIRST) >= standard_ioctl_num) | ||
911 | return -EOPNOTSUPP; | ||
912 | descr = &(standard_ioctl[cmd - SIOCIWFIRST]); | ||
913 | |||
914 | /* Check if we have a pointer to user space data or not */ | ||
915 | if (descr->header_type != IW_HEADER_TYPE_POINT) { | ||
916 | |||
917 | /* No extra arguments. Trivial to handle */ | ||
918 | ret = handler(dev, info, &(iwr->u), NULL); | ||
919 | |||
920 | /* Generate an event to notify listeners of the change */ | ||
921 | if ((descr->flags & IW_DESCR_FLAG_EVENT) && | ||
922 | ((ret == 0) || (ret == -EIWCOMMIT))) | ||
923 | wireless_send_event(dev, cmd, &(iwr->u), NULL); | ||
924 | } else { | ||
925 | ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr, | ||
926 | handler, dev, info); | ||
927 | } | ||
928 | |||
929 | /* Call commit handler if needed and defined */ | ||
930 | if (ret == -EIWCOMMIT) | ||
931 | ret = call_commit_handler(dev); | ||
932 | |||
933 | /* Here, we will generate the appropriate event if needed */ | ||
934 | |||
935 | return ret; | ||
936 | } | ||
937 | |||
938 | /* ---------------------------------------------------------------- */ | ||
939 | /* | ||
940 | * Wrapper to call a private Wireless Extension handler. | ||
941 | * We do various checks and also take care of moving data between | ||
942 | * user space and kernel space. | ||
943 | * It's not as nice and slimline as the standard wrapper. The cause | ||
944 | * is struct iw_priv_args, which was not really designed for the | ||
945 | * job we are going here. | ||
946 | * | 835 | * |
947 | * IMPORTANT : This function prevent to set and get data on the same | 836 | * Also, I'm waiting to see how many people will complain about the |
948 | * IOCTL and enforce the SET/GET convention. Not doing it would be | 837 | * netif_running(dev) test. I'm open on that one... |
949 | * far too hairy... | 838 | * Hopefully, the driver will remember to do a commit in "open()" ;-) |
950 | * If you need to set and get data at the same time, please don't use | ||
951 | * a iw_handler but process it in your ioctl handler (i.e. use the | ||
952 | * old driver API). | ||
953 | */ | 839 | */ |
954 | static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd, | 840 | int call_commit_handler(struct net_device *dev) |
955 | const struct iw_priv_args **descrp) | ||
956 | { | ||
957 | const struct iw_priv_args *descr; | ||
958 | int i, extra_size; | ||
959 | |||
960 | descr = NULL; | ||
961 | for (i = 0; i < dev->wireless_handlers->num_private_args; i++) { | ||
962 | if (cmd == dev->wireless_handlers->private_args[i].cmd) { | ||
963 | descr = &dev->wireless_handlers->private_args[i]; | ||
964 | break; | ||
965 | } | ||
966 | } | ||
967 | |||
968 | extra_size = 0; | ||
969 | if (descr) { | ||
970 | if (IW_IS_SET(cmd)) { | ||
971 | int offset = 0; /* For sub-ioctls */ | ||
972 | /* Check for sub-ioctl handler */ | ||
973 | if (descr->name[0] == '\0') | ||
974 | /* Reserve one int for sub-ioctl index */ | ||
975 | offset = sizeof(__u32); | ||
976 | |||
977 | /* Size of set arguments */ | ||
978 | extra_size = get_priv_size(descr->set_args); | ||
979 | |||
980 | /* Does it fits in iwr ? */ | ||
981 | if ((descr->set_args & IW_PRIV_SIZE_FIXED) && | ||
982 | ((extra_size + offset) <= IFNAMSIZ)) | ||
983 | extra_size = 0; | ||
984 | } else { | ||
985 | /* Size of get arguments */ | ||
986 | extra_size = get_priv_size(descr->get_args); | ||
987 | |||
988 | /* Does it fits in iwr ? */ | ||
989 | if ((descr->get_args & IW_PRIV_SIZE_FIXED) && | ||
990 | (extra_size <= IFNAMSIZ)) | ||
991 | extra_size = 0; | ||
992 | } | ||
993 | } | ||
994 | *descrp = descr; | ||
995 | return extra_size; | ||
996 | } | ||
997 | |||
998 | static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, | ||
999 | const struct iw_priv_args *descr, | ||
1000 | iw_handler handler, struct net_device *dev, | ||
1001 | struct iw_request_info *info, int extra_size) | ||
1002 | { | ||
1003 | char *extra; | ||
1004 | int err; | ||
1005 | |||
1006 | /* Check what user space is giving us */ | ||
1007 | if (IW_IS_SET(cmd)) { | ||
1008 | if (!iwp->pointer && iwp->length != 0) | ||
1009 | return -EFAULT; | ||
1010 | |||
1011 | if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK)) | ||
1012 | return -E2BIG; | ||
1013 | } else if (!iwp->pointer) | ||
1014 | return -EFAULT; | ||
1015 | |||
1016 | extra = kmalloc(extra_size, GFP_KERNEL); | ||
1017 | if (!extra) | ||
1018 | return -ENOMEM; | ||
1019 | |||
1020 | /* If it is a SET, get all the extra data in here */ | ||
1021 | if (IW_IS_SET(cmd) && (iwp->length != 0)) { | ||
1022 | if (copy_from_user(extra, iwp->pointer, extra_size)) { | ||
1023 | err = -EFAULT; | ||
1024 | goto out; | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | /* Call the handler */ | ||
1029 | err = handler(dev, info, (union iwreq_data *) iwp, extra); | ||
1030 | |||
1031 | /* If we have something to return to the user */ | ||
1032 | if (!err && IW_IS_GET(cmd)) { | ||
1033 | /* Adjust for the actual length if it's variable, | ||
1034 | * avoid leaking kernel bits outside. | ||
1035 | */ | ||
1036 | if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) | ||
1037 | extra_size = adjust_priv_size(descr->get_args, iwp); | ||
1038 | |||
1039 | if (copy_to_user(iwp->pointer, extra, extra_size)) | ||
1040 | err = -EFAULT; | ||
1041 | } | ||
1042 | |||
1043 | out: | ||
1044 | kfree(extra); | ||
1045 | return err; | ||
1046 | } | ||
1047 | |||
1048 | static int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, | ||
1049 | unsigned int cmd, struct iw_request_info *info, | ||
1050 | iw_handler handler) | ||
1051 | { | 841 | { |
1052 | int extra_size = 0, ret = -EINVAL; | 842 | #ifdef CONFIG_WIRELESS_EXT |
1053 | const struct iw_priv_args *descr; | 843 | if ((netif_running(dev)) && |
1054 | 844 | (dev->wireless_handlers->standard[0] != NULL)) | |
1055 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | 845 | /* Call the commit handler on the driver */ |
1056 | 846 | return dev->wireless_handlers->standard[0](dev, NULL, | |
1057 | /* Check if we have a pointer to user space data or not. */ | 847 | NULL, NULL); |
1058 | if (extra_size == 0) { | 848 | else |
1059 | /* No extra arguments. Trivial to handle */ | 849 | return 0; /* Command completed successfully */ |
1060 | ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); | 850 | #else |
1061 | } else { | 851 | /* cfg80211 has no commit */ |
1062 | ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, | 852 | return 0; |
1063 | handler, dev, info, extra_size); | 853 | #endif |
1064 | } | ||
1065 | |||
1066 | /* Call commit handler if needed and defined */ | ||
1067 | if (ret == -EIWCOMMIT) | ||
1068 | ret = call_commit_handler(dev); | ||
1069 | |||
1070 | return ret; | ||
1071 | } | 854 | } |
1072 | 855 | ||
1073 | /* ---------------------------------------------------------------- */ | ||
1074 | typedef int (*wext_ioctl_func)(struct net_device *, struct iwreq *, | ||
1075 | unsigned int, struct iw_request_info *, | ||
1076 | iw_handler); | ||
1077 | |||
1078 | /* | 856 | /* |
1079 | * Main IOCTl dispatcher. | 857 | * Main IOCTl dispatcher. |
1080 | * Check the type of IOCTL and call the appropriate wrapper... | 858 | * Check the type of IOCTL and call the appropriate wrapper... |
@@ -1103,9 +881,11 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, | |||
1103 | return standard(dev, iwr, cmd, info, | 881 | return standard(dev, iwr, cmd, info, |
1104 | &iw_handler_get_iwstats); | 882 | &iw_handler_get_iwstats); |
1105 | 883 | ||
884 | #ifdef CONFIG_WEXT_PRIV | ||
1106 | if (cmd == SIOCGIWPRIV && dev->wireless_handlers) | 885 | if (cmd == SIOCGIWPRIV && dev->wireless_handlers) |
1107 | return standard(dev, iwr, cmd, info, | 886 | return standard(dev, iwr, cmd, info, |
1108 | &iw_handler_get_private); | 887 | iw_handler_get_private); |
888 | #endif | ||
1109 | 889 | ||
1110 | /* Basic check */ | 890 | /* Basic check */ |
1111 | if (!netif_device_present(dev)) | 891 | if (!netif_device_present(dev)) |
@@ -1117,7 +897,7 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr, | |||
1117 | /* Standard and private are not the same */ | 897 | /* Standard and private are not the same */ |
1118 | if (cmd < SIOCIWFIRSTPRIV) | 898 | if (cmd < SIOCIWFIRSTPRIV) |
1119 | return standard(dev, iwr, cmd, info, handler); | 899 | return standard(dev, iwr, cmd, info, handler); |
1120 | else | 900 | else if (private) |
1121 | return private(dev, iwr, cmd, info, handler); | 901 | return private(dev, iwr, cmd, info, handler); |
1122 | } | 902 | } |
1123 | /* Old driver API : call driver ioctl handler */ | 903 | /* Old driver API : call driver ioctl handler */ |
@@ -1157,6 +937,50 @@ static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr, | |||
1157 | return ret; | 937 | return ret; |
1158 | } | 938 | } |
1159 | 939 | ||
940 | /* | ||
941 | * Wrapper to call a standard Wireless Extension handler. | ||
942 | * We do various checks and also take care of moving data between | ||
943 | * user space and kernel space. | ||
944 | */ | ||
945 | static int ioctl_standard_call(struct net_device * dev, | ||
946 | struct iwreq *iwr, | ||
947 | unsigned int cmd, | ||
948 | struct iw_request_info *info, | ||
949 | iw_handler handler) | ||
950 | { | ||
951 | const struct iw_ioctl_description * descr; | ||
952 | int ret = -EINVAL; | ||
953 | |||
954 | /* Get the description of the IOCTL */ | ||
955 | if ((cmd - SIOCIWFIRST) >= standard_ioctl_num) | ||
956 | return -EOPNOTSUPP; | ||
957 | descr = &(standard_ioctl[cmd - SIOCIWFIRST]); | ||
958 | |||
959 | /* Check if we have a pointer to user space data or not */ | ||
960 | if (descr->header_type != IW_HEADER_TYPE_POINT) { | ||
961 | |||
962 | /* No extra arguments. Trivial to handle */ | ||
963 | ret = handler(dev, info, &(iwr->u), NULL); | ||
964 | |||
965 | /* Generate an event to notify listeners of the change */ | ||
966 | if ((descr->flags & IW_DESCR_FLAG_EVENT) && | ||
967 | ((ret == 0) || (ret == -EIWCOMMIT))) | ||
968 | wireless_send_event(dev, cmd, &(iwr->u), NULL); | ||
969 | } else { | ||
970 | ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr, | ||
971 | handler, dev, info); | ||
972 | } | ||
973 | |||
974 | /* Call commit handler if needed and defined */ | ||
975 | if (ret == -EIWCOMMIT) | ||
976 | ret = call_commit_handler(dev); | ||
977 | |||
978 | /* Here, we will generate the appropriate event if needed */ | ||
979 | |||
980 | return ret; | ||
981 | } | ||
982 | |||
983 | |||
1160 | int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, | 984 | int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd, |
1161 | void __user *arg) | 985 | void __user *arg) |
1162 | { | 986 | { |
@@ -1205,43 +1029,6 @@ static int compat_standard_call(struct net_device *dev, | |||
1205 | return err; | 1029 | return err; |
1206 | } | 1030 | } |
1207 | 1031 | ||
1208 | static int compat_private_call(struct net_device *dev, struct iwreq *iwr, | ||
1209 | unsigned int cmd, struct iw_request_info *info, | ||
1210 | iw_handler handler) | ||
1211 | { | ||
1212 | const struct iw_priv_args *descr; | ||
1213 | int ret, extra_size; | ||
1214 | |||
1215 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | ||
1216 | |||
1217 | /* Check if we have a pointer to user space data or not. */ | ||
1218 | if (extra_size == 0) { | ||
1219 | /* No extra arguments. Trivial to handle */ | ||
1220 | ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); | ||
1221 | } else { | ||
1222 | struct compat_iw_point *iwp_compat; | ||
1223 | struct iw_point iwp; | ||
1224 | |||
1225 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | ||
1226 | iwp.pointer = compat_ptr(iwp_compat->pointer); | ||
1227 | iwp.length = iwp_compat->length; | ||
1228 | iwp.flags = iwp_compat->flags; | ||
1229 | |||
1230 | ret = ioctl_private_iw_point(&iwp, cmd, descr, | ||
1231 | handler, dev, info, extra_size); | ||
1232 | |||
1233 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | ||
1234 | iwp_compat->length = iwp.length; | ||
1235 | iwp_compat->flags = iwp.flags; | ||
1236 | } | ||
1237 | |||
1238 | /* Call commit handler if needed and defined */ | ||
1239 | if (ret == -EIWCOMMIT) | ||
1240 | ret = call_commit_handler(dev); | ||
1241 | |||
1242 | return ret; | ||
1243 | } | ||
1244 | |||
1245 | int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | 1032 | int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, |
1246 | unsigned long arg) | 1033 | unsigned long arg) |
1247 | { | 1034 | { |
@@ -1274,502 +1061,3 @@ int compat_wext_handle_ioctl(struct net *net, unsigned int cmd, | |||
1274 | return ret; | 1061 | return ret; |
1275 | } | 1062 | } |
1276 | #endif | 1063 | #endif |
1277 | |||
1278 | static int __net_init wext_pernet_init(struct net *net) | ||
1279 | { | ||
1280 | skb_queue_head_init(&net->wext_nlevents); | ||
1281 | return 0; | ||
1282 | } | ||
1283 | |||
1284 | static void __net_exit wext_pernet_exit(struct net *net) | ||
1285 | { | ||
1286 | skb_queue_purge(&net->wext_nlevents); | ||
1287 | } | ||
1288 | |||
1289 | static struct pernet_operations wext_pernet_ops = { | ||
1290 | .init = wext_pernet_init, | ||
1291 | .exit = wext_pernet_exit, | ||
1292 | }; | ||
1293 | |||
1294 | static int __init wireless_nlevent_init(void) | ||
1295 | { | ||
1296 | return register_pernet_subsys(&wext_pernet_ops); | ||
1297 | } | ||
1298 | |||
1299 | subsys_initcall(wireless_nlevent_init); | ||
1300 | |||
1301 | /* Process events generated by the wireless layer or the driver. */ | ||
1302 | static void wireless_nlevent_process(struct work_struct *work) | ||
1303 | { | ||
1304 | struct sk_buff *skb; | ||
1305 | struct net *net; | ||
1306 | |||
1307 | rtnl_lock(); | ||
1308 | |||
1309 | for_each_net(net) { | ||
1310 | while ((skb = skb_dequeue(&net->wext_nlevents))) | ||
1311 | rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, | ||
1312 | GFP_KERNEL); | ||
1313 | } | ||
1314 | |||
1315 | rtnl_unlock(); | ||
1316 | } | ||
1317 | |||
1318 | static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process); | ||
1319 | |||
1320 | static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev, | ||
1321 | struct sk_buff *skb) | ||
1322 | { | ||
1323 | struct ifinfomsg *r; | ||
1324 | struct nlmsghdr *nlh; | ||
1325 | |||
1326 | nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0); | ||
1327 | if (!nlh) | ||
1328 | return NULL; | ||
1329 | |||
1330 | r = nlmsg_data(nlh); | ||
1331 | r->ifi_family = AF_UNSPEC; | ||
1332 | r->__ifi_pad = 0; | ||
1333 | r->ifi_type = dev->type; | ||
1334 | r->ifi_index = dev->ifindex; | ||
1335 | r->ifi_flags = dev_get_flags(dev); | ||
1336 | r->ifi_change = 0; /* Wireless changes don't affect those flags */ | ||
1337 | |||
1338 | NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); | ||
1339 | |||
1340 | return nlh; | ||
1341 | nla_put_failure: | ||
1342 | nlmsg_cancel(skb, nlh); | ||
1343 | return NULL; | ||
1344 | } | ||
1345 | |||
1346 | |||
1347 | /* | ||
1348 | * Main event dispatcher. Called from other parts and drivers. | ||
1349 | * Send the event on the appropriate channels. | ||
1350 | * May be called from interrupt context. | ||
1351 | */ | ||
1352 | void wireless_send_event(struct net_device * dev, | ||
1353 | unsigned int cmd, | ||
1354 | union iwreq_data * wrqu, | ||
1355 | const char * extra) | ||
1356 | { | ||
1357 | const struct iw_ioctl_description * descr = NULL; | ||
1358 | int extra_len = 0; | ||
1359 | struct iw_event *event; /* Mallocated whole event */ | ||
1360 | int event_len; /* Its size */ | ||
1361 | int hdr_len; /* Size of the event header */ | ||
1362 | int wrqu_off = 0; /* Offset in wrqu */ | ||
1363 | /* Don't "optimise" the following variable, it will crash */ | ||
1364 | unsigned cmd_index; /* *MUST* be unsigned */ | ||
1365 | struct sk_buff *skb; | ||
1366 | struct nlmsghdr *nlh; | ||
1367 | struct nlattr *nla; | ||
1368 | #ifdef CONFIG_COMPAT | ||
1369 | struct __compat_iw_event *compat_event; | ||
1370 | struct compat_iw_point compat_wrqu; | ||
1371 | struct sk_buff *compskb; | ||
1372 | #endif | ||
1373 | |||
1374 | /* | ||
1375 | * Nothing in the kernel sends scan events with data, be safe. | ||
1376 | * This is necessary because we cannot fix up scan event data | ||
1377 | * for compat, due to being contained in 'extra', but normally | ||
1378 | * applications are required to retrieve the scan data anyway | ||
1379 | * and no data is included in the event, this codifies that | ||
1380 | * practice. | ||
1381 | */ | ||
1382 | if (WARN_ON(cmd == SIOCGIWSCAN && extra)) | ||
1383 | extra = NULL; | ||
1384 | |||
1385 | /* Get the description of the Event */ | ||
1386 | if (cmd <= SIOCIWLAST) { | ||
1387 | cmd_index = cmd - SIOCIWFIRST; | ||
1388 | if (cmd_index < standard_ioctl_num) | ||
1389 | descr = &(standard_ioctl[cmd_index]); | ||
1390 | } else { | ||
1391 | cmd_index = cmd - IWEVFIRST; | ||
1392 | if (cmd_index < standard_event_num) | ||
1393 | descr = &(standard_event[cmd_index]); | ||
1394 | } | ||
1395 | /* Don't accept unknown events */ | ||
1396 | if (descr == NULL) { | ||
1397 | /* Note : we don't return an error to the driver, because | ||
1398 | * the driver would not know what to do about it. It can't | ||
1399 | * return an error to the user, because the event is not | ||
1400 | * initiated by a user request. | ||
1401 | * The best the driver could do is to log an error message. | ||
1402 | * We will do it ourselves instead... | ||
1403 | */ | ||
1404 | printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n", | ||
1405 | dev->name, cmd); | ||
1406 | return; | ||
1407 | } | ||
1408 | |||
1409 | /* Check extra parameters and set extra_len */ | ||
1410 | if (descr->header_type == IW_HEADER_TYPE_POINT) { | ||
1411 | /* Check if number of token fits within bounds */ | ||
1412 | if (wrqu->data.length > descr->max_tokens) { | ||
1413 | printk(KERN_ERR "%s (WE) : Wireless Event too big (%d)\n", dev->name, wrqu->data.length); | ||
1414 | return; | ||
1415 | } | ||
1416 | if (wrqu->data.length < descr->min_tokens) { | ||
1417 | printk(KERN_ERR "%s (WE) : Wireless Event too small (%d)\n", dev->name, wrqu->data.length); | ||
1418 | return; | ||
1419 | } | ||
1420 | /* Calculate extra_len - extra is NULL for restricted events */ | ||
1421 | if (extra != NULL) | ||
1422 | extra_len = wrqu->data.length * descr->token_size; | ||
1423 | /* Always at an offset in wrqu */ | ||
1424 | wrqu_off = IW_EV_POINT_OFF; | ||
1425 | } | ||
1426 | |||
1427 | /* Total length of the event */ | ||
1428 | hdr_len = event_type_size[descr->header_type]; | ||
1429 | event_len = hdr_len + extra_len; | ||
1430 | |||
1431 | /* | ||
1432 | * The problem for 64/32 bit. | ||
1433 | * | ||
1434 | * On 64-bit, a regular event is laid out as follows: | ||
1435 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | ||
1436 | * | event.len | event.cmd | p a d d i n g | | ||
1437 | * | wrqu data ... (with the correct size) | | ||
1438 | * | ||
1439 | * This padding exists because we manipulate event->u, | ||
1440 | * and 'event' is not packed. | ||
1441 | * | ||
1442 | * An iw_point event is laid out like this instead: | ||
1443 | * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | ||
1444 | * | event.len | event.cmd | p a d d i n g | | ||
1445 | * | iwpnt.len | iwpnt.flg | p a d d i n g | | ||
1446 | * | extra data ... | ||
1447 | * | ||
1448 | * The second padding exists because struct iw_point is extended, | ||
1449 | * but this depends on the platform... | ||
1450 | * | ||
1451 | * On 32-bit, all the padding shouldn't be there. | ||
1452 | */ | ||
1453 | |||
1454 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); | ||
1455 | if (!skb) | ||
1456 | return; | ||
1457 | |||
1458 | /* Send via the RtNetlink event channel */ | ||
1459 | nlh = rtnetlink_ifinfo_prep(dev, skb); | ||
1460 | if (WARN_ON(!nlh)) { | ||
1461 | kfree_skb(skb); | ||
1462 | return; | ||
1463 | } | ||
1464 | |||
1465 | /* Add the wireless events in the netlink packet */ | ||
1466 | nla = nla_reserve(skb, IFLA_WIRELESS, event_len); | ||
1467 | if (!nla) { | ||
1468 | kfree_skb(skb); | ||
1469 | return; | ||
1470 | } | ||
1471 | event = nla_data(nla); | ||
1472 | |||
1473 | /* Fill event - first clear to avoid data leaking */ | ||
1474 | memset(event, 0, hdr_len); | ||
1475 | event->len = event_len; | ||
1476 | event->cmd = cmd; | ||
1477 | memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN); | ||
1478 | if (extra_len) | ||
1479 | memcpy(((char *) event) + hdr_len, extra, extra_len); | ||
1480 | |||
1481 | nlmsg_end(skb, nlh); | ||
1482 | #ifdef CONFIG_COMPAT | ||
1483 | hdr_len = compat_event_type_size[descr->header_type]; | ||
1484 | event_len = hdr_len + extra_len; | ||
1485 | |||
1486 | compskb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); | ||
1487 | if (!compskb) { | ||
1488 | kfree_skb(skb); | ||
1489 | return; | ||
1490 | } | ||
1491 | |||
1492 | /* Send via the RtNetlink event channel */ | ||
1493 | nlh = rtnetlink_ifinfo_prep(dev, compskb); | ||
1494 | if (WARN_ON(!nlh)) { | ||
1495 | kfree_skb(skb); | ||
1496 | kfree_skb(compskb); | ||
1497 | return; | ||
1498 | } | ||
1499 | |||
1500 | /* Add the wireless events in the netlink packet */ | ||
1501 | nla = nla_reserve(compskb, IFLA_WIRELESS, event_len); | ||
1502 | if (!nla) { | ||
1503 | kfree_skb(skb); | ||
1504 | kfree_skb(compskb); | ||
1505 | return; | ||
1506 | } | ||
1507 | compat_event = nla_data(nla); | ||
1508 | |||
1509 | compat_event->len = event_len; | ||
1510 | compat_event->cmd = cmd; | ||
1511 | if (descr->header_type == IW_HEADER_TYPE_POINT) { | ||
1512 | compat_wrqu.length = wrqu->data.length; | ||
1513 | compat_wrqu.flags = wrqu->data.flags; | ||
1514 | memcpy(&compat_event->pointer, | ||
1515 | ((char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF, | ||
1516 | hdr_len - IW_EV_COMPAT_LCP_LEN); | ||
1517 | if (extra_len) | ||
1518 | memcpy(((char *) compat_event) + hdr_len, | ||
1519 | extra, extra_len); | ||
1520 | } else { | ||
1521 | /* extra_len must be zero, so no if (extra) needed */ | ||
1522 | memcpy(&compat_event->pointer, wrqu, | ||
1523 | hdr_len - IW_EV_COMPAT_LCP_LEN); | ||
1524 | } | ||
1525 | |||
1526 | nlmsg_end(compskb, nlh); | ||
1527 | |||
1528 | skb_shinfo(skb)->frag_list = compskb; | ||
1529 | #endif | ||
1530 | skb_queue_tail(&dev_net(dev)->wext_nlevents, skb); | ||
1531 | schedule_work(&wireless_nlevent_work); | ||
1532 | } | ||
1533 | EXPORT_SYMBOL(wireless_send_event); | ||
1534 | |||
1535 | /********************** ENHANCED IWSPY SUPPORT **********************/ | ||
1536 | /* | ||
1537 | * In the old days, the driver was handling spy support all by itself. | ||
1538 | * Now, the driver can delegate this task to Wireless Extensions. | ||
1539 | * It needs to use those standard spy iw_handler in struct iw_handler_def, | ||
1540 | * push data to us via wireless_spy_update() and include struct iw_spy_data | ||
1541 | * in its private part (and export it in net_device->wireless_data->spy_data). | ||
1542 | * One of the main advantage of centralising spy support here is that | ||
1543 | * it becomes much easier to improve and extend it without having to touch | ||
1544 | * the drivers. One example is the addition of the Spy-Threshold events. | ||
1545 | */ | ||
1546 | |||
1547 | /* ---------------------------------------------------------------- */ | ||
1548 | /* | ||
1549 | * Return the pointer to the spy data in the driver. | ||
1550 | * Because this is called on the Rx path via wireless_spy_update(), | ||
1551 | * we want it to be efficient... | ||
1552 | */ | ||
1553 | static inline struct iw_spy_data *get_spydata(struct net_device *dev) | ||
1554 | { | ||
1555 | /* This is the new way */ | ||
1556 | if (dev->wireless_data) | ||
1557 | return dev->wireless_data->spy_data; | ||
1558 | return NULL; | ||
1559 | } | ||
1560 | |||
1561 | /*------------------------------------------------------------------*/ | ||
1562 | /* | ||
1563 | * Standard Wireless Handler : set Spy List | ||
1564 | */ | ||
1565 | int iw_handler_set_spy(struct net_device * dev, | ||
1566 | struct iw_request_info * info, | ||
1567 | union iwreq_data * wrqu, | ||
1568 | char * extra) | ||
1569 | { | ||
1570 | struct iw_spy_data * spydata = get_spydata(dev); | ||
1571 | struct sockaddr * address = (struct sockaddr *) extra; | ||
1572 | |||
1573 | /* Make sure driver is not buggy or using the old API */ | ||
1574 | if (!spydata) | ||
1575 | return -EOPNOTSUPP; | ||
1576 | |||
1577 | /* Disable spy collection while we copy the addresses. | ||
1578 | * While we copy addresses, any call to wireless_spy_update() | ||
1579 | * will NOP. This is OK, as anyway the addresses are changing. */ | ||
1580 | spydata->spy_number = 0; | ||
1581 | |||
1582 | /* We want to operate without locking, because wireless_spy_update() | ||
1583 | * most likely will happen in the interrupt handler, and therefore | ||
1584 | * have its own locking constraints and needs performance. | ||
1585 | * The rtnl_lock() make sure we don't race with the other iw_handlers. | ||
1586 | * This make sure wireless_spy_update() "see" that the spy list | ||
1587 | * is temporarily disabled. */ | ||
1588 | smp_wmb(); | ||
1589 | |||
1590 | /* Are there are addresses to copy? */ | ||
1591 | if (wrqu->data.length > 0) { | ||
1592 | int i; | ||
1593 | |||
1594 | /* Copy addresses */ | ||
1595 | for (i = 0; i < wrqu->data.length; i++) | ||
1596 | memcpy(spydata->spy_address[i], address[i].sa_data, | ||
1597 | ETH_ALEN); | ||
1598 | /* Reset stats */ | ||
1599 | memset(spydata->spy_stat, 0, | ||
1600 | sizeof(struct iw_quality) * IW_MAX_SPY); | ||
1601 | } | ||
1602 | |||
1603 | /* Make sure above is updated before re-enabling */ | ||
1604 | smp_wmb(); | ||
1605 | |||
1606 | /* Enable addresses */ | ||
1607 | spydata->spy_number = wrqu->data.length; | ||
1608 | |||
1609 | return 0; | ||
1610 | } | ||
1611 | EXPORT_SYMBOL(iw_handler_set_spy); | ||
1612 | |||
1613 | /*------------------------------------------------------------------*/ | ||
1614 | /* | ||
1615 | * Standard Wireless Handler : get Spy List | ||
1616 | */ | ||
1617 | int iw_handler_get_spy(struct net_device * dev, | ||
1618 | struct iw_request_info * info, | ||
1619 | union iwreq_data * wrqu, | ||
1620 | char * extra) | ||
1621 | { | ||
1622 | struct iw_spy_data * spydata = get_spydata(dev); | ||
1623 | struct sockaddr * address = (struct sockaddr *) extra; | ||
1624 | int i; | ||
1625 | |||
1626 | /* Make sure driver is not buggy or using the old API */ | ||
1627 | if (!spydata) | ||
1628 | return -EOPNOTSUPP; | ||
1629 | |||
1630 | wrqu->data.length = spydata->spy_number; | ||
1631 | |||
1632 | /* Copy addresses. */ | ||
1633 | for (i = 0; i < spydata->spy_number; i++) { | ||
1634 | memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN); | ||
1635 | address[i].sa_family = AF_UNIX; | ||
1636 | } | ||
1637 | /* Copy stats to the user buffer (just after). */ | ||
1638 | if (spydata->spy_number > 0) | ||
1639 | memcpy(extra + (sizeof(struct sockaddr) *spydata->spy_number), | ||
1640 | spydata->spy_stat, | ||
1641 | sizeof(struct iw_quality) * spydata->spy_number); | ||
1642 | /* Reset updated flags. */ | ||
1643 | for (i = 0; i < spydata->spy_number; i++) | ||
1644 | spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED; | ||
1645 | return 0; | ||
1646 | } | ||
1647 | EXPORT_SYMBOL(iw_handler_get_spy); | ||
1648 | |||
1649 | /*------------------------------------------------------------------*/ | ||
1650 | /* | ||
1651 | * Standard Wireless Handler : set spy threshold | ||
1652 | */ | ||
1653 | int iw_handler_set_thrspy(struct net_device * dev, | ||
1654 | struct iw_request_info *info, | ||
1655 | union iwreq_data * wrqu, | ||
1656 | char * extra) | ||
1657 | { | ||
1658 | struct iw_spy_data * spydata = get_spydata(dev); | ||
1659 | struct iw_thrspy * threshold = (struct iw_thrspy *) extra; | ||
1660 | |||
1661 | /* Make sure driver is not buggy or using the old API */ | ||
1662 | if (!spydata) | ||
1663 | return -EOPNOTSUPP; | ||
1664 | |||
1665 | /* Just do it */ | ||
1666 | memcpy(&(spydata->spy_thr_low), &(threshold->low), | ||
1667 | 2 * sizeof(struct iw_quality)); | ||
1668 | |||
1669 | /* Clear flag */ | ||
1670 | memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under)); | ||
1671 | |||
1672 | return 0; | ||
1673 | } | ||
1674 | EXPORT_SYMBOL(iw_handler_set_thrspy); | ||
1675 | |||
1676 | /*------------------------------------------------------------------*/ | ||
1677 | /* | ||
1678 | * Standard Wireless Handler : get spy threshold | ||
1679 | */ | ||
1680 | int iw_handler_get_thrspy(struct net_device * dev, | ||
1681 | struct iw_request_info *info, | ||
1682 | union iwreq_data * wrqu, | ||
1683 | char * extra) | ||
1684 | { | ||
1685 | struct iw_spy_data * spydata = get_spydata(dev); | ||
1686 | struct iw_thrspy * threshold = (struct iw_thrspy *) extra; | ||
1687 | |||
1688 | /* Make sure driver is not buggy or using the old API */ | ||
1689 | if (!spydata) | ||
1690 | return -EOPNOTSUPP; | ||
1691 | |||
1692 | /* Just do it */ | ||
1693 | memcpy(&(threshold->low), &(spydata->spy_thr_low), | ||
1694 | 2 * sizeof(struct iw_quality)); | ||
1695 | |||
1696 | return 0; | ||
1697 | } | ||
1698 | EXPORT_SYMBOL(iw_handler_get_thrspy); | ||
1699 | |||
1700 | /*------------------------------------------------------------------*/ | ||
1701 | /* | ||
1702 | * Prepare and send a Spy Threshold event | ||
1703 | */ | ||
1704 | static void iw_send_thrspy_event(struct net_device * dev, | ||
1705 | struct iw_spy_data * spydata, | ||
1706 | unsigned char * address, | ||
1707 | struct iw_quality * wstats) | ||
1708 | { | ||
1709 | union iwreq_data wrqu; | ||
1710 | struct iw_thrspy threshold; | ||
1711 | |||
1712 | /* Init */ | ||
1713 | wrqu.data.length = 1; | ||
1714 | wrqu.data.flags = 0; | ||
1715 | /* Copy address */ | ||
1716 | memcpy(threshold.addr.sa_data, address, ETH_ALEN); | ||
1717 | threshold.addr.sa_family = ARPHRD_ETHER; | ||
1718 | /* Copy stats */ | ||
1719 | memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality)); | ||
1720 | /* Copy also thresholds */ | ||
1721 | memcpy(&(threshold.low), &(spydata->spy_thr_low), | ||
1722 | 2 * sizeof(struct iw_quality)); | ||
1723 | |||
1724 | /* Send event to user space */ | ||
1725 | wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold); | ||
1726 | } | ||
1727 | |||
1728 | /* ---------------------------------------------------------------- */ | ||
1729 | /* | ||
1730 | * Call for the driver to update the spy data. | ||
1731 | * For now, the spy data is a simple array. As the size of the array is | ||
1732 | * small, this is good enough. If we wanted to support larger number of | ||
1733 | * spy addresses, we should use something more efficient... | ||
1734 | */ | ||
1735 | void wireless_spy_update(struct net_device * dev, | ||
1736 | unsigned char * address, | ||
1737 | struct iw_quality * wstats) | ||
1738 | { | ||
1739 | struct iw_spy_data * spydata = get_spydata(dev); | ||
1740 | int i; | ||
1741 | int match = -1; | ||
1742 | |||
1743 | /* Make sure driver is not buggy or using the old API */ | ||
1744 | if (!spydata) | ||
1745 | return; | ||
1746 | |||
1747 | /* Update all records that match */ | ||
1748 | for (i = 0; i < spydata->spy_number; i++) | ||
1749 | if (!compare_ether_addr(address, spydata->spy_address[i])) { | ||
1750 | memcpy(&(spydata->spy_stat[i]), wstats, | ||
1751 | sizeof(struct iw_quality)); | ||
1752 | match = i; | ||
1753 | } | ||
1754 | |||
1755 | /* Generate an event if we cross the spy threshold. | ||
1756 | * To avoid event storms, we have a simple hysteresis : we generate | ||
1757 | * event only when we go under the low threshold or above the | ||
1758 | * high threshold. */ | ||
1759 | if (match >= 0) { | ||
1760 | if (spydata->spy_thr_under[match]) { | ||
1761 | if (wstats->level > spydata->spy_thr_high.level) { | ||
1762 | spydata->spy_thr_under[match] = 0; | ||
1763 | iw_send_thrspy_event(dev, spydata, | ||
1764 | address, wstats); | ||
1765 | } | ||
1766 | } else { | ||
1767 | if (wstats->level < spydata->spy_thr_low.level) { | ||
1768 | spydata->spy_thr_under[match] = 1; | ||
1769 | iw_send_thrspy_event(dev, spydata, | ||
1770 | address, wstats); | ||
1771 | } | ||
1772 | } | ||
1773 | } | ||
1774 | } | ||
1775 | EXPORT_SYMBOL(wireless_spy_update); | ||
diff --git a/net/wireless/wext-priv.c b/net/wireless/wext-priv.c new file mode 100644 index 000000000000..a3c2277de9e5 --- /dev/null +++ b/net/wireless/wext-priv.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * This file implement the Wireless Extensions priv API. | ||
3 | * | ||
4 | * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> | ||
5 | * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. | ||
6 | * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> | ||
7 | * | ||
8 | * (As all part of the Linux kernel, this file is GPL) | ||
9 | */ | ||
10 | #include <linux/wireless.h> | ||
11 | #include <linux/netdevice.h> | ||
12 | #include <net/iw_handler.h> | ||
13 | #include <net/wext.h> | ||
14 | |||
15 | int iw_handler_get_private(struct net_device * dev, | ||
16 | struct iw_request_info * info, | ||
17 | union iwreq_data * wrqu, | ||
18 | char * extra) | ||
19 | { | ||
20 | /* Check if the driver has something to export */ | ||
21 | if ((dev->wireless_handlers->num_private_args == 0) || | ||
22 | (dev->wireless_handlers->private_args == NULL)) | ||
23 | return -EOPNOTSUPP; | ||
24 | |||
25 | /* Check if there is enough buffer up there */ | ||
26 | if (wrqu->data.length < dev->wireless_handlers->num_private_args) { | ||
27 | /* User space can't know in advance how large the buffer | ||
28 | * needs to be. Give it a hint, so that we can support | ||
29 | * any size buffer we want somewhat efficiently... */ | ||
30 | wrqu->data.length = dev->wireless_handlers->num_private_args; | ||
31 | return -E2BIG; | ||
32 | } | ||
33 | |||
34 | /* Set the number of available ioctls. */ | ||
35 | wrqu->data.length = dev->wireless_handlers->num_private_args; | ||
36 | |||
37 | /* Copy structure to the user buffer. */ | ||
38 | memcpy(extra, dev->wireless_handlers->private_args, | ||
39 | sizeof(struct iw_priv_args) * wrqu->data.length); | ||
40 | |||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | /* Size (in bytes) of the various private data types */ | ||
45 | static const char iw_priv_type_size[] = { | ||
46 | 0, /* IW_PRIV_TYPE_NONE */ | ||
47 | 1, /* IW_PRIV_TYPE_BYTE */ | ||
48 | 1, /* IW_PRIV_TYPE_CHAR */ | ||
49 | 0, /* Not defined */ | ||
50 | sizeof(__u32), /* IW_PRIV_TYPE_INT */ | ||
51 | sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ | ||
52 | sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ | ||
53 | 0, /* Not defined */ | ||
54 | }; | ||
55 | |||
56 | static int get_priv_size(__u16 args) | ||
57 | { | ||
58 | int num = args & IW_PRIV_SIZE_MASK; | ||
59 | int type = (args & IW_PRIV_TYPE_MASK) >> 12; | ||
60 | |||
61 | return num * iw_priv_type_size[type]; | ||
62 | } | ||
63 | |||
64 | static int adjust_priv_size(__u16 args, struct iw_point *iwp) | ||
65 | { | ||
66 | int num = iwp->length; | ||
67 | int max = args & IW_PRIV_SIZE_MASK; | ||
68 | int type = (args & IW_PRIV_TYPE_MASK) >> 12; | ||
69 | |||
70 | /* Make sure the driver doesn't goof up */ | ||
71 | if (max < num) | ||
72 | num = max; | ||
73 | |||
74 | return num * iw_priv_type_size[type]; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * Wrapper to call a private Wireless Extension handler. | ||
79 | * We do various checks and also take care of moving data between | ||
80 | * user space and kernel space. | ||
81 | * It's not as nice and slimline as the standard wrapper. The cause | ||
82 | * is struct iw_priv_args, which was not really designed for the | ||
83 | * job we are going here. | ||
84 | * | ||
85 | * IMPORTANT : This function prevent to set and get data on the same | ||
86 | * IOCTL and enforce the SET/GET convention. Not doing it would be | ||
87 | * far too hairy... | ||
88 | * If you need to set and get data at the same time, please don't use | ||
89 | * a iw_handler but process it in your ioctl handler (i.e. use the | ||
90 | * old driver API). | ||
91 | */ | ||
92 | static int get_priv_descr_and_size(struct net_device *dev, unsigned int cmd, | ||
93 | const struct iw_priv_args **descrp) | ||
94 | { | ||
95 | const struct iw_priv_args *descr; | ||
96 | int i, extra_size; | ||
97 | |||
98 | descr = NULL; | ||
99 | for (i = 0; i < dev->wireless_handlers->num_private_args; i++) { | ||
100 | if (cmd == dev->wireless_handlers->private_args[i].cmd) { | ||
101 | descr = &dev->wireless_handlers->private_args[i]; | ||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | extra_size = 0; | ||
107 | if (descr) { | ||
108 | if (IW_IS_SET(cmd)) { | ||
109 | int offset = 0; /* For sub-ioctls */ | ||
110 | /* Check for sub-ioctl handler */ | ||
111 | if (descr->name[0] == '\0') | ||
112 | /* Reserve one int for sub-ioctl index */ | ||
113 | offset = sizeof(__u32); | ||
114 | |||
115 | /* Size of set arguments */ | ||
116 | extra_size = get_priv_size(descr->set_args); | ||
117 | |||
118 | /* Does it fits in iwr ? */ | ||
119 | if ((descr->set_args & IW_PRIV_SIZE_FIXED) && | ||
120 | ((extra_size + offset) <= IFNAMSIZ)) | ||
121 | extra_size = 0; | ||
122 | } else { | ||
123 | /* Size of get arguments */ | ||
124 | extra_size = get_priv_size(descr->get_args); | ||
125 | |||
126 | /* Does it fits in iwr ? */ | ||
127 | if ((descr->get_args & IW_PRIV_SIZE_FIXED) && | ||
128 | (extra_size <= IFNAMSIZ)) | ||
129 | extra_size = 0; | ||
130 | } | ||
131 | } | ||
132 | *descrp = descr; | ||
133 | return extra_size; | ||
134 | } | ||
135 | |||
136 | static int ioctl_private_iw_point(struct iw_point *iwp, unsigned int cmd, | ||
137 | const struct iw_priv_args *descr, | ||
138 | iw_handler handler, struct net_device *dev, | ||
139 | struct iw_request_info *info, int extra_size) | ||
140 | { | ||
141 | char *extra; | ||
142 | int err; | ||
143 | |||
144 | /* Check what user space is giving us */ | ||
145 | if (IW_IS_SET(cmd)) { | ||
146 | if (!iwp->pointer && iwp->length != 0) | ||
147 | return -EFAULT; | ||
148 | |||
149 | if (iwp->length > (descr->set_args & IW_PRIV_SIZE_MASK)) | ||
150 | return -E2BIG; | ||
151 | } else if (!iwp->pointer) | ||
152 | return -EFAULT; | ||
153 | |||
154 | extra = kmalloc(extra_size, GFP_KERNEL); | ||
155 | if (!extra) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | /* If it is a SET, get all the extra data in here */ | ||
159 | if (IW_IS_SET(cmd) && (iwp->length != 0)) { | ||
160 | if (copy_from_user(extra, iwp->pointer, extra_size)) { | ||
161 | err = -EFAULT; | ||
162 | goto out; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | /* Call the handler */ | ||
167 | err = handler(dev, info, (union iwreq_data *) iwp, extra); | ||
168 | |||
169 | /* If we have something to return to the user */ | ||
170 | if (!err && IW_IS_GET(cmd)) { | ||
171 | /* Adjust for the actual length if it's variable, | ||
172 | * avoid leaking kernel bits outside. | ||
173 | */ | ||
174 | if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) | ||
175 | extra_size = adjust_priv_size(descr->get_args, iwp); | ||
176 | |||
177 | if (copy_to_user(iwp->pointer, extra, extra_size)) | ||
178 | err = -EFAULT; | ||
179 | } | ||
180 | |||
181 | out: | ||
182 | kfree(extra); | ||
183 | return err; | ||
184 | } | ||
185 | |||
186 | int ioctl_private_call(struct net_device *dev, struct iwreq *iwr, | ||
187 | unsigned int cmd, struct iw_request_info *info, | ||
188 | iw_handler handler) | ||
189 | { | ||
190 | int extra_size = 0, ret = -EINVAL; | ||
191 | const struct iw_priv_args *descr; | ||
192 | |||
193 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | ||
194 | |||
195 | /* Check if we have a pointer to user space data or not. */ | ||
196 | if (extra_size == 0) { | ||
197 | /* No extra arguments. Trivial to handle */ | ||
198 | ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); | ||
199 | } else { | ||
200 | ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr, | ||
201 | handler, dev, info, extra_size); | ||
202 | } | ||
203 | |||
204 | /* Call commit handler if needed and defined */ | ||
205 | if (ret == -EIWCOMMIT) | ||
206 | ret = call_commit_handler(dev); | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | #ifdef CONFIG_COMPAT | ||
212 | int compat_private_call(struct net_device *dev, struct iwreq *iwr, | ||
213 | unsigned int cmd, struct iw_request_info *info, | ||
214 | iw_handler handler) | ||
215 | { | ||
216 | const struct iw_priv_args *descr; | ||
217 | int ret, extra_size; | ||
218 | |||
219 | extra_size = get_priv_descr_and_size(dev, cmd, &descr); | ||
220 | |||
221 | /* Check if we have a pointer to user space data or not. */ | ||
222 | if (extra_size == 0) { | ||
223 | /* No extra arguments. Trivial to handle */ | ||
224 | ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u)); | ||
225 | } else { | ||
226 | struct compat_iw_point *iwp_compat; | ||
227 | struct iw_point iwp; | ||
228 | |||
229 | iwp_compat = (struct compat_iw_point *) &iwr->u.data; | ||
230 | iwp.pointer = compat_ptr(iwp_compat->pointer); | ||
231 | iwp.length = iwp_compat->length; | ||
232 | iwp.flags = iwp_compat->flags; | ||
233 | |||
234 | ret = ioctl_private_iw_point(&iwp, cmd, descr, | ||
235 | handler, dev, info, extra_size); | ||
236 | |||
237 | iwp_compat->pointer = ptr_to_compat(iwp.pointer); | ||
238 | iwp_compat->length = iwp.length; | ||
239 | iwp_compat->flags = iwp.flags; | ||
240 | } | ||
241 | |||
242 | /* Call commit handler if needed and defined */ | ||
243 | if (ret == -EIWCOMMIT) | ||
244 | ret = call_commit_handler(dev); | ||
245 | |||
246 | return ret; | ||
247 | } | ||
248 | #endif | ||
diff --git a/net/wireless/wext-proc.c b/net/wireless/wext-proc.c new file mode 100644 index 000000000000..273a7f77c834 --- /dev/null +++ b/net/wireless/wext-proc.c | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * This file implement the Wireless Extensions proc API. | ||
3 | * | ||
4 | * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> | ||
5 | * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. | ||
6 | * | ||
7 | * (As all part of the Linux kernel, this file is GPL) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * The /proc/net/wireless file is a human readable user-space interface | ||
12 | * exporting various wireless specific statistics from the wireless devices. | ||
13 | * This is the most popular part of the Wireless Extensions ;-) | ||
14 | * | ||
15 | * This interface is a pure clone of /proc/net/dev (in net/core/dev.c). | ||
16 | * The content of the file is basically the content of "struct iw_statistics". | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/proc_fs.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/wireless.h> | ||
23 | #include <linux/netdevice.h> | ||
24 | #include <linux/rtnetlink.h> | ||
25 | #include <net/iw_handler.h> | ||
26 | #include <net/wext.h> | ||
27 | |||
28 | |||
29 | static void wireless_seq_printf_stats(struct seq_file *seq, | ||
30 | struct net_device *dev) | ||
31 | { | ||
32 | /* Get stats from the driver */ | ||
33 | struct iw_statistics *stats = get_wireless_stats(dev); | ||
34 | static struct iw_statistics nullstats = {}; | ||
35 | |||
36 | /* show device if it's wireless regardless of current stats */ | ||
37 | if (!stats) { | ||
38 | #ifdef CONFIG_WIRELESS_EXT | ||
39 | if (dev->wireless_handlers) | ||
40 | stats = &nullstats; | ||
41 | #endif | ||
42 | #ifdef CONFIG_CFG80211 | ||
43 | if (dev->ieee80211_ptr) | ||
44 | stats = &nullstats; | ||
45 | #endif | ||
46 | } | ||
47 | |||
48 | if (stats) { | ||
49 | seq_printf(seq, "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d " | ||
50 | "%6d %6d %6d\n", | ||
51 | dev->name, stats->status, stats->qual.qual, | ||
52 | stats->qual.updated & IW_QUAL_QUAL_UPDATED | ||
53 | ? '.' : ' ', | ||
54 | ((__s32) stats->qual.level) - | ||
55 | ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0), | ||
56 | stats->qual.updated & IW_QUAL_LEVEL_UPDATED | ||
57 | ? '.' : ' ', | ||
58 | ((__s32) stats->qual.noise) - | ||
59 | ((stats->qual.updated & IW_QUAL_DBM) ? 0x100 : 0), | ||
60 | stats->qual.updated & IW_QUAL_NOISE_UPDATED | ||
61 | ? '.' : ' ', | ||
62 | stats->discard.nwid, stats->discard.code, | ||
63 | stats->discard.fragment, stats->discard.retries, | ||
64 | stats->discard.misc, stats->miss.beacon); | ||
65 | |||
66 | if (stats != &nullstats) | ||
67 | stats->qual.updated &= ~IW_QUAL_ALL_UPDATED; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /* ---------------------------------------------------------------- */ | ||
72 | /* | ||
73 | * Print info for /proc/net/wireless (print all entries) | ||
74 | */ | ||
75 | static int wireless_dev_seq_show(struct seq_file *seq, void *v) | ||
76 | { | ||
77 | might_sleep(); | ||
78 | |||
79 | if (v == SEQ_START_TOKEN) | ||
80 | seq_printf(seq, "Inter-| sta-| Quality | Discarded " | ||
81 | "packets | Missed | WE\n" | ||
82 | " face | tus | link level noise | nwid " | ||
83 | "crypt frag retry misc | beacon | %d\n", | ||
84 | WIRELESS_EXT); | ||
85 | else | ||
86 | wireless_seq_printf_stats(seq, v); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos) | ||
91 | { | ||
92 | struct net *net = seq_file_net(seq); | ||
93 | loff_t off; | ||
94 | struct net_device *dev; | ||
95 | |||
96 | rtnl_lock(); | ||
97 | if (!*pos) | ||
98 | return SEQ_START_TOKEN; | ||
99 | |||
100 | off = 1; | ||
101 | for_each_netdev(net, dev) | ||
102 | if (off++ == *pos) | ||
103 | return dev; | ||
104 | return NULL; | ||
105 | } | ||
106 | |||
107 | static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
108 | { | ||
109 | struct net *net = seq_file_net(seq); | ||
110 | |||
111 | ++*pos; | ||
112 | |||
113 | return v == SEQ_START_TOKEN ? | ||
114 | first_net_device(net) : next_net_device(v); | ||
115 | } | ||
116 | |||
117 | static void wireless_dev_seq_stop(struct seq_file *seq, void *v) | ||
118 | { | ||
119 | rtnl_unlock(); | ||
120 | } | ||
121 | |||
122 | static const struct seq_operations wireless_seq_ops = { | ||
123 | .start = wireless_dev_seq_start, | ||
124 | .next = wireless_dev_seq_next, | ||
125 | .stop = wireless_dev_seq_stop, | ||
126 | .show = wireless_dev_seq_show, | ||
127 | }; | ||
128 | |||
129 | static int seq_open_wireless(struct inode *inode, struct file *file) | ||
130 | { | ||
131 | return seq_open_net(inode, file, &wireless_seq_ops, | ||
132 | sizeof(struct seq_net_private)); | ||
133 | } | ||
134 | |||
135 | static const struct file_operations wireless_seq_fops = { | ||
136 | .owner = THIS_MODULE, | ||
137 | .open = seq_open_wireless, | ||
138 | .read = seq_read, | ||
139 | .llseek = seq_lseek, | ||
140 | .release = seq_release_net, | ||
141 | }; | ||
142 | |||
143 | int wext_proc_init(struct net *net) | ||
144 | { | ||
145 | /* Create /proc/net/wireless entry */ | ||
146 | if (!proc_net_fops_create(net, "wireless", S_IRUGO, &wireless_seq_fops)) | ||
147 | return -ENOMEM; | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | void wext_proc_exit(struct net *net) | ||
153 | { | ||
154 | proc_net_remove(net, "wireless"); | ||
155 | } | ||
diff --git a/net/wireless/wext-spy.c b/net/wireless/wext-spy.c new file mode 100644 index 000000000000..6dcfe65a2d1a --- /dev/null +++ b/net/wireless/wext-spy.c | |||
@@ -0,0 +1,231 @@ | |||
1 | /* | ||
2 | * This file implement the Wireless Extensions spy API. | ||
3 | * | ||
4 | * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> | ||
5 | * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. | ||
6 | * | ||
7 | * (As all part of the Linux kernel, this file is GPL) | ||
8 | */ | ||
9 | |||
10 | #include <linux/wireless.h> | ||
11 | #include <linux/netdevice.h> | ||
12 | #include <linux/etherdevice.h> | ||
13 | #include <net/iw_handler.h> | ||
14 | #include <net/arp.h> | ||
15 | #include <net/wext.h> | ||
16 | |||
17 | static inline struct iw_spy_data *get_spydata(struct net_device *dev) | ||
18 | { | ||
19 | /* This is the new way */ | ||
20 | if (dev->wireless_data) | ||
21 | return dev->wireless_data->spy_data; | ||
22 | return NULL; | ||
23 | } | ||
24 | |||
25 | int iw_handler_set_spy(struct net_device * dev, | ||
26 | struct iw_request_info * info, | ||
27 | union iwreq_data * wrqu, | ||
28 | char * extra) | ||
29 | { | ||
30 | struct iw_spy_data * spydata = get_spydata(dev); | ||
31 | struct sockaddr * address = (struct sockaddr *) extra; | ||
32 | |||
33 | /* Make sure driver is not buggy or using the old API */ | ||
34 | if (!spydata) | ||
35 | return -EOPNOTSUPP; | ||
36 | |||
37 | /* Disable spy collection while we copy the addresses. | ||
38 | * While we copy addresses, any call to wireless_spy_update() | ||
39 | * will NOP. This is OK, as anyway the addresses are changing. */ | ||
40 | spydata->spy_number = 0; | ||
41 | |||
42 | /* We want to operate without locking, because wireless_spy_update() | ||
43 | * most likely will happen in the interrupt handler, and therefore | ||
44 | * have its own locking constraints and needs performance. | ||
45 | * The rtnl_lock() make sure we don't race with the other iw_handlers. | ||
46 | * This make sure wireless_spy_update() "see" that the spy list | ||
47 | * is temporarily disabled. */ | ||
48 | smp_wmb(); | ||
49 | |||
50 | /* Are there are addresses to copy? */ | ||
51 | if (wrqu->data.length > 0) { | ||
52 | int i; | ||
53 | |||
54 | /* Copy addresses */ | ||
55 | for (i = 0; i < wrqu->data.length; i++) | ||
56 | memcpy(spydata->spy_address[i], address[i].sa_data, | ||
57 | ETH_ALEN); | ||
58 | /* Reset stats */ | ||
59 | memset(spydata->spy_stat, 0, | ||
60 | sizeof(struct iw_quality) * IW_MAX_SPY); | ||
61 | } | ||
62 | |||
63 | /* Make sure above is updated before re-enabling */ | ||
64 | smp_wmb(); | ||
65 | |||
66 | /* Enable addresses */ | ||
67 | spydata->spy_number = wrqu->data.length; | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | EXPORT_SYMBOL(iw_handler_set_spy); | ||
72 | |||
73 | int iw_handler_get_spy(struct net_device * dev, | ||
74 | struct iw_request_info * info, | ||
75 | union iwreq_data * wrqu, | ||
76 | char * extra) | ||
77 | { | ||
78 | struct iw_spy_data * spydata = get_spydata(dev); | ||
79 | struct sockaddr * address = (struct sockaddr *) extra; | ||
80 | int i; | ||
81 | |||
82 | /* Make sure driver is not buggy or using the old API */ | ||
83 | if (!spydata) | ||
84 | return -EOPNOTSUPP; | ||
85 | |||
86 | wrqu->data.length = spydata->spy_number; | ||
87 | |||
88 | /* Copy addresses. */ | ||
89 | for (i = 0; i < spydata->spy_number; i++) { | ||
90 | memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN); | ||
91 | address[i].sa_family = AF_UNIX; | ||
92 | } | ||
93 | /* Copy stats to the user buffer (just after). */ | ||
94 | if (spydata->spy_number > 0) | ||
95 | memcpy(extra + (sizeof(struct sockaddr) *spydata->spy_number), | ||
96 | spydata->spy_stat, | ||
97 | sizeof(struct iw_quality) * spydata->spy_number); | ||
98 | /* Reset updated flags. */ | ||
99 | for (i = 0; i < spydata->spy_number; i++) | ||
100 | spydata->spy_stat[i].updated &= ~IW_QUAL_ALL_UPDATED; | ||
101 | return 0; | ||
102 | } | ||
103 | EXPORT_SYMBOL(iw_handler_get_spy); | ||
104 | |||
105 | /*------------------------------------------------------------------*/ | ||
106 | /* | ||
107 | * Standard Wireless Handler : set spy threshold | ||
108 | */ | ||
109 | int iw_handler_set_thrspy(struct net_device * dev, | ||
110 | struct iw_request_info *info, | ||
111 | union iwreq_data * wrqu, | ||
112 | char * extra) | ||
113 | { | ||
114 | struct iw_spy_data * spydata = get_spydata(dev); | ||
115 | struct iw_thrspy * threshold = (struct iw_thrspy *) extra; | ||
116 | |||
117 | /* Make sure driver is not buggy or using the old API */ | ||
118 | if (!spydata) | ||
119 | return -EOPNOTSUPP; | ||
120 | |||
121 | /* Just do it */ | ||
122 | memcpy(&(spydata->spy_thr_low), &(threshold->low), | ||
123 | 2 * sizeof(struct iw_quality)); | ||
124 | |||
125 | /* Clear flag */ | ||
126 | memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under)); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | EXPORT_SYMBOL(iw_handler_set_thrspy); | ||
131 | |||
132 | /*------------------------------------------------------------------*/ | ||
133 | /* | ||
134 | * Standard Wireless Handler : get spy threshold | ||
135 | */ | ||
136 | int iw_handler_get_thrspy(struct net_device * dev, | ||
137 | struct iw_request_info *info, | ||
138 | union iwreq_data * wrqu, | ||
139 | char * extra) | ||
140 | { | ||
141 | struct iw_spy_data * spydata = get_spydata(dev); | ||
142 | struct iw_thrspy * threshold = (struct iw_thrspy *) extra; | ||
143 | |||
144 | /* Make sure driver is not buggy or using the old API */ | ||
145 | if (!spydata) | ||
146 | return -EOPNOTSUPP; | ||
147 | |||
148 | /* Just do it */ | ||
149 | memcpy(&(threshold->low), &(spydata->spy_thr_low), | ||
150 | 2 * sizeof(struct iw_quality)); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | EXPORT_SYMBOL(iw_handler_get_thrspy); | ||
155 | |||
156 | /*------------------------------------------------------------------*/ | ||
157 | /* | ||
158 | * Prepare and send a Spy Threshold event | ||
159 | */ | ||
160 | static void iw_send_thrspy_event(struct net_device * dev, | ||
161 | struct iw_spy_data * spydata, | ||
162 | unsigned char * address, | ||
163 | struct iw_quality * wstats) | ||
164 | { | ||
165 | union iwreq_data wrqu; | ||
166 | struct iw_thrspy threshold; | ||
167 | |||
168 | /* Init */ | ||
169 | wrqu.data.length = 1; | ||
170 | wrqu.data.flags = 0; | ||
171 | /* Copy address */ | ||
172 | memcpy(threshold.addr.sa_data, address, ETH_ALEN); | ||
173 | threshold.addr.sa_family = ARPHRD_ETHER; | ||
174 | /* Copy stats */ | ||
175 | memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality)); | ||
176 | /* Copy also thresholds */ | ||
177 | memcpy(&(threshold.low), &(spydata->spy_thr_low), | ||
178 | 2 * sizeof(struct iw_quality)); | ||
179 | |||
180 | /* Send event to user space */ | ||
181 | wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold); | ||
182 | } | ||
183 | |||
184 | /* ---------------------------------------------------------------- */ | ||
185 | /* | ||
186 | * Call for the driver to update the spy data. | ||
187 | * For now, the spy data is a simple array. As the size of the array is | ||
188 | * small, this is good enough. If we wanted to support larger number of | ||
189 | * spy addresses, we should use something more efficient... | ||
190 | */ | ||
191 | void wireless_spy_update(struct net_device * dev, | ||
192 | unsigned char * address, | ||
193 | struct iw_quality * wstats) | ||
194 | { | ||
195 | struct iw_spy_data * spydata = get_spydata(dev); | ||
196 | int i; | ||
197 | int match = -1; | ||
198 | |||
199 | /* Make sure driver is not buggy or using the old API */ | ||
200 | if (!spydata) | ||
201 | return; | ||
202 | |||
203 | /* Update all records that match */ | ||
204 | for (i = 0; i < spydata->spy_number; i++) | ||
205 | if (!compare_ether_addr(address, spydata->spy_address[i])) { | ||
206 | memcpy(&(spydata->spy_stat[i]), wstats, | ||
207 | sizeof(struct iw_quality)); | ||
208 | match = i; | ||
209 | } | ||
210 | |||
211 | /* Generate an event if we cross the spy threshold. | ||
212 | * To avoid event storms, we have a simple hysteresis : we generate | ||
213 | * event only when we go under the low threshold or above the | ||
214 | * high threshold. */ | ||
215 | if (match >= 0) { | ||
216 | if (spydata->spy_thr_under[match]) { | ||
217 | if (wstats->level > spydata->spy_thr_high.level) { | ||
218 | spydata->spy_thr_under[match] = 0; | ||
219 | iw_send_thrspy_event(dev, spydata, | ||
220 | address, wstats); | ||
221 | } | ||
222 | } else { | ||
223 | if (wstats->level < spydata->spy_thr_low.level) { | ||
224 | spydata->spy_thr_under[match] = 1; | ||
225 | iw_send_thrspy_event(dev, spydata, | ||
226 | address, wstats); | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | } | ||
231 | EXPORT_SYMBOL(wireless_spy_update); | ||