diff options
author | David S. Miller <davem@davemloft.net> | 2008-11-26 18:28:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-26 18:28:40 -0500 |
commit | b5ddedc9cc01b1d86015af08c5f1694191804530 (patch) | |
tree | db08f24da9ef4dcec0976ee4de4d77e5e596057e | |
parent | 244e6c2d0724bc4908a1995804704bdee3b31528 (diff) | |
parent | b235507cc5e552b9e75678d596727249e8fba01b (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
83 files changed, 6608 insertions, 5991 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 84b49c83ae67..ea543fcf2687 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -214,6 +214,21 @@ config HERMES | |||
214 | configure your card and that /etc/pcmcia/wireless.opts works : | 214 | configure your card and that /etc/pcmcia/wireless.opts works : |
215 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html> | 215 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html> |
216 | 216 | ||
217 | config HERMES_CACHE_FW_ON_INIT | ||
218 | bool "Cache Hermes firmware on driver initialisation" | ||
219 | depends on HERMES | ||
220 | default y | ||
221 | ---help--- | ||
222 | Say Y to cache any firmware required by the Hermes drivers | ||
223 | on startup. The firmware will remain cached until the | ||
224 | driver is unloaded. The cache uses 64K of RAM. | ||
225 | |||
226 | Otherwise load the firmware from userspace as required. In | ||
227 | this case the driver should be unloaded and restarted | ||
228 | whenever the firmware is changed. | ||
229 | |||
230 | If you are not sure, say Y. | ||
231 | |||
217 | config APPLE_AIRPORT | 232 | config APPLE_AIRPORT |
218 | tristate "Apple Airport support (built-in)" | 233 | tristate "Apple Airport support (built-in)" |
219 | depends on PPC_PMAC && HERMES | 234 | depends on PPC_PMAC && HERMES |
@@ -508,7 +523,7 @@ config RTL8180 | |||
508 | 523 | ||
509 | config RTL8187 | 524 | config RTL8187 |
510 | tristate "Realtek 8187 and 8187B USB support" | 525 | tristate "Realtek 8187 and 8187B USB support" |
511 | depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL | 526 | depends on MAC80211 && USB && WLAN_80211 |
512 | select EEPROM_93CX6 | 527 | select EEPROM_93CX6 |
513 | ---help--- | 528 | ---help--- |
514 | This is a driver for RTL8187 and RTL8187B based cards. | 529 | This is a driver for RTL8187 and RTL8187B based cards. |
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index a725bb94a52d..5ee2dd1814c2 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -821,13 +821,6 @@ struct ath5k_athchan_2ghz { | |||
821 | return (false); \ | 821 | return (false); \ |
822 | } while (0) | 822 | } while (0) |
823 | 823 | ||
824 | enum ath5k_ant_setting { | ||
825 | AR5K_ANT_VARIABLE = 0, /* variable by programming */ | ||
826 | AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ | ||
827 | AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */ | ||
828 | AR5K_ANT_MAX = 3, | ||
829 | }; | ||
830 | |||
831 | /* | 824 | /* |
832 | * Hardware interrupt abstraction | 825 | * Hardware interrupt abstraction |
833 | */ | 826 | */ |
diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c index 51d569883cdd..49d82d79d3fc 100644 --- a/drivers/net/wireless/ath5k/attach.c +++ b/drivers/net/wireless/ath5k/attach.c | |||
@@ -106,7 +106,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
106 | { | 106 | { |
107 | struct ath5k_hw *ah; | 107 | struct ath5k_hw *ah; |
108 | struct pci_dev *pdev = sc->pdev; | 108 | struct pci_dev *pdev = sc->pdev; |
109 | u8 mac[ETH_ALEN]; | 109 | u8 mac[ETH_ALEN] = {}; |
110 | int ret; | 110 | int ret; |
111 | u32 srev; | 111 | u32 srev; |
112 | 112 | ||
@@ -317,15 +317,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) | |||
317 | goto err_free; | 317 | goto err_free; |
318 | } | 318 | } |
319 | 319 | ||
320 | /* Set MAC address */ | 320 | /* MAC address is cleared until add_interface */ |
321 | ret = ath5k_eeprom_read_mac(ah, mac); | ||
322 | if (ret) { | ||
323 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", | ||
324 | sc->pdev->device); | ||
325 | goto err_free; | ||
326 | } | ||
327 | |||
328 | ath5k_hw_set_lladdr(ah, mac); | 321 | ath5k_hw_set_lladdr(ah, mac); |
322 | |||
329 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 323 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
330 | memset(ah->ah_bssid, 0xff, ETH_ALEN); | 324 | memset(ah->ah_bssid, 0xff, ETH_ALEN); |
331 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); | 325 | ath5k_hw_set_associd(ah, ah->ah_bssid, 0); |
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 34cd1a4a297f..4bcea5a9d70b 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -200,7 +200,7 @@ static int ath5k_pci_resume(struct pci_dev *pdev); | |||
200 | #endif /* CONFIG_PM */ | 200 | #endif /* CONFIG_PM */ |
201 | 201 | ||
202 | static struct pci_driver ath5k_pci_driver = { | 202 | static struct pci_driver ath5k_pci_driver = { |
203 | .name = "ath5k_pci", | 203 | .name = KBUILD_MODNAME, |
204 | .id_table = ath5k_pci_id_table, | 204 | .id_table = ath5k_pci_id_table, |
205 | .probe = ath5k_pci_probe, | 205 | .probe = ath5k_pci_probe, |
206 | .remove = __devexit_p(ath5k_pci_remove), | 206 | .remove = __devexit_p(ath5k_pci_remove), |
@@ -707,7 +707,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
707 | { | 707 | { |
708 | struct ath5k_softc *sc = hw->priv; | 708 | struct ath5k_softc *sc = hw->priv; |
709 | struct ath5k_hw *ah = sc->ah; | 709 | struct ath5k_hw *ah = sc->ah; |
710 | u8 mac[ETH_ALEN]; | 710 | u8 mac[ETH_ALEN] = {}; |
711 | int ret; | 711 | int ret; |
712 | 712 | ||
713 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); | 713 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); |
@@ -777,7 +777,13 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
777 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); | 777 | tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); |
778 | setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); | 778 | setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); |
779 | 779 | ||
780 | ath5k_hw_get_lladdr(ah, mac); | 780 | ret = ath5k_eeprom_read_mac(ah, mac); |
781 | if (ret) { | ||
782 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", | ||
783 | sc->pdev->device); | ||
784 | goto err_queues; | ||
785 | } | ||
786 | |||
781 | SET_IEEE80211_PERM_ADDR(hw, mac); | 787 | SET_IEEE80211_PERM_ADDR(hw, mac); |
782 | /* All MAC address bits matter for ACKs */ | 788 | /* All MAC address bits matter for ACKs */ |
783 | memset(sc->bssidmask, 0xff, ETH_ALEN); | 789 | memset(sc->bssidmask, 0xff, ETH_ALEN); |
@@ -2765,6 +2771,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2765 | /* Set to a reasonable value. Note that this will | 2771 | /* Set to a reasonable value. Note that this will |
2766 | * be set to mac80211's value at ath5k_config(). */ | 2772 | * be set to mac80211's value at ath5k_config(). */ |
2767 | sc->bintval = 1000; | 2773 | sc->bintval = 1000; |
2774 | ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); | ||
2768 | 2775 | ||
2769 | ret = 0; | 2776 | ret = 0; |
2770 | end: | 2777 | end: |
@@ -2777,11 +2784,13 @@ ath5k_remove_interface(struct ieee80211_hw *hw, | |||
2777 | struct ieee80211_if_init_conf *conf) | 2784 | struct ieee80211_if_init_conf *conf) |
2778 | { | 2785 | { |
2779 | struct ath5k_softc *sc = hw->priv; | 2786 | struct ath5k_softc *sc = hw->priv; |
2787 | u8 mac[ETH_ALEN] = {}; | ||
2780 | 2788 | ||
2781 | mutex_lock(&sc->lock); | 2789 | mutex_lock(&sc->lock); |
2782 | if (sc->vif != conf->vif) | 2790 | if (sc->vif != conf->vif) |
2783 | goto end; | 2791 | goto end; |
2784 | 2792 | ||
2793 | ath5k_hw_set_lladdr(sc->ah, mac); | ||
2785 | sc->vif = NULL; | 2794 | sc->vif = NULL; |
2786 | end: | 2795 | end: |
2787 | mutex_unlock(&sc->lock); | 2796 | mutex_unlock(&sc->lock); |
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c index a883839b6a9f..1cb7edfae625 100644 --- a/drivers/net/wireless/ath5k/eeprom.c +++ b/drivers/net/wireless/ath5k/eeprom.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> | 2 | * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> |
3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> | 3 | * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> |
4 | * Copyright (c) 2008 Felix Fietkau <nbd@openwrt.org> | ||
4 | * | 5 | * |
5 | * Permission to use, copy, modify, and distribute this software for any | 6 | * Permission to use, copy, modify, and distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -63,8 +64,8 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) | |||
63 | /* | 64 | /* |
64 | * Translate binary channel representation in EEPROM to frequency | 65 | * Translate binary channel representation in EEPROM to frequency |
65 | */ | 66 | */ |
66 | static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin, | 67 | static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, |
67 | unsigned int mode) | 68 | unsigned int mode) |
68 | { | 69 | { |
69 | u16 val; | 70 | u16 val; |
70 | 71 | ||
@@ -72,13 +73,13 @@ static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin, | |||
72 | return bin; | 73 | return bin; |
73 | 74 | ||
74 | if (mode == AR5K_EEPROM_MODE_11A) { | 75 | if (mode == AR5K_EEPROM_MODE_11A) { |
75 | if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2) | 76 | if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) |
76 | val = (5 * bin) + 4800; | 77 | val = (5 * bin) + 4800; |
77 | else | 78 | else |
78 | val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : | 79 | val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : |
79 | (bin * 10) + 5100; | 80 | (bin * 10) + 5100; |
80 | } else { | 81 | } else { |
81 | if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2) | 82 | if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) |
82 | val = bin + 2300; | 83 | val = bin + 2300; |
83 | else | 84 | else |
84 | val = bin + 2400; | 85 | val = bin + 2400; |
@@ -88,6 +89,71 @@ static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin, | |||
88 | } | 89 | } |
89 | 90 | ||
90 | /* | 91 | /* |
92 | * Initialize eeprom & capabilities structs | ||
93 | */ | ||
94 | static int | ||
95 | ath5k_eeprom_init_header(struct ath5k_hw *ah) | ||
96 | { | ||
97 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
98 | int ret; | ||
99 | u16 val; | ||
100 | |||
101 | /* Initial TX thermal adjustment values */ | ||
102 | ee->ee_tx_clip = 4; | ||
103 | ee->ee_pwd_84 = ee->ee_pwd_90 = 1; | ||
104 | ee->ee_gain_select = 1; | ||
105 | |||
106 | /* | ||
107 | * Read values from EEPROM and store them in the capability structure | ||
108 | */ | ||
109 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic); | ||
110 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect); | ||
111 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain); | ||
112 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version); | ||
113 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header); | ||
114 | |||
115 | /* Return if we have an old EEPROM */ | ||
116 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) | ||
117 | return 0; | ||
118 | |||
119 | #ifdef notyet | ||
120 | /* | ||
121 | * Validate the checksum of the EEPROM date. There are some | ||
122 | * devices with invalid EEPROMs. | ||
123 | */ | ||
124 | for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { | ||
125 | AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); | ||
126 | cksum ^= val; | ||
127 | } | ||
128 | if (cksum != AR5K_EEPROM_INFO_CKSUM) { | ||
129 | ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); | ||
130 | return -EIO; | ||
131 | } | ||
132 | #endif | ||
133 | |||
134 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), | ||
135 | ee_ant_gain); | ||
136 | |||
137 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
138 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); | ||
139 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); | ||
140 | } | ||
141 | |||
142 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { | ||
143 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); | ||
144 | ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; | ||
145 | ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; | ||
146 | |||
147 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); | ||
148 | ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; | ||
149 | ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; | ||
150 | } | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | |||
156 | /* | ||
91 | * Read antenna infos from eeprom | 157 | * Read antenna infos from eeprom |
92 | */ | 158 | */ |
93 | static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, | 159 | static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, |
@@ -100,7 +166,7 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, | |||
100 | 166 | ||
101 | AR5K_EEPROM_READ(o++, val); | 167 | AR5K_EEPROM_READ(o++, val); |
102 | ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; | 168 | ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; |
103 | ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f; | 169 | ee->ee_atn_tx_rx[mode] = (val >> 2) & 0x3f; |
104 | ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; | 170 | ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; |
105 | 171 | ||
106 | AR5K_EEPROM_READ(o++, val); | 172 | AR5K_EEPROM_READ(o++, val); |
@@ -157,6 +223,30 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
157 | u16 val; | 223 | u16 val; |
158 | int ret; | 224 | int ret; |
159 | 225 | ||
226 | ee->ee_n_piers[mode] = 0; | ||
227 | AR5K_EEPROM_READ(o++, val); | ||
228 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | ||
229 | switch(mode) { | ||
230 | case AR5K_EEPROM_MODE_11A: | ||
231 | ee->ee_ob[mode][3] = (val >> 5) & 0x7; | ||
232 | ee->ee_db[mode][3] = (val >> 2) & 0x7; | ||
233 | ee->ee_ob[mode][2] = (val << 1) & 0x7; | ||
234 | |||
235 | AR5K_EEPROM_READ(o++, val); | ||
236 | ee->ee_ob[mode][2] |= (val >> 15) & 0x1; | ||
237 | ee->ee_db[mode][2] = (val >> 12) & 0x7; | ||
238 | ee->ee_ob[mode][1] = (val >> 9) & 0x7; | ||
239 | ee->ee_db[mode][1] = (val >> 6) & 0x7; | ||
240 | ee->ee_ob[mode][0] = (val >> 3) & 0x7; | ||
241 | ee->ee_db[mode][0] = val & 0x7; | ||
242 | break; | ||
243 | case AR5K_EEPROM_MODE_11G: | ||
244 | case AR5K_EEPROM_MODE_11B: | ||
245 | ee->ee_ob[mode][1] = (val >> 4) & 0x7; | ||
246 | ee->ee_db[mode][1] = val & 0x7; | ||
247 | break; | ||
248 | } | ||
249 | |||
160 | AR5K_EEPROM_READ(o++, val); | 250 | AR5K_EEPROM_READ(o++, val); |
161 | ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; | 251 | ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; |
162 | ee->ee_thr_62[mode] = val & 0xff; | 252 | ee->ee_thr_62[mode] = val & 0xff; |
@@ -209,8 +299,11 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
209 | AR5K_EEPROM_READ(o++, val); | 299 | AR5K_EEPROM_READ(o++, val); |
210 | ee->ee_i_gain[mode] |= (val << 3) & 0x38; | 300 | ee->ee_i_gain[mode] |= (val << 3) & 0x38; |
211 | 301 | ||
212 | if (mode == AR5K_EEPROM_MODE_11G) | 302 | if (mode == AR5K_EEPROM_MODE_11G) { |
213 | ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; | 303 | ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; |
304 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6) | ||
305 | ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; | ||
306 | } | ||
214 | } | 307 | } |
215 | 308 | ||
216 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && | 309 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && |
@@ -219,10 +312,77 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
219 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | 312 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; |
220 | } | 313 | } |
221 | 314 | ||
222 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 && | 315 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0) |
223 | mode == AR5K_EEPROM_MODE_11G) | 316 | goto done; |
224 | ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; | 317 | |
318 | switch(mode) { | ||
319 | case AR5K_EEPROM_MODE_11A: | ||
320 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1) | ||
321 | break; | ||
322 | |||
323 | AR5K_EEPROM_READ(o++, val); | ||
324 | ee->ee_margin_tx_rx[mode] = val & 0x3f; | ||
325 | break; | ||
326 | case AR5K_EEPROM_MODE_11B: | ||
327 | AR5K_EEPROM_READ(o++, val); | ||
328 | |||
329 | ee->ee_pwr_cal_b[0].freq = | ||
330 | ath5k_eeprom_bin2freq(ee, val & 0xff, mode); | ||
331 | if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS) | ||
332 | ee->ee_n_piers[mode]++; | ||
333 | |||
334 | ee->ee_pwr_cal_b[1].freq = | ||
335 | ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); | ||
336 | if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS) | ||
337 | ee->ee_n_piers[mode]++; | ||
338 | |||
339 | AR5K_EEPROM_READ(o++, val); | ||
340 | ee->ee_pwr_cal_b[2].freq = | ||
341 | ath5k_eeprom_bin2freq(ee, val & 0xff, mode); | ||
342 | if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS) | ||
343 | ee->ee_n_piers[mode]++; | ||
344 | |||
345 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
346 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | ||
347 | break; | ||
348 | case AR5K_EEPROM_MODE_11G: | ||
349 | AR5K_EEPROM_READ(o++, val); | ||
350 | |||
351 | ee->ee_pwr_cal_g[0].freq = | ||
352 | ath5k_eeprom_bin2freq(ee, val & 0xff, mode); | ||
353 | if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS) | ||
354 | ee->ee_n_piers[mode]++; | ||
355 | |||
356 | ee->ee_pwr_cal_g[1].freq = | ||
357 | ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); | ||
358 | if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS) | ||
359 | ee->ee_n_piers[mode]++; | ||
360 | |||
361 | AR5K_EEPROM_READ(o++, val); | ||
362 | ee->ee_turbo_max_power[mode] = val & 0x7f; | ||
363 | ee->ee_xr_power[mode] = (val >> 7) & 0x3f; | ||
364 | |||
365 | AR5K_EEPROM_READ(o++, val); | ||
366 | ee->ee_pwr_cal_g[2].freq = | ||
367 | ath5k_eeprom_bin2freq(ee, val & 0xff, mode); | ||
368 | if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS) | ||
369 | ee->ee_n_piers[mode]++; | ||
225 | 370 | ||
371 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | ||
372 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | ||
373 | |||
374 | AR5K_EEPROM_READ(o++, val); | ||
375 | ee->ee_i_cal[mode] = (val >> 8) & 0x3f; | ||
376 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | ||
377 | |||
378 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { | ||
379 | AR5K_EEPROM_READ(o++, val); | ||
380 | ee->ee_cck_ofdm_gain_delta = val & 0xff; | ||
381 | } | ||
382 | break; | ||
383 | } | ||
384 | |||
385 | done: | ||
226 | /* return new offset */ | 386 | /* return new offset */ |
227 | *offset = o; | 387 | *offset = o; |
228 | 388 | ||
@@ -230,204 +390,944 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
230 | } | 390 | } |
231 | 391 | ||
232 | /* | 392 | /* |
233 | * Initialize eeprom & capabilities structs | 393 | * Read turbo mode information on newer EEPROM versions |
234 | */ | 394 | */ |
235 | int ath5k_eeprom_init(struct ath5k_hw *ah) | 395 | static int |
396 | ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah, | ||
397 | u32 *offset, unsigned int mode) | ||
236 | { | 398 | { |
237 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 399 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
238 | unsigned int mode, i; | 400 | u32 o = *offset; |
239 | int ret; | ||
240 | u32 offset; | ||
241 | u16 val; | 401 | u16 val; |
402 | int ret; | ||
242 | 403 | ||
243 | /* Initial TX thermal adjustment values */ | 404 | if (ee->ee_version < AR5K_EEPROM_VERSION_5_0) |
244 | ee->ee_tx_clip = 4; | 405 | return 0; |
245 | ee->ee_pwd_84 = ee->ee_pwd_90 = 1; | ||
246 | ee->ee_gain_select = 1; | ||
247 | 406 | ||
248 | /* | 407 | switch (mode){ |
249 | * Read values from EEPROM and store them in the capability structure | 408 | case AR5K_EEPROM_MODE_11A: |
250 | */ | 409 | ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f; |
251 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic); | ||
252 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect); | ||
253 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain); | ||
254 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version); | ||
255 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header); | ||
256 | 410 | ||
257 | /* Return if we have an old EEPROM */ | 411 | ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7; |
258 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) | 412 | AR5K_EEPROM_READ(o++, val); |
259 | return 0; | 413 | ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3; |
414 | ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f; | ||
415 | |||
416 | ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f; | ||
417 | AR5K_EEPROM_READ(o++, val); | ||
418 | ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7; | ||
419 | ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff; | ||
420 | |||
421 | if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2) | ||
422 | ee->ee_pd_gain_overlap = (val >> 9) & 0xf; | ||
423 | break; | ||
424 | case AR5K_EEPROM_MODE_11G: | ||
425 | ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f; | ||
426 | |||
427 | ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7; | ||
428 | AR5K_EEPROM_READ(o++, val); | ||
429 | ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1; | ||
430 | ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f; | ||
431 | |||
432 | ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f; | ||
433 | AR5K_EEPROM_READ(o++, val); | ||
434 | ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5; | ||
435 | ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff; | ||
436 | break; | ||
437 | } | ||
438 | |||
439 | /* return new offset */ | ||
440 | *offset = o; | ||
441 | |||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | |||
446 | static int | ||
447 | ath5k_eeprom_init_modes(struct ath5k_hw *ah) | ||
448 | { | ||
449 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
450 | u32 mode_offset[3]; | ||
451 | unsigned int mode; | ||
452 | u32 offset; | ||
453 | int ret; | ||
260 | 454 | ||
261 | #ifdef notyet | ||
262 | /* | 455 | /* |
263 | * Validate the checksum of the EEPROM date. There are some | 456 | * Get values for all modes |
264 | * devices with invalid EEPROMs. | ||
265 | */ | 457 | */ |
266 | for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) { | 458 | mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version); |
267 | AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); | 459 | mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version); |
268 | cksum ^= val; | 460 | mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version); |
461 | |||
462 | ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] = | ||
463 | AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); | ||
464 | |||
465 | for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) { | ||
466 | offset = mode_offset[mode]; | ||
467 | |||
468 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | ||
469 | if (ret) | ||
470 | return ret; | ||
471 | |||
472 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
473 | if (ret) | ||
474 | return ret; | ||
475 | |||
476 | ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode); | ||
477 | if (ret) | ||
478 | return ret; | ||
269 | } | 479 | } |
270 | if (cksum != AR5K_EEPROM_INFO_CKSUM) { | 480 | |
271 | ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum); | 481 | /* override for older eeprom versions for better performance */ |
272 | return -EIO; | 482 | if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) { |
483 | ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15; | ||
484 | ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28; | ||
485 | ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28; | ||
273 | } | 486 | } |
274 | #endif | ||
275 | 487 | ||
276 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), | 488 | return 0; |
277 | ee_ant_gain); | 489 | } |
278 | 490 | ||
279 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | 491 | static inline void |
280 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); | 492 | ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) |
281 | AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); | 493 | { |
282 | } | 494 | const static u16 intercepts3[] = |
495 | { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; | ||
496 | const static u16 intercepts3_2[] = | ||
497 | { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; | ||
498 | const u16 *ip; | ||
499 | int i; | ||
500 | |||
501 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2) | ||
502 | ip = intercepts3_2; | ||
503 | else | ||
504 | ip = intercepts3; | ||
283 | 505 | ||
284 | if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { | 506 | for (i = 0; i < ARRAY_SIZE(intercepts3); i++) |
285 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); | 507 | *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100; |
286 | ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; | 508 | } |
287 | ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; | ||
288 | 509 | ||
289 | AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); | 510 | static inline int |
290 | ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; | 511 | ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, |
291 | ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; | 512 | struct ath5k_chan_pcal_info *pc, u8 *count) |
513 | { | ||
514 | int o = *offset; | ||
515 | int i = 0; | ||
516 | u8 f1, f2; | ||
517 | int ret; | ||
518 | u16 val; | ||
519 | |||
520 | while(i < max) { | ||
521 | AR5K_EEPROM_READ(o++, val); | ||
522 | |||
523 | f1 = (val >> 8) & 0xff; | ||
524 | f2 = val & 0xff; | ||
525 | |||
526 | if (f1) | ||
527 | pc[i++].freq = f1; | ||
528 | |||
529 | if (f2) | ||
530 | pc[i++].freq = f2; | ||
531 | |||
532 | if (!f1 || !f2) | ||
533 | break; | ||
292 | } | 534 | } |
535 | *offset = o; | ||
536 | *count = i; | ||
293 | 537 | ||
294 | /* | 538 | return 0; |
295 | * Get conformance test limit values | 539 | } |
296 | */ | 540 | |
297 | offset = AR5K_EEPROM_CTL(ah->ah_ee_version); | 541 | static int |
298 | ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version); | 542 | ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) |
543 | { | ||
544 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
545 | struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; | ||
546 | int i, ret; | ||
547 | u16 val; | ||
548 | u8 mask; | ||
549 | |||
550 | if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { | ||
551 | ath5k_eeprom_read_freq_list(ah, &offset, | ||
552 | AR5K_EEPROM_N_5GHZ_CHAN, pcal, | ||
553 | &ee->ee_n_piers[AR5K_EEPROM_MODE_11A]); | ||
554 | } else { | ||
555 | mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version); | ||
299 | 556 | ||
300 | for (i = 0; i < ee->ee_ctls; i++) { | ||
301 | AR5K_EEPROM_READ(offset++, val); | 557 | AR5K_EEPROM_READ(offset++, val); |
302 | ee->ee_ctl[i] = (val >> 8) & 0xff; | 558 | pcal[0].freq = (val >> 9) & mask; |
303 | ee->ee_ctl[i + 1] = val & 0xff; | 559 | pcal[1].freq = (val >> 2) & mask; |
560 | pcal[2].freq = (val << 5) & mask; | ||
561 | |||
562 | AR5K_EEPROM_READ(offset++, val); | ||
563 | pcal[2].freq |= (val >> 11) & 0x1f; | ||
564 | pcal[3].freq = (val >> 4) & mask; | ||
565 | pcal[4].freq = (val << 3) & mask; | ||
566 | |||
567 | AR5K_EEPROM_READ(offset++, val); | ||
568 | pcal[4].freq |= (val >> 13) & 0x7; | ||
569 | pcal[5].freq = (val >> 6) & mask; | ||
570 | pcal[6].freq = (val << 1) & mask; | ||
571 | |||
572 | AR5K_EEPROM_READ(offset++, val); | ||
573 | pcal[6].freq |= (val >> 15) & 0x1; | ||
574 | pcal[7].freq = (val >> 8) & mask; | ||
575 | pcal[8].freq = (val >> 1) & mask; | ||
576 | pcal[9].freq = (val << 6) & mask; | ||
577 | |||
578 | AR5K_EEPROM_READ(offset++, val); | ||
579 | pcal[9].freq |= (val >> 10) & 0x3f; | ||
580 | ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10; | ||
304 | } | 581 | } |
305 | 582 | ||
306 | /* | 583 | for(i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i += 1) { |
307 | * Get values for 802.11a (5GHz) | 584 | pcal[i].freq = ath5k_eeprom_bin2freq(ee, |
308 | */ | 585 | pcal[i].freq, AR5K_EEPROM_MODE_11A); |
309 | mode = AR5K_EEPROM_MODE_11A; | 586 | } |
310 | 587 | ||
311 | ee->ee_turbo_max_power[mode] = | 588 | return 0; |
312 | AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); | 589 | } |
313 | 590 | ||
314 | offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version); | 591 | static inline int |
592 | ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) | ||
593 | { | ||
594 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
595 | struct ath5k_chan_pcal_info *pcal; | ||
596 | int i; | ||
597 | |||
598 | switch(mode) { | ||
599 | case AR5K_EEPROM_MODE_11B: | ||
600 | pcal = ee->ee_pwr_cal_b; | ||
601 | break; | ||
602 | case AR5K_EEPROM_MODE_11G: | ||
603 | pcal = ee->ee_pwr_cal_g; | ||
604 | break; | ||
605 | default: | ||
606 | return -EINVAL; | ||
607 | } | ||
315 | 608 | ||
316 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | 609 | ath5k_eeprom_read_freq_list(ah, &offset, |
317 | if (ret) | 610 | AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal, |
318 | return ret; | 611 | &ee->ee_n_piers[mode]); |
612 | for(i = 0; i < AR5K_EEPROM_N_2GHZ_CHAN_2413; i += 1) { | ||
613 | pcal[i].freq = ath5k_eeprom_bin2freq(ee, | ||
614 | pcal[i].freq, mode); | ||
615 | } | ||
319 | 616 | ||
320 | AR5K_EEPROM_READ(offset++, val); | 617 | return 0; |
321 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | 618 | } |
322 | ee->ee_ob[mode][3] = (val >> 5) & 0x7; | ||
323 | ee->ee_db[mode][3] = (val >> 2) & 0x7; | ||
324 | ee->ee_ob[mode][2] = (val << 1) & 0x7; | ||
325 | |||
326 | AR5K_EEPROM_READ(offset++, val); | ||
327 | ee->ee_ob[mode][2] |= (val >> 15) & 0x1; | ||
328 | ee->ee_db[mode][2] = (val >> 12) & 0x7; | ||
329 | ee->ee_ob[mode][1] = (val >> 9) & 0x7; | ||
330 | ee->ee_db[mode][1] = (val >> 6) & 0x7; | ||
331 | ee->ee_ob[mode][0] = (val >> 3) & 0x7; | ||
332 | ee->ee_db[mode][0] = val & 0x7; | ||
333 | |||
334 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | ||
335 | if (ret) | ||
336 | return ret; | ||
337 | 619 | ||
338 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) { | 620 | |
339 | AR5K_EEPROM_READ(offset++, val); | 621 | static int |
340 | ee->ee_margin_tx_rx[mode] = val & 0x3f; | 622 | ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) |
623 | { | ||
624 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
625 | struct ath5k_chan_pcal_info *pcal; | ||
626 | int offset, ret; | ||
627 | int i, j; | ||
628 | u16 val; | ||
629 | |||
630 | offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); | ||
631 | switch(mode) { | ||
632 | case AR5K_EEPROM_MODE_11A: | ||
633 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
634 | return 0; | ||
635 | |||
636 | ret = ath5k_eeprom_init_11a_pcal_freq(ah, | ||
637 | offset + AR5K_EEPROM_GROUP1_OFFSET); | ||
638 | if (ret < 0) | ||
639 | return ret; | ||
640 | |||
641 | offset += AR5K_EEPROM_GROUP2_OFFSET; | ||
642 | pcal = ee->ee_pwr_cal_a; | ||
643 | break; | ||
644 | case AR5K_EEPROM_MODE_11B: | ||
645 | if (!AR5K_EEPROM_HDR_11B(ee->ee_header) && | ||
646 | !AR5K_EEPROM_HDR_11G(ee->ee_header)) | ||
647 | return 0; | ||
648 | |||
649 | pcal = ee->ee_pwr_cal_b; | ||
650 | offset += AR5K_EEPROM_GROUP3_OFFSET; | ||
651 | |||
652 | /* fixed piers */ | ||
653 | pcal[0].freq = 2412; | ||
654 | pcal[1].freq = 2447; | ||
655 | pcal[2].freq = 2484; | ||
656 | ee->ee_n_piers[mode] = 3; | ||
657 | break; | ||
658 | case AR5K_EEPROM_MODE_11G: | ||
659 | if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) | ||
660 | return 0; | ||
661 | |||
662 | pcal = ee->ee_pwr_cal_g; | ||
663 | offset += AR5K_EEPROM_GROUP4_OFFSET; | ||
664 | |||
665 | /* fixed piers */ | ||
666 | pcal[0].freq = 2312; | ||
667 | pcal[1].freq = 2412; | ||
668 | pcal[2].freq = 2484; | ||
669 | ee->ee_n_piers[mode] = 3; | ||
670 | break; | ||
671 | default: | ||
672 | return -EINVAL; | ||
341 | } | 673 | } |
342 | 674 | ||
343 | /* | 675 | for (i = 0; i < ee->ee_n_piers[mode]; i++) { |
344 | * Get values for 802.11b (2.4GHz) | 676 | struct ath5k_chan_pcal_info_rf5111 *cdata = |
345 | */ | 677 | &pcal[i].rf5111_info; |
346 | mode = AR5K_EEPROM_MODE_11B; | ||
347 | offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version); | ||
348 | 678 | ||
349 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | 679 | AR5K_EEPROM_READ(offset++, val); |
350 | if (ret) | 680 | cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M); |
351 | return ret; | 681 | cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M); |
682 | cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M); | ||
352 | 683 | ||
353 | AR5K_EEPROM_READ(offset++, val); | 684 | AR5K_EEPROM_READ(offset++, val); |
354 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | 685 | cdata->pwr[0] |= ((val >> 14) & 0x3); |
355 | ee->ee_ob[mode][1] = (val >> 4) & 0x7; | 686 | cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M); |
356 | ee->ee_db[mode][1] = val & 0x7; | 687 | cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M); |
688 | cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M); | ||
357 | 689 | ||
358 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | 690 | AR5K_EEPROM_READ(offset++, val); |
359 | if (ret) | 691 | cdata->pwr[3] |= ((val >> 12) & 0xf); |
360 | return ret; | 692 | cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M); |
693 | cdata->pwr[5] = (val & AR5K_EEPROM_POWER_M); | ||
361 | 694 | ||
362 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | ||
363 | AR5K_EEPROM_READ(offset++, val); | 695 | AR5K_EEPROM_READ(offset++, val); |
364 | ee->ee_cal_pier[mode][0] = | 696 | cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M); |
365 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | 697 | cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M); |
366 | ee->ee_cal_pier[mode][1] = | 698 | cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M); |
367 | ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode); | ||
368 | 699 | ||
369 | AR5K_EEPROM_READ(offset++, val); | 700 | AR5K_EEPROM_READ(offset++, val); |
370 | ee->ee_cal_pier[mode][2] = | 701 | cdata->pwr[8] |= ((val >> 14) & 0x3); |
371 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | 702 | cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M); |
703 | cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M); | ||
704 | |||
705 | ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min, | ||
706 | cdata->pcdac_max, cdata->pcdac); | ||
707 | |||
708 | for (j = 0; j < AR5K_EEPROM_N_PCDAC; j++) { | ||
709 | cdata->pwr[j] = (u16) | ||
710 | (AR5K_EEPROM_POWER_STEP * cdata->pwr[j]); | ||
711 | } | ||
372 | } | 712 | } |
373 | 713 | ||
374 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | 714 | return 0; |
375 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | 715 | } |
376 | 716 | ||
377 | /* | 717 | static int |
378 | * Get values for 802.11g (2.4GHz) | 718 | ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) |
379 | */ | 719 | { |
380 | mode = AR5K_EEPROM_MODE_11G; | 720 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
381 | offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version); | 721 | struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info; |
722 | struct ath5k_chan_pcal_info *gen_chan_info; | ||
723 | u32 offset; | ||
724 | unsigned int i, c; | ||
725 | u16 val; | ||
726 | int ret; | ||
382 | 727 | ||
383 | ret = ath5k_eeprom_read_ants(ah, &offset, mode); | 728 | switch (mode) { |
384 | if (ret) | 729 | case AR5K_EEPROM_MODE_11A: |
385 | return ret; | 730 | /* |
731 | * Read 5GHz EEPROM channels | ||
732 | */ | ||
733 | offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); | ||
734 | ath5k_eeprom_init_11a_pcal_freq(ah, offset); | ||
735 | |||
736 | offset += AR5K_EEPROM_GROUP2_OFFSET; | ||
737 | gen_chan_info = ee->ee_pwr_cal_a; | ||
738 | break; | ||
739 | case AR5K_EEPROM_MODE_11B: | ||
740 | offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); | ||
741 | if (AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
742 | offset += AR5K_EEPROM_GROUP3_OFFSET; | ||
743 | |||
744 | /* NB: frequency piers parsed during mode init */ | ||
745 | gen_chan_info = ee->ee_pwr_cal_b; | ||
746 | break; | ||
747 | case AR5K_EEPROM_MODE_11G: | ||
748 | offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); | ||
749 | if (AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
750 | offset += AR5K_EEPROM_GROUP4_OFFSET; | ||
751 | else if (AR5K_EEPROM_HDR_11B(ee->ee_header)) | ||
752 | offset += AR5K_EEPROM_GROUP2_OFFSET; | ||
753 | |||
754 | /* NB: frequency piers parsed during mode init */ | ||
755 | gen_chan_info = ee->ee_pwr_cal_g; | ||
756 | break; | ||
757 | default: | ||
758 | return -EINVAL; | ||
759 | } | ||
386 | 760 | ||
387 | AR5K_EEPROM_READ(offset++, val); | 761 | for (i = 0; i < ee->ee_n_piers[mode]; i++) { |
388 | ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); | 762 | chan_pcal_info = &gen_chan_info[i].rf5112_info; |
389 | ee->ee_ob[mode][1] = (val >> 4) & 0x7; | ||
390 | ee->ee_db[mode][1] = val & 0x7; | ||
391 | 763 | ||
392 | ret = ath5k_eeprom_read_modes(ah, &offset, mode); | 764 | /* Power values in dBm * 4 |
393 | if (ret) | 765 | * for the lower xpd gain curve |
394 | return ret; | 766 | * (0 dBm -> higher output power) */ |
767 | for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { | ||
768 | AR5K_EEPROM_READ(offset++, val); | ||
769 | chan_pcal_info->pwr_x0[c] = (val & 0xff); | ||
770 | chan_pcal_info->pwr_x0[++c] = ((val >> 8) & 0xff); | ||
771 | } | ||
395 | 772 | ||
396 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { | 773 | /* PCDAC steps |
774 | * corresponding to the above power | ||
775 | * measurements */ | ||
397 | AR5K_EEPROM_READ(offset++, val); | 776 | AR5K_EEPROM_READ(offset++, val); |
398 | ee->ee_cal_pier[mode][0] = | 777 | chan_pcal_info->pcdac_x0[1] = (val & 0x1f); |
399 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | 778 | chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f); |
400 | ee->ee_cal_pier[mode][1] = | 779 | chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f); |
401 | ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode); | ||
402 | 780 | ||
781 | /* Power values in dBm * 4 | ||
782 | * for the higher xpd gain curve | ||
783 | * (18 dBm -> lower output power) */ | ||
403 | AR5K_EEPROM_READ(offset++, val); | 784 | AR5K_EEPROM_READ(offset++, val); |
404 | ee->ee_turbo_max_power[mode] = val & 0x7f; | 785 | chan_pcal_info->pwr_x3[0] = (val & 0xff); |
405 | ee->ee_xr_power[mode] = (val >> 7) & 0x3f; | 786 | chan_pcal_info->pwr_x3[1] = ((val >> 8) & 0xff); |
406 | 787 | ||
407 | AR5K_EEPROM_READ(offset++, val); | 788 | AR5K_EEPROM_READ(offset++, val); |
408 | ee->ee_cal_pier[mode][2] = | 789 | chan_pcal_info->pwr_x3[2] = (val & 0xff); |
409 | ath5k_eeprom_bin2freq(ah, val & 0xff, mode); | 790 | |
791 | /* PCDAC steps | ||
792 | * corresponding to the above power | ||
793 | * measurements (static) */ | ||
794 | chan_pcal_info->pcdac_x3[0] = 20; | ||
795 | chan_pcal_info->pcdac_x3[1] = 35; | ||
796 | chan_pcal_info->pcdac_x3[2] = 63; | ||
797 | |||
798 | if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) { | ||
799 | chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0xff); | ||
800 | |||
801 | /* Last xpd0 power level is also channel maximum */ | ||
802 | gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3]; | ||
803 | } else { | ||
804 | chan_pcal_info->pcdac_x0[0] = 1; | ||
805 | gen_chan_info[i].max_pwr = ((val >> 8) & 0xff); | ||
806 | } | ||
410 | 807 | ||
411 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) | 808 | /* Recreate pcdac_x0 table for this channel using pcdac steps */ |
412 | ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; | 809 | chan_pcal_info->pcdac_x0[1] += chan_pcal_info->pcdac_x0[0]; |
810 | chan_pcal_info->pcdac_x0[2] += chan_pcal_info->pcdac_x0[1]; | ||
811 | chan_pcal_info->pcdac_x0[3] += chan_pcal_info->pcdac_x0[2]; | ||
812 | } | ||
813 | |||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | static inline unsigned int | ||
818 | ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) | ||
819 | { | ||
820 | static const unsigned int pdgains_size[] = { 4, 6, 9, 12 }; | ||
821 | unsigned int sz; | ||
822 | |||
823 | sz = pdgains_size[ee->ee_pd_gains[mode] - 1]; | ||
824 | sz *= ee->ee_n_piers[mode]; | ||
825 | |||
826 | return sz; | ||
827 | } | ||
828 | |||
829 | static unsigned int | ||
830 | ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) | ||
831 | { | ||
832 | u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4); | ||
833 | |||
834 | switch(mode) { | ||
835 | case AR5K_EEPROM_MODE_11G: | ||
836 | if (AR5K_EEPROM_HDR_11B(ee->ee_header)) | ||
837 | offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + 2; | ||
838 | /* fall through */ | ||
839 | case AR5K_EEPROM_MODE_11B: | ||
840 | if (AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
841 | offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + 5; | ||
842 | /* fall through */ | ||
843 | case AR5K_EEPROM_MODE_11A: | ||
844 | break; | ||
845 | default: | ||
846 | break; | ||
847 | } | ||
848 | |||
849 | return offset; | ||
850 | } | ||
851 | |||
852 | static int | ||
853 | ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) | ||
854 | { | ||
855 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
856 | struct ath5k_chan_pcal_info_rf2413 *chan_pcal_info; | ||
857 | struct ath5k_chan_pcal_info *gen_chan_info; | ||
858 | unsigned int i, c; | ||
859 | u32 offset; | ||
860 | int ret; | ||
861 | u16 val; | ||
862 | u8 pd_gains = 0; | ||
863 | |||
864 | if (ee->ee_x_gain[mode] & 0x1) pd_gains++; | ||
865 | if ((ee->ee_x_gain[mode] >> 1) & 0x1) pd_gains++; | ||
866 | if ((ee->ee_x_gain[mode] >> 2) & 0x1) pd_gains++; | ||
867 | if ((ee->ee_x_gain[mode] >> 3) & 0x1) pd_gains++; | ||
868 | ee->ee_pd_gains[mode] = pd_gains; | ||
869 | |||
870 | offset = ath5k_cal_data_offset_2413(ee, mode); | ||
871 | switch (mode) { | ||
872 | case AR5K_EEPROM_MODE_11A: | ||
873 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
874 | return 0; | ||
875 | |||
876 | ath5k_eeprom_init_11a_pcal_freq(ah, offset); | ||
877 | offset += AR5K_EEPROM_N_5GHZ_CHAN / 2; | ||
878 | gen_chan_info = ee->ee_pwr_cal_a; | ||
879 | break; | ||
880 | case AR5K_EEPROM_MODE_11B: | ||
881 | if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) | ||
882 | return 0; | ||
413 | 883 | ||
884 | ath5k_eeprom_init_11bg_2413(ah, mode, offset); | ||
885 | offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; | ||
886 | gen_chan_info = ee->ee_pwr_cal_b; | ||
887 | break; | ||
888 | case AR5K_EEPROM_MODE_11G: | ||
889 | if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) | ||
890 | return 0; | ||
891 | |||
892 | ath5k_eeprom_init_11bg_2413(ah, mode, offset); | ||
893 | offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; | ||
894 | gen_chan_info = ee->ee_pwr_cal_g; | ||
895 | break; | ||
896 | default: | ||
897 | return -EINVAL; | ||
898 | } | ||
899 | |||
900 | if (pd_gains == 0) | ||
901 | return 0; | ||
902 | |||
903 | for (i = 0; i < ee->ee_n_piers[mode]; i++) { | ||
904 | chan_pcal_info = &gen_chan_info[i].rf2413_info; | ||
905 | |||
906 | /* | ||
907 | * Read pwr_i, pddac_i and the first | ||
908 | * 2 pd points (pwr, pddac) | ||
909 | */ | ||
414 | AR5K_EEPROM_READ(offset++, val); | 910 | AR5K_EEPROM_READ(offset++, val); |
415 | ee->ee_i_cal[mode] = (val >> 8) & 0x3f; | 911 | chan_pcal_info->pwr_i[0] = val & 0x1f; |
416 | ee->ee_q_cal[mode] = (val >> 3) & 0x1f; | 912 | chan_pcal_info->pddac_i[0] = (val >> 5) & 0x7f; |
913 | chan_pcal_info->pwr[0][0] = | ||
914 | (val >> 12) & 0xf; | ||
417 | 915 | ||
418 | if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { | 916 | AR5K_EEPROM_READ(offset++, val); |
917 | chan_pcal_info->pddac[0][0] = val & 0x3f; | ||
918 | chan_pcal_info->pwr[0][1] = (val >> 6) & 0xf; | ||
919 | chan_pcal_info->pddac[0][1] = | ||
920 | (val >> 10) & 0x3f; | ||
921 | |||
922 | AR5K_EEPROM_READ(offset++, val); | ||
923 | chan_pcal_info->pwr[0][2] = val & 0xf; | ||
924 | chan_pcal_info->pddac[0][2] = | ||
925 | (val >> 4) & 0x3f; | ||
926 | |||
927 | chan_pcal_info->pwr[0][3] = 0; | ||
928 | chan_pcal_info->pddac[0][3] = 0; | ||
929 | |||
930 | if (pd_gains > 1) { | ||
931 | /* | ||
932 | * Pd gain 0 is not the last pd gain | ||
933 | * so it only has 2 pd points. | ||
934 | * Continue wih pd gain 1. | ||
935 | */ | ||
936 | chan_pcal_info->pwr_i[1] = (val >> 10) & 0x1f; | ||
937 | |||
938 | chan_pcal_info->pddac_i[1] = (val >> 15) & 0x1; | ||
419 | AR5K_EEPROM_READ(offset++, val); | 939 | AR5K_EEPROM_READ(offset++, val); |
420 | ee->ee_cck_ofdm_gain_delta = val & 0xff; | 940 | chan_pcal_info->pddac_i[1] |= (val & 0x3F) << 1; |
941 | |||
942 | chan_pcal_info->pwr[1][0] = (val >> 6) & 0xf; | ||
943 | chan_pcal_info->pddac[1][0] = | ||
944 | (val >> 10) & 0x3f; | ||
945 | |||
946 | AR5K_EEPROM_READ(offset++, val); | ||
947 | chan_pcal_info->pwr[1][1] = val & 0xf; | ||
948 | chan_pcal_info->pddac[1][1] = | ||
949 | (val >> 4) & 0x3f; | ||
950 | chan_pcal_info->pwr[1][2] = | ||
951 | (val >> 10) & 0xf; | ||
952 | |||
953 | chan_pcal_info->pddac[1][2] = | ||
954 | (val >> 14) & 0x3; | ||
955 | AR5K_EEPROM_READ(offset++, val); | ||
956 | chan_pcal_info->pddac[1][2] |= | ||
957 | (val & 0xF) << 2; | ||
958 | |||
959 | chan_pcal_info->pwr[1][3] = 0; | ||
960 | chan_pcal_info->pddac[1][3] = 0; | ||
961 | } else if (pd_gains == 1) { | ||
962 | /* | ||
963 | * Pd gain 0 is the last one so | ||
964 | * read the extra point. | ||
965 | */ | ||
966 | chan_pcal_info->pwr[0][3] = | ||
967 | (val >> 10) & 0xf; | ||
968 | |||
969 | chan_pcal_info->pddac[0][3] = | ||
970 | (val >> 14) & 0x3; | ||
971 | AR5K_EEPROM_READ(offset++, val); | ||
972 | chan_pcal_info->pddac[0][3] |= | ||
973 | (val & 0xF) << 2; | ||
974 | } | ||
975 | |||
976 | /* | ||
977 | * Proceed with the other pd_gains | ||
978 | * as above. | ||
979 | */ | ||
980 | if (pd_gains > 2) { | ||
981 | chan_pcal_info->pwr_i[2] = (val >> 4) & 0x1f; | ||
982 | chan_pcal_info->pddac_i[2] = (val >> 9) & 0x7f; | ||
983 | |||
984 | AR5K_EEPROM_READ(offset++, val); | ||
985 | chan_pcal_info->pwr[2][0] = | ||
986 | (val >> 0) & 0xf; | ||
987 | chan_pcal_info->pddac[2][0] = | ||
988 | (val >> 4) & 0x3f; | ||
989 | chan_pcal_info->pwr[2][1] = | ||
990 | (val >> 10) & 0xf; | ||
991 | |||
992 | chan_pcal_info->pddac[2][1] = | ||
993 | (val >> 14) & 0x3; | ||
994 | AR5K_EEPROM_READ(offset++, val); | ||
995 | chan_pcal_info->pddac[2][1] |= | ||
996 | (val & 0xF) << 2; | ||
997 | |||
998 | chan_pcal_info->pwr[2][2] = | ||
999 | (val >> 4) & 0xf; | ||
1000 | chan_pcal_info->pddac[2][2] = | ||
1001 | (val >> 8) & 0x3f; | ||
1002 | |||
1003 | chan_pcal_info->pwr[2][3] = 0; | ||
1004 | chan_pcal_info->pddac[2][3] = 0; | ||
1005 | } else if (pd_gains == 2) { | ||
1006 | chan_pcal_info->pwr[1][3] = | ||
1007 | (val >> 4) & 0xf; | ||
1008 | chan_pcal_info->pddac[1][3] = | ||
1009 | (val >> 8) & 0x3f; | ||
1010 | } | ||
1011 | |||
1012 | if (pd_gains > 3) { | ||
1013 | chan_pcal_info->pwr_i[3] = (val >> 14) & 0x3; | ||
1014 | AR5K_EEPROM_READ(offset++, val); | ||
1015 | chan_pcal_info->pwr_i[3] |= ((val >> 0) & 0x7) << 2; | ||
1016 | |||
1017 | chan_pcal_info->pddac_i[3] = (val >> 3) & 0x7f; | ||
1018 | chan_pcal_info->pwr[3][0] = | ||
1019 | (val >> 10) & 0xf; | ||
1020 | chan_pcal_info->pddac[3][0] = | ||
1021 | (val >> 14) & 0x3; | ||
1022 | |||
1023 | AR5K_EEPROM_READ(offset++, val); | ||
1024 | chan_pcal_info->pddac[3][0] |= | ||
1025 | (val & 0xF) << 2; | ||
1026 | chan_pcal_info->pwr[3][1] = | ||
1027 | (val >> 4) & 0xf; | ||
1028 | chan_pcal_info->pddac[3][1] = | ||
1029 | (val >> 8) & 0x3f; | ||
1030 | |||
1031 | chan_pcal_info->pwr[3][2] = | ||
1032 | (val >> 14) & 0x3; | ||
1033 | AR5K_EEPROM_READ(offset++, val); | ||
1034 | chan_pcal_info->pwr[3][2] |= | ||
1035 | ((val >> 0) & 0x3) << 2; | ||
1036 | |||
1037 | chan_pcal_info->pddac[3][2] = | ||
1038 | (val >> 2) & 0x3f; | ||
1039 | chan_pcal_info->pwr[3][3] = | ||
1040 | (val >> 8) & 0xf; | ||
1041 | |||
1042 | chan_pcal_info->pddac[3][3] = | ||
1043 | (val >> 12) & 0xF; | ||
1044 | AR5K_EEPROM_READ(offset++, val); | ||
1045 | chan_pcal_info->pddac[3][3] |= | ||
1046 | ((val >> 0) & 0x3) << 4; | ||
1047 | } else if (pd_gains == 3) { | ||
1048 | chan_pcal_info->pwr[2][3] = | ||
1049 | (val >> 14) & 0x3; | ||
1050 | AR5K_EEPROM_READ(offset++, val); | ||
1051 | chan_pcal_info->pwr[2][3] |= | ||
1052 | ((val >> 0) & 0x3) << 2; | ||
1053 | |||
1054 | chan_pcal_info->pddac[2][3] = | ||
1055 | (val >> 2) & 0x3f; | ||
1056 | } | ||
1057 | |||
1058 | for (c = 0; c < pd_gains; c++) { | ||
1059 | /* Recreate pwr table for this channel using pwr steps */ | ||
1060 | chan_pcal_info->pwr[c][0] += chan_pcal_info->pwr_i[c] * 2; | ||
1061 | chan_pcal_info->pwr[c][1] += chan_pcal_info->pwr[c][0]; | ||
1062 | chan_pcal_info->pwr[c][2] += chan_pcal_info->pwr[c][1]; | ||
1063 | chan_pcal_info->pwr[c][3] += chan_pcal_info->pwr[c][2]; | ||
1064 | if (chan_pcal_info->pwr[c][3] == chan_pcal_info->pwr[c][2]) | ||
1065 | chan_pcal_info->pwr[c][3] = 0; | ||
1066 | |||
1067 | /* Recreate pddac table for this channel using pddac steps */ | ||
1068 | chan_pcal_info->pddac[c][0] += chan_pcal_info->pddac_i[c]; | ||
1069 | chan_pcal_info->pddac[c][1] += chan_pcal_info->pddac[c][0]; | ||
1070 | chan_pcal_info->pddac[c][2] += chan_pcal_info->pddac[c][1]; | ||
1071 | chan_pcal_info->pddac[c][3] += chan_pcal_info->pddac[c][2]; | ||
1072 | if (chan_pcal_info->pddac[c][3] == chan_pcal_info->pddac[c][2]) | ||
1073 | chan_pcal_info->pddac[c][3] = 0; | ||
421 | } | 1074 | } |
422 | } | 1075 | } |
423 | 1076 | ||
424 | /* | 1077 | return 0; |
425 | * Read 5GHz EEPROM channels | 1078 | } |
426 | */ | 1079 | |
1080 | /* | ||
1081 | * Read per rate target power (this is the maximum tx power | ||
1082 | * supported by the card). This info is used when setting | ||
1083 | * tx power, no matter the channel. | ||
1084 | * | ||
1085 | * This also works for v5 EEPROMs. | ||
1086 | */ | ||
1087 | static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) | ||
1088 | { | ||
1089 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1090 | struct ath5k_rate_pcal_info *rate_pcal_info; | ||
1091 | u16 *rate_target_pwr_num; | ||
1092 | u32 offset; | ||
1093 | u16 val; | ||
1094 | int ret, i; | ||
1095 | |||
1096 | offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); | ||
1097 | rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; | ||
1098 | switch (mode) { | ||
1099 | case AR5K_EEPROM_MODE_11A: | ||
1100 | offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version); | ||
1101 | rate_pcal_info = ee->ee_rate_tpwr_a; | ||
1102 | ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN; | ||
1103 | break; | ||
1104 | case AR5K_EEPROM_MODE_11B: | ||
1105 | offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version); | ||
1106 | rate_pcal_info = ee->ee_rate_tpwr_b; | ||
1107 | ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */ | ||
1108 | break; | ||
1109 | case AR5K_EEPROM_MODE_11G: | ||
1110 | offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version); | ||
1111 | rate_pcal_info = ee->ee_rate_tpwr_g; | ||
1112 | ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN; | ||
1113 | break; | ||
1114 | default: | ||
1115 | return -EINVAL; | ||
1116 | } | ||
1117 | |||
1118 | /* Different freq mask for older eeproms (<= v3.2) */ | ||
1119 | if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) { | ||
1120 | for (i = 0; i < (*rate_target_pwr_num); i++) { | ||
1121 | AR5K_EEPROM_READ(offset++, val); | ||
1122 | rate_pcal_info[i].freq = | ||
1123 | ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode); | ||
1124 | |||
1125 | rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f); | ||
1126 | rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f; | ||
1127 | |||
1128 | AR5K_EEPROM_READ(offset++, val); | ||
1129 | |||
1130 | if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || | ||
1131 | val == 0) { | ||
1132 | (*rate_target_pwr_num) = i; | ||
1133 | break; | ||
1134 | } | ||
1135 | |||
1136 | rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7); | ||
1137 | rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f); | ||
1138 | rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f); | ||
1139 | } | ||
1140 | } else { | ||
1141 | for (i = 0; i < (*rate_target_pwr_num); i++) { | ||
1142 | AR5K_EEPROM_READ(offset++, val); | ||
1143 | rate_pcal_info[i].freq = | ||
1144 | ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); | ||
1145 | |||
1146 | rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f); | ||
1147 | rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f; | ||
1148 | |||
1149 | AR5K_EEPROM_READ(offset++, val); | ||
1150 | |||
1151 | if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || | ||
1152 | val == 0) { | ||
1153 | (*rate_target_pwr_num) = i; | ||
1154 | break; | ||
1155 | } | ||
1156 | |||
1157 | rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf; | ||
1158 | rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f); | ||
1159 | rate_pcal_info[i].target_power_54 = (val & 0x3f); | ||
1160 | } | ||
1161 | } | ||
1162 | |||
1163 | return 0; | ||
1164 | } | ||
1165 | |||
1166 | static int | ||
1167 | ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) | ||
1168 | { | ||
1169 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1170 | int (*read_pcal)(struct ath5k_hw *hw, int mode); | ||
1171 | int mode; | ||
1172 | int err; | ||
1173 | |||
1174 | if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) && | ||
1175 | (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1)) | ||
1176 | read_pcal = ath5k_eeprom_read_pcal_info_5112; | ||
1177 | else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) && | ||
1178 | (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2)) | ||
1179 | read_pcal = ath5k_eeprom_read_pcal_info_2413; | ||
1180 | else | ||
1181 | read_pcal = ath5k_eeprom_read_pcal_info_5111; | ||
1182 | |||
1183 | for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) { | ||
1184 | err = read_pcal(ah, mode); | ||
1185 | if (err) | ||
1186 | return err; | ||
1187 | |||
1188 | err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode); | ||
1189 | if (err < 0) | ||
1190 | return err; | ||
1191 | } | ||
1192 | |||
1193 | return 0; | ||
1194 | } | ||
1195 | |||
1196 | /* Read conformance test limits */ | ||
1197 | static int | ||
1198 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) | ||
1199 | { | ||
1200 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1201 | struct ath5k_edge_power *rep; | ||
1202 | unsigned int fmask, pmask; | ||
1203 | unsigned int ctl_mode; | ||
1204 | int ret, i, j; | ||
1205 | u32 offset; | ||
1206 | u16 val; | ||
1207 | |||
1208 | pmask = AR5K_EEPROM_POWER_M; | ||
1209 | fmask = AR5K_EEPROM_FREQ_M(ee->ee_version); | ||
1210 | offset = AR5K_EEPROM_CTL(ee->ee_version); | ||
1211 | ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version); | ||
1212 | for (i = 0; i < ee->ee_ctls; i += 2) { | ||
1213 | AR5K_EEPROM_READ(offset++, val); | ||
1214 | ee->ee_ctl[i] = (val >> 8) & 0xff; | ||
1215 | ee->ee_ctl[i + 1] = val & 0xff; | ||
1216 | } | ||
1217 | |||
1218 | offset = AR5K_EEPROM_GROUP8_OFFSET; | ||
1219 | if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) | ||
1220 | offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) - | ||
1221 | AR5K_EEPROM_GROUP5_OFFSET; | ||
1222 | else | ||
1223 | offset += AR5K_EEPROM_GROUPS_START(ee->ee_version); | ||
1224 | |||
1225 | rep = ee->ee_ctl_pwr; | ||
1226 | for(i = 0; i < ee->ee_ctls; i++) { | ||
1227 | switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) { | ||
1228 | case AR5K_CTL_11A: | ||
1229 | case AR5K_CTL_TURBO: | ||
1230 | ctl_mode = AR5K_EEPROM_MODE_11A; | ||
1231 | break; | ||
1232 | default: | ||
1233 | ctl_mode = AR5K_EEPROM_MODE_11G; | ||
1234 | break; | ||
1235 | } | ||
1236 | if (ee->ee_ctl[i] == 0) { | ||
1237 | if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) | ||
1238 | offset += 8; | ||
1239 | else | ||
1240 | offset += 7; | ||
1241 | rep += AR5K_EEPROM_N_EDGES; | ||
1242 | continue; | ||
1243 | } | ||
1244 | if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { | ||
1245 | for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { | ||
1246 | AR5K_EEPROM_READ(offset++, val); | ||
1247 | rep[j].freq = (val >> 8) & fmask; | ||
1248 | rep[j + 1].freq = val & fmask; | ||
1249 | } | ||
1250 | for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { | ||
1251 | AR5K_EEPROM_READ(offset++, val); | ||
1252 | rep[j].edge = (val >> 8) & pmask; | ||
1253 | rep[j].flag = (val >> 14) & 1; | ||
1254 | rep[j + 1].edge = val & pmask; | ||
1255 | rep[j + 1].flag = (val >> 6) & 1; | ||
1256 | } | ||
1257 | } else { | ||
1258 | AR5K_EEPROM_READ(offset++, val); | ||
1259 | rep[0].freq = (val >> 9) & fmask; | ||
1260 | rep[1].freq = (val >> 2) & fmask; | ||
1261 | rep[2].freq = (val << 5) & fmask; | ||
1262 | |||
1263 | AR5K_EEPROM_READ(offset++, val); | ||
1264 | rep[2].freq |= (val >> 11) & 0x1f; | ||
1265 | rep[3].freq = (val >> 4) & fmask; | ||
1266 | rep[4].freq = (val << 3) & fmask; | ||
1267 | |||
1268 | AR5K_EEPROM_READ(offset++, val); | ||
1269 | rep[4].freq |= (val >> 13) & 0x7; | ||
1270 | rep[5].freq = (val >> 6) & fmask; | ||
1271 | rep[6].freq = (val << 1) & fmask; | ||
1272 | |||
1273 | AR5K_EEPROM_READ(offset++, val); | ||
1274 | rep[6].freq |= (val >> 15) & 0x1; | ||
1275 | rep[7].freq = (val >> 8) & fmask; | ||
1276 | |||
1277 | rep[0].edge = (val >> 2) & pmask; | ||
1278 | rep[1].edge = (val << 4) & pmask; | ||
1279 | |||
1280 | AR5K_EEPROM_READ(offset++, val); | ||
1281 | rep[1].edge |= (val >> 12) & 0xf; | ||
1282 | rep[2].edge = (val >> 6) & pmask; | ||
1283 | rep[3].edge = val & pmask; | ||
1284 | |||
1285 | AR5K_EEPROM_READ(offset++, val); | ||
1286 | rep[4].edge = (val >> 10) & pmask; | ||
1287 | rep[5].edge = (val >> 4) & pmask; | ||
1288 | rep[6].edge = (val << 2) & pmask; | ||
1289 | |||
1290 | AR5K_EEPROM_READ(offset++, val); | ||
1291 | rep[6].edge |= (val >> 14) & 0x3; | ||
1292 | rep[7].edge = (val >> 8) & pmask; | ||
1293 | } | ||
1294 | for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) { | ||
1295 | rep[j].freq = ath5k_eeprom_bin2freq(ee, | ||
1296 | rep[j].freq, ctl_mode); | ||
1297 | } | ||
1298 | rep += AR5K_EEPROM_N_EDGES; | ||
1299 | } | ||
427 | 1300 | ||
428 | return 0; | 1301 | return 0; |
429 | } | 1302 | } |
430 | 1303 | ||
1304 | |||
1305 | /* | ||
1306 | * Initialize eeprom power tables | ||
1307 | */ | ||
1308 | int | ||
1309 | ath5k_eeprom_init(struct ath5k_hw *ah) | ||
1310 | { | ||
1311 | int err; | ||
1312 | |||
1313 | err = ath5k_eeprom_init_header(ah); | ||
1314 | if (err < 0) | ||
1315 | return err; | ||
1316 | |||
1317 | err = ath5k_eeprom_init_modes(ah); | ||
1318 | if (err < 0) | ||
1319 | return err; | ||
1320 | |||
1321 | err = ath5k_eeprom_read_pcal_info(ah); | ||
1322 | if (err < 0) | ||
1323 | return err; | ||
1324 | |||
1325 | err = ath5k_eeprom_read_ctl_info(ah); | ||
1326 | if (err < 0) | ||
1327 | return err; | ||
1328 | |||
1329 | return 0; | ||
1330 | } | ||
431 | /* | 1331 | /* |
432 | * Read the MAC address from eeprom | 1332 | * Read the MAC address from eeprom |
433 | */ | 1333 | */ |
diff --git a/drivers/net/wireless/ath5k/eeprom.h b/drivers/net/wireless/ath5k/eeprom.h index a468ecfbb18a..09eb7d0176a4 100644 --- a/drivers/net/wireless/ath5k/eeprom.h +++ b/drivers/net/wireless/ath5k/eeprom.h | |||
@@ -25,24 +25,8 @@ | |||
25 | #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ | 25 | #define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ |
26 | #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ | 26 | #define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ |
27 | 27 | ||
28 | #define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */ | ||
29 | #define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */ | ||
30 | #define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */ | ||
31 | #define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */ | ||
32 | #define AR5K_EEPROM_PROTECT_WR_32_63 0x0008 | ||
33 | #define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */ | ||
34 | #define AR5K_EEPROM_PROTECT_WR_64_127 0x0020 | ||
35 | #define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */ | ||
36 | #define AR5K_EEPROM_PROTECT_WR_128_191 0x0080 | ||
37 | #define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */ | ||
38 | #define AR5K_EEPROM_PROTECT_WR_192_207 0x0200 | ||
39 | #define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */ | ||
40 | #define AR5K_EEPROM_PROTECT_WR_208_223 0x0800 | ||
41 | #define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */ | ||
42 | #define AR5K_EEPROM_PROTECT_WR_224_239 0x2000 | ||
43 | #define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */ | ||
44 | #define AR5K_EEPROM_PROTECT_WR_240_255 0x8000 | ||
45 | #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ | 28 | #define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ |
29 | #define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ | ||
46 | #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ | 30 | #define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ |
47 | #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) | 31 | #define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) |
48 | #define AR5K_EEPROM_INFO_CKSUM 0xffff | 32 | #define AR5K_EEPROM_INFO_CKSUM 0xffff |
@@ -53,15 +37,19 @@ | |||
53 | #define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */ | 37 | #define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */ |
54 | #define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */ | 38 | #define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */ |
55 | #define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */ | 39 | #define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */ |
56 | #define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */ | 40 | #define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */ |
57 | #define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */ | 41 | #define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */ |
58 | #define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */ | 42 | #define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */ |
59 | #define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */ | 43 | #define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */ |
60 | #define AR5K_EEPROM_VERSION_4_3 0x4003 | 44 | #define AR5K_EEPROM_VERSION_4_3 0x4003 /* power calibration changes */ |
61 | #define AR5K_EEPROM_VERSION_4_4 0x4004 | 45 | #define AR5K_EEPROM_VERSION_4_4 0x4004 |
62 | #define AR5K_EEPROM_VERSION_4_5 0x4005 | 46 | #define AR5K_EEPROM_VERSION_4_5 0x4005 |
63 | #define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ | 47 | #define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ |
64 | #define AR5K_EEPROM_VERSION_4_7 0x4007 | 48 | #define AR5K_EEPROM_VERSION_4_7 0x3007 /* 4007 ? */ |
49 | #define AR5K_EEPROM_VERSION_4_9 0x4009 /* EAR futureproofing */ | ||
50 | #define AR5K_EEPROM_VERSION_5_0 0x5000 /* Has 2413 PDADC calibration etc */ | ||
51 | #define AR5K_EEPROM_VERSION_5_1 0x5001 /* Has capability values */ | ||
52 | #define AR5K_EEPROM_VERSION_5_3 0x5003 /* Has spur mitigation tables */ | ||
65 | 53 | ||
66 | #define AR5K_EEPROM_MODE_11A 0 | 54 | #define AR5K_EEPROM_MODE_11A 0 |
67 | #define AR5K_EEPROM_MODE_11B 1 | 55 | #define AR5K_EEPROM_MODE_11B 1 |
@@ -74,8 +62,8 @@ | |||
74 | #define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ | 62 | #define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ |
75 | #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ | 63 | #define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ |
76 | #define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) | 64 | #define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) |
77 | #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */ | ||
78 | #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ | 65 | #define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ |
66 | #define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ | ||
79 | 67 | ||
80 | #define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c | 68 | #define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c |
81 | #define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 | 69 | #define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 |
@@ -87,27 +75,95 @@ | |||
87 | (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) | 75 | (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) |
88 | 76 | ||
89 | #define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3) | 77 | #define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3) |
90 | #define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff)) | 78 | #define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((s8)(((_v) >> 8) & 0xff)) |
91 | #define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff)) | 79 | #define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((s8)((_v) & 0xff)) |
80 | |||
81 | /* Misc values available since EEPROM 4.0 */ | ||
82 | #define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4) | ||
83 | #define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) | ||
84 | #define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1) | ||
85 | #define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1) | ||
86 | #define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) | ||
87 | |||
88 | #define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) | ||
89 | #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) | ||
90 | #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) | ||
91 | #define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1) | ||
92 | |||
93 | #define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6) | ||
94 | #define AR5K_EEPROM_EEP_FILE_VERSION(_v) (((_v) >> 8) & 0xff) | ||
95 | #define AR5K_EEPROM_EAR_FILE_VERSION(_v) ((_v) & 0xff) | ||
96 | |||
97 | #define AR5K_EEPROM_MISC3 AR5K_EEPROM_INFO(7) | ||
98 | #define AR5K_EEPROM_ART_BUILD_NUM(_v) (((_v) >> 10) & 0x3f) | ||
99 | #define AR5K_EEPROM_EAR_FILE_ID(_v) ((_v) & 0xff) | ||
100 | |||
101 | #define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8) | ||
102 | #define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff) | ||
103 | #define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) | ||
104 | #define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) | ||
105 | |||
106 | #define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9) | ||
107 | #define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) | ||
108 | #define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) | ||
109 | #define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) | ||
110 | #define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) | ||
111 | #define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) | ||
112 | #define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) | ||
113 | #define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) | ||
114 | |||
115 | #define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10) | ||
116 | #define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8) | ||
117 | #define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8) | ||
118 | #define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) | ||
119 | #define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) | ||
120 | #define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) | ||
121 | #define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1) | ||
122 | #define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1) | ||
92 | 123 | ||
93 | /* calibration settings */ | 124 | /* calibration settings */ |
94 | #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) | 125 | #define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) |
95 | #define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2) | 126 | #define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2) |
96 | #define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d) | 127 | #define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d) |
97 | #define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */ | 128 | #define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */ |
129 | #define AR5K_EEPROM_GROUPS_START(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* Start of Groups */ | ||
130 | #define AR5K_EEPROM_GROUP1_OFFSET 0x0 | ||
131 | #define AR5K_EEPROM_GROUP2_OFFSET 0x5 | ||
132 | #define AR5K_EEPROM_GROUP3_OFFSET 0x37 | ||
133 | #define AR5K_EEPROM_GROUP4_OFFSET 0x46 | ||
134 | #define AR5K_EEPROM_GROUP5_OFFSET 0x55 | ||
135 | #define AR5K_EEPROM_GROUP6_OFFSET 0x65 | ||
136 | #define AR5K_EEPROM_GROUP7_OFFSET 0x69 | ||
137 | #define AR5K_EEPROM_GROUP8_OFFSET 0x6f | ||
138 | |||
139 | #define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ | ||
140 | AR5K_EEPROM_GROUP5_OFFSET, 0x0000) | ||
141 | #define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ | ||
142 | AR5K_EEPROM_GROUP6_OFFSET, 0x0010) | ||
143 | #define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ | ||
144 | AR5K_EEPROM_GROUP7_OFFSET, 0x0014) | ||
98 | 145 | ||
99 | /* [3.1 - 3.3] */ | 146 | /* [3.1 - 3.3] */ |
100 | #define AR5K_EEPROM_OBDB0_2GHZ 0x00ec | 147 | #define AR5K_EEPROM_OBDB0_2GHZ 0x00ec |
101 | #define AR5K_EEPROM_OBDB1_2GHZ 0x00ed | 148 | #define AR5K_EEPROM_OBDB1_2GHZ 0x00ed |
102 | 149 | ||
103 | /* Misc values available since EEPROM 4.0 */ | 150 | #define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */ |
104 | #define AR5K_EEPROM_MISC0 0x00c4 | 151 | #define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */ |
105 | #define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) | 152 | #define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */ |
106 | #define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) | 153 | #define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */ |
107 | #define AR5K_EEPROM_MISC1 0x00c5 | 154 | #define AR5K_EEPROM_PROTECT_WR_32_63 0x0008 |
108 | #define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) | 155 | #define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */ |
109 | #define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) | 156 | #define AR5K_EEPROM_PROTECT_WR_64_127 0x0020 |
110 | 157 | #define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */ | |
158 | #define AR5K_EEPROM_PROTECT_WR_128_191 0x0080 | ||
159 | #define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */ | ||
160 | #define AR5K_EEPROM_PROTECT_WR_192_207 0x0200 | ||
161 | #define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */ | ||
162 | #define AR5K_EEPROM_PROTECT_WR_208_223 0x0800 | ||
163 | #define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */ | ||
164 | #define AR5K_EEPROM_PROTECT_WR_224_239 0x2000 | ||
165 | #define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */ | ||
166 | #define AR5K_EEPROM_PROTECT_WR_240_255 0x8000 | ||
111 | 167 | ||
112 | /* Some EEPROM defines */ | 168 | /* Some EEPROM defines */ |
113 | #define AR5K_EEPROM_EEP_SCALE 100 | 169 | #define AR5K_EEPROM_EEP_SCALE 100 |
@@ -115,8 +171,11 @@ | |||
115 | #define AR5K_EEPROM_N_MODES 3 | 171 | #define AR5K_EEPROM_N_MODES 3 |
116 | #define AR5K_EEPROM_N_5GHZ_CHAN 10 | 172 | #define AR5K_EEPROM_N_5GHZ_CHAN 10 |
117 | #define AR5K_EEPROM_N_2GHZ_CHAN 3 | 173 | #define AR5K_EEPROM_N_2GHZ_CHAN 3 |
174 | #define AR5K_EEPROM_N_2GHZ_CHAN_2413 4 | ||
118 | #define AR5K_EEPROM_MAX_CHAN 10 | 175 | #define AR5K_EEPROM_MAX_CHAN 10 |
176 | #define AR5K_EEPROM_N_PWR_POINTS_5111 11 | ||
119 | #define AR5K_EEPROM_N_PCDAC 11 | 177 | #define AR5K_EEPROM_N_PCDAC 11 |
178 | #define AR5K_EEPROM_N_PHASE_CAL 5 | ||
120 | #define AR5K_EEPROM_N_TEST_FREQ 8 | 179 | #define AR5K_EEPROM_N_TEST_FREQ 8 |
121 | #define AR5K_EEPROM_N_EDGES 8 | 180 | #define AR5K_EEPROM_N_EDGES 8 |
122 | #define AR5K_EEPROM_N_INTERCEPTS 11 | 181 | #define AR5K_EEPROM_N_INTERCEPTS 11 |
@@ -136,6 +195,8 @@ | |||
136 | #define AR5K_EEPROM_N_XPD_PER_CHANNEL 4 | 195 | #define AR5K_EEPROM_N_XPD_PER_CHANNEL 4 |
137 | #define AR5K_EEPROM_N_XPD0_POINTS 4 | 196 | #define AR5K_EEPROM_N_XPD0_POINTS 4 |
138 | #define AR5K_EEPROM_N_XPD3_POINTS 3 | 197 | #define AR5K_EEPROM_N_XPD3_POINTS 3 |
198 | #define AR5K_EEPROM_N_PD_GAINS 4 | ||
199 | #define AR5K_EEPROM_N_PD_POINTS 5 | ||
139 | #define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35 | 200 | #define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35 |
140 | #define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55 | 201 | #define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55 |
141 | #define AR5K_EEPROM_POWER_M 0x3f | 202 | #define AR5K_EEPROM_POWER_M 0x3f |
@@ -158,8 +219,99 @@ | |||
158 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ | 219 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ |
159 | AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ | 220 | AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ |
160 | 221 | ||
161 | /* Struct to hold EEPROM calibration data */ | 222 | enum ath5k_ant_setting { |
223 | AR5K_ANT_VARIABLE = 0, /* variable by programming */ | ||
224 | AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */ | ||
225 | AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */ | ||
226 | AR5K_ANT_MAX = 3, | ||
227 | }; | ||
228 | |||
229 | enum ath5k_ctl_mode { | ||
230 | AR5K_CTL_11A = 0, | ||
231 | AR5K_CTL_11B = 1, | ||
232 | AR5K_CTL_11G = 2, | ||
233 | AR5K_CTL_TURBO = 3, | ||
234 | AR5K_CTL_108G = 4, | ||
235 | AR5K_CTL_2GHT20 = 5, | ||
236 | AR5K_CTL_5GHT20 = 6, | ||
237 | AR5K_CTL_2GHT40 = 7, | ||
238 | AR5K_CTL_5GHT40 = 8, | ||
239 | AR5K_CTL_MODE_M = 15, | ||
240 | }; | ||
241 | |||
242 | /* Per channel calibration data, used for power table setup */ | ||
243 | struct ath5k_chan_pcal_info_rf5111 { | ||
244 | /* Power levels in half dbm units | ||
245 | * for one power curve. */ | ||
246 | u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111]; | ||
247 | /* PCDAC table steps | ||
248 | * for the above values */ | ||
249 | u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111]; | ||
250 | /* Starting PCDAC step */ | ||
251 | u8 pcdac_min; | ||
252 | /* Final PCDAC step */ | ||
253 | u8 pcdac_max; | ||
254 | }; | ||
255 | |||
256 | struct ath5k_chan_pcal_info_rf5112 { | ||
257 | /* Power levels in quarter dBm units | ||
258 | * for lower (0) and higher (3) | ||
259 | * level curves */ | ||
260 | s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS]; | ||
261 | s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS]; | ||
262 | /* PCDAC table steps | ||
263 | * for the above values */ | ||
264 | u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS]; | ||
265 | u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS]; | ||
266 | }; | ||
267 | |||
268 | struct ath5k_chan_pcal_info_rf2413 { | ||
269 | /* Starting pwr/pddac values */ | ||
270 | s8 pwr_i[AR5K_EEPROM_N_PD_GAINS]; | ||
271 | u8 pddac_i[AR5K_EEPROM_N_PD_GAINS]; | ||
272 | /* (pwr,pddac) points */ | ||
273 | s8 pwr[AR5K_EEPROM_N_PD_GAINS] | ||
274 | [AR5K_EEPROM_N_PD_POINTS]; | ||
275 | u8 pddac[AR5K_EEPROM_N_PD_GAINS] | ||
276 | [AR5K_EEPROM_N_PD_POINTS]; | ||
277 | }; | ||
278 | |||
279 | struct ath5k_chan_pcal_info { | ||
280 | /* Frequency */ | ||
281 | u16 freq; | ||
282 | /* Max available power */ | ||
283 | s8 max_pwr; | ||
284 | union { | ||
285 | struct ath5k_chan_pcal_info_rf5111 rf5111_info; | ||
286 | struct ath5k_chan_pcal_info_rf5112 rf5112_info; | ||
287 | struct ath5k_chan_pcal_info_rf2413 rf2413_info; | ||
288 | }; | ||
289 | }; | ||
290 | |||
291 | /* Per rate calibration data for each mode, used for power table setup */ | ||
292 | struct ath5k_rate_pcal_info { | ||
293 | u16 freq; /* Frequency */ | ||
294 | /* Power level for 6-24Mbit/s rates */ | ||
295 | u16 target_power_6to24; | ||
296 | /* Power level for 36Mbit rate */ | ||
297 | u16 target_power_36; | ||
298 | /* Power level for 48Mbit rate */ | ||
299 | u16 target_power_48; | ||
300 | /* Power level for 54Mbit rate */ | ||
301 | u16 target_power_54; | ||
302 | }; | ||
303 | |||
304 | /* Power edges for conformance test limits */ | ||
305 | struct ath5k_edge_power { | ||
306 | u16 freq; | ||
307 | u16 edge; /* in half dBm */ | ||
308 | bool flag; | ||
309 | }; | ||
310 | |||
311 | /* EEPROM calibration data */ | ||
162 | struct ath5k_eeprom_info { | 312 | struct ath5k_eeprom_info { |
313 | |||
314 | /* Header information */ | ||
163 | u16 ee_magic; | 315 | u16 ee_magic; |
164 | u16 ee_protect; | 316 | u16 ee_protect; |
165 | u16 ee_regdomain; | 317 | u16 ee_regdomain; |
@@ -168,6 +320,11 @@ struct ath5k_eeprom_info { | |||
168 | u16 ee_ant_gain; | 320 | u16 ee_ant_gain; |
169 | u16 ee_misc0; | 321 | u16 ee_misc0; |
170 | u16 ee_misc1; | 322 | u16 ee_misc1; |
323 | u16 ee_misc2; | ||
324 | u16 ee_misc3; | ||
325 | u16 ee_misc4; | ||
326 | u16 ee_misc5; | ||
327 | u16 ee_misc6; | ||
171 | u16 ee_cck_ofdm_gain_delta; | 328 | u16 ee_cck_ofdm_gain_delta; |
172 | u16 ee_cck_ofdm_power_delta; | 329 | u16 ee_cck_ofdm_power_delta; |
173 | u16 ee_scaled_cck_delta; | 330 | u16 ee_scaled_cck_delta; |
@@ -185,7 +342,7 @@ struct ath5k_eeprom_info { | |||
185 | u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES]; | 342 | u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES]; |
186 | u16 ee_xr_power[AR5K_EEPROM_N_MODES]; | 343 | u16 ee_xr_power[AR5K_EEPROM_N_MODES]; |
187 | u16 ee_switch_settling[AR5K_EEPROM_N_MODES]; | 344 | u16 ee_switch_settling[AR5K_EEPROM_N_MODES]; |
188 | u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES]; | 345 | u16 ee_atn_tx_rx[AR5K_EEPROM_N_MODES]; |
189 | u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC]; | 346 | u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC]; |
190 | u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; | 347 | u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; |
191 | u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; | 348 | u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; |
@@ -198,18 +355,40 @@ struct ath5k_eeprom_info { | |||
198 | u16 ee_x_gain[AR5K_EEPROM_N_MODES]; | 355 | u16 ee_x_gain[AR5K_EEPROM_N_MODES]; |
199 | u16 ee_i_gain[AR5K_EEPROM_N_MODES]; | 356 | u16 ee_i_gain[AR5K_EEPROM_N_MODES]; |
200 | u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES]; | 357 | u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES]; |
358 | u16 ee_switch_settling_turbo[AR5K_EEPROM_N_MODES]; | ||
359 | u16 ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES]; | ||
360 | u16 ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES]; | ||
201 | 361 | ||
202 | /* Unused */ | 362 | /* Power calibration data */ |
203 | u16 ee_false_detect[AR5K_EEPROM_N_MODES]; | 363 | u16 ee_false_detect[AR5K_EEPROM_N_MODES]; |
204 | u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN]; | 364 | |
205 | u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/ | 365 | /* Number of pd gain curves per mode (RF2413) */ |
366 | u8 ee_pd_gains[AR5K_EEPROM_N_MODES]; | ||
367 | |||
368 | u8 ee_n_piers[AR5K_EEPROM_N_MODES]; | ||
369 | struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN]; | ||
370 | struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN]; | ||
371 | struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN]; | ||
372 | |||
373 | /* Per rate target power levels */ | ||
374 | u16 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES]; | ||
375 | struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN]; | ||
376 | struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN]; | ||
377 | struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN]; | ||
206 | 378 | ||
207 | /* Conformance test limits (Unused) */ | 379 | /* Conformance test limits (Unused) */ |
208 | u16 ee_ctls; | 380 | u16 ee_ctls; |
209 | u16 ee_ctl[AR5K_EEPROM_MAX_CTLS]; | 381 | u16 ee_ctl[AR5K_EEPROM_MAX_CTLS]; |
382 | struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS]; | ||
210 | 383 | ||
211 | /* Noise Floor Calibration settings */ | 384 | /* Noise Floor Calibration settings */ |
212 | s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES]; | 385 | s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES]; |
213 | s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES]; | 386 | s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES]; |
214 | s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES]; | 387 | s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES]; |
388 | s8 ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES]; | ||
389 | s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES]; | ||
390 | s8 ee_pd_gain_overlap; | ||
391 | |||
392 | u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | ||
215 | }; | 393 | }; |
394 | |||
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c index 5003263c9ea4..dc2d7d8bdb7a 100644 --- a/drivers/net/wireless/ath5k/reset.c +++ b/drivers/net/wireless/ath5k/reset.c | |||
@@ -674,7 +674,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
674 | (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, | 674 | (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, |
675 | 0xffffc07f); | 675 | 0xffffc07f); |
676 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN, | 676 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN, |
677 | (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, | 677 | (ee->ee_atn_tx_rx[ee_mode] << 12) & 0x3f000, |
678 | 0xfffc0fff); | 678 | 0xfffc0fff); |
679 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE, | 679 | AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE, |
680 | (ee->ee_adc_desired_size[ee_mode] & 0x00ff) | | 680 | (ee->ee_adc_desired_size[ee_mode] & 0x00ff) | |
diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath9k/Makefile index c58cfdeb49c9..c741e8d34748 100644 --- a/drivers/net/wireless/ath9k/Makefile +++ b/drivers/net/wireless/ath9k/Makefile | |||
@@ -9,7 +9,6 @@ ath9k-y += hw.o \ | |||
9 | main.o \ | 9 | main.o \ |
10 | recv.o \ | 10 | recv.o \ |
11 | xmit.o \ | 11 | xmit.o \ |
12 | rc.o \ | 12 | rc.o |
13 | core.o | ||
14 | 13 | ||
15 | obj-$(CONFIG_ATH9K) += ath9k.o | 14 | obj-$(CONFIG_ATH9K) += ath9k.o |
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 3a180ce1770b..5b9bc545e964 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h | |||
@@ -401,22 +401,6 @@ enum ath9k_int { | |||
401 | ATH9K_INT_NOCARD = 0xffffffff | 401 | ATH9K_INT_NOCARD = 0xffffffff |
402 | }; | 402 | }; |
403 | 403 | ||
404 | struct ath9k_rate_table { | ||
405 | int rateCount; | ||
406 | u8 rateCodeToIndex[256]; | ||
407 | struct { | ||
408 | u8 valid; | ||
409 | u8 phy; | ||
410 | u32 rateKbps; | ||
411 | u8 rateCode; | ||
412 | u8 shortPreamble; | ||
413 | u8 dot11Rate; | ||
414 | u8 controlRate; | ||
415 | u16 lpAckDuration; | ||
416 | u16 spAckDuration; | ||
417 | } info[32]; | ||
418 | }; | ||
419 | |||
420 | #define ATH9K_RATESERIES_RTS_CTS 0x0001 | 404 | #define ATH9K_RATESERIES_RTS_CTS 0x0001 |
421 | #define ATH9K_RATESERIES_2040 0x0002 | 405 | #define ATH9K_RATESERIES_2040 0x0002 |
422 | #define ATH9K_RATESERIES_HALFGI 0x0004 | 406 | #define ATH9K_RATESERIES_HALFGI 0x0004 |
@@ -492,12 +476,10 @@ struct ath9k_channel { | |||
492 | (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \ | 476 | (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \ |
493 | (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \ | 477 | (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \ |
494 | (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS)) | 478 | (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS)) |
495 | #define IS_CHAN_B(_c) (((_c)->channelFlags & CHANNEL_B) == CHANNEL_B) | ||
496 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 479 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ |
497 | (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ | 480 | (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ |
498 | (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ | 481 | (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ |
499 | (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) | 482 | (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) |
500 | #define IS_CHAN_CCK(_c) (((_c)->channelFlags & CHANNEL_CCK) != 0) | ||
501 | #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) | 483 | #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) |
502 | #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) | 484 | #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) |
503 | #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) | 485 | #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) |
@@ -506,6 +488,7 @@ struct ath9k_channel { | |||
506 | #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) | 488 | #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) |
507 | 489 | ||
508 | /* These macros check chanmode and not channelFlags */ | 490 | /* These macros check chanmode and not channelFlags */ |
491 | #define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B) | ||
509 | #define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ | 492 | #define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ |
510 | ((_c)->chanmode == CHANNEL_G_HT20)) | 493 | ((_c)->chanmode == CHANNEL_G_HT20)) |
511 | #define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ | 494 | #define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ |
@@ -702,13 +685,19 @@ enum ath9k_ani_cmd { | |||
702 | ATH9K_ANI_ALL = 0xff | 685 | ATH9K_ANI_ALL = 0xff |
703 | }; | 686 | }; |
704 | 687 | ||
705 | enum phytype { | 688 | enum { |
706 | PHY_DS, | 689 | WLAN_RC_PHY_OFDM, |
707 | PHY_FH, | 690 | WLAN_RC_PHY_CCK, |
708 | PHY_OFDM, | 691 | WLAN_RC_PHY_HT_20_SS, |
709 | PHY_HT, | 692 | WLAN_RC_PHY_HT_20_DS, |
693 | WLAN_RC_PHY_HT_40_SS, | ||
694 | WLAN_RC_PHY_HT_40_DS, | ||
695 | WLAN_RC_PHY_HT_20_SS_HGI, | ||
696 | WLAN_RC_PHY_HT_20_DS_HGI, | ||
697 | WLAN_RC_PHY_HT_40_SS_HGI, | ||
698 | WLAN_RC_PHY_HT_40_DS_HGI, | ||
699 | WLAN_RC_PHY_MAX | ||
710 | }; | 700 | }; |
711 | #define PHY_CCK PHY_DS | ||
712 | 701 | ||
713 | enum ath9k_tp_scale { | 702 | enum ath9k_tp_scale { |
714 | ATH9K_TP_SCALE_MAX = 0, | 703 | ATH9K_TP_SCALE_MAX = 0, |
@@ -828,6 +817,8 @@ struct chan_centers { | |||
828 | u16 ext_center; | 817 | u16 ext_center; |
829 | }; | 818 | }; |
830 | 819 | ||
820 | struct ath_rate_table; | ||
821 | |||
831 | /* Helpers */ | 822 | /* Helpers */ |
832 | 823 | ||
833 | enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah, | 824 | enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah, |
@@ -838,7 +829,7 @@ bool ath9k_get_channel_edges(struct ath_hal *ah, | |||
838 | u16 flags, u16 *low, | 829 | u16 flags, u16 *low, |
839 | u16 *high); | 830 | u16 *high); |
840 | u16 ath9k_hw_computetxtime(struct ath_hal *ah, | 831 | u16 ath9k_hw_computetxtime(struct ath_hal *ah, |
841 | const struct ath9k_rate_table *rates, | 832 | struct ath_rate_table *rates, |
842 | u32 frameLen, u16 rateix, | 833 | u32 frameLen, u16 rateix, |
843 | bool shortPreamble); | 834 | bool shortPreamble); |
844 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); | 835 | u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags); |
@@ -883,12 +874,6 @@ void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore); | |||
883 | void ath9k_hw_beaconinit(struct ath_hal *ah, u32 next_beacon, u32 beacon_period); | 874 | void ath9k_hw_beaconinit(struct ath_hal *ah, u32 next_beacon, u32 beacon_period); |
884 | void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah, | 875 | void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah, |
885 | const struct ath9k_beacon_state *bs); | 876 | const struct ath9k_beacon_state *bs); |
886 | |||
887 | /* Rate table */ | ||
888 | |||
889 | const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah, | ||
890 | u32 mode); | ||
891 | |||
892 | /* HW Capabilities */ | 877 | /* HW Capabilities */ |
893 | 878 | ||
894 | bool ath9k_hw_fill_cap_info(struct ath_hal *ah); | 879 | bool ath9k_hw_fill_cap_info(struct ath_hal *ah); |
@@ -904,7 +889,7 @@ u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio); | |||
904 | void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, | 889 | void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio, |
905 | u32 ah_signal_type); | 890 | u32 ah_signal_type); |
906 | void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val); | 891 | void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val); |
907 | #ifdef CONFIG_RFKILL | 892 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
908 | void ath9k_enable_rfkill(struct ath_hal *ah); | 893 | void ath9k_enable_rfkill(struct ath_hal *ah); |
909 | #endif | 894 | #endif |
910 | int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg); | 895 | int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg); |
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index d186cd41c235..377d2df05316 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c | |||
@@ -14,13 +14,9 @@ | |||
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 | /* Implementation of beacon processing. */ | ||
18 | |||
19 | #include "core.h" | 17 | #include "core.h" |
20 | 18 | ||
21 | /* | 19 | /* |
22 | * Configure parameters for the beacon queue | ||
23 | * | ||
24 | * This function will modify certain transmit queue properties depending on | 20 | * This function will modify certain transmit queue properties depending on |
25 | * the operating mode of the station (AP or AdHoc). Parameters are AIFS | 21 | * the operating mode of the station (AP or AdHoc). Parameters are AIFS |
26 | * settings and channel width min/max | 22 | * settings and channel width min/max |
@@ -54,9 +50,15 @@ static int ath_beaconq_config(struct ath_softc *sc) | |||
54 | } | 50 | } |
55 | } | 51 | } |
56 | 52 | ||
53 | static void ath_bstuck_process(struct ath_softc *sc) | ||
54 | { | ||
55 | DPRINTF(sc, ATH_DBG_BEACON, | ||
56 | "%s: stuck beacon; resetting (bmiss count %u)\n", | ||
57 | __func__, sc->sc_bmisscount); | ||
58 | ath_reset(sc, false); | ||
59 | } | ||
60 | |||
57 | /* | 61 | /* |
58 | * Setup the beacon frame for transmit. | ||
59 | * | ||
60 | * Associates the beacon frame buffer with a transmit descriptor. Will set | 62 | * Associates the beacon frame buffer with a transmit descriptor. Will set |
61 | * up all required antenna switch parameters, rate codes, and channel flags. | 63 | * up all required antenna switch parameters, rate codes, and channel flags. |
62 | * Beacons are always sent out at the lowest rate, and are not retried. | 64 | * Beacons are always sent out at the lowest rate, and are not retried. |
@@ -68,7 +70,7 @@ static void ath_beacon_setup(struct ath_softc *sc, | |||
68 | struct ath_hal *ah = sc->sc_ah; | 70 | struct ath_hal *ah = sc->sc_ah; |
69 | struct ath_desc *ds; | 71 | struct ath_desc *ds; |
70 | struct ath9k_11n_rate_series series[4]; | 72 | struct ath9k_11n_rate_series series[4]; |
71 | const struct ath9k_rate_table *rt; | 73 | struct ath_rate_table *rt; |
72 | int flags, antenna; | 74 | int flags, antenna; |
73 | u8 rix, rate; | 75 | u8 rix, rate; |
74 | int ctsrate = 0; | 76 | int ctsrate = 0; |
@@ -106,10 +108,10 @@ static void ath_beacon_setup(struct ath_softc *sc, | |||
106 | * XXX everything at min xmit rate | 108 | * XXX everything at min xmit rate |
107 | */ | 109 | */ |
108 | rix = 0; | 110 | rix = 0; |
109 | rt = sc->sc_currates; | 111 | rt = sc->hw_rate_table[sc->sc_curmode]; |
110 | rate = rt->info[rix].rateCode; | 112 | rate = rt->info[rix].ratecode; |
111 | if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) | 113 | if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) |
112 | rate |= rt->info[rix].shortPreamble; | 114 | rate |= rt->info[rix].short_preamble; |
113 | 115 | ||
114 | ath9k_hw_set11n_txdesc(ah, ds, | 116 | ath9k_hw_set11n_txdesc(ah, ds, |
115 | skb->len + FCS_LEN, /* frame length */ | 117 | skb->len + FCS_LEN, /* frame length */ |
@@ -138,14 +140,7 @@ static void ath_beacon_setup(struct ath_softc *sc, | |||
138 | ctsrate, ctsduration, series, 4, 0); | 140 | ctsrate, ctsduration, series, 4, 0); |
139 | } | 141 | } |
140 | 142 | ||
141 | /* | 143 | /* Generate beacon frame and queue cab data for a vap */ |
142 | * Generate beacon frame and queue cab data for a vap. | ||
143 | * | ||
144 | * Updates the contents of the beacon frame. It is assumed that the buffer for | ||
145 | * the beacon frame has been allocated in the ATH object, and simply needs to | ||
146 | * be filled for this cycle. Also, any CAB (crap after beacon?) traffic will | ||
147 | * be added to the beacon frame at this point. | ||
148 | */ | ||
149 | static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) | 144 | static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id) |
150 | { | 145 | { |
151 | struct ath_buf *bf; | 146 | struct ath_buf *bf; |
@@ -275,14 +270,6 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id) | |||
275 | sc->sc_bhalq, ito64(bf->bf_daddr), bf->bf_desc); | 270 | sc->sc_bhalq, ito64(bf->bf_daddr), bf->bf_desc); |
276 | } | 271 | } |
277 | 272 | ||
278 | /* | ||
279 | * Setup a h/w transmit queue for beacons. | ||
280 | * | ||
281 | * This function allocates an information structure (struct ath9k_txq_info) | ||
282 | * on the stack, sets some specific parameters (zero out channel width | ||
283 | * min/max, and enable aifs). The info structure does not need to be | ||
284 | * persistant. | ||
285 | */ | ||
286 | int ath_beaconq_setup(struct ath_hal *ah) | 273 | int ath_beaconq_setup(struct ath_hal *ah) |
287 | { | 274 | { |
288 | struct ath9k_tx_queue_info qi; | 275 | struct ath9k_tx_queue_info qi; |
@@ -295,14 +282,6 @@ int ath_beaconq_setup(struct ath_hal *ah) | |||
295 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); | 282 | return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); |
296 | } | 283 | } |
297 | 284 | ||
298 | |||
299 | /* | ||
300 | * Allocate and setup an initial beacon frame. | ||
301 | * | ||
302 | * Allocate a beacon state variable for a specific VAP instance created on | ||
303 | * the ATH interface. This routine also calculates the beacon "slot" for | ||
304 | * staggared beacons in the mBSSID case. | ||
305 | */ | ||
306 | int ath_beacon_alloc(struct ath_softc *sc, int if_id) | 285 | int ath_beacon_alloc(struct ath_softc *sc, int if_id) |
307 | { | 286 | { |
308 | struct ieee80211_vif *vif; | 287 | struct ieee80211_vif *vif; |
@@ -321,7 +300,6 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
321 | if (!avp->av_bcbuf) { | 300 | if (!avp->av_bcbuf) { |
322 | /* Allocate beacon state for hostap/ibss. We know | 301 | /* Allocate beacon state for hostap/ibss. We know |
323 | * a buffer is available. */ | 302 | * a buffer is available. */ |
324 | |||
325 | avp->av_bcbuf = list_first_entry(&sc->sc_bbuf, | 303 | avp->av_bcbuf = list_first_entry(&sc->sc_bbuf, |
326 | struct ath_buf, list); | 304 | struct ath_buf, list); |
327 | list_del(&avp->av_bcbuf->list); | 305 | list_del(&avp->av_bcbuf->list); |
@@ -427,12 +405,6 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id) | |||
427 | return 0; | 405 | return 0; |
428 | } | 406 | } |
429 | 407 | ||
430 | /* | ||
431 | * Reclaim beacon resources and return buffer to the pool. | ||
432 | * | ||
433 | * Checks the VAP to put the beacon frame buffer back to the ATH object | ||
434 | * queue, and de-allocates any skbs that were sent as CAB traffic. | ||
435 | */ | ||
436 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) | 408 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) |
437 | { | 409 | { |
438 | if (avp->av_bcbuf != NULL) { | 410 | if (avp->av_bcbuf != NULL) { |
@@ -458,13 +430,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp) | |||
458 | } | 430 | } |
459 | } | 431 | } |
460 | 432 | ||
461 | /* | ||
462 | * Tasklet for Sending Beacons | ||
463 | * | ||
464 | * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame | ||
465 | * contents are done as needed and the slot time is also adjusted based on | ||
466 | * current state. | ||
467 | */ | ||
468 | void ath9k_beacon_tasklet(unsigned long data) | 433 | void ath9k_beacon_tasklet(unsigned long data) |
469 | { | 434 | { |
470 | struct ath_softc *sc = (struct ath_softc *)data; | 435 | struct ath_softc *sc = (struct ath_softc *)data; |
@@ -481,9 +446,7 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
481 | 446 | ||
482 | if (sc->sc_flags & SC_OP_NO_RESET) { | 447 | if (sc->sc_flags & SC_OP_NO_RESET) { |
483 | show_cycles = ath9k_hw_GetMibCycleCountsPct(ah, | 448 | show_cycles = ath9k_hw_GetMibCycleCountsPct(ah, |
484 | &rx_clear, | 449 | &rx_clear, &rx_frame, &tx_frame); |
485 | &rx_frame, | ||
486 | &tx_frame); | ||
487 | } | 450 | } |
488 | 451 | ||
489 | /* | 452 | /* |
@@ -605,9 +568,10 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
605 | if (sc->sc_updateslot == UPDATE) { | 568 | if (sc->sc_updateslot == UPDATE) { |
606 | sc->sc_updateslot = COMMIT; /* commit next beacon */ | 569 | sc->sc_updateslot = COMMIT; /* commit next beacon */ |
607 | sc->sc_slotupdate = slot; | 570 | sc->sc_slotupdate = slot; |
608 | } else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot) | 571 | } else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot) { |
609 | ath_setslottime(sc); /* commit change to hardware */ | 572 | ath9k_hw_setslottime(sc->sc_ah, sc->sc_slottime); |
610 | 573 | sc->sc_updateslot = OK; | |
574 | } | ||
611 | if (bfaddr != 0) { | 575 | if (bfaddr != 0) { |
612 | /* | 576 | /* |
613 | * Stop any current dma and put the new frame(s) on the queue. | 577 | * Stop any current dma and put the new frame(s) on the queue. |
@@ -630,20 +594,6 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
630 | } | 594 | } |
631 | 595 | ||
632 | /* | 596 | /* |
633 | * Tasklet for Beacon Stuck processing | ||
634 | * | ||
635 | * Processing for Beacon Stuck. | ||
636 | * Basically resets the chip. | ||
637 | */ | ||
638 | void ath_bstuck_process(struct ath_softc *sc) | ||
639 | { | ||
640 | DPRINTF(sc, ATH_DBG_BEACON, | ||
641 | "%s: stuck beacon; resetting (bmiss count %u)\n", | ||
642 | __func__, sc->sc_bmisscount); | ||
643 | ath_reset(sc, false); | ||
644 | } | ||
645 | |||
646 | /* | ||
647 | * Configure the beacon and sleep timers. | 597 | * Configure the beacon and sleep timers. |
648 | * | 598 | * |
649 | * When operating as an AP this resets the TSF and sets | 599 | * When operating as an AP this resets the TSF and sets |
@@ -886,8 +836,6 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
886 | } | 836 | } |
887 | } | 837 | } |
888 | 838 | ||
889 | /* Function to collect beacon rssi data and resync beacon if necessary */ | ||
890 | |||
891 | void ath_beacon_sync(struct ath_softc *sc, int if_id) | 839 | void ath_beacon_sync(struct ath_softc *sc, int if_id) |
892 | { | 840 | { |
893 | /* | 841 | /* |
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 1690759fe7b8..0e214f746a96 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c | |||
@@ -176,14 +176,14 @@ static bool getNoiseFloorThresh(struct ath_hal *ah, | |||
176 | case CHANNEL_A_HT20: | 176 | case CHANNEL_A_HT20: |
177 | case CHANNEL_A_HT40PLUS: | 177 | case CHANNEL_A_HT40PLUS: |
178 | case CHANNEL_A_HT40MINUS: | 178 | case CHANNEL_A_HT40MINUS: |
179 | *nft = (int16_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5); | 179 | *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5); |
180 | break; | 180 | break; |
181 | case CHANNEL_B: | 181 | case CHANNEL_B: |
182 | case CHANNEL_G: | 182 | case CHANNEL_G: |
183 | case CHANNEL_G_HT20: | 183 | case CHANNEL_G_HT20: |
184 | case CHANNEL_G_HT40PLUS: | 184 | case CHANNEL_G_HT40PLUS: |
185 | case CHANNEL_G_HT40MINUS: | 185 | case CHANNEL_G_HT40MINUS: |
186 | *nft = (int16_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2); | 186 | *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2); |
187 | break; | 187 | break; |
188 | default: | 188 | default: |
189 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | 189 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, |
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c deleted file mode 100644 index 5f5184acb274..000000000000 --- a/drivers/net/wireless/ath9k/core.c +++ /dev/null | |||
@@ -1,1652 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008, 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 "core.h" | ||
18 | #include "regd.h" | ||
19 | |||
20 | static u32 ath_chainmask_sel_up_rssi_thres = | ||
21 | ATH_CHAINMASK_SEL_UP_RSSI_THRES; | ||
22 | static u32 ath_chainmask_sel_down_rssi_thres = | ||
23 | ATH_CHAINMASK_SEL_DOWN_RSSI_THRES; | ||
24 | static u32 ath_chainmask_sel_period = | ||
25 | ATH_CHAINMASK_SEL_TIMEOUT; | ||
26 | |||
27 | /* return bus cachesize in 4B word units */ | ||
28 | |||
29 | static void bus_read_cachesize(struct ath_softc *sc, int *csz) | ||
30 | { | ||
31 | u8 u8tmp; | ||
32 | |||
33 | pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, (u8 *)&u8tmp); | ||
34 | *csz = (int)u8tmp; | ||
35 | |||
36 | /* | ||
37 | * This check was put in to avoid "unplesant" consequences if | ||
38 | * the bootrom has not fully initialized all PCI devices. | ||
39 | * Sometimes the cache line size register is not set | ||
40 | */ | ||
41 | |||
42 | if (*csz == 0) | ||
43 | *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ | ||
44 | } | ||
45 | |||
46 | static u8 parse_mpdudensity(u8 mpdudensity) | ||
47 | { | ||
48 | /* | ||
49 | * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": | ||
50 | * 0 for no restriction | ||
51 | * 1 for 1/4 us | ||
52 | * 2 for 1/2 us | ||
53 | * 3 for 1 us | ||
54 | * 4 for 2 us | ||
55 | * 5 for 4 us | ||
56 | * 6 for 8 us | ||
57 | * 7 for 16 us | ||
58 | */ | ||
59 | switch (mpdudensity) { | ||
60 | case 0: | ||
61 | return 0; | ||
62 | case 1: | ||
63 | case 2: | ||
64 | case 3: | ||
65 | /* Our lower layer calculations limit our precision to | ||
66 | 1 microsecond */ | ||
67 | return 1; | ||
68 | case 4: | ||
69 | return 2; | ||
70 | case 5: | ||
71 | return 4; | ||
72 | case 6: | ||
73 | return 8; | ||
74 | case 7: | ||
75 | return 16; | ||
76 | default: | ||
77 | return 0; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | /* | ||
82 | * Set current operating mode | ||
83 | * | ||
84 | * This function initializes and fills the rate table in the ATH object based | ||
85 | * on the operating mode. | ||
86 | */ | ||
87 | static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) | ||
88 | { | ||
89 | const struct ath9k_rate_table *rt; | ||
90 | int i; | ||
91 | |||
92 | memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap)); | ||
93 | rt = ath9k_hw_getratetable(sc->sc_ah, mode); | ||
94 | BUG_ON(!rt); | ||
95 | |||
96 | for (i = 0; i < rt->rateCount; i++) | ||
97 | sc->sc_rixmap[rt->info[i].rateCode] = (u8) i; | ||
98 | |||
99 | memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap)); | ||
100 | for (i = 0; i < 256; i++) { | ||
101 | u8 ix = rt->rateCodeToIndex[i]; | ||
102 | |||
103 | if (ix == 0xff) | ||
104 | continue; | ||
105 | |||
106 | sc->sc_hwmap[i].ieeerate = | ||
107 | rt->info[ix].dot11Rate & IEEE80211_RATE_VAL; | ||
108 | sc->sc_hwmap[i].rateKbps = rt->info[ix].rateKbps; | ||
109 | |||
110 | if (rt->info[ix].shortPreamble || | ||
111 | rt->info[ix].phy == PHY_OFDM) { | ||
112 | /* XXX: Handle this */ | ||
113 | } | ||
114 | |||
115 | /* NB: this uses the last entry if the rate isn't found */ | ||
116 | /* XXX beware of overlow */ | ||
117 | } | ||
118 | sc->sc_currates = rt; | ||
119 | sc->sc_curmode = mode; | ||
120 | /* | ||
121 | * All protection frames are transmited at 2Mb/s for | ||
122 | * 11g, otherwise at 1Mb/s. | ||
123 | * XXX select protection rate index from rate table. | ||
124 | */ | ||
125 | sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0); | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Set up rate table (legacy rates) | ||
130 | */ | ||
131 | static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) | ||
132 | { | ||
133 | struct ath_hal *ah = sc->sc_ah; | ||
134 | const struct ath9k_rate_table *rt = NULL; | ||
135 | struct ieee80211_supported_band *sband; | ||
136 | struct ieee80211_rate *rate; | ||
137 | int i, maxrates; | ||
138 | |||
139 | switch (band) { | ||
140 | case IEEE80211_BAND_2GHZ: | ||
141 | rt = ath9k_hw_getratetable(ah, ATH9K_MODE_11G); | ||
142 | break; | ||
143 | case IEEE80211_BAND_5GHZ: | ||
144 | rt = ath9k_hw_getratetable(ah, ATH9K_MODE_11A); | ||
145 | break; | ||
146 | default: | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | if (rt == NULL) | ||
151 | return; | ||
152 | |||
153 | sband = &sc->sbands[band]; | ||
154 | rate = sc->rates[band]; | ||
155 | |||
156 | if (rt->rateCount > ATH_RATE_MAX) | ||
157 | maxrates = ATH_RATE_MAX; | ||
158 | else | ||
159 | maxrates = rt->rateCount; | ||
160 | |||
161 | for (i = 0; i < maxrates; i++) { | ||
162 | rate[i].bitrate = rt->info[i].rateKbps / 100; | ||
163 | rate[i].hw_value = rt->info[i].rateCode; | ||
164 | sband->n_bitrates++; | ||
165 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
166 | "%s: Rate: %2dMbps, ratecode: %2d\n", | ||
167 | __func__, | ||
168 | rate[i].bitrate / 10, | ||
169 | rate[i].hw_value); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Set up channel list | ||
175 | */ | ||
176 | static int ath_setup_channels(struct ath_softc *sc) | ||
177 | { | ||
178 | struct ath_hal *ah = sc->sc_ah; | ||
179 | int nchan, i, a = 0, b = 0; | ||
180 | u8 regclassids[ATH_REGCLASSIDS_MAX]; | ||
181 | u32 nregclass = 0; | ||
182 | struct ieee80211_supported_band *band_2ghz; | ||
183 | struct ieee80211_supported_band *band_5ghz; | ||
184 | struct ieee80211_channel *chan_2ghz; | ||
185 | struct ieee80211_channel *chan_5ghz; | ||
186 | struct ath9k_channel *c; | ||
187 | |||
188 | /* Fill in ah->ah_channels */ | ||
189 | if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan, | ||
190 | regclassids, ATH_REGCLASSIDS_MAX, | ||
191 | &nregclass, CTRY_DEFAULT, false, 1)) { | ||
192 | u32 rd = ah->ah_currentRD; | ||
193 | DPRINTF(sc, ATH_DBG_FATAL, | ||
194 | "%s: unable to collect channel list; " | ||
195 | "regdomain likely %u country code %u\n", | ||
196 | __func__, rd, CTRY_DEFAULT); | ||
197 | return -EINVAL; | ||
198 | } | ||
199 | |||
200 | band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
201 | band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
202 | chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ]; | ||
203 | chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ]; | ||
204 | |||
205 | for (i = 0; i < nchan; i++) { | ||
206 | c = &ah->ah_channels[i]; | ||
207 | if (IS_CHAN_2GHZ(c)) { | ||
208 | chan_2ghz[a].band = IEEE80211_BAND_2GHZ; | ||
209 | chan_2ghz[a].center_freq = c->channel; | ||
210 | chan_2ghz[a].max_power = c->maxTxPower; | ||
211 | |||
212 | if (c->privFlags & CHANNEL_DISALLOW_ADHOC) | ||
213 | chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS; | ||
214 | if (c->channelFlags & CHANNEL_PASSIVE) | ||
215 | chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
216 | |||
217 | band_2ghz->n_channels = ++a; | ||
218 | |||
219 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
220 | "%s: 2MHz channel: %d, " | ||
221 | "channelFlags: 0x%x\n", | ||
222 | __func__, c->channel, c->channelFlags); | ||
223 | } else if (IS_CHAN_5GHZ(c)) { | ||
224 | chan_5ghz[b].band = IEEE80211_BAND_5GHZ; | ||
225 | chan_5ghz[b].center_freq = c->channel; | ||
226 | chan_5ghz[b].max_power = c->maxTxPower; | ||
227 | |||
228 | if (c->privFlags & CHANNEL_DISALLOW_ADHOC) | ||
229 | chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS; | ||
230 | if (c->channelFlags & CHANNEL_PASSIVE) | ||
231 | chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
232 | |||
233 | band_5ghz->n_channels = ++b; | ||
234 | |||
235 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
236 | "%s: 5MHz channel: %d, " | ||
237 | "channelFlags: 0x%x\n", | ||
238 | __func__, c->channel, c->channelFlags); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * Determine mode from channel flags | ||
247 | * | ||
248 | * This routine will provide the enumerated WIRELESSS_MODE value based | ||
249 | * on the settings of the channel flags. If no valid set of flags | ||
250 | * exist, the lowest mode (11b) is selected. | ||
251 | */ | ||
252 | |||
253 | static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan) | ||
254 | { | ||
255 | if (chan->chanmode == CHANNEL_A) | ||
256 | return ATH9K_MODE_11A; | ||
257 | else if (chan->chanmode == CHANNEL_G) | ||
258 | return ATH9K_MODE_11G; | ||
259 | else if (chan->chanmode == CHANNEL_B) | ||
260 | return ATH9K_MODE_11B; | ||
261 | else if (chan->chanmode == CHANNEL_A_HT20) | ||
262 | return ATH9K_MODE_11NA_HT20; | ||
263 | else if (chan->chanmode == CHANNEL_G_HT20) | ||
264 | return ATH9K_MODE_11NG_HT20; | ||
265 | else if (chan->chanmode == CHANNEL_A_HT40PLUS) | ||
266 | return ATH9K_MODE_11NA_HT40PLUS; | ||
267 | else if (chan->chanmode == CHANNEL_A_HT40MINUS) | ||
268 | return ATH9K_MODE_11NA_HT40MINUS; | ||
269 | else if (chan->chanmode == CHANNEL_G_HT40PLUS) | ||
270 | return ATH9K_MODE_11NG_HT40PLUS; | ||
271 | else if (chan->chanmode == CHANNEL_G_HT40MINUS) | ||
272 | return ATH9K_MODE_11NG_HT40MINUS; | ||
273 | |||
274 | WARN_ON(1); /* should not get here */ | ||
275 | |||
276 | return ATH9K_MODE_11B; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * Set the current channel | ||
281 | * | ||
282 | * Set/change channels. If the channel is really being changed, it's done | ||
283 | * by reseting the chip. To accomplish this we must first cleanup any pending | ||
284 | * DMA, then restart stuff after a la ath_init. | ||
285 | */ | ||
286 | int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) | ||
287 | { | ||
288 | struct ath_hal *ah = sc->sc_ah; | ||
289 | bool fastcc = true, stopped; | ||
290 | |||
291 | if (sc->sc_flags & SC_OP_INVALID) /* the device is invalid or removed */ | ||
292 | return -EIO; | ||
293 | |||
294 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
295 | "%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n", | ||
296 | __func__, | ||
297 | ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel, | ||
298 | sc->sc_ah->ah_curchan->channelFlags), | ||
299 | sc->sc_ah->ah_curchan->channel, | ||
300 | ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags), | ||
301 | hchan->channel, hchan->channelFlags); | ||
302 | |||
303 | if (hchan->channel != sc->sc_ah->ah_curchan->channel || | ||
304 | hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags || | ||
305 | (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) || | ||
306 | (sc->sc_flags & SC_OP_FULL_RESET)) { | ||
307 | int status; | ||
308 | /* | ||
309 | * This is only performed if the channel settings have | ||
310 | * actually changed. | ||
311 | * | ||
312 | * To switch channels clear any pending DMA operations; | ||
313 | * wait long enough for the RX fifo to drain, reset the | ||
314 | * hardware at the new frequency, and then re-enable | ||
315 | * the relevant bits of the h/w. | ||
316 | */ | ||
317 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ | ||
318 | ath_draintxq(sc, false); /* clear pending tx frames */ | ||
319 | stopped = ath_stoprecv(sc); /* turn off frame recv */ | ||
320 | |||
321 | /* XXX: do not flush receive queue here. We don't want | ||
322 | * to flush data frames already in queue because of | ||
323 | * changing channel. */ | ||
324 | |||
325 | if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) | ||
326 | fastcc = false; | ||
327 | |||
328 | spin_lock_bh(&sc->sc_resetlock); | ||
329 | if (!ath9k_hw_reset(ah, hchan, | ||
330 | sc->sc_ht_info.tx_chan_width, | ||
331 | sc->sc_tx_chainmask, | ||
332 | sc->sc_rx_chainmask, | ||
333 | sc->sc_ht_extprotspacing, | ||
334 | fastcc, &status)) { | ||
335 | DPRINTF(sc, ATH_DBG_FATAL, | ||
336 | "%s: unable to reset channel %u (%uMhz) " | ||
337 | "flags 0x%x hal status %u\n", __func__, | ||
338 | ath9k_hw_mhz2ieee(ah, hchan->channel, | ||
339 | hchan->channelFlags), | ||
340 | hchan->channel, hchan->channelFlags, status); | ||
341 | spin_unlock_bh(&sc->sc_resetlock); | ||
342 | return -EIO; | ||
343 | } | ||
344 | spin_unlock_bh(&sc->sc_resetlock); | ||
345 | |||
346 | sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE; | ||
347 | sc->sc_flags &= ~SC_OP_FULL_RESET; | ||
348 | |||
349 | /* Re-enable rx framework */ | ||
350 | if (ath_startrecv(sc) != 0) { | ||
351 | DPRINTF(sc, ATH_DBG_FATAL, | ||
352 | "%s: unable to restart recv logic\n", __func__); | ||
353 | return -EIO; | ||
354 | } | ||
355 | /* | ||
356 | * Change channels and update the h/w rate map | ||
357 | * if we're switching; e.g. 11a to 11b/g. | ||
358 | */ | ||
359 | ath_setcurmode(sc, ath_chan2mode(hchan)); | ||
360 | |||
361 | ath_update_txpow(sc); /* update tx power state */ | ||
362 | /* | ||
363 | * Re-enable interrupts. | ||
364 | */ | ||
365 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
366 | } | ||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | /**********************/ | ||
371 | /* Chainmask Handling */ | ||
372 | /**********************/ | ||
373 | |||
374 | static void ath_chainmask_sel_timertimeout(unsigned long data) | ||
375 | { | ||
376 | struct ath_chainmask_sel *cm = (struct ath_chainmask_sel *)data; | ||
377 | cm->switch_allowed = 1; | ||
378 | } | ||
379 | |||
380 | /* Start chainmask select timer */ | ||
381 | static void ath_chainmask_sel_timerstart(struct ath_chainmask_sel *cm) | ||
382 | { | ||
383 | cm->switch_allowed = 0; | ||
384 | mod_timer(&cm->timer, ath_chainmask_sel_period); | ||
385 | } | ||
386 | |||
387 | /* Stop chainmask select timer */ | ||
388 | static void ath_chainmask_sel_timerstop(struct ath_chainmask_sel *cm) | ||
389 | { | ||
390 | cm->switch_allowed = 0; | ||
391 | del_timer_sync(&cm->timer); | ||
392 | } | ||
393 | |||
394 | static void ath_chainmask_sel_init(struct ath_softc *sc, struct ath_node *an) | ||
395 | { | ||
396 | struct ath_chainmask_sel *cm = &an->an_chainmask_sel; | ||
397 | |||
398 | memset(cm, 0, sizeof(struct ath_chainmask_sel)); | ||
399 | |||
400 | cm->cur_tx_mask = sc->sc_tx_chainmask; | ||
401 | cm->cur_rx_mask = sc->sc_rx_chainmask; | ||
402 | cm->tx_avgrssi = ATH_RSSI_DUMMY_MARKER; | ||
403 | setup_timer(&cm->timer, | ||
404 | ath_chainmask_sel_timertimeout, (unsigned long) cm); | ||
405 | } | ||
406 | |||
407 | int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an) | ||
408 | { | ||
409 | struct ath_chainmask_sel *cm = &an->an_chainmask_sel; | ||
410 | |||
411 | /* | ||
412 | * Disable auto-swtiching in one of the following if conditions. | ||
413 | * sc_chainmask_auto_sel is used for internal global auto-switching | ||
414 | * enabled/disabled setting | ||
415 | */ | ||
416 | if (sc->sc_ah->ah_caps.tx_chainmask != ATH_CHAINMASK_SEL_3X3) { | ||
417 | cm->cur_tx_mask = sc->sc_tx_chainmask; | ||
418 | return cm->cur_tx_mask; | ||
419 | } | ||
420 | |||
421 | if (cm->tx_avgrssi == ATH_RSSI_DUMMY_MARKER) | ||
422 | return cm->cur_tx_mask; | ||
423 | |||
424 | if (cm->switch_allowed) { | ||
425 | /* Switch down from tx 3 to tx 2. */ | ||
426 | if (cm->cur_tx_mask == ATH_CHAINMASK_SEL_3X3 && | ||
427 | ATH_RSSI_OUT(cm->tx_avgrssi) >= | ||
428 | ath_chainmask_sel_down_rssi_thres) { | ||
429 | cm->cur_tx_mask = sc->sc_tx_chainmask; | ||
430 | |||
431 | /* Don't let another switch happen until | ||
432 | * this timer expires */ | ||
433 | ath_chainmask_sel_timerstart(cm); | ||
434 | } | ||
435 | /* Switch up from tx 2 to 3. */ | ||
436 | else if (cm->cur_tx_mask == sc->sc_tx_chainmask && | ||
437 | ATH_RSSI_OUT(cm->tx_avgrssi) <= | ||
438 | ath_chainmask_sel_up_rssi_thres) { | ||
439 | cm->cur_tx_mask = ATH_CHAINMASK_SEL_3X3; | ||
440 | |||
441 | /* Don't let another switch happen | ||
442 | * until this timer expires */ | ||
443 | ath_chainmask_sel_timerstart(cm); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | return cm->cur_tx_mask; | ||
448 | } | ||
449 | |||
450 | /* | ||
451 | * Update tx/rx chainmask. For legacy association, | ||
452 | * hard code chainmask to 1x1, for 11n association, use | ||
453 | * the chainmask configuration. | ||
454 | */ | ||
455 | |||
456 | void ath_update_chainmask(struct ath_softc *sc, int is_ht) | ||
457 | { | ||
458 | sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; | ||
459 | if (is_ht) { | ||
460 | sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask; | ||
461 | sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask; | ||
462 | } else { | ||
463 | sc->sc_tx_chainmask = 1; | ||
464 | sc->sc_rx_chainmask = 1; | ||
465 | } | ||
466 | |||
467 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: tx chmask: %d, rx chmask: %d\n", | ||
468 | __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask); | ||
469 | } | ||
470 | |||
471 | /*******/ | ||
472 | /* ANI */ | ||
473 | /*******/ | ||
474 | |||
475 | /* | ||
476 | * This routine performs the periodic noise floor calibration function | ||
477 | * that is used to adjust and optimize the chip performance. This | ||
478 | * takes environmental changes (location, temperature) into account. | ||
479 | * When the task is complete, it reschedules itself depending on the | ||
480 | * appropriate interval that was calculated. | ||
481 | */ | ||
482 | |||
483 | static void ath_ani_calibrate(unsigned long data) | ||
484 | { | ||
485 | struct ath_softc *sc; | ||
486 | struct ath_hal *ah; | ||
487 | bool longcal = false; | ||
488 | bool shortcal = false; | ||
489 | bool aniflag = false; | ||
490 | unsigned int timestamp = jiffies_to_msecs(jiffies); | ||
491 | u32 cal_interval; | ||
492 | |||
493 | sc = (struct ath_softc *)data; | ||
494 | ah = sc->sc_ah; | ||
495 | |||
496 | /* | ||
497 | * don't calibrate when we're scanning. | ||
498 | * we are most likely not on our home channel. | ||
499 | */ | ||
500 | if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC) | ||
501 | return; | ||
502 | |||
503 | /* Long calibration runs independently of short calibration. */ | ||
504 | if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) { | ||
505 | longcal = true; | ||
506 | DPRINTF(sc, ATH_DBG_ANI, "%s: longcal @%lu\n", | ||
507 | __func__, jiffies); | ||
508 | sc->sc_ani.sc_longcal_timer = timestamp; | ||
509 | } | ||
510 | |||
511 | /* Short calibration applies only while sc_caldone is false */ | ||
512 | if (!sc->sc_ani.sc_caldone) { | ||
513 | if ((timestamp - sc->sc_ani.sc_shortcal_timer) >= | ||
514 | ATH_SHORT_CALINTERVAL) { | ||
515 | shortcal = true; | ||
516 | DPRINTF(sc, ATH_DBG_ANI, "%s: shortcal @%lu\n", | ||
517 | __func__, jiffies); | ||
518 | sc->sc_ani.sc_shortcal_timer = timestamp; | ||
519 | sc->sc_ani.sc_resetcal_timer = timestamp; | ||
520 | } | ||
521 | } else { | ||
522 | if ((timestamp - sc->sc_ani.sc_resetcal_timer) >= | ||
523 | ATH_RESTART_CALINTERVAL) { | ||
524 | ath9k_hw_reset_calvalid(ah, ah->ah_curchan, | ||
525 | &sc->sc_ani.sc_caldone); | ||
526 | if (sc->sc_ani.sc_caldone) | ||
527 | sc->sc_ani.sc_resetcal_timer = timestamp; | ||
528 | } | ||
529 | } | ||
530 | |||
531 | /* Verify whether we must check ANI */ | ||
532 | if ((timestamp - sc->sc_ani.sc_checkani_timer) >= | ||
533 | ATH_ANI_POLLINTERVAL) { | ||
534 | aniflag = true; | ||
535 | sc->sc_ani.sc_checkani_timer = timestamp; | ||
536 | } | ||
537 | |||
538 | /* Skip all processing if there's nothing to do. */ | ||
539 | if (longcal || shortcal || aniflag) { | ||
540 | /* Call ANI routine if necessary */ | ||
541 | if (aniflag) | ||
542 | ath9k_hw_ani_monitor(ah, &sc->sc_halstats, | ||
543 | ah->ah_curchan); | ||
544 | |||
545 | /* Perform calibration if necessary */ | ||
546 | if (longcal || shortcal) { | ||
547 | bool iscaldone = false; | ||
548 | |||
549 | if (ath9k_hw_calibrate(ah, ah->ah_curchan, | ||
550 | sc->sc_rx_chainmask, longcal, | ||
551 | &iscaldone)) { | ||
552 | if (longcal) | ||
553 | sc->sc_ani.sc_noise_floor = | ||
554 | ath9k_hw_getchan_noise(ah, | ||
555 | ah->ah_curchan); | ||
556 | |||
557 | DPRINTF(sc, ATH_DBG_ANI, | ||
558 | "%s: calibrate chan %u/%x nf: %d\n", | ||
559 | __func__, | ||
560 | ah->ah_curchan->channel, | ||
561 | ah->ah_curchan->channelFlags, | ||
562 | sc->sc_ani.sc_noise_floor); | ||
563 | } else { | ||
564 | DPRINTF(sc, ATH_DBG_ANY, | ||
565 | "%s: calibrate chan %u/%x failed\n", | ||
566 | __func__, | ||
567 | ah->ah_curchan->channel, | ||
568 | ah->ah_curchan->channelFlags); | ||
569 | } | ||
570 | sc->sc_ani.sc_caldone = iscaldone; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | /* | ||
575 | * Set timer interval based on previous results. | ||
576 | * The interval must be the shortest necessary to satisfy ANI, | ||
577 | * short calibration and long calibration. | ||
578 | */ | ||
579 | |||
580 | cal_interval = ATH_ANI_POLLINTERVAL; | ||
581 | if (!sc->sc_ani.sc_caldone) | ||
582 | cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL); | ||
583 | |||
584 | mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | ||
585 | } | ||
586 | |||
587 | /********/ | ||
588 | /* Core */ | ||
589 | /********/ | ||
590 | |||
591 | int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | ||
592 | { | ||
593 | struct ath_hal *ah = sc->sc_ah; | ||
594 | int status; | ||
595 | int error = 0; | ||
596 | |||
597 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n", | ||
598 | __func__, sc->sc_ah->ah_opmode); | ||
599 | |||
600 | /* Reset SERDES registers */ | ||
601 | ath9k_hw_configpcipowersave(ah, 0); | ||
602 | |||
603 | /* | ||
604 | * The basic interface to setting the hardware in a good | ||
605 | * state is ``reset''. On return the hardware is known to | ||
606 | * be powered up and with interrupts disabled. This must | ||
607 | * be followed by initialization of the appropriate bits | ||
608 | * and then setup of the interrupt mask. | ||
609 | */ | ||
610 | |||
611 | spin_lock_bh(&sc->sc_resetlock); | ||
612 | if (!ath9k_hw_reset(ah, initial_chan, | ||
613 | sc->sc_ht_info.tx_chan_width, | ||
614 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
615 | sc->sc_ht_extprotspacing, false, &status)) { | ||
616 | DPRINTF(sc, ATH_DBG_FATAL, | ||
617 | "%s: unable to reset hardware; hal status %u " | ||
618 | "(freq %u flags 0x%x)\n", __func__, status, | ||
619 | initial_chan->channel, initial_chan->channelFlags); | ||
620 | error = -EIO; | ||
621 | spin_unlock_bh(&sc->sc_resetlock); | ||
622 | goto done; | ||
623 | } | ||
624 | spin_unlock_bh(&sc->sc_resetlock); | ||
625 | |||
626 | /* | ||
627 | * This is needed only to setup initial state | ||
628 | * but it's best done after a reset. | ||
629 | */ | ||
630 | ath_update_txpow(sc); | ||
631 | |||
632 | /* | ||
633 | * Setup the hardware after reset: | ||
634 | * The receive engine is set going. | ||
635 | * Frame transmit is handled entirely | ||
636 | * in the frame output path; there's nothing to do | ||
637 | * here except setup the interrupt mask. | ||
638 | */ | ||
639 | if (ath_startrecv(sc) != 0) { | ||
640 | DPRINTF(sc, ATH_DBG_FATAL, | ||
641 | "%s: unable to start recv logic\n", __func__); | ||
642 | error = -EIO; | ||
643 | goto done; | ||
644 | } | ||
645 | |||
646 | /* Setup our intr mask. */ | ||
647 | sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX | ||
648 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | ||
649 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; | ||
650 | |||
651 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_GTT) | ||
652 | sc->sc_imask |= ATH9K_INT_GTT; | ||
653 | |||
654 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) | ||
655 | sc->sc_imask |= ATH9K_INT_CST; | ||
656 | |||
657 | /* | ||
658 | * Enable MIB interrupts when there are hardware phy counters. | ||
659 | * Note we only do this (at the moment) for station mode. | ||
660 | */ | ||
661 | if (ath9k_hw_phycounters(ah) && | ||
662 | ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || | ||
663 | (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))) | ||
664 | sc->sc_imask |= ATH9K_INT_MIB; | ||
665 | /* | ||
666 | * Some hardware processes the TIM IE and fires an | ||
667 | * interrupt when the TIM bit is set. For hardware | ||
668 | * that does, if not overridden by configuration, | ||
669 | * enable the TIM interrupt when operating as station. | ||
670 | */ | ||
671 | if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && | ||
672 | (sc->sc_ah->ah_opmode == ATH9K_M_STA) && | ||
673 | !sc->sc_config.swBeaconProcess) | ||
674 | sc->sc_imask |= ATH9K_INT_TIM; | ||
675 | |||
676 | ath_setcurmode(sc, ath_chan2mode(initial_chan)); | ||
677 | |||
678 | sc->sc_flags &= ~SC_OP_INVALID; | ||
679 | |||
680 | /* Disable BMISS interrupt when we're not associated */ | ||
681 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | ||
682 | ath9k_hw_set_interrupts(sc->sc_ah,sc->sc_imask); | ||
683 | |||
684 | ieee80211_wake_queues(sc->hw); | ||
685 | done: | ||
686 | return error; | ||
687 | } | ||
688 | |||
689 | void ath_stop(struct ath_softc *sc) | ||
690 | { | ||
691 | struct ath_hal *ah = sc->sc_ah; | ||
692 | |||
693 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Cleaning up\n", __func__); | ||
694 | |||
695 | ieee80211_stop_queues(sc->hw); | ||
696 | |||
697 | /* make sure h/w will not generate any interrupt | ||
698 | * before setting the invalid flag. */ | ||
699 | ath9k_hw_set_interrupts(ah, 0); | ||
700 | |||
701 | if (!(sc->sc_flags & SC_OP_INVALID)) { | ||
702 | ath_draintxq(sc, false); | ||
703 | ath_stoprecv(sc); | ||
704 | ath9k_hw_phy_disable(ah); | ||
705 | } else | ||
706 | sc->sc_rxlink = NULL; | ||
707 | |||
708 | #ifdef CONFIG_RFKILL | ||
709 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
710 | cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); | ||
711 | #endif | ||
712 | /* disable HAL and put h/w to sleep */ | ||
713 | ath9k_hw_disable(sc->sc_ah); | ||
714 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); | ||
715 | |||
716 | sc->sc_flags |= SC_OP_INVALID; | ||
717 | } | ||
718 | |||
719 | int ath_reset(struct ath_softc *sc, bool retry_tx) | ||
720 | { | ||
721 | struct ath_hal *ah = sc->sc_ah; | ||
722 | int status; | ||
723 | int error = 0; | ||
724 | |||
725 | ath9k_hw_set_interrupts(ah, 0); | ||
726 | ath_draintxq(sc, retry_tx); | ||
727 | ath_stoprecv(sc); | ||
728 | ath_flushrecv(sc); | ||
729 | |||
730 | /* Reset chip */ | ||
731 | spin_lock_bh(&sc->sc_resetlock); | ||
732 | if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, | ||
733 | sc->sc_ht_info.tx_chan_width, | ||
734 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
735 | sc->sc_ht_extprotspacing, false, &status)) { | ||
736 | DPRINTF(sc, ATH_DBG_FATAL, | ||
737 | "%s: unable to reset hardware; hal status %u\n", | ||
738 | __func__, status); | ||
739 | error = -EIO; | ||
740 | } | ||
741 | spin_unlock_bh(&sc->sc_resetlock); | ||
742 | |||
743 | if (ath_startrecv(sc) != 0) | ||
744 | DPRINTF(sc, ATH_DBG_FATAL, | ||
745 | "%s: unable to start recv logic\n", __func__); | ||
746 | |||
747 | /* | ||
748 | * We may be doing a reset in response to a request | ||
749 | * that changes the channel so update any state that | ||
750 | * might change as a result. | ||
751 | */ | ||
752 | ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan)); | ||
753 | |||
754 | ath_update_txpow(sc); | ||
755 | |||
756 | if (sc->sc_flags & SC_OP_BEACONS) | ||
757 | ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ | ||
758 | |||
759 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
760 | |||
761 | /* Restart the txq */ | ||
762 | if (retry_tx) { | ||
763 | int i; | ||
764 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
765 | if (ATH_TXQ_SETUP(sc, i)) { | ||
766 | spin_lock_bh(&sc->sc_txq[i].axq_lock); | ||
767 | ath_txq_schedule(sc, &sc->sc_txq[i]); | ||
768 | spin_unlock_bh(&sc->sc_txq[i].axq_lock); | ||
769 | } | ||
770 | } | ||
771 | } | ||
772 | |||
773 | return error; | ||
774 | } | ||
775 | |||
776 | /* Interrupt handler. Most of the actual processing is deferred. | ||
777 | * It's the caller's responsibility to ensure the chip is awake. */ | ||
778 | |||
779 | irqreturn_t ath_isr(int irq, void *dev) | ||
780 | { | ||
781 | struct ath_softc *sc = dev; | ||
782 | struct ath_hal *ah = sc->sc_ah; | ||
783 | enum ath9k_int status; | ||
784 | bool sched = false; | ||
785 | |||
786 | do { | ||
787 | if (sc->sc_flags & SC_OP_INVALID) { | ||
788 | /* | ||
789 | * The hardware is not ready/present, don't | ||
790 | * touch anything. Note this can happen early | ||
791 | * on if the IRQ is shared. | ||
792 | */ | ||
793 | return IRQ_NONE; | ||
794 | } | ||
795 | if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */ | ||
796 | return IRQ_NONE; | ||
797 | } | ||
798 | |||
799 | /* | ||
800 | * Figure out the reason(s) for the interrupt. Note | ||
801 | * that the hal returns a pseudo-ISR that may include | ||
802 | * bits we haven't explicitly enabled so we mask the | ||
803 | * value to insure we only process bits we requested. | ||
804 | */ | ||
805 | ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ | ||
806 | |||
807 | status &= sc->sc_imask; /* discard unasked-for bits */ | ||
808 | |||
809 | /* | ||
810 | * If there are no status bits set, then this interrupt was not | ||
811 | * for me (should have been caught above). | ||
812 | */ | ||
813 | |||
814 | if (!status) | ||
815 | return IRQ_NONE; | ||
816 | |||
817 | sc->sc_intrstatus = status; | ||
818 | |||
819 | if (status & ATH9K_INT_FATAL) { | ||
820 | /* need a chip reset */ | ||
821 | sched = true; | ||
822 | } else if (status & ATH9K_INT_RXORN) { | ||
823 | /* need a chip reset */ | ||
824 | sched = true; | ||
825 | } else { | ||
826 | if (status & ATH9K_INT_SWBA) { | ||
827 | /* schedule a tasklet for beacon handling */ | ||
828 | tasklet_schedule(&sc->bcon_tasklet); | ||
829 | } | ||
830 | if (status & ATH9K_INT_RXEOL) { | ||
831 | /* | ||
832 | * NB: the hardware should re-read the link when | ||
833 | * RXE bit is written, but it doesn't work | ||
834 | * at least on older hardware revs. | ||
835 | */ | ||
836 | sched = true; | ||
837 | } | ||
838 | |||
839 | if (status & ATH9K_INT_TXURN) | ||
840 | /* bump tx trigger level */ | ||
841 | ath9k_hw_updatetxtriglevel(ah, true); | ||
842 | /* XXX: optimize this */ | ||
843 | if (status & ATH9K_INT_RX) | ||
844 | sched = true; | ||
845 | if (status & ATH9K_INT_TX) | ||
846 | sched = true; | ||
847 | if (status & ATH9K_INT_BMISS) | ||
848 | sched = true; | ||
849 | /* carrier sense timeout */ | ||
850 | if (status & ATH9K_INT_CST) | ||
851 | sched = true; | ||
852 | if (status & ATH9K_INT_MIB) { | ||
853 | /* | ||
854 | * Disable interrupts until we service the MIB | ||
855 | * interrupt; otherwise it will continue to | ||
856 | * fire. | ||
857 | */ | ||
858 | ath9k_hw_set_interrupts(ah, 0); | ||
859 | /* | ||
860 | * Let the hal handle the event. We assume | ||
861 | * it will clear whatever condition caused | ||
862 | * the interrupt. | ||
863 | */ | ||
864 | ath9k_hw_procmibevent(ah, &sc->sc_halstats); | ||
865 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
866 | } | ||
867 | if (status & ATH9K_INT_TIM_TIMER) { | ||
868 | if (!(ah->ah_caps.hw_caps & | ||
869 | ATH9K_HW_CAP_AUTOSLEEP)) { | ||
870 | /* Clear RxAbort bit so that we can | ||
871 | * receive frames */ | ||
872 | ath9k_hw_setrxabort(ah, 0); | ||
873 | sched = true; | ||
874 | } | ||
875 | } | ||
876 | } | ||
877 | } while (0); | ||
878 | |||
879 | if (sched) { | ||
880 | /* turn off every interrupt except SWBA */ | ||
881 | ath9k_hw_set_interrupts(ah, (sc->sc_imask & ATH9K_INT_SWBA)); | ||
882 | tasklet_schedule(&sc->intr_tq); | ||
883 | } | ||
884 | |||
885 | return IRQ_HANDLED; | ||
886 | } | ||
887 | |||
888 | /* Deferred interrupt processing */ | ||
889 | |||
890 | static void ath9k_tasklet(unsigned long data) | ||
891 | { | ||
892 | struct ath_softc *sc = (struct ath_softc *)data; | ||
893 | u32 status = sc->sc_intrstatus; | ||
894 | |||
895 | if (status & ATH9K_INT_FATAL) { | ||
896 | /* need a chip reset */ | ||
897 | ath_reset(sc, false); | ||
898 | return; | ||
899 | } else { | ||
900 | |||
901 | if (status & | ||
902 | (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { | ||
903 | /* XXX: fill me in */ | ||
904 | /* | ||
905 | if (status & ATH9K_INT_RXORN) { | ||
906 | } | ||
907 | if (status & ATH9K_INT_RXEOL) { | ||
908 | } | ||
909 | */ | ||
910 | spin_lock_bh(&sc->sc_rxflushlock); | ||
911 | ath_rx_tasklet(sc, 0); | ||
912 | spin_unlock_bh(&sc->sc_rxflushlock); | ||
913 | } | ||
914 | /* XXX: optimize this */ | ||
915 | if (status & ATH9K_INT_TX) | ||
916 | ath_tx_tasklet(sc); | ||
917 | /* XXX: fill me in */ | ||
918 | /* | ||
919 | if (status & ATH9K_INT_BMISS) { | ||
920 | } | ||
921 | if (status & (ATH9K_INT_TIM | ATH9K_INT_DTIMSYNC)) { | ||
922 | if (status & ATH9K_INT_TIM) { | ||
923 | } | ||
924 | if (status & ATH9K_INT_DTIMSYNC) { | ||
925 | } | ||
926 | } | ||
927 | */ | ||
928 | } | ||
929 | |||
930 | /* re-enable hardware interrupt */ | ||
931 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask); | ||
932 | } | ||
933 | |||
934 | int ath_init(u16 devid, struct ath_softc *sc) | ||
935 | { | ||
936 | struct ath_hal *ah = NULL; | ||
937 | int status; | ||
938 | int error = 0, i; | ||
939 | int csz = 0; | ||
940 | |||
941 | /* XXX: hardware will not be ready until ath_open() being called */ | ||
942 | sc->sc_flags |= SC_OP_INVALID; | ||
943 | sc->sc_debug = DBG_DEFAULT; | ||
944 | |||
945 | spin_lock_init(&sc->sc_resetlock); | ||
946 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | ||
947 | tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, | ||
948 | (unsigned long)sc); | ||
949 | |||
950 | /* | ||
951 | * Cache line size is used to size and align various | ||
952 | * structures used to communicate with the hardware. | ||
953 | */ | ||
954 | bus_read_cachesize(sc, &csz); | ||
955 | /* XXX assert csz is non-zero */ | ||
956 | sc->sc_cachelsz = csz << 2; /* convert to bytes */ | ||
957 | |||
958 | ah = ath9k_hw_attach(devid, sc, sc->mem, &status); | ||
959 | if (ah == NULL) { | ||
960 | DPRINTF(sc, ATH_DBG_FATAL, | ||
961 | "%s: unable to attach hardware; HAL status %u\n", | ||
962 | __func__, status); | ||
963 | error = -ENXIO; | ||
964 | goto bad; | ||
965 | } | ||
966 | sc->sc_ah = ah; | ||
967 | |||
968 | /* Get the hardware key cache size. */ | ||
969 | sc->sc_keymax = ah->ah_caps.keycache_size; | ||
970 | if (sc->sc_keymax > ATH_KEYMAX) { | ||
971 | DPRINTF(sc, ATH_DBG_KEYCACHE, | ||
972 | "%s: Warning, using only %u entries in %u key cache\n", | ||
973 | __func__, ATH_KEYMAX, sc->sc_keymax); | ||
974 | sc->sc_keymax = ATH_KEYMAX; | ||
975 | } | ||
976 | |||
977 | /* | ||
978 | * Reset the key cache since some parts do not | ||
979 | * reset the contents on initial power up. | ||
980 | */ | ||
981 | for (i = 0; i < sc->sc_keymax; i++) | ||
982 | ath9k_hw_keyreset(ah, (u16) i); | ||
983 | /* | ||
984 | * Mark key cache slots associated with global keys | ||
985 | * as in use. If we knew TKIP was not to be used we | ||
986 | * could leave the +32, +64, and +32+64 slots free. | ||
987 | * XXX only for splitmic. | ||
988 | */ | ||
989 | for (i = 0; i < IEEE80211_WEP_NKID; i++) { | ||
990 | set_bit(i, sc->sc_keymap); | ||
991 | set_bit(i + 32, sc->sc_keymap); | ||
992 | set_bit(i + 64, sc->sc_keymap); | ||
993 | set_bit(i + 32 + 64, sc->sc_keymap); | ||
994 | } | ||
995 | |||
996 | /* Collect the channel list using the default country code */ | ||
997 | |||
998 | error = ath_setup_channels(sc); | ||
999 | if (error) | ||
1000 | goto bad; | ||
1001 | |||
1002 | /* default to MONITOR mode */ | ||
1003 | sc->sc_ah->ah_opmode = ATH9K_M_MONITOR; | ||
1004 | |||
1005 | /* Setup rate tables */ | ||
1006 | |||
1007 | ath_setup_rates(sc, IEEE80211_BAND_2GHZ); | ||
1008 | ath_setup_rates(sc, IEEE80211_BAND_5GHZ); | ||
1009 | |||
1010 | /* NB: setup here so ath_rate_update is happy */ | ||
1011 | ath_setcurmode(sc, ATH9K_MODE_11A); | ||
1012 | |||
1013 | /* | ||
1014 | * Allocate hardware transmit queues: one queue for | ||
1015 | * beacon frames and one data queue for each QoS | ||
1016 | * priority. Note that the hal handles reseting | ||
1017 | * these queues at the needed time. | ||
1018 | */ | ||
1019 | sc->sc_bhalq = ath_beaconq_setup(ah); | ||
1020 | if (sc->sc_bhalq == -1) { | ||
1021 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1022 | "%s: unable to setup a beacon xmit queue\n", __func__); | ||
1023 | error = -EIO; | ||
1024 | goto bad2; | ||
1025 | } | ||
1026 | sc->sc_cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | ||
1027 | if (sc->sc_cabq == NULL) { | ||
1028 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1029 | "%s: unable to setup CAB xmit queue\n", __func__); | ||
1030 | error = -EIO; | ||
1031 | goto bad2; | ||
1032 | } | ||
1033 | |||
1034 | sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME; | ||
1035 | ath_cabq_update(sc); | ||
1036 | |||
1037 | for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++) | ||
1038 | sc->sc_haltype2q[i] = -1; | ||
1039 | |||
1040 | /* Setup data queues */ | ||
1041 | /* NB: ensure BK queue is the lowest priority h/w queue */ | ||
1042 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | ||
1043 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1044 | "%s: unable to setup xmit queue for BK traffic\n", | ||
1045 | __func__); | ||
1046 | error = -EIO; | ||
1047 | goto bad2; | ||
1048 | } | ||
1049 | |||
1050 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | ||
1051 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1052 | "%s: unable to setup xmit queue for BE traffic\n", | ||
1053 | __func__); | ||
1054 | error = -EIO; | ||
1055 | goto bad2; | ||
1056 | } | ||
1057 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | ||
1058 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1059 | "%s: unable to setup xmit queue for VI traffic\n", | ||
1060 | __func__); | ||
1061 | error = -EIO; | ||
1062 | goto bad2; | ||
1063 | } | ||
1064 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | ||
1065 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1066 | "%s: unable to setup xmit queue for VO traffic\n", | ||
1067 | __func__); | ||
1068 | error = -EIO; | ||
1069 | goto bad2; | ||
1070 | } | ||
1071 | |||
1072 | /* Initializes the noise floor to a reasonable default value. | ||
1073 | * Later on this will be updated during ANI processing. */ | ||
1074 | |||
1075 | sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR; | ||
1076 | setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc); | ||
1077 | |||
1078 | sc->sc_rc = ath_rate_attach(ah); | ||
1079 | if (sc->sc_rc == NULL) { | ||
1080 | error = -EIO; | ||
1081 | goto bad2; | ||
1082 | } | ||
1083 | |||
1084 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1085 | ATH9K_CIPHER_TKIP, NULL)) { | ||
1086 | /* | ||
1087 | * Whether we should enable h/w TKIP MIC. | ||
1088 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
1089 | * report WMM capable, so it's always safe to turn on | ||
1090 | * TKIP MIC in this case. | ||
1091 | */ | ||
1092 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, | ||
1093 | 0, 1, NULL); | ||
1094 | } | ||
1095 | |||
1096 | /* | ||
1097 | * Check whether the separate key cache entries | ||
1098 | * are required to handle both tx+rx MIC keys. | ||
1099 | * With split mic keys the number of stations is limited | ||
1100 | * to 27 otherwise 59. | ||
1101 | */ | ||
1102 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1103 | ATH9K_CIPHER_TKIP, NULL) | ||
1104 | && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1105 | ATH9K_CIPHER_MIC, NULL) | ||
1106 | && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, | ||
1107 | 0, NULL)) | ||
1108 | sc->sc_splitmic = 1; | ||
1109 | |||
1110 | /* turn on mcast key search if possible */ | ||
1111 | if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
1112 | (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, | ||
1113 | 1, NULL); | ||
1114 | |||
1115 | sc->sc_config.txpowlimit = ATH_TXPOWER_MAX; | ||
1116 | sc->sc_config.txpowlimit_override = 0; | ||
1117 | |||
1118 | /* 11n Capabilities */ | ||
1119 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
1120 | sc->sc_flags |= SC_OP_TXAGGR; | ||
1121 | sc->sc_flags |= SC_OP_RXAGGR; | ||
1122 | } | ||
1123 | |||
1124 | sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask; | ||
1125 | sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask; | ||
1126 | |||
1127 | ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); | ||
1128 | sc->sc_defant = ath9k_hw_getdefantenna(ah); | ||
1129 | |||
1130 | ath9k_hw_getmac(ah, sc->sc_myaddr); | ||
1131 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) { | ||
1132 | ath9k_hw_getbssidmask(ah, sc->sc_bssidmask); | ||
1133 | ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask); | ||
1134 | ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); | ||
1135 | } | ||
1136 | |||
1137 | sc->sc_slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ | ||
1138 | |||
1139 | /* initialize beacon slots */ | ||
1140 | for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++) | ||
1141 | sc->sc_bslot[i] = ATH_IF_ID_ANY; | ||
1142 | |||
1143 | /* save MISC configurations */ | ||
1144 | sc->sc_config.swBeaconProcess = 1; | ||
1145 | |||
1146 | #ifdef CONFIG_SLOW_ANT_DIV | ||
1147 | /* range is 40 - 255, we use something in the middle */ | ||
1148 | ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127); | ||
1149 | #endif | ||
1150 | |||
1151 | /* setup channels and rates */ | ||
1152 | |||
1153 | sc->sbands[IEEE80211_BAND_2GHZ].channels = | ||
1154 | sc->channels[IEEE80211_BAND_2GHZ]; | ||
1155 | sc->sbands[IEEE80211_BAND_2GHZ].bitrates = | ||
1156 | sc->rates[IEEE80211_BAND_2GHZ]; | ||
1157 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | ||
1158 | |||
1159 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { | ||
1160 | sc->sbands[IEEE80211_BAND_5GHZ].channels = | ||
1161 | sc->channels[IEEE80211_BAND_5GHZ]; | ||
1162 | sc->sbands[IEEE80211_BAND_5GHZ].bitrates = | ||
1163 | sc->rates[IEEE80211_BAND_5GHZ]; | ||
1164 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | ||
1165 | } | ||
1166 | |||
1167 | return 0; | ||
1168 | bad2: | ||
1169 | /* cleanup tx queues */ | ||
1170 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1171 | if (ATH_TXQ_SETUP(sc, i)) | ||
1172 | ath_tx_cleanupq(sc, &sc->sc_txq[i]); | ||
1173 | bad: | ||
1174 | if (ah) | ||
1175 | ath9k_hw_detach(ah); | ||
1176 | |||
1177 | return error; | ||
1178 | } | ||
1179 | |||
1180 | /*******************/ | ||
1181 | /* Node Management */ | ||
1182 | /*******************/ | ||
1183 | |||
1184 | void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) | ||
1185 | { | ||
1186 | struct ath_node *an; | ||
1187 | |||
1188 | an = (struct ath_node *)sta->drv_priv; | ||
1189 | |||
1190 | if (sc->sc_flags & SC_OP_TXAGGR) | ||
1191 | ath_tx_node_init(sc, an); | ||
1192 | |||
1193 | an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + | ||
1194 | sta->ht_cap.ampdu_factor); | ||
1195 | an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); | ||
1196 | |||
1197 | ath_chainmask_sel_init(sc, an); | ||
1198 | ath_chainmask_sel_timerstart(&an->an_chainmask_sel); | ||
1199 | } | ||
1200 | |||
1201 | void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | ||
1202 | { | ||
1203 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | ||
1204 | |||
1205 | ath_chainmask_sel_timerstop(&an->an_chainmask_sel); | ||
1206 | |||
1207 | if (sc->sc_flags & SC_OP_TXAGGR) | ||
1208 | ath_tx_node_cleanup(sc, an); | ||
1209 | } | ||
1210 | |||
1211 | /* | ||
1212 | * Set up New Node | ||
1213 | * | ||
1214 | * Setup driver-specific state for a newly associated node. This routine | ||
1215 | * really only applies if compression or XR are enabled, there is no code | ||
1216 | * covering any other cases. | ||
1217 | */ | ||
1218 | |||
1219 | void ath_newassoc(struct ath_softc *sc, | ||
1220 | struct ath_node *an, int isnew, int isuapsd) | ||
1221 | { | ||
1222 | int tidno; | ||
1223 | |||
1224 | /* if station reassociates, tear down the aggregation state. */ | ||
1225 | if (!isnew) { | ||
1226 | for (tidno = 0; tidno < WME_NUM_TID; tidno++) { | ||
1227 | if (sc->sc_flags & SC_OP_TXAGGR) | ||
1228 | ath_tx_aggr_teardown(sc, an, tidno); | ||
1229 | } | ||
1230 | } | ||
1231 | } | ||
1232 | |||
1233 | /**************/ | ||
1234 | /* Encryption */ | ||
1235 | /**************/ | ||
1236 | |||
1237 | void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot) | ||
1238 | { | ||
1239 | ath9k_hw_keyreset(sc->sc_ah, keyix); | ||
1240 | if (freeslot) | ||
1241 | clear_bit(keyix, sc->sc_keymap); | ||
1242 | } | ||
1243 | |||
1244 | int ath_keyset(struct ath_softc *sc, | ||
1245 | u16 keyix, | ||
1246 | struct ath9k_keyval *hk, | ||
1247 | const u8 mac[ETH_ALEN]) | ||
1248 | { | ||
1249 | bool status; | ||
1250 | |||
1251 | status = ath9k_hw_set_keycache_entry(sc->sc_ah, | ||
1252 | keyix, hk, mac, false); | ||
1253 | |||
1254 | return status != false; | ||
1255 | } | ||
1256 | |||
1257 | /***********************/ | ||
1258 | /* TX Power/Regulatory */ | ||
1259 | /***********************/ | ||
1260 | |||
1261 | /* | ||
1262 | * Set Transmit power in HAL | ||
1263 | * | ||
1264 | * This routine makes the actual HAL calls to set the new transmit power | ||
1265 | * limit. | ||
1266 | */ | ||
1267 | |||
1268 | void ath_update_txpow(struct ath_softc *sc) | ||
1269 | { | ||
1270 | struct ath_hal *ah = sc->sc_ah; | ||
1271 | u32 txpow; | ||
1272 | |||
1273 | if (sc->sc_curtxpow != sc->sc_config.txpowlimit) { | ||
1274 | ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit); | ||
1275 | /* read back in case value is clamped */ | ||
1276 | ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); | ||
1277 | sc->sc_curtxpow = txpow; | ||
1278 | } | ||
1279 | } | ||
1280 | |||
1281 | /**************************/ | ||
1282 | /* Slow Antenna Diversity */ | ||
1283 | /**************************/ | ||
1284 | |||
1285 | void ath_slow_ant_div_init(struct ath_antdiv *antdiv, | ||
1286 | struct ath_softc *sc, | ||
1287 | int32_t rssitrig) | ||
1288 | { | ||
1289 | int trig; | ||
1290 | |||
1291 | /* antdivf_rssitrig can range from 40 - 0xff */ | ||
1292 | trig = (rssitrig > 0xff) ? 0xff : rssitrig; | ||
1293 | trig = (rssitrig < 40) ? 40 : rssitrig; | ||
1294 | |||
1295 | antdiv->antdiv_sc = sc; | ||
1296 | antdiv->antdivf_rssitrig = trig; | ||
1297 | } | ||
1298 | |||
1299 | void ath_slow_ant_div_start(struct ath_antdiv *antdiv, | ||
1300 | u8 num_antcfg, | ||
1301 | const u8 *bssid) | ||
1302 | { | ||
1303 | antdiv->antdiv_num_antcfg = | ||
1304 | num_antcfg < ATH_ANT_DIV_MAX_CFG ? | ||
1305 | num_antcfg : ATH_ANT_DIV_MAX_CFG; | ||
1306 | antdiv->antdiv_state = ATH_ANT_DIV_IDLE; | ||
1307 | antdiv->antdiv_curcfg = 0; | ||
1308 | antdiv->antdiv_bestcfg = 0; | ||
1309 | antdiv->antdiv_laststatetsf = 0; | ||
1310 | |||
1311 | memcpy(antdiv->antdiv_bssid, bssid, sizeof(antdiv->antdiv_bssid)); | ||
1312 | |||
1313 | antdiv->antdiv_start = 1; | ||
1314 | } | ||
1315 | |||
1316 | void ath_slow_ant_div_stop(struct ath_antdiv *antdiv) | ||
1317 | { | ||
1318 | antdiv->antdiv_start = 0; | ||
1319 | } | ||
1320 | |||
1321 | static int32_t ath_find_max_val(int32_t *val, | ||
1322 | u8 num_val, u8 *max_index) | ||
1323 | { | ||
1324 | u32 MaxVal = *val++; | ||
1325 | u32 cur_index = 0; | ||
1326 | |||
1327 | *max_index = 0; | ||
1328 | while (++cur_index < num_val) { | ||
1329 | if (*val > MaxVal) { | ||
1330 | MaxVal = *val; | ||
1331 | *max_index = cur_index; | ||
1332 | } | ||
1333 | |||
1334 | val++; | ||
1335 | } | ||
1336 | |||
1337 | return MaxVal; | ||
1338 | } | ||
1339 | |||
1340 | void ath_slow_ant_div(struct ath_antdiv *antdiv, | ||
1341 | struct ieee80211_hdr *hdr, | ||
1342 | struct ath_rx_status *rx_stats) | ||
1343 | { | ||
1344 | struct ath_softc *sc = antdiv->antdiv_sc; | ||
1345 | struct ath_hal *ah = sc->sc_ah; | ||
1346 | u64 curtsf = 0; | ||
1347 | u8 bestcfg, curcfg = antdiv->antdiv_curcfg; | ||
1348 | __le16 fc = hdr->frame_control; | ||
1349 | |||
1350 | if (antdiv->antdiv_start && ieee80211_is_beacon(fc) | ||
1351 | && !compare_ether_addr(hdr->addr3, antdiv->antdiv_bssid)) { | ||
1352 | antdiv->antdiv_lastbrssi[curcfg] = rx_stats->rs_rssi; | ||
1353 | antdiv->antdiv_lastbtsf[curcfg] = ath9k_hw_gettsf64(sc->sc_ah); | ||
1354 | curtsf = antdiv->antdiv_lastbtsf[curcfg]; | ||
1355 | } else { | ||
1356 | return; | ||
1357 | } | ||
1358 | |||
1359 | switch (antdiv->antdiv_state) { | ||
1360 | case ATH_ANT_DIV_IDLE: | ||
1361 | if ((antdiv->antdiv_lastbrssi[curcfg] < | ||
1362 | antdiv->antdivf_rssitrig) | ||
1363 | && ((curtsf - antdiv->antdiv_laststatetsf) > | ||
1364 | ATH_ANT_DIV_MIN_IDLE_US)) { | ||
1365 | |||
1366 | curcfg++; | ||
1367 | if (curcfg == antdiv->antdiv_num_antcfg) | ||
1368 | curcfg = 0; | ||
1369 | |||
1370 | if (!ath9k_hw_select_antconfig(ah, curcfg)) { | ||
1371 | antdiv->antdiv_bestcfg = antdiv->antdiv_curcfg; | ||
1372 | antdiv->antdiv_curcfg = curcfg; | ||
1373 | antdiv->antdiv_laststatetsf = curtsf; | ||
1374 | antdiv->antdiv_state = ATH_ANT_DIV_SCAN; | ||
1375 | } | ||
1376 | } | ||
1377 | break; | ||
1378 | |||
1379 | case ATH_ANT_DIV_SCAN: | ||
1380 | if ((curtsf - antdiv->antdiv_laststatetsf) < | ||
1381 | ATH_ANT_DIV_MIN_SCAN_US) | ||
1382 | break; | ||
1383 | |||
1384 | curcfg++; | ||
1385 | if (curcfg == antdiv->antdiv_num_antcfg) | ||
1386 | curcfg = 0; | ||
1387 | |||
1388 | if (curcfg == antdiv->antdiv_bestcfg) { | ||
1389 | ath_find_max_val(antdiv->antdiv_lastbrssi, | ||
1390 | antdiv->antdiv_num_antcfg, &bestcfg); | ||
1391 | if (!ath9k_hw_select_antconfig(ah, bestcfg)) { | ||
1392 | antdiv->antdiv_bestcfg = bestcfg; | ||
1393 | antdiv->antdiv_curcfg = bestcfg; | ||
1394 | antdiv->antdiv_laststatetsf = curtsf; | ||
1395 | antdiv->antdiv_state = ATH_ANT_DIV_IDLE; | ||
1396 | } | ||
1397 | } else { | ||
1398 | if (!ath9k_hw_select_antconfig(ah, curcfg)) { | ||
1399 | antdiv->antdiv_curcfg = curcfg; | ||
1400 | antdiv->antdiv_laststatetsf = curtsf; | ||
1401 | antdiv->antdiv_state = ATH_ANT_DIV_SCAN; | ||
1402 | } | ||
1403 | } | ||
1404 | |||
1405 | break; | ||
1406 | } | ||
1407 | } | ||
1408 | |||
1409 | /***********************/ | ||
1410 | /* Descriptor Handling */ | ||
1411 | /***********************/ | ||
1412 | |||
1413 | /* | ||
1414 | * Set up DMA descriptors | ||
1415 | * | ||
1416 | * This function will allocate both the DMA descriptor structure, and the | ||
1417 | * buffers it contains. These are used to contain the descriptors used | ||
1418 | * by the system. | ||
1419 | */ | ||
1420 | |||
1421 | int ath_descdma_setup(struct ath_softc *sc, | ||
1422 | struct ath_descdma *dd, | ||
1423 | struct list_head *head, | ||
1424 | const char *name, | ||
1425 | int nbuf, | ||
1426 | int ndesc) | ||
1427 | { | ||
1428 | #define DS2PHYS(_dd, _ds) \ | ||
1429 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) | ||
1430 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) | ||
1431 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) | ||
1432 | |||
1433 | struct ath_desc *ds; | ||
1434 | struct ath_buf *bf; | ||
1435 | int i, bsize, error; | ||
1436 | |||
1437 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA: %u buffers %u desc/buf\n", | ||
1438 | __func__, name, nbuf, ndesc); | ||
1439 | |||
1440 | /* ath_desc must be a multiple of DWORDs */ | ||
1441 | if ((sizeof(struct ath_desc) % 4) != 0) { | ||
1442 | DPRINTF(sc, ATH_DBG_FATAL, "%s: ath_desc not DWORD aligned\n", | ||
1443 | __func__); | ||
1444 | ASSERT((sizeof(struct ath_desc) % 4) == 0); | ||
1445 | error = -ENOMEM; | ||
1446 | goto fail; | ||
1447 | } | ||
1448 | |||
1449 | dd->dd_name = name; | ||
1450 | dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; | ||
1451 | |||
1452 | /* | ||
1453 | * Need additional DMA memory because we can't use | ||
1454 | * descriptors that cross the 4K page boundary. Assume | ||
1455 | * one skipped descriptor per 4K page. | ||
1456 | */ | ||
1457 | if (!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
1458 | u32 ndesc_skipped = | ||
1459 | ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); | ||
1460 | u32 dma_len; | ||
1461 | |||
1462 | while (ndesc_skipped) { | ||
1463 | dma_len = ndesc_skipped * sizeof(struct ath_desc); | ||
1464 | dd->dd_desc_len += dma_len; | ||
1465 | |||
1466 | ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); | ||
1467 | }; | ||
1468 | } | ||
1469 | |||
1470 | /* allocate descriptors */ | ||
1471 | dd->dd_desc = pci_alloc_consistent(sc->pdev, | ||
1472 | dd->dd_desc_len, | ||
1473 | &dd->dd_desc_paddr); | ||
1474 | if (dd->dd_desc == NULL) { | ||
1475 | error = -ENOMEM; | ||
1476 | goto fail; | ||
1477 | } | ||
1478 | ds = dd->dd_desc; | ||
1479 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA map: %p (%u) -> %llx (%u)\n", | ||
1480 | __func__, dd->dd_name, ds, (u32) dd->dd_desc_len, | ||
1481 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | ||
1482 | |||
1483 | /* allocate buffers */ | ||
1484 | bsize = sizeof(struct ath_buf) * nbuf; | ||
1485 | bf = kmalloc(bsize, GFP_KERNEL); | ||
1486 | if (bf == NULL) { | ||
1487 | error = -ENOMEM; | ||
1488 | goto fail2; | ||
1489 | } | ||
1490 | memset(bf, 0, bsize); | ||
1491 | dd->dd_bufptr = bf; | ||
1492 | |||
1493 | INIT_LIST_HEAD(head); | ||
1494 | for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { | ||
1495 | bf->bf_desc = ds; | ||
1496 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
1497 | |||
1498 | if (!(sc->sc_ah->ah_caps.hw_caps & | ||
1499 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
1500 | /* | ||
1501 | * Skip descriptor addresses which can cause 4KB | ||
1502 | * boundary crossing (addr + length) with a 32 dword | ||
1503 | * descriptor fetch. | ||
1504 | */ | ||
1505 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | ||
1506 | ASSERT((caddr_t) bf->bf_desc < | ||
1507 | ((caddr_t) dd->dd_desc + | ||
1508 | dd->dd_desc_len)); | ||
1509 | |||
1510 | ds += ndesc; | ||
1511 | bf->bf_desc = ds; | ||
1512 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
1513 | } | ||
1514 | } | ||
1515 | list_add_tail(&bf->list, head); | ||
1516 | } | ||
1517 | return 0; | ||
1518 | fail2: | ||
1519 | pci_free_consistent(sc->pdev, | ||
1520 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); | ||
1521 | fail: | ||
1522 | memset(dd, 0, sizeof(*dd)); | ||
1523 | return error; | ||
1524 | #undef ATH_DESC_4KB_BOUND_CHECK | ||
1525 | #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED | ||
1526 | #undef DS2PHYS | ||
1527 | } | ||
1528 | |||
1529 | /* | ||
1530 | * Cleanup DMA descriptors | ||
1531 | * | ||
1532 | * This function will free the DMA block that was allocated for the descriptor | ||
1533 | * pool. Since this was allocated as one "chunk", it is freed in the same | ||
1534 | * manner. | ||
1535 | */ | ||
1536 | |||
1537 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
1538 | struct ath_descdma *dd, | ||
1539 | struct list_head *head) | ||
1540 | { | ||
1541 | /* Free memory associated with descriptors */ | ||
1542 | pci_free_consistent(sc->pdev, | ||
1543 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); | ||
1544 | |||
1545 | INIT_LIST_HEAD(head); | ||
1546 | kfree(dd->dd_bufptr); | ||
1547 | memset(dd, 0, sizeof(*dd)); | ||
1548 | } | ||
1549 | |||
1550 | /*************/ | ||
1551 | /* Utilities */ | ||
1552 | /*************/ | ||
1553 | |||
1554 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) | ||
1555 | { | ||
1556 | int qnum; | ||
1557 | |||
1558 | switch (queue) { | ||
1559 | case 0: | ||
1560 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO]; | ||
1561 | break; | ||
1562 | case 1: | ||
1563 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI]; | ||
1564 | break; | ||
1565 | case 2: | ||
1566 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; | ||
1567 | break; | ||
1568 | case 3: | ||
1569 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK]; | ||
1570 | break; | ||
1571 | default: | ||
1572 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; | ||
1573 | break; | ||
1574 | } | ||
1575 | |||
1576 | return qnum; | ||
1577 | } | ||
1578 | |||
1579 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) | ||
1580 | { | ||
1581 | int qnum; | ||
1582 | |||
1583 | switch (queue) { | ||
1584 | case ATH9K_WME_AC_VO: | ||
1585 | qnum = 0; | ||
1586 | break; | ||
1587 | case ATH9K_WME_AC_VI: | ||
1588 | qnum = 1; | ||
1589 | break; | ||
1590 | case ATH9K_WME_AC_BE: | ||
1591 | qnum = 2; | ||
1592 | break; | ||
1593 | case ATH9K_WME_AC_BK: | ||
1594 | qnum = 3; | ||
1595 | break; | ||
1596 | default: | ||
1597 | qnum = -1; | ||
1598 | break; | ||
1599 | } | ||
1600 | |||
1601 | return qnum; | ||
1602 | } | ||
1603 | |||
1604 | |||
1605 | /* | ||
1606 | * Expand time stamp to TSF | ||
1607 | * | ||
1608 | * Extend 15-bit time stamp from rx descriptor to | ||
1609 | * a full 64-bit TSF using the current h/w TSF. | ||
1610 | */ | ||
1611 | |||
1612 | u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) | ||
1613 | { | ||
1614 | u64 tsf; | ||
1615 | |||
1616 | tsf = ath9k_hw_gettsf64(sc->sc_ah); | ||
1617 | if ((tsf & 0x7fff) < rstamp) | ||
1618 | tsf -= 0x8000; | ||
1619 | return (tsf & ~0x7fff) | rstamp; | ||
1620 | } | ||
1621 | |||
1622 | /* | ||
1623 | * Set Default Antenna | ||
1624 | * | ||
1625 | * Call into the HAL to set the default antenna to use. Not really valid for | ||
1626 | * MIMO technology. | ||
1627 | */ | ||
1628 | |||
1629 | void ath_setdefantenna(void *context, u32 antenna) | ||
1630 | { | ||
1631 | struct ath_softc *sc = (struct ath_softc *)context; | ||
1632 | struct ath_hal *ah = sc->sc_ah; | ||
1633 | |||
1634 | /* XXX block beacon interrupts */ | ||
1635 | ath9k_hw_setantenna(ah, antenna); | ||
1636 | sc->sc_defant = antenna; | ||
1637 | sc->sc_rxotherant = 0; | ||
1638 | } | ||
1639 | |||
1640 | /* | ||
1641 | * Set Slot Time | ||
1642 | * | ||
1643 | * This will wake up the chip if required, and set the slot time for the | ||
1644 | * frame (maximum transmit time). Slot time is assumed to be already set | ||
1645 | * in the ATH object member sc_slottime | ||
1646 | */ | ||
1647 | |||
1648 | void ath_setslottime(struct ath_softc *sc) | ||
1649 | { | ||
1650 | ath9k_hw_setslottime(sc->sc_ah, sc->sc_slottime); | ||
1651 | sc->sc_updateslot = OK; | ||
1652 | } | ||
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 69e8d3e41131..f0c54377dfe6 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h | |||
@@ -47,10 +47,6 @@ | |||
47 | 47 | ||
48 | struct ath_node; | 48 | struct ath_node; |
49 | 49 | ||
50 | /******************/ | ||
51 | /* Utility macros */ | ||
52 | /******************/ | ||
53 | |||
54 | /* Macro to expand scalars to 64-bit objects */ | 50 | /* Macro to expand scalars to 64-bit objects */ |
55 | 51 | ||
56 | #define ito64(x) (sizeof(x) == 8) ? \ | 52 | #define ito64(x) (sizeof(x) == 8) ? \ |
@@ -86,11 +82,6 @@ struct ath_node; | |||
86 | 82 | ||
87 | #define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i)) | 83 | #define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i)) |
88 | 84 | ||
89 | static inline unsigned long get_timestamp(void) | ||
90 | { | ||
91 | return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ); | ||
92 | } | ||
93 | |||
94 | static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 85 | static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
95 | 86 | ||
96 | /*************/ | 87 | /*************/ |
@@ -141,34 +132,6 @@ struct ath_config { | |||
141 | u8 swBeaconProcess; /* Process received beacons in SW (vs HW) */ | 132 | u8 swBeaconProcess; /* Process received beacons in SW (vs HW) */ |
142 | }; | 133 | }; |
143 | 134 | ||
144 | /***********************/ | ||
145 | /* Chainmask Selection */ | ||
146 | /***********************/ | ||
147 | |||
148 | #define ATH_CHAINMASK_SEL_TIMEOUT 6000 | ||
149 | /* Default - Number of last RSSI values that is used for | ||
150 | * chainmask selection */ | ||
151 | #define ATH_CHAINMASK_SEL_RSSI_CNT 10 | ||
152 | /* Means use 3x3 chainmask instead of configured chainmask */ | ||
153 | #define ATH_CHAINMASK_SEL_3X3 7 | ||
154 | /* Default - Rssi threshold below which we have to switch to 3x3 */ | ||
155 | #define ATH_CHAINMASK_SEL_UP_RSSI_THRES 20 | ||
156 | /* Default - Rssi threshold above which we have to switch to | ||
157 | * user configured values */ | ||
158 | #define ATH_CHAINMASK_SEL_DOWN_RSSI_THRES 35 | ||
159 | /* Struct to store the chainmask select related info */ | ||
160 | struct ath_chainmask_sel { | ||
161 | struct timer_list timer; | ||
162 | int cur_tx_mask; /* user configured or 3x3 */ | ||
163 | int cur_rx_mask; /* user configured or 3x3 */ | ||
164 | int tx_avgrssi; | ||
165 | u8 switch_allowed:1, /* timer will set this */ | ||
166 | cm_sel_enabled : 1; | ||
167 | }; | ||
168 | |||
169 | int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an); | ||
170 | void ath_update_chainmask(struct ath_softc *sc, int is_ht); | ||
171 | |||
172 | /*************************/ | 135 | /*************************/ |
173 | /* Descriptor Management */ | 136 | /* Descriptor Management */ |
174 | /*************************/ | 137 | /*************************/ |
@@ -203,7 +166,6 @@ struct ath_buf_state { | |||
203 | int bfs_seqno; /* sequence number */ | 166 | int bfs_seqno; /* sequence number */ |
204 | int bfs_tidno; /* tid of this frame */ | 167 | int bfs_tidno; /* tid of this frame */ |
205 | int bfs_retries; /* current retries */ | 168 | int bfs_retries; /* current retries */ |
206 | struct ath_rc_series bfs_rcs[4]; /* rate series */ | ||
207 | u32 bf_type; /* BUF_* (enum buffer_type) */ | 169 | u32 bf_type; /* BUF_* (enum buffer_type) */ |
208 | /* key type use to encrypt this frame */ | 170 | /* key type use to encrypt this frame */ |
209 | u32 bfs_keyix; | 171 | u32 bfs_keyix; |
@@ -241,7 +203,6 @@ struct ath_buf { | |||
241 | an aggregate) */ | 203 | an aggregate) */ |
242 | struct ath_buf *bf_lastfrm; /* last buf of this frame */ | 204 | struct ath_buf *bf_lastfrm; /* last buf of this frame */ |
243 | struct ath_buf *bf_next; /* next subframe in the aggregate */ | 205 | struct ath_buf *bf_next; /* next subframe in the aggregate */ |
244 | struct ath_buf *bf_rifslast; /* last buf for RIFS burst */ | ||
245 | void *bf_mpdu; /* enclosing frame structure */ | 206 | void *bf_mpdu; /* enclosing frame structure */ |
246 | struct ath_desc *bf_desc; /* virtual addr of desc */ | 207 | struct ath_desc *bf_desc; /* virtual addr of desc */ |
247 | dma_addr_t bf_daddr; /* physical addr of desc */ | 208 | dma_addr_t bf_daddr; /* physical addr of desc */ |
@@ -279,80 +240,27 @@ struct ath_descdma { | |||
279 | dma_addr_t dd_dmacontext; | 240 | dma_addr_t dd_dmacontext; |
280 | }; | 241 | }; |
281 | 242 | ||
282 | /* Abstraction of a received RX MPDU/MMPDU, or a RX fragment */ | 243 | int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, |
283 | 244 | struct list_head *head, const char *name, | |
284 | struct ath_rx_context { | 245 | int nbuf, int ndesc); |
285 | struct ath_buf *ctx_rxbuf; /* associated ath_buf for rx */ | 246 | void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, |
286 | }; | ||
287 | #define ATH_RX_CONTEXT(skb) ((struct ath_rx_context *)skb->cb) | ||
288 | |||
289 | int ath_descdma_setup(struct ath_softc *sc, | ||
290 | struct ath_descdma *dd, | ||
291 | struct list_head *head, | ||
292 | const char *name, | ||
293 | int nbuf, | ||
294 | int ndesc); | ||
295 | int ath_desc_alloc(struct ath_softc *sc); | ||
296 | void ath_desc_free(struct ath_softc *sc); | ||
297 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
298 | struct ath_descdma *dd, | ||
299 | struct list_head *head); | 247 | struct list_head *head); |
300 | 248 | ||
301 | /******/ | 249 | /***********/ |
302 | /* RX */ | 250 | /* RX / TX */ |
303 | /******/ | 251 | /***********/ |
304 | 252 | ||
305 | #define ATH_MAX_ANTENNA 3 | 253 | #define ATH_MAX_ANTENNA 3 |
306 | #define ATH_RXBUF 512 | 254 | #define ATH_RXBUF 512 |
307 | #define WME_NUM_TID 16 | 255 | #define WME_NUM_TID 16 |
308 | 256 | ||
309 | /* per frame rx status block */ | ||
310 | struct ath_recv_status { | ||
311 | u64 tsf; /* mac tsf */ | ||
312 | int8_t rssi; /* RSSI (noise floor ajusted) */ | ||
313 | int8_t rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
314 | int8_t rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */ | ||
315 | int8_t abs_rssi; /* absolute RSSI */ | ||
316 | u8 rateieee; /* data rate received (IEEE rate code) */ | ||
317 | u8 ratecode; /* phy rate code */ | ||
318 | int rateKbps; /* data rate received (Kbps) */ | ||
319 | int antenna; /* rx antenna */ | ||
320 | int flags; /* status of associated skb */ | ||
321 | #define ATH_RX_FCS_ERROR 0x01 | ||
322 | #define ATH_RX_MIC_ERROR 0x02 | ||
323 | #define ATH_RX_DECRYPT_ERROR 0x04 | ||
324 | #define ATH_RX_RSSI_VALID 0x08 | ||
325 | /* if any of ctl,extn chainrssis are valid */ | ||
326 | #define ATH_RX_CHAIN_RSSI_VALID 0x10 | ||
327 | /* if extn chain rssis are valid */ | ||
328 | #define ATH_RX_RSSI_EXTN_VALID 0x20 | ||
329 | /* set if 40Mhz, clear if 20Mhz */ | ||
330 | #define ATH_RX_40MHZ 0x40 | ||
331 | /* set if short GI, clear if full GI */ | ||
332 | #define ATH_RX_SHORT_GI 0x80 | ||
333 | }; | ||
334 | |||
335 | struct ath_rxbuf { | ||
336 | struct sk_buff *rx_wbuf; | ||
337 | unsigned long rx_time; /* system time when received */ | ||
338 | struct ath_recv_status rx_status; /* cached rx status */ | ||
339 | }; | ||
340 | |||
341 | int ath_startrecv(struct ath_softc *sc); | 257 | int ath_startrecv(struct ath_softc *sc); |
342 | bool ath_stoprecv(struct ath_softc *sc); | 258 | bool ath_stoprecv(struct ath_softc *sc); |
343 | void ath_flushrecv(struct ath_softc *sc); | 259 | void ath_flushrecv(struct ath_softc *sc); |
344 | u32 ath_calcrxfilter(struct ath_softc *sc); | 260 | u32 ath_calcrxfilter(struct ath_softc *sc); |
345 | void ath_handle_rx_intr(struct ath_softc *sc); | ||
346 | int ath_rx_init(struct ath_softc *sc, int nbufs); | 261 | int ath_rx_init(struct ath_softc *sc, int nbufs); |
347 | void ath_rx_cleanup(struct ath_softc *sc); | 262 | void ath_rx_cleanup(struct ath_softc *sc); |
348 | int ath_rx_tasklet(struct ath_softc *sc, int flush); | 263 | int ath_rx_tasklet(struct ath_softc *sc, int flush); |
349 | int _ath_rx_indicate(struct ath_softc *sc, | ||
350 | struct sk_buff *skb, | ||
351 | struct ath_recv_status *status, | ||
352 | u16 keyix); | ||
353 | /******/ | ||
354 | /* TX */ | ||
355 | /******/ | ||
356 | 264 | ||
357 | #define ATH_TXBUF 512 | 265 | #define ATH_TXBUF 512 |
358 | /* max number of transmit attempts (tries) */ | 266 | /* max number of transmit attempts (tries) */ |
@@ -500,9 +408,6 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, | |||
500 | void ath_tx_tasklet(struct ath_softc *sc); | 408 | void ath_tx_tasklet(struct ath_softc *sc); |
501 | u32 ath_txq_depth(struct ath_softc *sc, int qnum); | 409 | u32 ath_txq_depth(struct ath_softc *sc, int qnum); |
502 | u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum); | 410 | u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum); |
503 | void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth); | ||
504 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | ||
505 | struct ath_xmit_status *tx_status); | ||
506 | void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb); | 411 | void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb); |
507 | 412 | ||
508 | /**********************/ | 413 | /**********************/ |
@@ -567,25 +472,41 @@ struct ath_node_aggr { | |||
567 | /* driver-specific node state */ | 472 | /* driver-specific node state */ |
568 | struct ath_node { | 473 | struct ath_node { |
569 | struct ath_softc *an_sc; | 474 | struct ath_softc *an_sc; |
570 | struct ath_chainmask_sel an_chainmask_sel; | ||
571 | struct ath_node_aggr an_aggr; | 475 | struct ath_node_aggr an_aggr; |
572 | u16 maxampdu; | 476 | u16 maxampdu; |
573 | u8 mpdudensity; | 477 | u8 mpdudensity; |
574 | }; | 478 | }; |
575 | 479 | ||
576 | void ath_tx_resume_tid(struct ath_softc *sc, | 480 | void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid); |
577 | struct ath_atx_tid *tid); | ||
578 | bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); | 481 | bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); |
579 | void ath_tx_aggr_teardown(struct ath_softc *sc, | 482 | void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tidno); |
580 | struct ath_node *an, u8 tidno); | ||
581 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 483 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
582 | u16 tid, u16 *ssn); | 484 | u16 tid, u16 *ssn); |
583 | int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 485 | int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
584 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 486 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
585 | void ath_newassoc(struct ath_softc *sc, | 487 | |
586 | struct ath_node *node, int isnew, int isuapsd); | 488 | /********/ |
587 | void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta); | 489 | /* VAPs */ |
588 | void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta); | 490 | /********/ |
491 | |||
492 | /* | ||
493 | * Define the scheme that we select MAC address for multiple | ||
494 | * BSS on the same radio. The very first VAP will just use the MAC | ||
495 | * address from the EEPROM. For the next 3 VAPs, we set the | ||
496 | * U/L bit (bit 1) in MAC address, and use the next two bits as the | ||
497 | * index of the VAP. | ||
498 | */ | ||
499 | |||
500 | #define ATH_SET_VAP_BSSID_MASK(bssid_mask) \ | ||
501 | ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02)) | ||
502 | |||
503 | /* driver-specific vap state */ | ||
504 | struct ath_vap { | ||
505 | int av_bslot; /* beacon slot index */ | ||
506 | enum ath9k_opmode av_opmode; /* VAP operational mode */ | ||
507 | struct ath_buf *av_bcbuf; /* beacon buffer */ | ||
508 | struct ath_tx_control av_btxctl; /* txctl information for beacon */ | ||
509 | }; | ||
589 | 510 | ||
590 | /*******************/ | 511 | /*******************/ |
591 | /* Beacon Handling */ | 512 | /* Beacon Handling */ |
@@ -620,80 +541,8 @@ void ath9k_beacon_tasklet(unsigned long data); | |||
620 | void ath_beacon_config(struct ath_softc *sc, int if_id); | 541 | void ath_beacon_config(struct ath_softc *sc, int if_id); |
621 | int ath_beaconq_setup(struct ath_hal *ah); | 542 | int ath_beaconq_setup(struct ath_hal *ah); |
622 | int ath_beacon_alloc(struct ath_softc *sc, int if_id); | 543 | int ath_beacon_alloc(struct ath_softc *sc, int if_id); |
623 | void ath_bstuck_process(struct ath_softc *sc); | ||
624 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp); | 544 | void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp); |
625 | void ath_beacon_sync(struct ath_softc *sc, int if_id); | 545 | void ath_beacon_sync(struct ath_softc *sc, int if_id); |
626 | void ath_get_beaconconfig(struct ath_softc *sc, | ||
627 | int if_id, | ||
628 | struct ath_beacon_config *conf); | ||
629 | /********/ | ||
630 | /* VAPs */ | ||
631 | /********/ | ||
632 | |||
633 | /* | ||
634 | * Define the scheme that we select MAC address for multiple | ||
635 | * BSS on the same radio. The very first VAP will just use the MAC | ||
636 | * address from the EEPROM. For the next 3 VAPs, we set the | ||
637 | * U/L bit (bit 1) in MAC address, and use the next two bits as the | ||
638 | * index of the VAP. | ||
639 | */ | ||
640 | |||
641 | #define ATH_SET_VAP_BSSID_MASK(bssid_mask) \ | ||
642 | ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02)) | ||
643 | |||
644 | /* VAP configuration (from protocol layer) */ | ||
645 | struct ath_vap_config { | ||
646 | u32 av_fixed_rateset; | ||
647 | u32 av_fixed_retryset; | ||
648 | }; | ||
649 | |||
650 | /* driver-specific vap state */ | ||
651 | struct ath_vap { | ||
652 | int av_bslot; /* beacon slot index */ | ||
653 | enum ath9k_opmode av_opmode; /* VAP operational mode */ | ||
654 | struct ath_buf *av_bcbuf; /* beacon buffer */ | ||
655 | struct ath_tx_control av_btxctl; /* txctl information for beacon */ | ||
656 | struct ath_vap_config av_config;/* vap configuration parameters*/ | ||
657 | struct ath_rate_node *rc_node; | ||
658 | }; | ||
659 | |||
660 | /*********************/ | ||
661 | /* Antenna diversity */ | ||
662 | /*********************/ | ||
663 | |||
664 | #define ATH_ANT_DIV_MAX_CFG 2 | ||
665 | #define ATH_ANT_DIV_MIN_IDLE_US 1000000 /* us */ | ||
666 | #define ATH_ANT_DIV_MIN_SCAN_US 50000 /* us */ | ||
667 | |||
668 | enum ATH_ANT_DIV_STATE{ | ||
669 | ATH_ANT_DIV_IDLE, | ||
670 | ATH_ANT_DIV_SCAN, /* evaluating antenna */ | ||
671 | }; | ||
672 | |||
673 | struct ath_antdiv { | ||
674 | struct ath_softc *antdiv_sc; | ||
675 | u8 antdiv_start; | ||
676 | enum ATH_ANT_DIV_STATE antdiv_state; | ||
677 | u8 antdiv_num_antcfg; | ||
678 | u8 antdiv_curcfg; | ||
679 | u8 antdiv_bestcfg; | ||
680 | int32_t antdivf_rssitrig; | ||
681 | int32_t antdiv_lastbrssi[ATH_ANT_DIV_MAX_CFG]; | ||
682 | u64 antdiv_lastbtsf[ATH_ANT_DIV_MAX_CFG]; | ||
683 | u64 antdiv_laststatetsf; | ||
684 | u8 antdiv_bssid[ETH_ALEN]; | ||
685 | }; | ||
686 | |||
687 | void ath_slow_ant_div_init(struct ath_antdiv *antdiv, | ||
688 | struct ath_softc *sc, int32_t rssitrig); | ||
689 | void ath_slow_ant_div_start(struct ath_antdiv *antdiv, | ||
690 | u8 num_antcfg, | ||
691 | const u8 *bssid); | ||
692 | void ath_slow_ant_div_stop(struct ath_antdiv *antdiv); | ||
693 | void ath_slow_ant_div(struct ath_antdiv *antdiv, | ||
694 | struct ieee80211_hdr *wh, | ||
695 | struct ath_rx_status *rx_stats); | ||
696 | void ath_setdefantenna(void *sc, u32 antenna); | ||
697 | 546 | ||
698 | /*******/ | 547 | /*******/ |
699 | /* ANI */ | 548 | /* ANI */ |
@@ -775,30 +624,8 @@ struct ath_rfkill { | |||
775 | 624 | ||
776 | #define ATH_IF_ID_ANY 0xff | 625 | #define ATH_IF_ID_ANY 0xff |
777 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 626 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
778 | 627 | #define ATH_RSSI_DUMMY_MARKER 0x127 | |
779 | #define RSSI_LPF_THRESHOLD -20 | 628 | #define ATH_RATE_DUMMY_MARKER 0 |
780 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */ | ||
781 | #define ATH_RATE_DUMMY_MARKER 0 | ||
782 | #define ATH_RSSI_LPF_LEN 10 | ||
783 | #define ATH_RSSI_DUMMY_MARKER 0x127 | ||
784 | |||
785 | #define ATH_EP_MUL(x, mul) ((x) * (mul)) | ||
786 | #define ATH_EP_RND(x, mul) \ | ||
787 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | ||
788 | #define ATH_RSSI_OUT(x) \ | ||
789 | (((x) != ATH_RSSI_DUMMY_MARKER) ? \ | ||
790 | (ATH_EP_RND((x), ATH_RSSI_EP_MULTIPLIER)) : ATH_RSSI_DUMMY_MARKER) | ||
791 | #define ATH_RSSI_IN(x) \ | ||
792 | (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) | ||
793 | #define ATH_LPF_RSSI(x, y, len) \ | ||
794 | ((x != ATH_RSSI_DUMMY_MARKER) ? \ | ||
795 | (((x) * ((len) - 1) + (y)) / (len)) : (y)) | ||
796 | #define ATH_RSSI_LPF(x, y) do { \ | ||
797 | if ((y) >= RSSI_LPF_THRESHOLD) \ | ||
798 | x = ATH_LPF_RSSI((x), \ | ||
799 | ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ | ||
800 | } while (0) | ||
801 | |||
802 | 629 | ||
803 | enum PROT_MODE { | 630 | enum PROT_MODE { |
804 | PROT_M_NONE = 0, | 631 | PROT_M_NONE = 0, |
@@ -806,17 +633,6 @@ enum PROT_MODE { | |||
806 | PROT_M_CTSONLY | 633 | PROT_M_CTSONLY |
807 | }; | 634 | }; |
808 | 635 | ||
809 | enum RATE_TYPE { | ||
810 | NORMAL_RATE = 0, | ||
811 | HALF_RATE, | ||
812 | QUARTER_RATE | ||
813 | }; | ||
814 | |||
815 | struct ath_ht_info { | ||
816 | enum ath9k_ht_macmode tx_chan_width; | ||
817 | u8 ext_chan_offset; | ||
818 | }; | ||
819 | |||
820 | #define SC_OP_INVALID BIT(0) | 636 | #define SC_OP_INVALID BIT(0) |
821 | #define SC_OP_BEACONS BIT(1) | 637 | #define SC_OP_BEACONS BIT(1) |
822 | #define SC_OP_RXAGGR BIT(2) | 638 | #define SC_OP_RXAGGR BIT(2) |
@@ -839,7 +655,6 @@ struct ath_softc { | |||
839 | struct tasklet_struct bcon_tasklet; | 655 | struct tasklet_struct bcon_tasklet; |
840 | struct ath_config sc_config; | 656 | struct ath_config sc_config; |
841 | struct ath_hal *sc_ah; | 657 | struct ath_hal *sc_ah; |
842 | struct ath_rate_softc *sc_rc; | ||
843 | void __iomem *mem; | 658 | void __iomem *mem; |
844 | 659 | ||
845 | u8 sc_curbssid[ETH_ALEN]; | 660 | u8 sc_curbssid[ETH_ALEN]; |
@@ -871,8 +686,8 @@ struct ath_softc { | |||
871 | u8 sc_rxotherant; /* rx's on non-default antenna */ | 686 | u8 sc_rxotherant; /* rx's on non-default antenna */ |
872 | 687 | ||
873 | struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ | 688 | struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */ |
874 | struct ath_ht_info sc_ht_info; | ||
875 | enum ath9k_ht_extprotspacing sc_ht_extprotspacing; | 689 | enum ath9k_ht_extprotspacing sc_ht_extprotspacing; |
690 | enum ath9k_ht_macmode tx_chan_width; | ||
876 | 691 | ||
877 | #ifdef CONFIG_SLOW_ANT_DIV | 692 | #ifdef CONFIG_SLOW_ANT_DIV |
878 | struct ath_antdiv sc_antdiv; | 693 | struct ath_antdiv sc_antdiv; |
@@ -914,13 +729,8 @@ struct ath_softc { | |||
914 | 729 | ||
915 | /* Rate */ | 730 | /* Rate */ |
916 | struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; | 731 | struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; |
917 | const struct ath9k_rate_table *sc_currates; | 732 | struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; |
918 | u8 sc_rixmap[256]; /* IEEE to h/w rate table ix */ | ||
919 | u8 sc_protrix; /* protection rate index */ | 733 | u8 sc_protrix; /* protection rate index */ |
920 | struct { | ||
921 | u32 rateKbps; /* transfer rate in kbs */ | ||
922 | u8 ieeerate; /* IEEE rate */ | ||
923 | } sc_hwmap[256]; /* h/w rate ix mappings */ | ||
924 | 734 | ||
925 | /* Channel, Band */ | 735 | /* Channel, Band */ |
926 | struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX]; | 736 | struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX]; |
@@ -945,27 +755,9 @@ struct ath_softc { | |||
945 | struct ath_ani sc_ani; | 755 | struct ath_ani sc_ani; |
946 | }; | 756 | }; |
947 | 757 | ||
948 | int ath_init(u16 devid, struct ath_softc *sc); | ||
949 | int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan); | ||
950 | void ath_stop(struct ath_softc *sc); | ||
951 | irqreturn_t ath_isr(int irq, void *dev); | ||
952 | int ath_reset(struct ath_softc *sc, bool retry_tx); | 758 | int ath_reset(struct ath_softc *sc, bool retry_tx); |
953 | int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan); | ||
954 | |||
955 | /*********************/ | ||
956 | /* Utility Functions */ | ||
957 | /*********************/ | ||
958 | |||
959 | void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot); | ||
960 | int ath_keyset(struct ath_softc *sc, | ||
961 | u16 keyix, | ||
962 | struct ath9k_keyval *hk, | ||
963 | const u8 mac[ETH_ALEN]); | ||
964 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); | 759 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); |
965 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); | 760 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); |
966 | void ath_setslottime(struct ath_softc *sc); | ||
967 | void ath_update_txpow(struct ath_softc *sc); | ||
968 | int ath_cabq_update(struct ath_softc *); | 761 | int ath_cabq_update(struct ath_softc *); |
969 | u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp); | ||
970 | 762 | ||
971 | #endif /* CORE_H */ | 763 | #endif /* CORE_H */ |
diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index f5fd03c0edd7..466dbce2c5f7 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c | |||
@@ -1244,7 +1244,7 @@ bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah, | |||
1244 | 1244 | ||
1245 | txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; | 1245 | txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; |
1246 | 1246 | ||
1247 | ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 1, &ant_config); | 1247 | ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config); |
1248 | REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config); | 1248 | REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config); |
1249 | 1249 | ||
1250 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | 1250 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { |
@@ -1551,9 +1551,9 @@ u32 ath9k_hw_get_eeprom(struct ath_hal *ah, | |||
1551 | 1551 | ||
1552 | switch (param) { | 1552 | switch (param) { |
1553 | case EEP_NFTHRESH_5: | 1553 | case EEP_NFTHRESH_5: |
1554 | return -pModal[0].noiseFloorThreshCh[0]; | 1554 | return pModal[0].noiseFloorThreshCh[0]; |
1555 | case EEP_NFTHRESH_2: | 1555 | case EEP_NFTHRESH_2: |
1556 | return -pModal[1].noiseFloorThreshCh[0]; | 1556 | return pModal[1].noiseFloorThreshCh[0]; |
1557 | case AR_EEPROM_MAC(0): | 1557 | case AR_EEPROM_MAC(0): |
1558 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; | 1558 | return pBase->macAddr[0] << 8 | pBase->macAddr[1]; |
1559 | case AR_EEPROM_MAC(1): | 1559 | case AR_EEPROM_MAC(1): |
@@ -1584,6 +1584,11 @@ u32 ath9k_hw_get_eeprom(struct ath_hal *ah, | |||
1584 | return pBase->txMask; | 1584 | return pBase->txMask; |
1585 | case EEP_RX_MASK: | 1585 | case EEP_RX_MASK: |
1586 | return pBase->rxMask; | 1586 | return pBase->rxMask; |
1587 | case EEP_RXGAIN_TYPE: | ||
1588 | return pBase->rxGainType; | ||
1589 | case EEP_TXGAIN_TYPE: | ||
1590 | return pBase->txGainType; | ||
1591 | |||
1587 | default: | 1592 | default: |
1588 | return 0; | 1593 | return 0; |
1589 | } | 1594 | } |
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index ff6457e0cb00..6eef10477896 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -86,10 +86,11 @@ static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs) | |||
86 | enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah, | 86 | enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah, |
87 | const struct ath9k_channel *chan) | 87 | const struct ath9k_channel *chan) |
88 | { | 88 | { |
89 | if (IS_CHAN_CCK(chan)) | 89 | if (IS_CHAN_B(chan)) |
90 | return ATH9K_MODE_11A; | 90 | return ATH9K_MODE_11B; |
91 | if (IS_CHAN_G(chan)) | 91 | if (IS_CHAN_G(chan)) |
92 | return ATH9K_MODE_11G; | 92 | return ATH9K_MODE_11G; |
93 | |||
93 | return ATH9K_MODE_11A; | 94 | return ATH9K_MODE_11A; |
94 | } | 95 | } |
95 | 96 | ||
@@ -142,27 +143,27 @@ bool ath9k_get_channel_edges(struct ath_hal *ah, | |||
142 | } | 143 | } |
143 | 144 | ||
144 | u16 ath9k_hw_computetxtime(struct ath_hal *ah, | 145 | u16 ath9k_hw_computetxtime(struct ath_hal *ah, |
145 | const struct ath9k_rate_table *rates, | 146 | struct ath_rate_table *rates, |
146 | u32 frameLen, u16 rateix, | 147 | u32 frameLen, u16 rateix, |
147 | bool shortPreamble) | 148 | bool shortPreamble) |
148 | { | 149 | { |
149 | u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; | 150 | u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; |
150 | u32 kbps; | 151 | u32 kbps; |
151 | 152 | ||
152 | kbps = rates->info[rateix].rateKbps; | 153 | kbps = rates->info[rateix].ratekbps; |
153 | 154 | ||
154 | if (kbps == 0) | 155 | if (kbps == 0) |
155 | return 0; | 156 | return 0; |
156 | 157 | ||
157 | switch (rates->info[rateix].phy) { | 158 | switch (rates->info[rateix].phy) { |
158 | case PHY_CCK: | 159 | case WLAN_RC_PHY_CCK: |
159 | phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; | 160 | phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; |
160 | if (shortPreamble && rates->info[rateix].shortPreamble) | 161 | if (shortPreamble && rates->info[rateix].short_preamble) |
161 | phyTime >>= 1; | 162 | phyTime >>= 1; |
162 | numBits = frameLen << 3; | 163 | numBits = frameLen << 3; |
163 | txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps); | 164 | txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps); |
164 | break; | 165 | break; |
165 | case PHY_OFDM: | 166 | case WLAN_RC_PHY_OFDM: |
166 | if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) { | 167 | if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) { |
167 | bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; | 168 | bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; |
168 | numBits = OFDM_PLCP_BITS + (frameLen << 3); | 169 | numBits = OFDM_PLCP_BITS + (frameLen << 3); |
@@ -557,6 +558,54 @@ static int ath9k_hw_init_macaddr(struct ath_hal *ah) | |||
557 | return 0; | 558 | return 0; |
558 | } | 559 | } |
559 | 560 | ||
561 | static void ath9k_hw_init_rxgain_ini(struct ath_hal *ah) | ||
562 | { | ||
563 | u32 rxgain_type; | ||
564 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
565 | |||
566 | if (ath9k_hw_get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) { | ||
567 | rxgain_type = ath9k_hw_get_eeprom(ah, EEP_RXGAIN_TYPE); | ||
568 | |||
569 | if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) | ||
570 | INIT_INI_ARRAY(&ahp->ah_iniModesRxGain, | ||
571 | ar9280Modes_backoff_13db_rxgain_9280_2, | ||
572 | ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); | ||
573 | else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) | ||
574 | INIT_INI_ARRAY(&ahp->ah_iniModesRxGain, | ||
575 | ar9280Modes_backoff_23db_rxgain_9280_2, | ||
576 | ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); | ||
577 | else | ||
578 | INIT_INI_ARRAY(&ahp->ah_iniModesRxGain, | ||
579 | ar9280Modes_original_rxgain_9280_2, | ||
580 | ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); | ||
581 | } else | ||
582 | INIT_INI_ARRAY(&ahp->ah_iniModesRxGain, | ||
583 | ar9280Modes_original_rxgain_9280_2, | ||
584 | ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); | ||
585 | } | ||
586 | |||
587 | static void ath9k_hw_init_txgain_ini(struct ath_hal *ah) | ||
588 | { | ||
589 | u32 txgain_type; | ||
590 | struct ath_hal_5416 *ahp = AH5416(ah); | ||
591 | |||
592 | if (ath9k_hw_get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) { | ||
593 | txgain_type = ath9k_hw_get_eeprom(ah, EEP_TXGAIN_TYPE); | ||
594 | |||
595 | if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) | ||
596 | INIT_INI_ARRAY(&ahp->ah_iniModesTxGain, | ||
597 | ar9280Modes_high_power_tx_gain_9280_2, | ||
598 | ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); | ||
599 | else | ||
600 | INIT_INI_ARRAY(&ahp->ah_iniModesTxGain, | ||
601 | ar9280Modes_original_tx_gain_9280_2, | ||
602 | ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); | ||
603 | } else | ||
604 | INIT_INI_ARRAY(&ahp->ah_iniModesTxGain, | ||
605 | ar9280Modes_original_tx_gain_9280_2, | ||
606 | ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); | ||
607 | } | ||
608 | |||
560 | static int ath9k_hw_post_attach(struct ath_hal *ah) | 609 | static int ath9k_hw_post_attach(struct ath_hal *ah) |
561 | { | 610 | { |
562 | int ecode; | 611 | int ecode; |
@@ -800,6 +849,14 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, | |||
800 | if (ecode != 0) | 849 | if (ecode != 0) |
801 | goto bad; | 850 | goto bad; |
802 | 851 | ||
852 | /* rxgain table */ | ||
853 | if (AR_SREV_9280_20_OR_LATER(ah)) | ||
854 | ath9k_hw_init_rxgain_ini(ah); | ||
855 | |||
856 | /* txgain table */ | ||
857 | if (AR_SREV_9280_20_OR_LATER(ah)) | ||
858 | ath9k_hw_init_txgain_ini(ah); | ||
859 | |||
803 | #ifndef CONFIG_SLOW_ANT_DIV | 860 | #ifndef CONFIG_SLOW_ANT_DIV |
804 | if (ah->ah_devid == AR9280_DEVID_PCI) { | 861 | if (ah->ah_devid == AR9280_DEVID_PCI) { |
805 | for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) { | 862 | for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) { |
@@ -853,7 +910,7 @@ static void ath9k_hw_init_bb(struct ath_hal *ah, | |||
853 | u32 synthDelay; | 910 | u32 synthDelay; |
854 | 911 | ||
855 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; | 912 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; |
856 | if (IS_CHAN_CCK(chan)) | 913 | if (IS_CHAN_B(chan)) |
857 | synthDelay = (4 * synthDelay) / 22; | 914 | synthDelay = (4 * synthDelay) / 22; |
858 | else | 915 | else |
859 | synthDelay /= 10; | 916 | synthDelay /= 10; |
@@ -1258,6 +1315,12 @@ static int ath9k_hw_process_ini(struct ath_hal *ah, | |||
1258 | DO_DELAY(regWrites); | 1315 | DO_DELAY(regWrites); |
1259 | } | 1316 | } |
1260 | 1317 | ||
1318 | if (AR_SREV_9280_20_OR_LATER(ah)) | ||
1319 | REG_WRITE_ARRAY(&ahp->ah_iniModesRxGain, modesIndex, regWrites); | ||
1320 | |||
1321 | if (AR_SREV_9280_20_OR_LATER(ah)) | ||
1322 | REG_WRITE_ARRAY(&ahp->ah_iniModesTxGain, modesIndex, regWrites); | ||
1323 | |||
1261 | for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) { | 1324 | for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) { |
1262 | u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0); | 1325 | u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0); |
1263 | u32 val = INI_RA(&ahp->ah_iniCommon, i, 1); | 1326 | u32 val = INI_RA(&ahp->ah_iniCommon, i, 1); |
@@ -1585,7 +1648,7 @@ static struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah, | |||
1585 | } | 1648 | } |
1586 | 1649 | ||
1587 | if (!IS_CHAN_OFDM(chan) && | 1650 | if (!IS_CHAN_OFDM(chan) && |
1588 | !IS_CHAN_CCK(chan) && | 1651 | !IS_CHAN_B(chan) && |
1589 | !IS_CHAN_HT20(chan) && | 1652 | !IS_CHAN_HT20(chan) && |
1590 | !IS_CHAN_HT40(chan)) { | 1653 | !IS_CHAN_HT40(chan)) { |
1591 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, | 1654 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, |
@@ -1649,7 +1712,7 @@ static bool ath9k_hw_channel_change(struct ath_hal *ah, | |||
1649 | } | 1712 | } |
1650 | 1713 | ||
1651 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; | 1714 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; |
1652 | if (IS_CHAN_CCK(chan)) | 1715 | if (IS_CHAN_B(chan)) |
1653 | synthDelay = (4 * synthDelay) / 22; | 1716 | synthDelay = (4 * synthDelay) / 22; |
1654 | else | 1717 | else |
1655 | synthDelay /= 10; | 1718 | synthDelay /= 10; |
@@ -2169,8 +2232,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, | |||
2169 | ((chan->channelFlags & CHANNEL_ALL) == | 2232 | ((chan->channelFlags & CHANNEL_ALL) == |
2170 | (ah->ah_curchan->channelFlags & CHANNEL_ALL)) && | 2233 | (ah->ah_curchan->channelFlags & CHANNEL_ALL)) && |
2171 | (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && | 2234 | (!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) && |
2172 | !IS_CHAN_A_5MHZ_SPACED(ah-> | 2235 | !IS_CHAN_A_5MHZ_SPACED(ah->ah_curchan)))) { |
2173 | ah_curchan)))) { | ||
2174 | 2236 | ||
2175 | if (ath9k_hw_channel_change(ah, chan, macmode)) { | 2237 | if (ath9k_hw_channel_change(ah, chan, macmode)) { |
2176 | ath9k_hw_loadnf(ah, ah->ah_curchan); | 2238 | ath9k_hw_loadnf(ah, ah->ah_curchan); |
@@ -2278,7 +2340,7 @@ bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan, | |||
2278 | ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode); | 2340 | ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode); |
2279 | ath9k_hw_init_qos(ah); | 2341 | ath9k_hw_init_qos(ah); |
2280 | 2342 | ||
2281 | #ifdef CONFIG_RFKILL | 2343 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
2282 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | 2344 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
2283 | ath9k_enable_rfkill(ah); | 2345 | ath9k_enable_rfkill(ah); |
2284 | #endif | 2346 | #endif |
@@ -3128,190 +3190,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah, | |||
3128 | 3190 | ||
3129 | } | 3191 | } |
3130 | 3192 | ||
3131 | /***************/ | ||
3132 | /* Rate tables */ | ||
3133 | /***************/ | ||
3134 | |||
3135 | static struct ath9k_rate_table ar5416_11a_table = { | ||
3136 | 8, | ||
3137 | {0}, | ||
3138 | { | ||
3139 | {true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0}, | ||
3140 | {true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0}, | ||
3141 | {true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2}, | ||
3142 | {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2}, | ||
3143 | {true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4}, | ||
3144 | {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4}, | ||
3145 | {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4}, | ||
3146 | {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4} | ||
3147 | }, | ||
3148 | }; | ||
3149 | |||
3150 | static struct ath9k_rate_table ar5416_11b_table = { | ||
3151 | 4, | ||
3152 | {0}, | ||
3153 | { | ||
3154 | {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0}, | ||
3155 | {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1}, | ||
3156 | {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 1}, | ||
3157 | {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 1} | ||
3158 | }, | ||
3159 | }; | ||
3160 | |||
3161 | static struct ath9k_rate_table ar5416_11g_table = { | ||
3162 | 12, | ||
3163 | {0}, | ||
3164 | { | ||
3165 | {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0}, | ||
3166 | {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1}, | ||
3167 | {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2}, | ||
3168 | {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3}, | ||
3169 | |||
3170 | {false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4}, | ||
3171 | {false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4}, | ||
3172 | {true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6}, | ||
3173 | {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6}, | ||
3174 | {true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8}, | ||
3175 | {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8}, | ||
3176 | {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8}, | ||
3177 | {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8} | ||
3178 | }, | ||
3179 | }; | ||
3180 | |||
3181 | static struct ath9k_rate_table ar5416_11ng_table = { | ||
3182 | 28, | ||
3183 | {0}, | ||
3184 | { | ||
3185 | {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0}, | ||
3186 | {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1}, | ||
3187 | {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2}, | ||
3188 | {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3}, | ||
3189 | |||
3190 | {false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4}, | ||
3191 | {false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4}, | ||
3192 | {true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6}, | ||
3193 | {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6}, | ||
3194 | {true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8}, | ||
3195 | {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8}, | ||
3196 | {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8}, | ||
3197 | {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8}, | ||
3198 | {true, PHY_HT, 6500, 0x80, 0x00, 0, 4}, | ||
3199 | {true, PHY_HT, 13000, 0x81, 0x00, 1, 6}, | ||
3200 | {true, PHY_HT, 19500, 0x82, 0x00, 2, 6}, | ||
3201 | {true, PHY_HT, 26000, 0x83, 0x00, 3, 8}, | ||
3202 | {true, PHY_HT, 39000, 0x84, 0x00, 4, 8}, | ||
3203 | {true, PHY_HT, 52000, 0x85, 0x00, 5, 8}, | ||
3204 | {true, PHY_HT, 58500, 0x86, 0x00, 6, 8}, | ||
3205 | {true, PHY_HT, 65000, 0x87, 0x00, 7, 8}, | ||
3206 | {true, PHY_HT, 13000, 0x88, 0x00, 8, 4}, | ||
3207 | {true, PHY_HT, 26000, 0x89, 0x00, 9, 6}, | ||
3208 | {true, PHY_HT, 39000, 0x8a, 0x00, 10, 6}, | ||
3209 | {true, PHY_HT, 52000, 0x8b, 0x00, 11, 8}, | ||
3210 | {true, PHY_HT, 78000, 0x8c, 0x00, 12, 8}, | ||
3211 | {true, PHY_HT, 104000, 0x8d, 0x00, 13, 8}, | ||
3212 | {true, PHY_HT, 117000, 0x8e, 0x00, 14, 8}, | ||
3213 | {true, PHY_HT, 130000, 0x8f, 0x00, 15, 8}, | ||
3214 | }, | ||
3215 | }; | ||
3216 | |||
3217 | static struct ath9k_rate_table ar5416_11na_table = { | ||
3218 | 24, | ||
3219 | {0}, | ||
3220 | { | ||
3221 | {true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0}, | ||
3222 | {true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0}, | ||
3223 | {true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2}, | ||
3224 | {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2}, | ||
3225 | {true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4}, | ||
3226 | {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4}, | ||
3227 | {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4}, | ||
3228 | {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4}, | ||
3229 | {true, PHY_HT, 6500, 0x80, 0x00, 0, 0}, | ||
3230 | {true, PHY_HT, 13000, 0x81, 0x00, 1, 2}, | ||
3231 | {true, PHY_HT, 19500, 0x82, 0x00, 2, 2}, | ||
3232 | {true, PHY_HT, 26000, 0x83, 0x00, 3, 4}, | ||
3233 | {true, PHY_HT, 39000, 0x84, 0x00, 4, 4}, | ||
3234 | {true, PHY_HT, 52000, 0x85, 0x00, 5, 4}, | ||
3235 | {true, PHY_HT, 58500, 0x86, 0x00, 6, 4}, | ||
3236 | {true, PHY_HT, 65000, 0x87, 0x00, 7, 4}, | ||
3237 | {true, PHY_HT, 13000, 0x88, 0x00, 8, 0}, | ||
3238 | {true, PHY_HT, 26000, 0x89, 0x00, 9, 2}, | ||
3239 | {true, PHY_HT, 39000, 0x8a, 0x00, 10, 2}, | ||
3240 | {true, PHY_HT, 52000, 0x8b, 0x00, 11, 4}, | ||
3241 | {true, PHY_HT, 78000, 0x8c, 0x00, 12, 4}, | ||
3242 | {true, PHY_HT, 104000, 0x8d, 0x00, 13, 4}, | ||
3243 | {true, PHY_HT, 117000, 0x8e, 0x00, 14, 4}, | ||
3244 | {true, PHY_HT, 130000, 0x8f, 0x00, 15, 4}, | ||
3245 | }, | ||
3246 | }; | ||
3247 | |||
3248 | static void ath9k_hw_setup_rate_table(struct ath_hal *ah, | ||
3249 | struct ath9k_rate_table *rt) | ||
3250 | { | ||
3251 | int i; | ||
3252 | |||
3253 | if (rt->rateCodeToIndex[0] != 0) | ||
3254 | return; | ||
3255 | |||
3256 | for (i = 0; i < 256; i++) | ||
3257 | rt->rateCodeToIndex[i] = (u8) -1; | ||
3258 | |||
3259 | for (i = 0; i < rt->rateCount; i++) { | ||
3260 | u8 code = rt->info[i].rateCode; | ||
3261 | u8 cix = rt->info[i].controlRate; | ||
3262 | |||
3263 | rt->rateCodeToIndex[code] = i; | ||
3264 | rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i; | ||
3265 | |||
3266 | rt->info[i].lpAckDuration = | ||
3267 | ath9k_hw_computetxtime(ah, rt, | ||
3268 | WLAN_CTRL_FRAME_SIZE, | ||
3269 | cix, | ||
3270 | false); | ||
3271 | rt->info[i].spAckDuration = | ||
3272 | ath9k_hw_computetxtime(ah, rt, | ||
3273 | WLAN_CTRL_FRAME_SIZE, | ||
3274 | cix, | ||
3275 | true); | ||
3276 | } | ||
3277 | } | ||
3278 | |||
3279 | const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah, | ||
3280 | u32 mode) | ||
3281 | { | ||
3282 | struct ath9k_rate_table *rt; | ||
3283 | |||
3284 | switch (mode) { | ||
3285 | case ATH9K_MODE_11A: | ||
3286 | rt = &ar5416_11a_table; | ||
3287 | break; | ||
3288 | case ATH9K_MODE_11B: | ||
3289 | rt = &ar5416_11b_table; | ||
3290 | break; | ||
3291 | case ATH9K_MODE_11G: | ||
3292 | rt = &ar5416_11g_table; | ||
3293 | break; | ||
3294 | case ATH9K_MODE_11NG_HT20: | ||
3295 | case ATH9K_MODE_11NG_HT40PLUS: | ||
3296 | case ATH9K_MODE_11NG_HT40MINUS: | ||
3297 | rt = &ar5416_11ng_table; | ||
3298 | break; | ||
3299 | case ATH9K_MODE_11NA_HT20: | ||
3300 | case ATH9K_MODE_11NA_HT40PLUS: | ||
3301 | case ATH9K_MODE_11NA_HT40MINUS: | ||
3302 | rt = &ar5416_11na_table; | ||
3303 | break; | ||
3304 | default: | ||
3305 | DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "%s: invalid mode 0x%x\n", | ||
3306 | __func__, mode); | ||
3307 | return NULL; | ||
3308 | } | ||
3309 | |||
3310 | ath9k_hw_setup_rate_table(ah, rt); | ||
3311 | |||
3312 | return rt; | ||
3313 | } | ||
3314 | |||
3315 | /*******************/ | 3193 | /*******************/ |
3316 | /* HW Capabilities */ | 3194 | /* HW Capabilities */ |
3317 | /*******************/ | 3195 | /*******************/ |
@@ -3453,7 +3331,7 @@ bool ath9k_hw_fill_cap_info(struct ath_hal *ah) | |||
3453 | 3331 | ||
3454 | pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; | 3332 | pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; |
3455 | 3333 | ||
3456 | #ifdef CONFIG_RFKILL | 3334 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
3457 | ah->ah_rfsilent = ath9k_hw_get_eeprom(ah, EEP_RF_SILENT); | 3335 | ah->ah_rfsilent = ath9k_hw_get_eeprom(ah, EEP_RF_SILENT); |
3458 | if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) { | 3336 | if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) { |
3459 | ah->ah_rfkill_gpio = | 3337 | ah->ah_rfkill_gpio = |
@@ -3710,7 +3588,7 @@ void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val) | |||
3710 | AR_GPIO_BIT(gpio)); | 3588 | AR_GPIO_BIT(gpio)); |
3711 | } | 3589 | } |
3712 | 3590 | ||
3713 | #ifdef CONFIG_RFKILL | 3591 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
3714 | void ath9k_enable_rfkill(struct ath_hal *ah) | 3592 | void ath9k_enable_rfkill(struct ath_hal *ah) |
3715 | { | 3593 | { |
3716 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | 3594 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, |
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index 6a29f2d43c21..02256c3ec076 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h | |||
@@ -415,6 +415,9 @@ struct ar5416Stats { | |||
415 | #define AR5416_EEP_MINOR_VER_3 0x3 | 415 | #define AR5416_EEP_MINOR_VER_3 0x3 |
416 | #define AR5416_EEP_MINOR_VER_7 0x7 | 416 | #define AR5416_EEP_MINOR_VER_7 0x7 |
417 | #define AR5416_EEP_MINOR_VER_9 0x9 | 417 | #define AR5416_EEP_MINOR_VER_9 0x9 |
418 | #define AR5416_EEP_MINOR_VER_16 0x10 | ||
419 | #define AR5416_EEP_MINOR_VER_17 0x11 | ||
420 | #define AR5416_EEP_MINOR_VER_19 0x13 | ||
418 | 421 | ||
419 | #define AR5416_NUM_5G_CAL_PIERS 8 | 422 | #define AR5416_NUM_5G_CAL_PIERS 8 |
420 | #define AR5416_NUM_2G_CAL_PIERS 4 | 423 | #define AR5416_NUM_2G_CAL_PIERS 4 |
@@ -436,6 +439,16 @@ struct ar5416Stats { | |||
436 | #define AR5416_MAX_CHAINS 3 | 439 | #define AR5416_MAX_CHAINS 3 |
437 | #define AR5416_PWR_TABLE_OFFSET -5 | 440 | #define AR5416_PWR_TABLE_OFFSET -5 |
438 | 441 | ||
442 | /* Rx gain type values */ | ||
443 | #define AR5416_EEP_RXGAIN_23DB_BACKOFF 0 | ||
444 | #define AR5416_EEP_RXGAIN_13DB_BACKOFF 1 | ||
445 | #define AR5416_EEP_RXGAIN_ORIG 2 | ||
446 | |||
447 | /* Tx gain type values */ | ||
448 | #define AR5416_EEP_TXGAIN_ORIGINAL 0 | ||
449 | #define AR5416_EEP_TXGAIN_HIGH_POWER 1 | ||
450 | |||
451 | |||
439 | enum eeprom_param { | 452 | enum eeprom_param { |
440 | EEP_NFTHRESH_5, | 453 | EEP_NFTHRESH_5, |
441 | EEP_NFTHRESH_2, | 454 | EEP_NFTHRESH_2, |
@@ -454,6 +467,8 @@ enum eeprom_param { | |||
454 | EEP_MINOR_REV, | 467 | EEP_MINOR_REV, |
455 | EEP_TX_MASK, | 468 | EEP_TX_MASK, |
456 | EEP_RX_MASK, | 469 | EEP_RX_MASK, |
470 | EEP_RXGAIN_TYPE, | ||
471 | EEP_TXGAIN_TYPE, | ||
457 | }; | 472 | }; |
458 | 473 | ||
459 | enum ar5416_rates { | 474 | enum ar5416_rates { |
@@ -485,7 +500,11 @@ struct base_eep_header { | |||
485 | u32 binBuildNumber; | 500 | u32 binBuildNumber; |
486 | u8 deviceType; | 501 | u8 deviceType; |
487 | u8 pwdclkind; | 502 | u8 pwdclkind; |
488 | u8 futureBase[32]; | 503 | u8 futureBase_1[2]; |
504 | u8 rxGainType; | ||
505 | u8 futureBase_2[3]; | ||
506 | u8 txGainType; | ||
507 | u8 futureBase_3[25]; | ||
489 | } __packed; | 508 | } __packed; |
490 | 509 | ||
491 | struct spur_chan { | 510 | struct spur_chan { |
@@ -792,6 +811,8 @@ struct ath_hal_5416 { | |||
792 | struct ar5416IniArray ah_iniAddac; | 811 | struct ar5416IniArray ah_iniAddac; |
793 | struct ar5416IniArray ah_iniPcieSerdes; | 812 | struct ar5416IniArray ah_iniPcieSerdes; |
794 | struct ar5416IniArray ah_iniModesAdditional; | 813 | struct ar5416IniArray ah_iniModesAdditional; |
814 | struct ar5416IniArray ah_iniModesRxGain; | ||
815 | struct ar5416IniArray ah_iniModesTxGain; | ||
795 | }; | 816 | }; |
796 | #define AH5416(_ah) ((struct ath_hal_5416 *)(_ah)) | 817 | #define AH5416(_ah) ((struct ath_hal_5416 *)(_ah)) |
797 | 818 | ||
diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h index 3dd3815940a4..1b08b54b31d7 100644 --- a/drivers/net/wireless/ath9k/initvals.h +++ b/drivers/net/wireless/ath9k/initvals.h | |||
@@ -14,6 +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 | /* AR5416 to Fowl ar5146.ini */ | ||
17 | static const u32 ar5416Modes_9100[][6] = { | 18 | static const u32 ar5416Modes_9100[][6] = { |
18 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 19 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
19 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 20 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
@@ -31,17 +32,17 @@ static const u32 ar5416Modes_9100[][6] = { | |||
31 | { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | 32 | { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, |
32 | { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | 33 | { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, |
33 | { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | 34 | { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, |
34 | { 0x00009850, 0x6de8b4e0, 0x6de8b4e0, 0x6de8b0de, 0x6de8b0de, 0x6de8b0de }, | 35 | { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de }, |
35 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, | 36 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, |
36 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, | 37 | { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, |
37 | { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, | 38 | { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, |
38 | { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | 39 | { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, |
39 | { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, | 40 | { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, |
40 | { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, | 41 | { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, |
41 | { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, | 42 | { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, |
42 | { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, | 43 | { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, |
43 | { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, | 44 | { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, |
44 | { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, | 45 | { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, |
45 | { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, | 46 | { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, |
46 | { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, | 47 | { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, |
47 | { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, | 48 | { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, |
@@ -207,7 +208,7 @@ static const u32 ar5416Common_9100[][2] = { | |||
207 | { 0x00008134, 0x00000000 }, | 208 | { 0x00008134, 0x00000000 }, |
208 | { 0x00008138, 0x00000000 }, | 209 | { 0x00008138, 0x00000000 }, |
209 | { 0x0000813c, 0x00000000 }, | 210 | { 0x0000813c, 0x00000000 }, |
210 | { 0x00008144, 0x00000000 }, | 211 | { 0x00008144, 0xffffffff }, |
211 | { 0x00008168, 0x00000000 }, | 212 | { 0x00008168, 0x00000000 }, |
212 | { 0x0000816c, 0x00000000 }, | 213 | { 0x0000816c, 0x00000000 }, |
213 | { 0x00008170, 0x32143320 }, | 214 | { 0x00008170, 0x32143320 }, |
@@ -266,7 +267,7 @@ static const u32 ar5416Common_9100[][2] = { | |||
266 | { 0x0000832c, 0x00000007 }, | 267 | { 0x0000832c, 0x00000007 }, |
267 | { 0x00008330, 0x00000302 }, | 268 | { 0x00008330, 0x00000302 }, |
268 | { 0x00008334, 0x00000e00 }, | 269 | { 0x00008334, 0x00000e00 }, |
269 | { 0x00008338, 0x00000000 }, | 270 | { 0x00008338, 0x00070000 }, |
270 | { 0x0000833c, 0x00000000 }, | 271 | { 0x0000833c, 0x00000000 }, |
271 | { 0x00008340, 0x000107ff }, | 272 | { 0x00008340, 0x000107ff }, |
272 | { 0x00009808, 0x00000000 }, | 273 | { 0x00009808, 0x00000000 }, |
@@ -661,6 +662,7 @@ static const u32 ar5416Addac_9100[][2] = { | |||
661 | {0x000098c4, 0x00000000 }, | 662 | {0x000098c4, 0x00000000 }, |
662 | }; | 663 | }; |
663 | 664 | ||
665 | /* ar5416 - howl ar5416_howl.ini */ | ||
664 | static const u32 ar5416Modes[][6] = { | 666 | static const u32 ar5416Modes[][6] = { |
665 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 667 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
666 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 668 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
@@ -952,7 +954,7 @@ static const u32 ar5416Common[][2] = { | |||
952 | { 0x0000994c, 0x00020028 }, | 954 | { 0x0000994c, 0x00020028 }, |
953 | { 0x0000c95c, 0x004b6a8e }, | 955 | { 0x0000c95c, 0x004b6a8e }, |
954 | { 0x0000c968, 0x000003ce }, | 956 | { 0x0000c968, 0x000003ce }, |
955 | { 0x00009970, 0x190fb514 }, | 957 | { 0x00009970, 0x190fb515 }, |
956 | { 0x00009974, 0x00000000 }, | 958 | { 0x00009974, 0x00000000 }, |
957 | { 0x00009978, 0x00000001 }, | 959 | { 0x00009978, 0x00000001 }, |
958 | { 0x0000997c, 0x00000000 }, | 960 | { 0x0000997c, 0x00000000 }, |
@@ -1311,7 +1313,7 @@ static const u32 ar5416Addac[][2] = { | |||
1311 | {0x000098cc, 0x00000000 }, | 1313 | {0x000098cc, 0x00000000 }, |
1312 | }; | 1314 | }; |
1313 | 1315 | ||
1314 | 1316 | /* AR5416 9160 Sowl ar5416_sowl.ini */ | |
1315 | static const u32 ar5416Modes_9160[][6] = { | 1317 | static const u32 ar5416Modes_9160[][6] = { |
1316 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 1318 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
1317 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 1319 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
@@ -1329,21 +1331,22 @@ static const u32 ar5416Modes_9160[][6] = { | |||
1329 | { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | 1331 | { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, |
1330 | { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | 1332 | { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, |
1331 | { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, | 1333 | { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, |
1332 | { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, | 1334 | { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, |
1333 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, | 1335 | { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, |
1334 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, | 1336 | { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, |
1335 | { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, | 1337 | { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, |
1336 | { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | 1338 | { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, |
1337 | { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, | 1339 | { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, |
1338 | { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, | 1340 | { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, |
1339 | { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, | 1341 | { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, |
1340 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, | 1342 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, |
1341 | { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, | 1343 | { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, |
1342 | { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, | 1344 | { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, |
1343 | { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, | 1345 | { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, |
1344 | { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, | 1346 | { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, |
1345 | { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, | 1347 | { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, |
1346 | { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, | 1348 | { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, |
1349 | { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, | ||
1347 | { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, | 1350 | { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, |
1348 | { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, | 1351 | { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, |
1349 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | 1352 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, |
@@ -1505,7 +1508,7 @@ static const u32 ar5416Common_9160[][2] = { | |||
1505 | { 0x00008134, 0x00000000 }, | 1508 | { 0x00008134, 0x00000000 }, |
1506 | { 0x00008138, 0x00000000 }, | 1509 | { 0x00008138, 0x00000000 }, |
1507 | { 0x0000813c, 0x00000000 }, | 1510 | { 0x0000813c, 0x00000000 }, |
1508 | { 0x00008144, 0x00000000 }, | 1511 | { 0x00008144, 0xffffffff }, |
1509 | { 0x00008168, 0x00000000 }, | 1512 | { 0x00008168, 0x00000000 }, |
1510 | { 0x0000816c, 0x00000000 }, | 1513 | { 0x0000816c, 0x00000000 }, |
1511 | { 0x00008170, 0x32143320 }, | 1514 | { 0x00008170, 0x32143320 }, |
@@ -1564,7 +1567,7 @@ static const u32 ar5416Common_9160[][2] = { | |||
1564 | { 0x0000832c, 0x00000007 }, | 1567 | { 0x0000832c, 0x00000007 }, |
1565 | { 0x00008330, 0x00000302 }, | 1568 | { 0x00008330, 0x00000302 }, |
1566 | { 0x00008334, 0x00000e00 }, | 1569 | { 0x00008334, 0x00000e00 }, |
1567 | { 0x00008338, 0x00000000 }, | 1570 | { 0x00008338, 0x00ff0000 }, |
1568 | { 0x0000833c, 0x00000000 }, | 1571 | { 0x0000833c, 0x00000000 }, |
1569 | { 0x00008340, 0x000107ff }, | 1572 | { 0x00008340, 0x000107ff }, |
1570 | { 0x00009808, 0x00000000 }, | 1573 | { 0x00009808, 0x00000000 }, |
@@ -1597,7 +1600,6 @@ static const u32 ar5416Common_9160[][2] = { | |||
1597 | { 0x00009958, 0x2108ecff }, | 1600 | { 0x00009958, 0x2108ecff }, |
1598 | { 0x00009940, 0x00750604 }, | 1601 | { 0x00009940, 0x00750604 }, |
1599 | { 0x0000c95c, 0x004b6a8e }, | 1602 | { 0x0000c95c, 0x004b6a8e }, |
1600 | { 0x0000c968, 0x000003ce }, | ||
1601 | { 0x00009970, 0x190fb515 }, | 1603 | { 0x00009970, 0x190fb515 }, |
1602 | { 0x00009974, 0x00000000 }, | 1604 | { 0x00009974, 0x00000000 }, |
1603 | { 0x00009978, 0x00000001 }, | 1605 | { 0x00009978, 0x00000001 }, |
@@ -1699,7 +1701,7 @@ static const u32 ar5416Common_9160[][2] = { | |||
1699 | { 0x0000a244, 0x00007bb6 }, | 1701 | { 0x0000a244, 0x00007bb6 }, |
1700 | { 0x0000a248, 0x0fff3ffc }, | 1702 | { 0x0000a248, 0x0fff3ffc }, |
1701 | { 0x0000a24c, 0x00000001 }, | 1703 | { 0x0000a24c, 0x00000001 }, |
1702 | { 0x0000a250, 0x0000a000 }, | 1704 | { 0x0000a250, 0x0000e000 }, |
1703 | { 0x0000a254, 0x00000000 }, | 1705 | { 0x0000a254, 0x00000000 }, |
1704 | { 0x0000a258, 0x0cc75380 }, | 1706 | { 0x0000a258, 0x0cc75380 }, |
1705 | { 0x0000a25c, 0x0f0f0f01 }, | 1707 | { 0x0000a25c, 0x0f0f0f01 }, |
@@ -1719,7 +1721,7 @@ static const u32 ar5416Common_9160[][2] = { | |||
1719 | { 0x0000a34c, 0x3fffffff }, | 1721 | { 0x0000a34c, 0x3fffffff }, |
1720 | { 0x0000a350, 0x3fffffff }, | 1722 | { 0x0000a350, 0x3fffffff }, |
1721 | { 0x0000a354, 0x0003ffff }, | 1723 | { 0x0000a354, 0x0003ffff }, |
1722 | { 0x0000a358, 0x79a8aa33 }, | 1724 | { 0x0000a358, 0x79bfaa03 }, |
1723 | { 0x0000d35c, 0x07ffffef }, | 1725 | { 0x0000d35c, 0x07ffffef }, |
1724 | { 0x0000d360, 0x0fffffe7 }, | 1726 | { 0x0000d360, 0x0fffffe7 }, |
1725 | { 0x0000d364, 0x17ffffe5 }, | 1727 | { 0x0000d364, 0x17ffffe5 }, |
@@ -1842,7 +1844,6 @@ static const u32 ar5416Bank3_9160[][3] = { | |||
1842 | }; | 1844 | }; |
1843 | 1845 | ||
1844 | static const u32 ar5416Bank6_9160[][3] = { | 1846 | static const u32 ar5416Bank6_9160[][3] = { |
1845 | |||
1846 | { 0x0000989c, 0x00000000, 0x00000000 }, | 1847 | { 0x0000989c, 0x00000000, 0x00000000 }, |
1847 | { 0x0000989c, 0x00000000, 0x00000000 }, | 1848 | { 0x0000989c, 0x00000000, 0x00000000 }, |
1848 | { 0x0000989c, 0x00000000, 0x00000000 }, | 1849 | { 0x0000989c, 0x00000000, 0x00000000 }, |
@@ -1920,7 +1921,6 @@ static const u32 ar5416Bank7_9160[][2] = { | |||
1920 | { 0x000098cc, 0x0000000e }, | 1921 | { 0x000098cc, 0x0000000e }, |
1921 | }; | 1922 | }; |
1922 | 1923 | ||
1923 | |||
1924 | static u32 ar5416Addac_9160[][2] = { | 1924 | static u32 ar5416Addac_9160[][2] = { |
1925 | {0x0000989c, 0x00000000 }, | 1925 | {0x0000989c, 0x00000000 }, |
1926 | {0x0000989c, 0x00000000 }, | 1926 | {0x0000989c, 0x00000000 }, |
@@ -1956,7 +1956,6 @@ static u32 ar5416Addac_9160[][2] = { | |||
1956 | {0x000098cc, 0x00000000 }, | 1956 | {0x000098cc, 0x00000000 }, |
1957 | }; | 1957 | }; |
1958 | 1958 | ||
1959 | |||
1960 | static u32 ar5416Addac_91601_1[][2] = { | 1959 | static u32 ar5416Addac_91601_1[][2] = { |
1961 | {0x0000989c, 0x00000000 }, | 1960 | {0x0000989c, 0x00000000 }, |
1962 | {0x0000989c, 0x00000000 }, | 1961 | {0x0000989c, 0x00000000 }, |
@@ -1992,8 +1991,7 @@ static u32 ar5416Addac_91601_1[][2] = { | |||
1992 | {0x000098cc, 0x00000000 }, | 1991 | {0x000098cc, 0x00000000 }, |
1993 | }; | 1992 | }; |
1994 | 1993 | ||
1995 | 1994 | /* XXX 9280 1 */ | |
1996 | |||
1997 | static const u32 ar9280Modes_9280[][6] = { | 1995 | static const u32 ar9280Modes_9280[][6] = { |
1998 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 1996 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
1999 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 1997 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
@@ -2543,9 +2541,7 @@ static const u32 ar9280Common_9280[][2] = { | |||
2543 | { 0x00007898, 0x2a850160 }, | 2541 | { 0x00007898, 0x2a850160 }, |
2544 | }; | 2542 | }; |
2545 | 2543 | ||
2546 | 2544 | /* XXX 9280 2 */ | |
2547 | |||
2548 | |||
2549 | static const u32 ar9280Modes_9280_2[][6] = { | 2545 | static const u32 ar9280Modes_9280_2[][6] = { |
2550 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, | 2546 | { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, |
2551 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, | 2547 | { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, |
@@ -2560,26 +2556,24 @@ static const u32 ar9280Modes_9280_2[][6] = { | |||
2560 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, | 2556 | { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, |
2561 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, | 2557 | { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, |
2562 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, | 2558 | { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, |
2563 | { 0x00009840, 0x206a012e, 0x206a012e, 0x206a022e, 0x206a022e, 0x206a022e }, | 2559 | { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, |
2564 | { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, | 2560 | { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, |
2565 | { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, | 2561 | { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, |
2566 | { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, | 2562 | { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, |
2567 | { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, | 2563 | { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e }, |
2568 | { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e }, | ||
2569 | { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, | ||
2570 | { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, | 2564 | { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, |
2571 | { 0x0000c864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, | 2565 | { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, |
2572 | { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, | 2566 | { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, |
2573 | { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, | 2567 | { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, |
2574 | { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, | 2568 | { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, |
2575 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, | 2569 | { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, |
2576 | { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, | 2570 | { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, |
2577 | { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 }, | 2571 | { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, |
2578 | { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, | 2572 | { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, |
2579 | { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, | 2573 | { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, |
2580 | { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, | 2574 | { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, |
2581 | { 0x0000c9b8, 0x0000000f, 0x0000000f, 0x0000001c, 0x0000001c, 0x0000001c }, | 2575 | { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, |
2582 | { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, | 2576 | { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, |
2583 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, | 2577 | { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, |
2584 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, | 2578 | { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, |
2585 | { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, | 2579 | { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, |
@@ -2587,164 +2581,13 @@ static const u32 ar9280Modes_9280_2[][6] = { | |||
2587 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, | 2581 | { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, |
2588 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 2582 | { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
2589 | { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 2583 | { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
2590 | { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, | ||
2591 | { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, | ||
2592 | { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, | ||
2593 | { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, | ||
2594 | { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, | ||
2595 | { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, | ||
2596 | { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, | ||
2597 | { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, | ||
2598 | { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, | ||
2599 | { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, | ||
2600 | { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, | ||
2601 | { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, | ||
2602 | { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, | ||
2603 | { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, | ||
2604 | { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, | ||
2605 | { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, | ||
2606 | { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, | ||
2607 | { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, | ||
2608 | { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, | ||
2609 | { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, | ||
2610 | { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, | ||
2611 | { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, | ||
2612 | { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, | ||
2613 | { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, | ||
2614 | { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, | ||
2615 | { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, | ||
2616 | { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, | ||
2617 | { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, | ||
2618 | { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, | ||
2619 | { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, | ||
2620 | { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, | ||
2621 | { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, | ||
2622 | { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, | ||
2623 | { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, | ||
2624 | { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, | ||
2625 | { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, | ||
2626 | { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, | ||
2627 | { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, | ||
2628 | { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, | ||
2629 | { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, | ||
2630 | { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, | ||
2631 | { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, | ||
2632 | { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, | ||
2633 | { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, | ||
2634 | { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, | ||
2635 | { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, | ||
2636 | { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, | ||
2637 | { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, | ||
2638 | { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, | ||
2639 | { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, | ||
2640 | { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, | ||
2641 | { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, | ||
2642 | { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, | ||
2643 | { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, | ||
2644 | { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, | ||
2645 | { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, | ||
2646 | { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, | ||
2647 | { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, | ||
2648 | { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, | ||
2649 | { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, | ||
2650 | { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, | ||
2651 | { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, | ||
2652 | { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, | ||
2653 | { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, | ||
2654 | { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, | ||
2655 | { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, | ||
2656 | { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, | ||
2657 | { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, | ||
2658 | { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, | ||
2659 | { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, | ||
2660 | { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, | ||
2661 | { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, | ||
2662 | { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, | ||
2663 | { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, | ||
2664 | { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, | ||
2665 | { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, | ||
2666 | { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, | ||
2667 | { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, | ||
2668 | { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, | ||
2669 | { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, | ||
2670 | { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, | ||
2671 | { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, | ||
2672 | { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, | ||
2673 | { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, | ||
2674 | { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, | ||
2675 | { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, | ||
2676 | { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, | ||
2677 | { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, | ||
2678 | { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, | ||
2679 | { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, | ||
2680 | { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, | ||
2681 | { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, | ||
2682 | { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, | ||
2683 | { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, | ||
2684 | { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, | ||
2685 | { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, | ||
2686 | { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, | ||
2687 | { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, | ||
2688 | { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, | ||
2689 | { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, | ||
2690 | { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, | ||
2691 | { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, | ||
2692 | { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2693 | { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2694 | { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2695 | { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2696 | { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2697 | { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2698 | { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2699 | { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2700 | { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2701 | { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2702 | { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2703 | { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2704 | { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2705 | { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2706 | { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2707 | { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2708 | { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2709 | { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2710 | { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2711 | { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2712 | { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2713 | { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2714 | { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2715 | { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2716 | { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2717 | { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
2718 | { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, | 2584 | { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, |
2719 | { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 }, | ||
2720 | { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, | 2585 | { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, |
2721 | { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, | 2586 | { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, |
2722 | { 0x0000a21c, 0x1463800a, 0x1463800a, 0x1463800a, 0x1463800a, 0x1463800a }, | 2587 | { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, |
2723 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, | 2588 | { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, |
2724 | { 0x0000a250, 0x001ff000, 0x001ff000, 0x001da000, 0x001da000, 0x001da000 }, | 2589 | { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, |
2725 | { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, | 2590 | { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, |
2726 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
2727 | { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, | ||
2728 | { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, | ||
2729 | { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, | ||
2730 | { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, | ||
2731 | { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, | ||
2732 | { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, | ||
2733 | { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, | ||
2734 | { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, | ||
2735 | { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, | ||
2736 | { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, | ||
2737 | { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, | ||
2738 | { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, | ||
2739 | { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, | ||
2740 | { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, | ||
2741 | { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, | ||
2742 | { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, | ||
2743 | { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, | ||
2744 | { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, | ||
2745 | { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, | ||
2746 | { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, | ||
2747 | { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, | ||
2748 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, | 2591 | { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, |
2749 | { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | 2592 | { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, |
2750 | { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, | 2593 | { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, |
@@ -2884,7 +2727,7 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2884 | { 0x00008134, 0x00000000 }, | 2727 | { 0x00008134, 0x00000000 }, |
2885 | { 0x00008138, 0x00000000 }, | 2728 | { 0x00008138, 0x00000000 }, |
2886 | { 0x0000813c, 0x00000000 }, | 2729 | { 0x0000813c, 0x00000000 }, |
2887 | { 0x00008144, 0x00000000 }, | 2730 | { 0x00008144, 0xffffffff }, |
2888 | { 0x00008168, 0x00000000 }, | 2731 | { 0x00008168, 0x00000000 }, |
2889 | { 0x0000816c, 0x00000000 }, | 2732 | { 0x0000816c, 0x00000000 }, |
2890 | { 0x00008170, 0x32143320 }, | 2733 | { 0x00008170, 0x32143320 }, |
@@ -2923,6 +2766,7 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2923 | { 0x00008258, 0x00000000 }, | 2766 | { 0x00008258, 0x00000000 }, |
2924 | { 0x0000825c, 0x400000ff }, | 2767 | { 0x0000825c, 0x400000ff }, |
2925 | { 0x00008260, 0x00080922 }, | 2768 | { 0x00008260, 0x00080922 }, |
2769 | { 0x00008264, 0xa8a00010 }, | ||
2926 | { 0x00008270, 0x00000000 }, | 2770 | { 0x00008270, 0x00000000 }, |
2927 | { 0x00008274, 0x40000000 }, | 2771 | { 0x00008274, 0x40000000 }, |
2928 | { 0x00008278, 0x003e4180 }, | 2772 | { 0x00008278, 0x003e4180 }, |
@@ -2939,7 +2783,7 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2939 | { 0x0000832c, 0x00000007 }, | 2783 | { 0x0000832c, 0x00000007 }, |
2940 | { 0x00008330, 0x00000302 }, | 2784 | { 0x00008330, 0x00000302 }, |
2941 | { 0x00008334, 0x00000e00 }, | 2785 | { 0x00008334, 0x00000e00 }, |
2942 | { 0x00008338, 0x00000000 }, | 2786 | { 0x00008338, 0x00ff0000 }, |
2943 | { 0x0000833c, 0x00000000 }, | 2787 | { 0x0000833c, 0x00000000 }, |
2944 | { 0x00008340, 0x000107ff }, | 2788 | { 0x00008340, 0x000107ff }, |
2945 | { 0x00008344, 0x00581043 }, | 2789 | { 0x00008344, 0x00581043 }, |
@@ -2973,7 +2817,7 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2973 | { 0x00009958, 0x2108ecff }, | 2817 | { 0x00009958, 0x2108ecff }, |
2974 | { 0x00009940, 0x14750604 }, | 2818 | { 0x00009940, 0x14750604 }, |
2975 | { 0x0000c95c, 0x004b6a8e }, | 2819 | { 0x0000c95c, 0x004b6a8e }, |
2976 | { 0x0000c968, 0x000003ce }, | 2820 | { 0x00009968, 0x000003ce }, |
2977 | { 0x00009970, 0x190fb515 }, | 2821 | { 0x00009970, 0x190fb515 }, |
2978 | { 0x00009974, 0x00000000 }, | 2822 | { 0x00009974, 0x00000000 }, |
2979 | { 0x00009978, 0x00000001 }, | 2823 | { 0x00009978, 0x00000001 }, |
@@ -2999,13 +2843,14 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
2999 | { 0x000099ec, 0x0cc80caa }, | 2843 | { 0x000099ec, 0x0cc80caa }, |
3000 | { 0x000099f0, 0x00000000 }, | 2844 | { 0x000099f0, 0x00000000 }, |
3001 | { 0x000099fc, 0x00001042 }, | 2845 | { 0x000099fc, 0x00001042 }, |
2846 | { 0x0000a208, 0x803e4788 }, | ||
3002 | { 0x0000a210, 0x4080a333 }, | 2847 | { 0x0000a210, 0x4080a333 }, |
3003 | { 0x0000a214, 0x40206c10 }, | 2848 | { 0x0000a214, 0x40206c10 }, |
3004 | { 0x0000a218, 0x009c4060 }, | 2849 | { 0x0000a218, 0x009c4060 }, |
3005 | { 0x0000a220, 0x01834061 }, | 2850 | { 0x0000a220, 0x01834061 }, |
3006 | { 0x0000a224, 0x00000400 }, | 2851 | { 0x0000a224, 0x00000400 }, |
3007 | { 0x0000a228, 0x000003b5 }, | 2852 | { 0x0000a228, 0x000003b5 }, |
3008 | { 0x0000a22c, 0x233f71c0 }, | 2853 | { 0x0000a22c, 0x233f7180 }, |
3009 | { 0x0000a234, 0x20202020 }, | 2854 | { 0x0000a234, 0x20202020 }, |
3010 | { 0x0000a238, 0x20202020 }, | 2855 | { 0x0000a238, 0x20202020 }, |
3011 | { 0x0000a23c, 0x13c88000 }, | 2856 | { 0x0000a23c, 0x13c88000 }, |
@@ -3022,7 +2867,6 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
3022 | { 0x0000b26c, 0x0ebae9c6 }, | 2867 | { 0x0000b26c, 0x0ebae9c6 }, |
3023 | { 0x0000d270, 0x00820820 }, | 2868 | { 0x0000d270, 0x00820820 }, |
3024 | { 0x0000a278, 0x1ce739ce }, | 2869 | { 0x0000a278, 0x1ce739ce }, |
3025 | { 0x0000a27c, 0x050701ce }, | ||
3026 | { 0x0000d35c, 0x07ffffef }, | 2870 | { 0x0000d35c, 0x07ffffef }, |
3027 | { 0x0000d360, 0x0fffffe7 }, | 2871 | { 0x0000d360, 0x0fffffe7 }, |
3028 | { 0x0000d364, 0x17ffffe5 }, | 2872 | { 0x0000d364, 0x17ffffe5 }, |
@@ -3064,7 +2908,6 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
3064 | { 0x00007808, 0x04924914 }, | 2908 | { 0x00007808, 0x04924914 }, |
3065 | { 0x0000780c, 0x21084210 }, | 2909 | { 0x0000780c, 0x21084210 }, |
3066 | { 0x00007810, 0x6d801300 }, | 2910 | { 0x00007810, 0x6d801300 }, |
3067 | { 0x00007814, 0x0019beff }, | ||
3068 | { 0x00007818, 0x07e41000 }, | 2911 | { 0x00007818, 0x07e41000 }, |
3069 | { 0x0000781c, 0x00392000 }, | 2912 | { 0x0000781c, 0x00392000 }, |
3070 | { 0x00007820, 0x92592480 }, | 2913 | { 0x00007820, 0x92592480 }, |
@@ -3073,7 +2916,6 @@ static const u32 ar9280Common_9280_2[][2] = { | |||
3073 | { 0x0000782c, 0x04924914 }, | 2916 | { 0x0000782c, 0x04924914 }, |
3074 | { 0x00007830, 0x21084210 }, | 2917 | { 0x00007830, 0x21084210 }, |
3075 | { 0x00007834, 0x6d801300 }, | 2918 | { 0x00007834, 0x6d801300 }, |
3076 | { 0x00007838, 0x0019beff }, | ||
3077 | { 0x0000783c, 0x07e40000 }, | 2919 | { 0x0000783c, 0x07e40000 }, |
3078 | { 0x00007840, 0x00392000 }, | 2920 | { 0x00007840, 0x00392000 }, |
3079 | { 0x00007844, 0x92592480 }, | 2921 | { 0x00007844, 0x92592480 }, |
@@ -3110,12 +2952,465 @@ static const u32 ar9280Modes_fast_clock_9280_2[][3] = { | |||
3110 | { 0x00009828, 0x0b020001, 0x0b020001 }, | 2952 | { 0x00009828, 0x0b020001, 0x0b020001 }, |
3111 | { 0x00009834, 0x00000f0f, 0x00000f0f }, | 2953 | { 0x00009834, 0x00000f0f, 0x00000f0f }, |
3112 | { 0x00009844, 0x03721821, 0x03721821 }, | 2954 | { 0x00009844, 0x03721821, 0x03721821 }, |
3113 | { 0x00009914, 0x00000898, 0x00000898 }, | 2955 | { 0x00009914, 0x00000898, 0x00001130 }, |
3114 | { 0x00009918, 0x0000000b, 0x00000016 }, | 2956 | { 0x00009918, 0x0000000b, 0x00000016 }, |
3115 | { 0x00009944, 0xdfbc1210, 0xdfbc1210 }, | 2957 | { 0x00009944, 0xdfbc1210, 0xdfbc1210 }, |
3116 | }; | 2958 | }; |
3117 | 2959 | ||
2960 | static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { | ||
2961 | { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, | ||
2962 | { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, | ||
2963 | { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, | ||
2964 | { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, | ||
2965 | { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, | ||
2966 | { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, | ||
2967 | { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, | ||
2968 | { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, | ||
2969 | { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, | ||
2970 | { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, | ||
2971 | { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, | ||
2972 | { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, | ||
2973 | { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, | ||
2974 | { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, | ||
2975 | { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, | ||
2976 | { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, | ||
2977 | { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, | ||
2978 | { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, | ||
2979 | { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, | ||
2980 | { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, | ||
2981 | { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, | ||
2982 | { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, | ||
2983 | { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, | ||
2984 | { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, | ||
2985 | { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, | ||
2986 | { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, | ||
2987 | { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, | ||
2988 | { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, | ||
2989 | { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, | ||
2990 | { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, | ||
2991 | { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, | ||
2992 | { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, | ||
2993 | { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, | ||
2994 | { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, | ||
2995 | { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, | ||
2996 | { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, | ||
2997 | { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, | ||
2998 | { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, | ||
2999 | { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, | ||
3000 | { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, | ||
3001 | { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, | ||
3002 | { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, | ||
3003 | { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, | ||
3004 | { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, | ||
3005 | { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, | ||
3006 | { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, | ||
3007 | { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, | ||
3008 | { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, | ||
3009 | { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 }, | ||
3010 | { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 }, | ||
3011 | { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 }, | ||
3012 | { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 }, | ||
3013 | { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 }, | ||
3014 | { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d }, | ||
3015 | { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 }, | ||
3016 | { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 }, | ||
3017 | { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 }, | ||
3018 | { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 }, | ||
3019 | { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a }, | ||
3020 | { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e }, | ||
3021 | { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 }, | ||
3022 | { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 }, | ||
3023 | { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 }, | ||
3024 | { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 }, | ||
3025 | { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b }, | ||
3026 | { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f }, | ||
3027 | { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 }, | ||
3028 | { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 }, | ||
3029 | { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 }, | ||
3030 | { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 }, | ||
3031 | { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b }, | ||
3032 | { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f }, | ||
3033 | { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 }, | ||
3034 | { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 }, | ||
3035 | { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 }, | ||
3036 | { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 }, | ||
3037 | { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b }, | ||
3038 | { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f }, | ||
3039 | { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 }, | ||
3040 | { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 }, | ||
3041 | { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3042 | { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3043 | { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3044 | { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3045 | { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3046 | { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3047 | { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3048 | { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3049 | { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3050 | { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3051 | { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3052 | { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3053 | { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3054 | { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3055 | { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3056 | { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3057 | { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3058 | { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3059 | { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3060 | { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3061 | { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3062 | { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3063 | { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3064 | { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3065 | { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3066 | { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3067 | { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3068 | { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3069 | { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3070 | { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3071 | { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3072 | { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3073 | { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3074 | { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3075 | { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3076 | { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3077 | { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3078 | { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3079 | { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3080 | { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3081 | { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3082 | { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3083 | { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3084 | { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3085 | { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3086 | { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3087 | { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3088 | { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, | ||
3089 | { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, | ||
3090 | { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, | ||
3091 | }; | ||
3092 | |||
3093 | static const u32 ar9280Modes_original_rxgain_9280_2[][6] = { | ||
3094 | { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, | ||
3095 | { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, | ||
3096 | { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, | ||
3097 | { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, | ||
3098 | { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, | ||
3099 | { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, | ||
3100 | { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, | ||
3101 | { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, | ||
3102 | { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, | ||
3103 | { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, | ||
3104 | { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, | ||
3105 | { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, | ||
3106 | { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, | ||
3107 | { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, | ||
3108 | { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, | ||
3109 | { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, | ||
3110 | { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, | ||
3111 | { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, | ||
3112 | { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, | ||
3113 | { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, | ||
3114 | { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, | ||
3115 | { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, | ||
3116 | { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, | ||
3117 | { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, | ||
3118 | { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, | ||
3119 | { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, | ||
3120 | { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, | ||
3121 | { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, | ||
3122 | { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, | ||
3123 | { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, | ||
3124 | { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, | ||
3125 | { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, | ||
3126 | { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, | ||
3127 | { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, | ||
3128 | { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, | ||
3129 | { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, | ||
3130 | { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, | ||
3131 | { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, | ||
3132 | { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, | ||
3133 | { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, | ||
3134 | { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, | ||
3135 | { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, | ||
3136 | { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, | ||
3137 | { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, | ||
3138 | { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, | ||
3139 | { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, | ||
3140 | { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, | ||
3141 | { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, | ||
3142 | { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, | ||
3143 | { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, | ||
3144 | { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, | ||
3145 | { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, | ||
3146 | { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, | ||
3147 | { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, | ||
3148 | { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, | ||
3149 | { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, | ||
3150 | { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, | ||
3151 | { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, | ||
3152 | { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, | ||
3153 | { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, | ||
3154 | { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, | ||
3155 | { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, | ||
3156 | { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, | ||
3157 | { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, | ||
3158 | { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, | ||
3159 | { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, | ||
3160 | { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, | ||
3161 | { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, | ||
3162 | { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, | ||
3163 | { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, | ||
3164 | { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, | ||
3165 | { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, | ||
3166 | { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, | ||
3167 | { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, | ||
3168 | { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, | ||
3169 | { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, | ||
3170 | { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, | ||
3171 | { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, | ||
3172 | { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, | ||
3173 | { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, | ||
3174 | { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, | ||
3175 | { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, | ||
3176 | { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, | ||
3177 | { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, | ||
3178 | { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, | ||
3179 | { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, | ||
3180 | { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, | ||
3181 | { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, | ||
3182 | { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, | ||
3183 | { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, | ||
3184 | { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, | ||
3185 | { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, | ||
3186 | { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, | ||
3187 | { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, | ||
3188 | { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, | ||
3189 | { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, | ||
3190 | { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, | ||
3191 | { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, | ||
3192 | { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, | ||
3193 | { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, | ||
3194 | { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, | ||
3195 | { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, | ||
3196 | { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3197 | { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3198 | { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3199 | { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3200 | { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3201 | { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3202 | { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3203 | { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3204 | { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3205 | { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3206 | { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3207 | { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3208 | { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3209 | { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3210 | { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3211 | { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3212 | { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3213 | { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3214 | { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3215 | { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3216 | { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3217 | { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3218 | { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3219 | { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3220 | { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3221 | { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, | ||
3222 | { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, | ||
3223 | { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, | ||
3224 | }; | ||
3118 | 3225 | ||
3226 | static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { | ||
3227 | { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, | ||
3228 | { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, | ||
3229 | { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, | ||
3230 | { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, | ||
3231 | { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, | ||
3232 | { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, | ||
3233 | { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, | ||
3234 | { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, | ||
3235 | { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, | ||
3236 | { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, | ||
3237 | { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, | ||
3238 | { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, | ||
3239 | { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, | ||
3240 | { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, | ||
3241 | { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, | ||
3242 | { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, | ||
3243 | { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, | ||
3244 | { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, | ||
3245 | { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, | ||
3246 | { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, | ||
3247 | { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, | ||
3248 | { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, | ||
3249 | { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, | ||
3250 | { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, | ||
3251 | { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, | ||
3252 | { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, | ||
3253 | { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, | ||
3254 | { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, | ||
3255 | { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, | ||
3256 | { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, | ||
3257 | { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, | ||
3258 | { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, | ||
3259 | { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, | ||
3260 | { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, | ||
3261 | { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, | ||
3262 | { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, | ||
3263 | { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, | ||
3264 | { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, | ||
3265 | { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, | ||
3266 | { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, | ||
3267 | { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, | ||
3268 | { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, | ||
3269 | { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, | ||
3270 | { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, | ||
3271 | { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, | ||
3272 | { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, | ||
3273 | { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, | ||
3274 | { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, | ||
3275 | { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, | ||
3276 | { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, | ||
3277 | { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, | ||
3278 | { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, | ||
3279 | { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, | ||
3280 | { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, | ||
3281 | { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, | ||
3282 | { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, | ||
3283 | { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, | ||
3284 | { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, | ||
3285 | { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 }, | ||
3286 | { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 }, | ||
3287 | { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 }, | ||
3288 | { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 }, | ||
3289 | { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 }, | ||
3290 | { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c }, | ||
3291 | { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 }, | ||
3292 | { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 }, | ||
3293 | { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 }, | ||
3294 | { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 }, | ||
3295 | { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 }, | ||
3296 | { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d }, | ||
3297 | { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 }, | ||
3298 | { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 }, | ||
3299 | { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 }, | ||
3300 | { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 }, | ||
3301 | { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a }, | ||
3302 | { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e }, | ||
3303 | { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 }, | ||
3304 | { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 }, | ||
3305 | { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 }, | ||
3306 | { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 }, | ||
3307 | { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b }, | ||
3308 | { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f }, | ||
3309 | { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 }, | ||
3310 | { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 }, | ||
3311 | { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 }, | ||
3312 | { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 }, | ||
3313 | { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b }, | ||
3314 | { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f }, | ||
3315 | { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 }, | ||
3316 | { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 }, | ||
3317 | { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3318 | { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3319 | { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3320 | { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3321 | { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3322 | { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3323 | { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3324 | { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3325 | { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3326 | { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3327 | { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3328 | { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3329 | { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3330 | { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3331 | { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3332 | { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3333 | { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3334 | { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3335 | { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3336 | { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3337 | { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3338 | { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3339 | { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3340 | { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3341 | { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3342 | { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3343 | { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3344 | { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3345 | { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3346 | { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3347 | { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3348 | { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3349 | { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3350 | { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3351 | { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3352 | { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3353 | { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3354 | { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, | ||
3355 | { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, | ||
3356 | { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, | ||
3357 | }; | ||
3358 | |||
3359 | static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { | ||
3360 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
3361 | { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, | ||
3362 | { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, | ||
3363 | { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 }, | ||
3364 | { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 }, | ||
3365 | { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 }, | ||
3366 | { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a }, | ||
3367 | { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 }, | ||
3368 | { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, | ||
3369 | { 0x0000a324, 0x00020092, 0x00020092, 0x00022411, 0x00022411, 0x00022411 }, | ||
3370 | { 0x0000a328, 0x0002410a, 0x0002410a, 0x00025413, 0x00025413, 0x00025413 }, | ||
3371 | { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00029811, 0x00029811, 0x00029811 }, | ||
3372 | { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002c813, 0x0002c813, 0x0002c813 }, | ||
3373 | { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, | ||
3374 | { 0x0000a338, 0x000321ec, 0x000321ec, 0x00035a50, 0x00035a50, 0x00035a50 }, | ||
3375 | { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, | ||
3376 | { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, | ||
3377 | { 0x0000a344, 0x000321ec, 0x000321ec, 0x00042e92, 0x00042e92, 0x00042e92 }, | ||
3378 | { 0x0000a348, 0x000321ec, 0x000321ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, | ||
3379 | { 0x0000a34c, 0x000321ec, 0x000321ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, | ||
3380 | { 0x0000a350, 0x000321ec, 0x000321ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, | ||
3381 | { 0x0000a354, 0x000321ec, 0x000321ec, 0x00053fd5, 0x00053fd5, 0x00053fd5 }, | ||
3382 | { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, | ||
3383 | { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, | ||
3384 | { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, | ||
3385 | }; | ||
3386 | |||
3387 | static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { | ||
3388 | { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, | ||
3389 | { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, | ||
3390 | { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, | ||
3391 | { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, | ||
3392 | { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, | ||
3393 | { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, | ||
3394 | { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, | ||
3395 | { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, | ||
3396 | { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, | ||
3397 | { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, | ||
3398 | { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, | ||
3399 | { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, | ||
3400 | { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, | ||
3401 | { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, | ||
3402 | { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, | ||
3403 | { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, | ||
3404 | { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, | ||
3405 | { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, | ||
3406 | { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, | ||
3407 | { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, | ||
3408 | { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, | ||
3409 | { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, | ||
3410 | { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, | ||
3411 | { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, | ||
3412 | { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, | ||
3413 | }; | ||
3119 | 3414 | ||
3120 | static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { | 3415 | static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { |
3121 | {0x00004040, 0x9248fd00 }, | 3416 | {0x00004040, 0x9248fd00 }, |
@@ -3123,23 +3418,21 @@ static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { | |||
3123 | {0x00004040, 0xa8000019 }, | 3418 | {0x00004040, 0xa8000019 }, |
3124 | {0x00004040, 0x13160820 }, | 3419 | {0x00004040, 0x13160820 }, |
3125 | {0x00004040, 0xe5980560 }, | 3420 | {0x00004040, 0xe5980560 }, |
3126 | {0x00004040, 0x401dcffc }, | 3421 | {0x00004040, 0xc01dcffc }, |
3127 | {0x00004040, 0x1aaabe40 }, | 3422 | {0x00004040, 0x1aaabe41 }, |
3128 | {0x00004040, 0xbe105554 }, | 3423 | {0x00004040, 0xbe105554 }, |
3129 | {0x00004040, 0x00043007 }, | 3424 | {0x00004040, 0x00043007 }, |
3130 | {0x00004044, 0x00000000 }, | 3425 | {0x00004044, 0x00000000 }, |
3131 | }; | 3426 | }; |
3132 | 3427 | ||
3133 | |||
3134 | |||
3135 | static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { | 3428 | static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { |
3136 | {0x00004040, 0x9248fd00 }, | 3429 | {0x00004040, 0x9248fd00 }, |
3137 | {0x00004040, 0x24924924 }, | 3430 | {0x00004040, 0x24924924 }, |
3138 | {0x00004040, 0xa8000019 }, | 3431 | {0x00004040, 0xa8000019 }, |
3139 | {0x00004040, 0x13160820 }, | 3432 | {0x00004040, 0x13160820 }, |
3140 | {0x00004040, 0xe5980560 }, | 3433 | {0x00004040, 0xe5980560 }, |
3141 | {0x00004040, 0x401dcffd }, | 3434 | {0x00004040, 0xc01dcffd }, |
3142 | {0x00004040, 0x1aaabe40 }, | 3435 | {0x00004040, 0x1aaabe41 }, |
3143 | {0x00004040, 0xbe105554 }, | 3436 | {0x00004040, 0xbe105554 }, |
3144 | {0x00004040, 0x00043007 }, | 3437 | {0x00004040, 0x00043007 }, |
3145 | {0x00004044, 0x00000000 }, | 3438 | {0x00004044, 0x00000000 }, |
diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c index c344a81e738a..36955e0b1849 100644 --- a/drivers/net/wireless/ath9k/mac.c +++ b/drivers/net/wireless/ath9k/mac.c | |||
@@ -293,8 +293,10 @@ int ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds) | |||
293 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; | 293 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; |
294 | if (ads->ds_txstatus1 & AR_Filtered) | 294 | if (ads->ds_txstatus1 & AR_Filtered) |
295 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; | 295 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; |
296 | if (ads->ds_txstatus1 & AR_FIFOUnderrun) | 296 | if (ads->ds_txstatus1 & AR_FIFOUnderrun) { |
297 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; | 297 | ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; |
298 | ath9k_hw_updatetxtriglevel(ah, true); | ||
299 | } | ||
298 | if (ads->ds_txstatus9 & AR_TxOpExceeded) | 300 | if (ads->ds_txstatus9 & AR_TxOpExceeded) |
299 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; | 301 | ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; |
300 | if (ads->ds_txstatus1 & AR_TxTimerExpired) | 302 | if (ads->ds_txstatus1 & AR_TxTimerExpired) |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index fbb2dd2373c8..437e38a3c6d7 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -14,8 +14,6 @@ | |||
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 | /* mac80211 and PCI callbacks */ | ||
18 | |||
19 | #include <linux/nl80211.h> | 17 | #include <linux/nl80211.h> |
20 | #include "core.h" | 18 | #include "core.h" |
21 | #include "reg.h" | 19 | #include "reg.h" |
@@ -40,6 +38,577 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = { | |||
40 | 38 | ||
41 | static void ath_detach(struct ath_softc *sc); | 39 | static void ath_detach(struct ath_softc *sc); |
42 | 40 | ||
41 | /* return bus cachesize in 4B word units */ | ||
42 | |||
43 | static void bus_read_cachesize(struct ath_softc *sc, int *csz) | ||
44 | { | ||
45 | u8 u8tmp; | ||
46 | |||
47 | pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, (u8 *)&u8tmp); | ||
48 | *csz = (int)u8tmp; | ||
49 | |||
50 | /* | ||
51 | * This check was put in to avoid "unplesant" consequences if | ||
52 | * the bootrom has not fully initialized all PCI devices. | ||
53 | * Sometimes the cache line size register is not set | ||
54 | */ | ||
55 | |||
56 | if (*csz == 0) | ||
57 | *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ | ||
58 | } | ||
59 | |||
60 | static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) | ||
61 | { | ||
62 | sc->sc_curmode = mode; | ||
63 | /* | ||
64 | * All protection frames are transmited at 2Mb/s for | ||
65 | * 11g, otherwise at 1Mb/s. | ||
66 | * XXX select protection rate index from rate table. | ||
67 | */ | ||
68 | sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0); | ||
69 | } | ||
70 | |||
71 | static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan) | ||
72 | { | ||
73 | if (chan->chanmode == CHANNEL_A) | ||
74 | return ATH9K_MODE_11A; | ||
75 | else if (chan->chanmode == CHANNEL_G) | ||
76 | return ATH9K_MODE_11G; | ||
77 | else if (chan->chanmode == CHANNEL_B) | ||
78 | return ATH9K_MODE_11B; | ||
79 | else if (chan->chanmode == CHANNEL_A_HT20) | ||
80 | return ATH9K_MODE_11NA_HT20; | ||
81 | else if (chan->chanmode == CHANNEL_G_HT20) | ||
82 | return ATH9K_MODE_11NG_HT20; | ||
83 | else if (chan->chanmode == CHANNEL_A_HT40PLUS) | ||
84 | return ATH9K_MODE_11NA_HT40PLUS; | ||
85 | else if (chan->chanmode == CHANNEL_A_HT40MINUS) | ||
86 | return ATH9K_MODE_11NA_HT40MINUS; | ||
87 | else if (chan->chanmode == CHANNEL_G_HT40PLUS) | ||
88 | return ATH9K_MODE_11NG_HT40PLUS; | ||
89 | else if (chan->chanmode == CHANNEL_G_HT40MINUS) | ||
90 | return ATH9K_MODE_11NG_HT40MINUS; | ||
91 | |||
92 | WARN_ON(1); /* should not get here */ | ||
93 | |||
94 | return ATH9K_MODE_11B; | ||
95 | } | ||
96 | |||
97 | static void ath_update_txpow(struct ath_softc *sc) | ||
98 | { | ||
99 | struct ath_hal *ah = sc->sc_ah; | ||
100 | u32 txpow; | ||
101 | |||
102 | if (sc->sc_curtxpow != sc->sc_config.txpowlimit) { | ||
103 | ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit); | ||
104 | /* read back in case value is clamped */ | ||
105 | ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); | ||
106 | sc->sc_curtxpow = txpow; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static u8 parse_mpdudensity(u8 mpdudensity) | ||
111 | { | ||
112 | /* | ||
113 | * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": | ||
114 | * 0 for no restriction | ||
115 | * 1 for 1/4 us | ||
116 | * 2 for 1/2 us | ||
117 | * 3 for 1 us | ||
118 | * 4 for 2 us | ||
119 | * 5 for 4 us | ||
120 | * 6 for 8 us | ||
121 | * 7 for 16 us | ||
122 | */ | ||
123 | switch (mpdudensity) { | ||
124 | case 0: | ||
125 | return 0; | ||
126 | case 1: | ||
127 | case 2: | ||
128 | case 3: | ||
129 | /* Our lower layer calculations limit our precision to | ||
130 | 1 microsecond */ | ||
131 | return 1; | ||
132 | case 4: | ||
133 | return 2; | ||
134 | case 5: | ||
135 | return 4; | ||
136 | case 6: | ||
137 | return 8; | ||
138 | case 7: | ||
139 | return 16; | ||
140 | default: | ||
141 | return 0; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) | ||
146 | { | ||
147 | struct ath_rate_table *rate_table = NULL; | ||
148 | struct ieee80211_supported_band *sband; | ||
149 | struct ieee80211_rate *rate; | ||
150 | int i, maxrates; | ||
151 | |||
152 | switch (band) { | ||
153 | case IEEE80211_BAND_2GHZ: | ||
154 | rate_table = sc->hw_rate_table[ATH9K_MODE_11G]; | ||
155 | break; | ||
156 | case IEEE80211_BAND_5GHZ: | ||
157 | rate_table = sc->hw_rate_table[ATH9K_MODE_11A]; | ||
158 | break; | ||
159 | default: | ||
160 | break; | ||
161 | } | ||
162 | |||
163 | if (rate_table == NULL) | ||
164 | return; | ||
165 | |||
166 | sband = &sc->sbands[band]; | ||
167 | rate = sc->rates[band]; | ||
168 | |||
169 | if (rate_table->rate_cnt > ATH_RATE_MAX) | ||
170 | maxrates = ATH_RATE_MAX; | ||
171 | else | ||
172 | maxrates = rate_table->rate_cnt; | ||
173 | |||
174 | for (i = 0; i < maxrates; i++) { | ||
175 | rate[i].bitrate = rate_table->info[i].ratekbps / 100; | ||
176 | rate[i].hw_value = rate_table->info[i].ratecode; | ||
177 | sband->n_bitrates++; | ||
178 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Rate: %2dMbps, ratecode: %2d\n", | ||
179 | __func__, rate[i].bitrate / 10, rate[i].hw_value); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | static int ath_setup_channels(struct ath_softc *sc) | ||
184 | { | ||
185 | struct ath_hal *ah = sc->sc_ah; | ||
186 | int nchan, i, a = 0, b = 0; | ||
187 | u8 regclassids[ATH_REGCLASSIDS_MAX]; | ||
188 | u32 nregclass = 0; | ||
189 | struct ieee80211_supported_band *band_2ghz; | ||
190 | struct ieee80211_supported_band *band_5ghz; | ||
191 | struct ieee80211_channel *chan_2ghz; | ||
192 | struct ieee80211_channel *chan_5ghz; | ||
193 | struct ath9k_channel *c; | ||
194 | |||
195 | /* Fill in ah->ah_channels */ | ||
196 | if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan, | ||
197 | regclassids, ATH_REGCLASSIDS_MAX, | ||
198 | &nregclass, CTRY_DEFAULT, false, 1)) { | ||
199 | u32 rd = ah->ah_currentRD; | ||
200 | DPRINTF(sc, ATH_DBG_FATAL, | ||
201 | "%s: unable to collect channel list; " | ||
202 | "regdomain likely %u country code %u\n", | ||
203 | __func__, rd, CTRY_DEFAULT); | ||
204 | return -EINVAL; | ||
205 | } | ||
206 | |||
207 | band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ]; | ||
208 | band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ]; | ||
209 | chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ]; | ||
210 | chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ]; | ||
211 | |||
212 | for (i = 0; i < nchan; i++) { | ||
213 | c = &ah->ah_channels[i]; | ||
214 | if (IS_CHAN_2GHZ(c)) { | ||
215 | chan_2ghz[a].band = IEEE80211_BAND_2GHZ; | ||
216 | chan_2ghz[a].center_freq = c->channel; | ||
217 | chan_2ghz[a].max_power = c->maxTxPower; | ||
218 | |||
219 | if (c->privFlags & CHANNEL_DISALLOW_ADHOC) | ||
220 | chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS; | ||
221 | if (c->channelFlags & CHANNEL_PASSIVE) | ||
222 | chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
223 | |||
224 | band_2ghz->n_channels = ++a; | ||
225 | |||
226 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: 2MHz channel: %d, " | ||
227 | "channelFlags: 0x%x\n", | ||
228 | __func__, c->channel, c->channelFlags); | ||
229 | } else if (IS_CHAN_5GHZ(c)) { | ||
230 | chan_5ghz[b].band = IEEE80211_BAND_5GHZ; | ||
231 | chan_5ghz[b].center_freq = c->channel; | ||
232 | chan_5ghz[b].max_power = c->maxTxPower; | ||
233 | |||
234 | if (c->privFlags & CHANNEL_DISALLOW_ADHOC) | ||
235 | chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS; | ||
236 | if (c->channelFlags & CHANNEL_PASSIVE) | ||
237 | chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN; | ||
238 | |||
239 | band_5ghz->n_channels = ++b; | ||
240 | |||
241 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: 5MHz channel: %d, " | ||
242 | "channelFlags: 0x%x\n", | ||
243 | __func__, c->channel, c->channelFlags); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Set/change channels. If the channel is really being changed, it's done | ||
252 | * by reseting the chip. To accomplish this we must first cleanup any pending | ||
253 | * DMA, then restart stuff. | ||
254 | */ | ||
255 | static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan) | ||
256 | { | ||
257 | struct ath_hal *ah = sc->sc_ah; | ||
258 | bool fastcc = true, stopped; | ||
259 | |||
260 | if (sc->sc_flags & SC_OP_INVALID) | ||
261 | return -EIO; | ||
262 | |||
263 | if (hchan->channel != sc->sc_ah->ah_curchan->channel || | ||
264 | hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags || | ||
265 | (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) || | ||
266 | (sc->sc_flags & SC_OP_FULL_RESET)) { | ||
267 | int status; | ||
268 | /* | ||
269 | * This is only performed if the channel settings have | ||
270 | * actually changed. | ||
271 | * | ||
272 | * To switch channels clear any pending DMA operations; | ||
273 | * wait long enough for the RX fifo to drain, reset the | ||
274 | * hardware at the new frequency, and then re-enable | ||
275 | * the relevant bits of the h/w. | ||
276 | */ | ||
277 | ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */ | ||
278 | ath_draintxq(sc, false); /* clear pending tx frames */ | ||
279 | stopped = ath_stoprecv(sc); /* turn off frame recv */ | ||
280 | |||
281 | /* XXX: do not flush receive queue here. We don't want | ||
282 | * to flush data frames already in queue because of | ||
283 | * changing channel. */ | ||
284 | |||
285 | if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) | ||
286 | fastcc = false; | ||
287 | |||
288 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
289 | "%s: (%u MHz) -> (%u MHz), cflags:%x, chanwidth: %d\n", | ||
290 | __func__, | ||
291 | sc->sc_ah->ah_curchan->channel, | ||
292 | hchan->channel, hchan->channelFlags, sc->tx_chan_width); | ||
293 | |||
294 | spin_lock_bh(&sc->sc_resetlock); | ||
295 | if (!ath9k_hw_reset(ah, hchan, sc->tx_chan_width, | ||
296 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
297 | sc->sc_ht_extprotspacing, fastcc, &status)) { | ||
298 | DPRINTF(sc, ATH_DBG_FATAL, | ||
299 | "%s: unable to reset channel %u (%uMhz) " | ||
300 | "flags 0x%x hal status %u\n", __func__, | ||
301 | ath9k_hw_mhz2ieee(ah, hchan->channel, | ||
302 | hchan->channelFlags), | ||
303 | hchan->channel, hchan->channelFlags, status); | ||
304 | spin_unlock_bh(&sc->sc_resetlock); | ||
305 | return -EIO; | ||
306 | } | ||
307 | spin_unlock_bh(&sc->sc_resetlock); | ||
308 | |||
309 | sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE; | ||
310 | sc->sc_flags &= ~SC_OP_FULL_RESET; | ||
311 | |||
312 | if (ath_startrecv(sc) != 0) { | ||
313 | DPRINTF(sc, ATH_DBG_FATAL, | ||
314 | "%s: unable to restart recv logic\n", __func__); | ||
315 | return -EIO; | ||
316 | } | ||
317 | |||
318 | ath_setcurmode(sc, ath_chan2mode(hchan)); | ||
319 | ath_update_txpow(sc); | ||
320 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
321 | } | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * This routine performs the periodic noise floor calibration function | ||
327 | * that is used to adjust and optimize the chip performance. This | ||
328 | * takes environmental changes (location, temperature) into account. | ||
329 | * When the task is complete, it reschedules itself depending on the | ||
330 | * appropriate interval that was calculated. | ||
331 | */ | ||
332 | static void ath_ani_calibrate(unsigned long data) | ||
333 | { | ||
334 | struct ath_softc *sc; | ||
335 | struct ath_hal *ah; | ||
336 | bool longcal = false; | ||
337 | bool shortcal = false; | ||
338 | bool aniflag = false; | ||
339 | unsigned int timestamp = jiffies_to_msecs(jiffies); | ||
340 | u32 cal_interval; | ||
341 | |||
342 | sc = (struct ath_softc *)data; | ||
343 | ah = sc->sc_ah; | ||
344 | |||
345 | /* | ||
346 | * don't calibrate when we're scanning. | ||
347 | * we are most likely not on our home channel. | ||
348 | */ | ||
349 | if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC) | ||
350 | return; | ||
351 | |||
352 | /* Long calibration runs independently of short calibration. */ | ||
353 | if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) { | ||
354 | longcal = true; | ||
355 | DPRINTF(sc, ATH_DBG_ANI, "%s: longcal @%lu\n", | ||
356 | __func__, jiffies); | ||
357 | sc->sc_ani.sc_longcal_timer = timestamp; | ||
358 | } | ||
359 | |||
360 | /* Short calibration applies only while sc_caldone is false */ | ||
361 | if (!sc->sc_ani.sc_caldone) { | ||
362 | if ((timestamp - sc->sc_ani.sc_shortcal_timer) >= | ||
363 | ATH_SHORT_CALINTERVAL) { | ||
364 | shortcal = true; | ||
365 | DPRINTF(sc, ATH_DBG_ANI, "%s: shortcal @%lu\n", | ||
366 | __func__, jiffies); | ||
367 | sc->sc_ani.sc_shortcal_timer = timestamp; | ||
368 | sc->sc_ani.sc_resetcal_timer = timestamp; | ||
369 | } | ||
370 | } else { | ||
371 | if ((timestamp - sc->sc_ani.sc_resetcal_timer) >= | ||
372 | ATH_RESTART_CALINTERVAL) { | ||
373 | ath9k_hw_reset_calvalid(ah, ah->ah_curchan, | ||
374 | &sc->sc_ani.sc_caldone); | ||
375 | if (sc->sc_ani.sc_caldone) | ||
376 | sc->sc_ani.sc_resetcal_timer = timestamp; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | /* Verify whether we must check ANI */ | ||
381 | if ((timestamp - sc->sc_ani.sc_checkani_timer) >= | ||
382 | ATH_ANI_POLLINTERVAL) { | ||
383 | aniflag = true; | ||
384 | sc->sc_ani.sc_checkani_timer = timestamp; | ||
385 | } | ||
386 | |||
387 | /* Skip all processing if there's nothing to do. */ | ||
388 | if (longcal || shortcal || aniflag) { | ||
389 | /* Call ANI routine if necessary */ | ||
390 | if (aniflag) | ||
391 | ath9k_hw_ani_monitor(ah, &sc->sc_halstats, | ||
392 | ah->ah_curchan); | ||
393 | |||
394 | /* Perform calibration if necessary */ | ||
395 | if (longcal || shortcal) { | ||
396 | bool iscaldone = false; | ||
397 | |||
398 | if (ath9k_hw_calibrate(ah, ah->ah_curchan, | ||
399 | sc->sc_rx_chainmask, longcal, | ||
400 | &iscaldone)) { | ||
401 | if (longcal) | ||
402 | sc->sc_ani.sc_noise_floor = | ||
403 | ath9k_hw_getchan_noise(ah, | ||
404 | ah->ah_curchan); | ||
405 | |||
406 | DPRINTF(sc, ATH_DBG_ANI, | ||
407 | "%s: calibrate chan %u/%x nf: %d\n", | ||
408 | __func__, | ||
409 | ah->ah_curchan->channel, | ||
410 | ah->ah_curchan->channelFlags, | ||
411 | sc->sc_ani.sc_noise_floor); | ||
412 | } else { | ||
413 | DPRINTF(sc, ATH_DBG_ANY, | ||
414 | "%s: calibrate chan %u/%x failed\n", | ||
415 | __func__, | ||
416 | ah->ah_curchan->channel, | ||
417 | ah->ah_curchan->channelFlags); | ||
418 | } | ||
419 | sc->sc_ani.sc_caldone = iscaldone; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | * Set timer interval based on previous results. | ||
425 | * The interval must be the shortest necessary to satisfy ANI, | ||
426 | * short calibration and long calibration. | ||
427 | */ | ||
428 | |||
429 | cal_interval = ATH_ANI_POLLINTERVAL; | ||
430 | if (!sc->sc_ani.sc_caldone) | ||
431 | cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL); | ||
432 | |||
433 | mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | ||
434 | } | ||
435 | |||
436 | /* | ||
437 | * Update tx/rx chainmask. For legacy association, | ||
438 | * hard code chainmask to 1x1, for 11n association, use | ||
439 | * the chainmask configuration. | ||
440 | */ | ||
441 | static void ath_update_chainmask(struct ath_softc *sc, int is_ht) | ||
442 | { | ||
443 | sc->sc_flags |= SC_OP_CHAINMASK_UPDATE; | ||
444 | if (is_ht) { | ||
445 | sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask; | ||
446 | sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask; | ||
447 | } else { | ||
448 | sc->sc_tx_chainmask = 1; | ||
449 | sc->sc_rx_chainmask = 1; | ||
450 | } | ||
451 | |||
452 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: tx chmask: %d, rx chmask: %d\n", | ||
453 | __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask); | ||
454 | } | ||
455 | |||
456 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) | ||
457 | { | ||
458 | struct ath_node *an; | ||
459 | |||
460 | an = (struct ath_node *)sta->drv_priv; | ||
461 | |||
462 | if (sc->sc_flags & SC_OP_TXAGGR) | ||
463 | ath_tx_node_init(sc, an); | ||
464 | |||
465 | an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + | ||
466 | sta->ht_cap.ampdu_factor); | ||
467 | an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); | ||
468 | } | ||
469 | |||
470 | static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | ||
471 | { | ||
472 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | ||
473 | |||
474 | if (sc->sc_flags & SC_OP_TXAGGR) | ||
475 | ath_tx_node_cleanup(sc, an); | ||
476 | } | ||
477 | |||
478 | static void ath9k_tasklet(unsigned long data) | ||
479 | { | ||
480 | struct ath_softc *sc = (struct ath_softc *)data; | ||
481 | u32 status = sc->sc_intrstatus; | ||
482 | |||
483 | if (status & ATH9K_INT_FATAL) { | ||
484 | /* need a chip reset */ | ||
485 | ath_reset(sc, false); | ||
486 | return; | ||
487 | } else { | ||
488 | |||
489 | if (status & | ||
490 | (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { | ||
491 | spin_lock_bh(&sc->sc_rxflushlock); | ||
492 | ath_rx_tasklet(sc, 0); | ||
493 | spin_unlock_bh(&sc->sc_rxflushlock); | ||
494 | } | ||
495 | /* XXX: optimize this */ | ||
496 | if (status & ATH9K_INT_TX) | ||
497 | ath_tx_tasklet(sc); | ||
498 | } | ||
499 | |||
500 | /* re-enable hardware interrupt */ | ||
501 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask); | ||
502 | } | ||
503 | |||
504 | static irqreturn_t ath_isr(int irq, void *dev) | ||
505 | { | ||
506 | struct ath_softc *sc = dev; | ||
507 | struct ath_hal *ah = sc->sc_ah; | ||
508 | enum ath9k_int status; | ||
509 | bool sched = false; | ||
510 | |||
511 | do { | ||
512 | if (sc->sc_flags & SC_OP_INVALID) { | ||
513 | /* | ||
514 | * The hardware is not ready/present, don't | ||
515 | * touch anything. Note this can happen early | ||
516 | * on if the IRQ is shared. | ||
517 | */ | ||
518 | return IRQ_NONE; | ||
519 | } | ||
520 | if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */ | ||
521 | return IRQ_NONE; | ||
522 | } | ||
523 | |||
524 | /* | ||
525 | * Figure out the reason(s) for the interrupt. Note | ||
526 | * that the hal returns a pseudo-ISR that may include | ||
527 | * bits we haven't explicitly enabled so we mask the | ||
528 | * value to insure we only process bits we requested. | ||
529 | */ | ||
530 | ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ | ||
531 | |||
532 | status &= sc->sc_imask; /* discard unasked-for bits */ | ||
533 | |||
534 | /* | ||
535 | * If there are no status bits set, then this interrupt was not | ||
536 | * for me (should have been caught above). | ||
537 | */ | ||
538 | if (!status) | ||
539 | return IRQ_NONE; | ||
540 | |||
541 | sc->sc_intrstatus = status; | ||
542 | |||
543 | if (status & ATH9K_INT_FATAL) { | ||
544 | /* need a chip reset */ | ||
545 | sched = true; | ||
546 | } else if (status & ATH9K_INT_RXORN) { | ||
547 | /* need a chip reset */ | ||
548 | sched = true; | ||
549 | } else { | ||
550 | if (status & ATH9K_INT_SWBA) { | ||
551 | /* schedule a tasklet for beacon handling */ | ||
552 | tasklet_schedule(&sc->bcon_tasklet); | ||
553 | } | ||
554 | if (status & ATH9K_INT_RXEOL) { | ||
555 | /* | ||
556 | * NB: the hardware should re-read the link when | ||
557 | * RXE bit is written, but it doesn't work | ||
558 | * at least on older hardware revs. | ||
559 | */ | ||
560 | sched = true; | ||
561 | } | ||
562 | |||
563 | if (status & ATH9K_INT_TXURN) | ||
564 | /* bump tx trigger level */ | ||
565 | ath9k_hw_updatetxtriglevel(ah, true); | ||
566 | /* XXX: optimize this */ | ||
567 | if (status & ATH9K_INT_RX) | ||
568 | sched = true; | ||
569 | if (status & ATH9K_INT_TX) | ||
570 | sched = true; | ||
571 | if (status & ATH9K_INT_BMISS) | ||
572 | sched = true; | ||
573 | /* carrier sense timeout */ | ||
574 | if (status & ATH9K_INT_CST) | ||
575 | sched = true; | ||
576 | if (status & ATH9K_INT_MIB) { | ||
577 | /* | ||
578 | * Disable interrupts until we service the MIB | ||
579 | * interrupt; otherwise it will continue to | ||
580 | * fire. | ||
581 | */ | ||
582 | ath9k_hw_set_interrupts(ah, 0); | ||
583 | /* | ||
584 | * Let the hal handle the event. We assume | ||
585 | * it will clear whatever condition caused | ||
586 | * the interrupt. | ||
587 | */ | ||
588 | ath9k_hw_procmibevent(ah, &sc->sc_halstats); | ||
589 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
590 | } | ||
591 | if (status & ATH9K_INT_TIM_TIMER) { | ||
592 | if (!(ah->ah_caps.hw_caps & | ||
593 | ATH9K_HW_CAP_AUTOSLEEP)) { | ||
594 | /* Clear RxAbort bit so that we can | ||
595 | * receive frames */ | ||
596 | ath9k_hw_setrxabort(ah, 0); | ||
597 | sched = true; | ||
598 | } | ||
599 | } | ||
600 | } | ||
601 | } while (0); | ||
602 | |||
603 | if (sched) { | ||
604 | /* turn off every interrupt except SWBA */ | ||
605 | ath9k_hw_set_interrupts(ah, (sc->sc_imask & ATH9K_INT_SWBA)); | ||
606 | tasklet_schedule(&sc->intr_tq); | ||
607 | } | ||
608 | |||
609 | return IRQ_HANDLED; | ||
610 | } | ||
611 | |||
43 | static int ath_get_channel(struct ath_softc *sc, | 612 | static int ath_get_channel(struct ath_softc *sc, |
44 | struct ieee80211_channel *chan) | 613 | struct ieee80211_channel *chan) |
45 | { | 614 | { |
@@ -54,11 +623,13 @@ static int ath_get_channel(struct ath_softc *sc, | |||
54 | } | 623 | } |
55 | 624 | ||
56 | static u32 ath_get_extchanmode(struct ath_softc *sc, | 625 | static u32 ath_get_extchanmode(struct ath_softc *sc, |
57 | struct ieee80211_channel *chan) | 626 | struct ieee80211_channel *chan, |
627 | struct ieee80211_bss_conf *bss_conf) | ||
58 | { | 628 | { |
59 | u32 chanmode = 0; | 629 | u32 chanmode = 0; |
60 | u8 ext_chan_offset = sc->sc_ht_info.ext_chan_offset; | 630 | u8 ext_chan_offset = bss_conf->ht.secondary_channel_offset; |
61 | enum ath9k_ht_macmode tx_chan_width = sc->sc_ht_info.tx_chan_width; | 631 | enum ath9k_ht_macmode tx_chan_width = (bss_conf->ht.width_40_ok) ? |
632 | ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; | ||
62 | 633 | ||
63 | switch (chan->band) { | 634 | switch (chan->band) { |
64 | case IEEE80211_BAND_2GHZ: | 635 | case IEEE80211_BAND_2GHZ: |
@@ -90,6 +661,23 @@ static u32 ath_get_extchanmode(struct ath_softc *sc, | |||
90 | return chanmode; | 661 | return chanmode; |
91 | } | 662 | } |
92 | 663 | ||
664 | static void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot) | ||
665 | { | ||
666 | ath9k_hw_keyreset(sc->sc_ah, keyix); | ||
667 | if (freeslot) | ||
668 | clear_bit(keyix, sc->sc_keymap); | ||
669 | } | ||
670 | |||
671 | static int ath_keyset(struct ath_softc *sc, u16 keyix, | ||
672 | struct ath9k_keyval *hk, const u8 mac[ETH_ALEN]) | ||
673 | { | ||
674 | bool status; | ||
675 | |||
676 | status = ath9k_hw_set_keycache_entry(sc->sc_ah, | ||
677 | keyix, hk, mac, false); | ||
678 | |||
679 | return status != false; | ||
680 | } | ||
93 | 681 | ||
94 | static int ath_setkey_tkip(struct ath_softc *sc, | 682 | static int ath_setkey_tkip(struct ath_softc *sc, |
95 | struct ieee80211_key_conf *key, | 683 | struct ieee80211_key_conf *key, |
@@ -236,82 +824,20 @@ static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info) | |||
236 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 824 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
237 | } | 825 | } |
238 | 826 | ||
239 | static int ath_rate2idx(struct ath_softc *sc, int rate) | ||
240 | { | ||
241 | int i = 0, cur_band, n_rates; | ||
242 | struct ieee80211_hw *hw = sc->hw; | ||
243 | |||
244 | cur_band = hw->conf.channel->band; | ||
245 | n_rates = sc->sbands[cur_band].n_bitrates; | ||
246 | |||
247 | for (i = 0; i < n_rates; i++) { | ||
248 | if (sc->sbands[cur_band].bitrates[i].bitrate == rate) | ||
249 | break; | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * NB:mac80211 validates rx rate index against the supported legacy rate | ||
254 | * index only (should be done against ht rates also), return the highest | ||
255 | * legacy rate index for rx rate which does not match any one of the | ||
256 | * supported basic and extended rates to make mac80211 happy. | ||
257 | * The following hack will be cleaned up once the issue with | ||
258 | * the rx rate index validation in mac80211 is fixed. | ||
259 | */ | ||
260 | if (i == n_rates) | ||
261 | return n_rates - 1; | ||
262 | return i; | ||
263 | } | ||
264 | |||
265 | static void ath9k_rx_prepare(struct ath_softc *sc, | ||
266 | struct sk_buff *skb, | ||
267 | struct ath_recv_status *status, | ||
268 | struct ieee80211_rx_status *rx_status) | ||
269 | { | ||
270 | struct ieee80211_hw *hw = sc->hw; | ||
271 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
272 | |||
273 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); | ||
274 | |||
275 | rx_status->mactime = status->tsf; | ||
276 | rx_status->band = curchan->band; | ||
277 | rx_status->freq = curchan->center_freq; | ||
278 | rx_status->noise = sc->sc_ani.sc_noise_floor; | ||
279 | rx_status->signal = rx_status->noise + status->rssi; | ||
280 | rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100)); | ||
281 | rx_status->antenna = status->antenna; | ||
282 | |||
283 | /* at 45 you will be able to use MCS 15 reliably. A more elaborate | ||
284 | * scheme can be used here but it requires tables of SNR/throughput for | ||
285 | * each possible mode used. */ | ||
286 | rx_status->qual = status->rssi * 100 / 45; | ||
287 | |||
288 | /* rssi can be more than 45 though, anything above that | ||
289 | * should be considered at 100% */ | ||
290 | if (rx_status->qual > 100) | ||
291 | rx_status->qual = 100; | ||
292 | |||
293 | if (status->flags & ATH_RX_MIC_ERROR) | ||
294 | rx_status->flag |= RX_FLAG_MMIC_ERROR; | ||
295 | if (status->flags & ATH_RX_FCS_ERROR) | ||
296 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
297 | |||
298 | rx_status->flag |= RX_FLAG_TSFT; | ||
299 | } | ||
300 | |||
301 | static void ath9k_ht_conf(struct ath_softc *sc, | 827 | static void ath9k_ht_conf(struct ath_softc *sc, |
302 | struct ieee80211_bss_conf *bss_conf) | 828 | struct ieee80211_bss_conf *bss_conf) |
303 | { | 829 | { |
304 | struct ath_ht_info *ht_info = &sc->sc_ht_info; | ||
305 | |||
306 | if (sc->hw->conf.ht.enabled) { | 830 | if (sc->hw->conf.ht.enabled) { |
307 | ht_info->ext_chan_offset = bss_conf->ht.secondary_channel_offset; | ||
308 | |||
309 | if (bss_conf->ht.width_40_ok) | 831 | if (bss_conf->ht.width_40_ok) |
310 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; | 832 | sc->tx_chan_width = ATH9K_HT_MACMODE_2040; |
311 | else | 833 | else |
312 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; | 834 | sc->tx_chan_width = ATH9K_HT_MACMODE_20; |
313 | 835 | ||
314 | ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); | 836 | ath9k_hw_set11nmac2040(sc->sc_ah, sc->tx_chan_width); |
837 | |||
838 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
839 | "%s: BSS Changed HT, chanwidth: %d\n", | ||
840 | __func__, sc->tx_chan_width); | ||
315 | } | 841 | } |
316 | } | 842 | } |
317 | 843 | ||
@@ -365,120 +891,34 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
365 | return; | 891 | return; |
366 | } | 892 | } |
367 | 893 | ||
368 | if (hw->conf.ht.enabled) | 894 | if (hw->conf.ht.enabled) { |
369 | sc->sc_ah->ah_channels[pos].chanmode = | 895 | sc->sc_ah->ah_channels[pos].chanmode = |
370 | ath_get_extchanmode(sc, curchan); | 896 | ath_get_extchanmode(sc, curchan, bss_conf); |
371 | else | 897 | |
898 | if (bss_conf->ht.width_40_ok) | ||
899 | sc->tx_chan_width = ATH9K_HT_MACMODE_2040; | ||
900 | else | ||
901 | sc->tx_chan_width = ATH9K_HT_MACMODE_20; | ||
902 | } else { | ||
372 | sc->sc_ah->ah_channels[pos].chanmode = | 903 | sc->sc_ah->ah_channels[pos].chanmode = |
373 | (curchan->band == IEEE80211_BAND_2GHZ) ? | 904 | (curchan->band == IEEE80211_BAND_2GHZ) ? |
374 | CHANNEL_G : CHANNEL_A; | 905 | CHANNEL_G : CHANNEL_A; |
906 | } | ||
375 | 907 | ||
376 | /* set h/w channel */ | 908 | /* set h/w channel */ |
377 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | 909 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) |
378 | DPRINTF(sc, ATH_DBG_FATAL, | 910 | DPRINTF(sc, ATH_DBG_FATAL, |
379 | "%s: Unable to set channel\n", | 911 | "%s: Unable to set channel\n", __func__); |
380 | __func__); | ||
381 | |||
382 | ath_rate_newstate(sc, avp); | ||
383 | /* Update ratectrl about the new state */ | ||
384 | ath_rc_node_update(hw, avp->rc_node); | ||
385 | |||
386 | /* Start ANI */ | 912 | /* Start ANI */ |
387 | mod_timer(&sc->sc_ani.timer, | 913 | mod_timer(&sc->sc_ani.timer, |
388 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 914 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); |
389 | 915 | ||
390 | } else { | 916 | } else { |
391 | DPRINTF(sc, ATH_DBG_CONFIG, | 917 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info DISSOC\n", __func__); |
392 | "%s: Bss Info DISSOC\n", __func__); | ||
393 | sc->sc_curaid = 0; | 918 | sc->sc_curaid = 0; |
394 | } | 919 | } |
395 | } | 920 | } |
396 | 921 | ||
397 | void ath_get_beaconconfig(struct ath_softc *sc, | ||
398 | int if_id, | ||
399 | struct ath_beacon_config *conf) | ||
400 | { | ||
401 | struct ieee80211_hw *hw = sc->hw; | ||
402 | |||
403 | /* fill in beacon config data */ | ||
404 | |||
405 | conf->beacon_interval = hw->conf.beacon_int; | ||
406 | conf->listen_interval = 100; | ||
407 | conf->dtim_count = 1; | ||
408 | conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; | ||
409 | } | ||
410 | |||
411 | void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | ||
412 | struct ath_xmit_status *tx_status) | ||
413 | { | ||
414 | struct ieee80211_hw *hw = sc->hw; | ||
415 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
416 | |||
417 | DPRINTF(sc, ATH_DBG_XMIT, | ||
418 | "%s: TX complete: skb: %p\n", __func__, skb); | ||
419 | |||
420 | ieee80211_tx_info_clear_status(tx_info); | ||
421 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || | ||
422 | tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | ||
423 | /* free driver's private data area of tx_info, XXX: HACK! */ | ||
424 | if (tx_info->control.vif != NULL) | ||
425 | kfree(tx_info->control.vif); | ||
426 | tx_info->control.vif = NULL; | ||
427 | } | ||
428 | |||
429 | if (tx_status->flags & ATH_TX_BAR) { | ||
430 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
431 | tx_status->flags &= ~ATH_TX_BAR; | ||
432 | } | ||
433 | |||
434 | if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { | ||
435 | /* Frame was ACKed */ | ||
436 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | ||
437 | } | ||
438 | |||
439 | tx_info->status.rates[0].count = tx_status->retries + 1; | ||
440 | |||
441 | ieee80211_tx_status(hw, skb); | ||
442 | } | ||
443 | |||
444 | int _ath_rx_indicate(struct ath_softc *sc, | ||
445 | struct sk_buff *skb, | ||
446 | struct ath_recv_status *status, | ||
447 | u16 keyix) | ||
448 | { | ||
449 | struct ieee80211_hw *hw = sc->hw; | ||
450 | struct ieee80211_rx_status rx_status; | ||
451 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
452 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
453 | int padsize; | ||
454 | |||
455 | /* see if any padding is done by the hw and remove it */ | ||
456 | if (hdrlen & 3) { | ||
457 | padsize = hdrlen % 4; | ||
458 | memmove(skb->data + padsize, skb->data, hdrlen); | ||
459 | skb_pull(skb, padsize); | ||
460 | } | ||
461 | |||
462 | /* Prepare rx status */ | ||
463 | ath9k_rx_prepare(sc, skb, status, &rx_status); | ||
464 | |||
465 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && | ||
466 | !(status->flags & ATH_RX_DECRYPT_ERROR)) { | ||
467 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
468 | } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) | ||
469 | && !(status->flags & ATH_RX_DECRYPT_ERROR) | ||
470 | && skb->len >= hdrlen + 4) { | ||
471 | keyix = skb->data[hdrlen + 3] >> 6; | ||
472 | |||
473 | if (test_bit(keyix, sc->sc_keymap)) | ||
474 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
475 | } | ||
476 | |||
477 | __ieee80211_rx(hw, skb, &rx_status); | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | /********************************/ | 922 | /********************************/ |
483 | /* LED functions */ | 923 | /* LED functions */ |
484 | /********************************/ | 924 | /********************************/ |
@@ -594,7 +1034,7 @@ fail: | |||
594 | ath_deinit_leds(sc); | 1034 | ath_deinit_leds(sc); |
595 | } | 1035 | } |
596 | 1036 | ||
597 | #ifdef CONFIG_RFKILL | 1037 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
598 | 1038 | ||
599 | /*******************/ | 1039 | /*******************/ |
600 | /* Rfkill */ | 1040 | /* Rfkill */ |
@@ -607,7 +1047,7 @@ static void ath_radio_enable(struct ath_softc *sc) | |||
607 | 1047 | ||
608 | spin_lock_bh(&sc->sc_resetlock); | 1048 | spin_lock_bh(&sc->sc_resetlock); |
609 | if (!ath9k_hw_reset(ah, ah->ah_curchan, | 1049 | if (!ath9k_hw_reset(ah, ah->ah_curchan, |
610 | sc->sc_ht_info.tx_chan_width, | 1050 | sc->tx_chan_width, |
611 | sc->sc_tx_chainmask, | 1051 | sc->sc_tx_chainmask, |
612 | sc->sc_rx_chainmask, | 1052 | sc->sc_rx_chainmask, |
613 | sc->sc_ht_extprotspacing, | 1053 | sc->sc_ht_extprotspacing, |
@@ -665,7 +1105,7 @@ static void ath_radio_disable(struct ath_softc *sc) | |||
665 | 1105 | ||
666 | spin_lock_bh(&sc->sc_resetlock); | 1106 | spin_lock_bh(&sc->sc_resetlock); |
667 | if (!ath9k_hw_reset(ah, ah->ah_curchan, | 1107 | if (!ath9k_hw_reset(ah, ah->ah_curchan, |
668 | sc->sc_ht_info.tx_chan_width, | 1108 | sc->tx_chan_width, |
669 | sc->sc_tx_chainmask, | 1109 | sc->sc_tx_chainmask, |
670 | sc->sc_rx_chainmask, | 1110 | sc->sc_rx_chainmask, |
671 | sc->sc_ht_extprotspacing, | 1111 | sc->sc_ht_extprotspacing, |
@@ -810,9 +1250,9 @@ static int ath_start_rfkill_poll(struct ath_softc *sc) | |||
810 | rfkill_free(sc->rf_kill.rfkill); | 1250 | rfkill_free(sc->rf_kill.rfkill); |
811 | 1251 | ||
812 | /* Deinitialize the device */ | 1252 | /* Deinitialize the device */ |
1253 | ath_detach(sc); | ||
813 | if (sc->pdev->irq) | 1254 | if (sc->pdev->irq) |
814 | free_irq(sc->pdev->irq, sc); | 1255 | free_irq(sc->pdev->irq, sc); |
815 | ath_detach(sc); | ||
816 | pci_iounmap(sc->pdev, sc->mem); | 1256 | pci_iounmap(sc->pdev, sc->mem); |
817 | pci_release_region(sc->pdev, 0); | 1257 | pci_release_region(sc->pdev, 0); |
818 | pci_disable_device(sc->pdev); | 1258 | pci_disable_device(sc->pdev); |
@@ -834,15 +1274,14 @@ static void ath_detach(struct ath_softc *sc) | |||
834 | 1274 | ||
835 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); | 1275 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__); |
836 | 1276 | ||
837 | ieee80211_unregister_hw(hw); | 1277 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
838 | |||
839 | ath_deinit_leds(sc); | ||
840 | |||
841 | #ifdef CONFIG_RFKILL | ||
842 | ath_deinit_rfkill(sc); | 1278 | ath_deinit_rfkill(sc); |
843 | #endif | 1279 | #endif |
1280 | ath_deinit_leds(sc); | ||
1281 | |||
1282 | ieee80211_unregister_hw(hw); | ||
1283 | |||
844 | ath_rate_control_unregister(); | 1284 | ath_rate_control_unregister(); |
845 | ath_rate_detach(sc->sc_rc); | ||
846 | 1285 | ||
847 | ath_rx_cleanup(sc); | 1286 | ath_rx_cleanup(sc); |
848 | ath_tx_cleanup(sc); | 1287 | ath_tx_cleanup(sc); |
@@ -861,6 +1300,244 @@ static void ath_detach(struct ath_softc *sc) | |||
861 | ath9k_hw_detach(sc->sc_ah); | 1300 | ath9k_hw_detach(sc->sc_ah); |
862 | } | 1301 | } |
863 | 1302 | ||
1303 | static int ath_init(u16 devid, struct ath_softc *sc) | ||
1304 | { | ||
1305 | struct ath_hal *ah = NULL; | ||
1306 | int status; | ||
1307 | int error = 0, i; | ||
1308 | int csz = 0; | ||
1309 | |||
1310 | /* XXX: hardware will not be ready until ath_open() being called */ | ||
1311 | sc->sc_flags |= SC_OP_INVALID; | ||
1312 | sc->sc_debug = DBG_DEFAULT; | ||
1313 | |||
1314 | spin_lock_init(&sc->sc_resetlock); | ||
1315 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | ||
1316 | tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, | ||
1317 | (unsigned long)sc); | ||
1318 | |||
1319 | /* | ||
1320 | * Cache line size is used to size and align various | ||
1321 | * structures used to communicate with the hardware. | ||
1322 | */ | ||
1323 | bus_read_cachesize(sc, &csz); | ||
1324 | /* XXX assert csz is non-zero */ | ||
1325 | sc->sc_cachelsz = csz << 2; /* convert to bytes */ | ||
1326 | |||
1327 | ah = ath9k_hw_attach(devid, sc, sc->mem, &status); | ||
1328 | if (ah == NULL) { | ||
1329 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1330 | "%s: unable to attach hardware; HAL status %u\n", | ||
1331 | __func__, status); | ||
1332 | error = -ENXIO; | ||
1333 | goto bad; | ||
1334 | } | ||
1335 | sc->sc_ah = ah; | ||
1336 | |||
1337 | /* Get the hardware key cache size. */ | ||
1338 | sc->sc_keymax = ah->ah_caps.keycache_size; | ||
1339 | if (sc->sc_keymax > ATH_KEYMAX) { | ||
1340 | DPRINTF(sc, ATH_DBG_KEYCACHE, | ||
1341 | "%s: Warning, using only %u entries in %u key cache\n", | ||
1342 | __func__, ATH_KEYMAX, sc->sc_keymax); | ||
1343 | sc->sc_keymax = ATH_KEYMAX; | ||
1344 | } | ||
1345 | |||
1346 | /* | ||
1347 | * Reset the key cache since some parts do not | ||
1348 | * reset the contents on initial power up. | ||
1349 | */ | ||
1350 | for (i = 0; i < sc->sc_keymax; i++) | ||
1351 | ath9k_hw_keyreset(ah, (u16) i); | ||
1352 | /* | ||
1353 | * Mark key cache slots associated with global keys | ||
1354 | * as in use. If we knew TKIP was not to be used we | ||
1355 | * could leave the +32, +64, and +32+64 slots free. | ||
1356 | * XXX only for splitmic. | ||
1357 | */ | ||
1358 | for (i = 0; i < IEEE80211_WEP_NKID; i++) { | ||
1359 | set_bit(i, sc->sc_keymap); | ||
1360 | set_bit(i + 32, sc->sc_keymap); | ||
1361 | set_bit(i + 64, sc->sc_keymap); | ||
1362 | set_bit(i + 32 + 64, sc->sc_keymap); | ||
1363 | } | ||
1364 | |||
1365 | /* Collect the channel list using the default country code */ | ||
1366 | |||
1367 | error = ath_setup_channels(sc); | ||
1368 | if (error) | ||
1369 | goto bad; | ||
1370 | |||
1371 | /* default to MONITOR mode */ | ||
1372 | sc->sc_ah->ah_opmode = ATH9K_M_MONITOR; | ||
1373 | |||
1374 | /* Setup rate tables */ | ||
1375 | |||
1376 | ath_rate_attach(sc); | ||
1377 | ath_setup_rates(sc, IEEE80211_BAND_2GHZ); | ||
1378 | ath_setup_rates(sc, IEEE80211_BAND_5GHZ); | ||
1379 | |||
1380 | /* | ||
1381 | * Allocate hardware transmit queues: one queue for | ||
1382 | * beacon frames and one data queue for each QoS | ||
1383 | * priority. Note that the hal handles reseting | ||
1384 | * these queues at the needed time. | ||
1385 | */ | ||
1386 | sc->sc_bhalq = ath_beaconq_setup(ah); | ||
1387 | if (sc->sc_bhalq == -1) { | ||
1388 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1389 | "%s: unable to setup a beacon xmit queue\n", __func__); | ||
1390 | error = -EIO; | ||
1391 | goto bad2; | ||
1392 | } | ||
1393 | sc->sc_cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | ||
1394 | if (sc->sc_cabq == NULL) { | ||
1395 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1396 | "%s: unable to setup CAB xmit queue\n", __func__); | ||
1397 | error = -EIO; | ||
1398 | goto bad2; | ||
1399 | } | ||
1400 | |||
1401 | sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME; | ||
1402 | ath_cabq_update(sc); | ||
1403 | |||
1404 | for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++) | ||
1405 | sc->sc_haltype2q[i] = -1; | ||
1406 | |||
1407 | /* Setup data queues */ | ||
1408 | /* NB: ensure BK queue is the lowest priority h/w queue */ | ||
1409 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { | ||
1410 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1411 | "%s: unable to setup xmit queue for BK traffic\n", | ||
1412 | __func__); | ||
1413 | error = -EIO; | ||
1414 | goto bad2; | ||
1415 | } | ||
1416 | |||
1417 | if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { | ||
1418 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1419 | "%s: unable to setup xmit queue for BE traffic\n", | ||
1420 | __func__); | ||
1421 | error = -EIO; | ||
1422 | goto bad2; | ||
1423 | } | ||
1424 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { | ||
1425 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1426 | "%s: unable to setup xmit queue for VI traffic\n", | ||
1427 | __func__); | ||
1428 | error = -EIO; | ||
1429 | goto bad2; | ||
1430 | } | ||
1431 | if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { | ||
1432 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1433 | "%s: unable to setup xmit queue for VO traffic\n", | ||
1434 | __func__); | ||
1435 | error = -EIO; | ||
1436 | goto bad2; | ||
1437 | } | ||
1438 | |||
1439 | /* Initializes the noise floor to a reasonable default value. | ||
1440 | * Later on this will be updated during ANI processing. */ | ||
1441 | |||
1442 | sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR; | ||
1443 | setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc); | ||
1444 | |||
1445 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1446 | ATH9K_CIPHER_TKIP, NULL)) { | ||
1447 | /* | ||
1448 | * Whether we should enable h/w TKIP MIC. | ||
1449 | * XXX: if we don't support WME TKIP MIC, then we wouldn't | ||
1450 | * report WMM capable, so it's always safe to turn on | ||
1451 | * TKIP MIC in this case. | ||
1452 | */ | ||
1453 | ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, | ||
1454 | 0, 1, NULL); | ||
1455 | } | ||
1456 | |||
1457 | /* | ||
1458 | * Check whether the separate key cache entries | ||
1459 | * are required to handle both tx+rx MIC keys. | ||
1460 | * With split mic keys the number of stations is limited | ||
1461 | * to 27 otherwise 59. | ||
1462 | */ | ||
1463 | if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1464 | ATH9K_CIPHER_TKIP, NULL) | ||
1465 | && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, | ||
1466 | ATH9K_CIPHER_MIC, NULL) | ||
1467 | && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, | ||
1468 | 0, NULL)) | ||
1469 | sc->sc_splitmic = 1; | ||
1470 | |||
1471 | /* turn on mcast key search if possible */ | ||
1472 | if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) | ||
1473 | (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, | ||
1474 | 1, NULL); | ||
1475 | |||
1476 | sc->sc_config.txpowlimit = ATH_TXPOWER_MAX; | ||
1477 | sc->sc_config.txpowlimit_override = 0; | ||
1478 | |||
1479 | /* 11n Capabilities */ | ||
1480 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { | ||
1481 | sc->sc_flags |= SC_OP_TXAGGR; | ||
1482 | sc->sc_flags |= SC_OP_RXAGGR; | ||
1483 | } | ||
1484 | |||
1485 | sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask; | ||
1486 | sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask; | ||
1487 | |||
1488 | ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); | ||
1489 | sc->sc_defant = ath9k_hw_getdefantenna(ah); | ||
1490 | |||
1491 | ath9k_hw_getmac(ah, sc->sc_myaddr); | ||
1492 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) { | ||
1493 | ath9k_hw_getbssidmask(ah, sc->sc_bssidmask); | ||
1494 | ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask); | ||
1495 | ath9k_hw_setbssidmask(ah, sc->sc_bssidmask); | ||
1496 | } | ||
1497 | |||
1498 | sc->sc_slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ | ||
1499 | |||
1500 | /* initialize beacon slots */ | ||
1501 | for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++) | ||
1502 | sc->sc_bslot[i] = ATH_IF_ID_ANY; | ||
1503 | |||
1504 | /* save MISC configurations */ | ||
1505 | sc->sc_config.swBeaconProcess = 1; | ||
1506 | |||
1507 | #ifdef CONFIG_SLOW_ANT_DIV | ||
1508 | /* range is 40 - 255, we use something in the middle */ | ||
1509 | ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127); | ||
1510 | #endif | ||
1511 | |||
1512 | /* setup channels and rates */ | ||
1513 | |||
1514 | sc->sbands[IEEE80211_BAND_2GHZ].channels = | ||
1515 | sc->channels[IEEE80211_BAND_2GHZ]; | ||
1516 | sc->sbands[IEEE80211_BAND_2GHZ].bitrates = | ||
1517 | sc->rates[IEEE80211_BAND_2GHZ]; | ||
1518 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | ||
1519 | |||
1520 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) { | ||
1521 | sc->sbands[IEEE80211_BAND_5GHZ].channels = | ||
1522 | sc->channels[IEEE80211_BAND_5GHZ]; | ||
1523 | sc->sbands[IEEE80211_BAND_5GHZ].bitrates = | ||
1524 | sc->rates[IEEE80211_BAND_5GHZ]; | ||
1525 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | ||
1526 | } | ||
1527 | |||
1528 | return 0; | ||
1529 | bad2: | ||
1530 | /* cleanup tx queues */ | ||
1531 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
1532 | if (ATH_TXQ_SETUP(sc, i)) | ||
1533 | ath_tx_cleanupq(sc, &sc->sc_txq[i]); | ||
1534 | bad: | ||
1535 | if (ah) | ||
1536 | ath9k_hw_detach(ah); | ||
1537 | |||
1538 | return error; | ||
1539 | } | ||
1540 | |||
864 | static int ath_attach(u16 devid, struct ath_softc *sc) | 1541 | static int ath_attach(u16 devid, struct ath_softc *sc) |
865 | { | 1542 | { |
866 | struct ieee80211_hw *hw = sc->hw; | 1543 | struct ieee80211_hw *hw = sc->hw; |
@@ -887,6 +1564,8 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
887 | BIT(NL80211_IFTYPE_ADHOC); | 1564 | BIT(NL80211_IFTYPE_ADHOC); |
888 | 1565 | ||
889 | hw->queues = 4; | 1566 | hw->queues = 4; |
1567 | hw->max_rates = 4; | ||
1568 | hw->max_rate_tries = ATH_11N_TXMAXTRY; | ||
890 | hw->sta_data_size = sizeof(struct ath_node); | 1569 | hw->sta_data_size = sizeof(struct ath_node); |
891 | hw->vif_data_size = sizeof(struct ath_vap); | 1570 | hw->vif_data_size = sizeof(struct ath_vap); |
892 | 1571 | ||
@@ -912,16 +1591,16 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
912 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 1591 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
913 | &sc->sbands[IEEE80211_BAND_5GHZ]; | 1592 | &sc->sbands[IEEE80211_BAND_5GHZ]; |
914 | 1593 | ||
915 | error = ieee80211_register_hw(hw); | 1594 | /* initialize tx/rx engine */ |
916 | if (error != 0) { | 1595 | error = ath_tx_init(sc, ATH_TXBUF); |
917 | ath_rate_control_unregister(); | 1596 | if (error != 0) |
918 | goto bad; | 1597 | goto detach; |
919 | } | ||
920 | 1598 | ||
921 | /* Initialize LED control */ | 1599 | error = ath_rx_init(sc, ATH_RXBUF); |
922 | ath_init_leds(sc); | 1600 | if (error != 0) |
1601 | goto detach; | ||
923 | 1602 | ||
924 | #ifdef CONFIG_RFKILL | 1603 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
925 | /* Initialze h/w Rfkill */ | 1604 | /* Initialze h/w Rfkill */ |
926 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | 1605 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
927 | INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); | 1606 | INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll); |
@@ -931,15 +1610,14 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
931 | goto detach; | 1610 | goto detach; |
932 | #endif | 1611 | #endif |
933 | 1612 | ||
934 | /* initialize tx/rx engine */ | 1613 | error = ieee80211_register_hw(hw); |
935 | 1614 | if (error != 0) { | |
936 | error = ath_tx_init(sc, ATH_TXBUF); | 1615 | ath_rate_control_unregister(); |
937 | if (error != 0) | 1616 | goto bad; |
938 | goto detach; | 1617 | } |
939 | 1618 | ||
940 | error = ath_rx_init(sc, ATH_RXBUF); | 1619 | /* Initialize LED control */ |
941 | if (error != 0) | 1620 | ath_init_leds(sc); |
942 | goto detach; | ||
943 | 1621 | ||
944 | return 0; | 1622 | return 0; |
945 | detach: | 1623 | detach: |
@@ -948,41 +1626,351 @@ bad: | |||
948 | return error; | 1626 | return error; |
949 | } | 1627 | } |
950 | 1628 | ||
1629 | int ath_reset(struct ath_softc *sc, bool retry_tx) | ||
1630 | { | ||
1631 | struct ath_hal *ah = sc->sc_ah; | ||
1632 | int status; | ||
1633 | int error = 0; | ||
1634 | |||
1635 | ath9k_hw_set_interrupts(ah, 0); | ||
1636 | ath_draintxq(sc, retry_tx); | ||
1637 | ath_stoprecv(sc); | ||
1638 | ath_flushrecv(sc); | ||
1639 | |||
1640 | spin_lock_bh(&sc->sc_resetlock); | ||
1641 | if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan, | ||
1642 | sc->tx_chan_width, | ||
1643 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
1644 | sc->sc_ht_extprotspacing, false, &status)) { | ||
1645 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1646 | "%s: unable to reset hardware; hal status %u\n", | ||
1647 | __func__, status); | ||
1648 | error = -EIO; | ||
1649 | } | ||
1650 | spin_unlock_bh(&sc->sc_resetlock); | ||
1651 | |||
1652 | if (ath_startrecv(sc) != 0) | ||
1653 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1654 | "%s: unable to start recv logic\n", __func__); | ||
1655 | |||
1656 | /* | ||
1657 | * We may be doing a reset in response to a request | ||
1658 | * that changes the channel so update any state that | ||
1659 | * might change as a result. | ||
1660 | */ | ||
1661 | ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan)); | ||
1662 | |||
1663 | ath_update_txpow(sc); | ||
1664 | |||
1665 | if (sc->sc_flags & SC_OP_BEACONS) | ||
1666 | ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */ | ||
1667 | |||
1668 | ath9k_hw_set_interrupts(ah, sc->sc_imask); | ||
1669 | |||
1670 | if (retry_tx) { | ||
1671 | int i; | ||
1672 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
1673 | if (ATH_TXQ_SETUP(sc, i)) { | ||
1674 | spin_lock_bh(&sc->sc_txq[i].axq_lock); | ||
1675 | ath_txq_schedule(sc, &sc->sc_txq[i]); | ||
1676 | spin_unlock_bh(&sc->sc_txq[i].axq_lock); | ||
1677 | } | ||
1678 | } | ||
1679 | } | ||
1680 | |||
1681 | return error; | ||
1682 | } | ||
1683 | |||
1684 | /* | ||
1685 | * This function will allocate both the DMA descriptor structure, and the | ||
1686 | * buffers it contains. These are used to contain the descriptors used | ||
1687 | * by the system. | ||
1688 | */ | ||
1689 | int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | ||
1690 | struct list_head *head, const char *name, | ||
1691 | int nbuf, int ndesc) | ||
1692 | { | ||
1693 | #define DS2PHYS(_dd, _ds) \ | ||
1694 | ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) | ||
1695 | #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) | ||
1696 | #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) | ||
1697 | |||
1698 | struct ath_desc *ds; | ||
1699 | struct ath_buf *bf; | ||
1700 | int i, bsize, error; | ||
1701 | |||
1702 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA: %u buffers %u desc/buf\n", | ||
1703 | __func__, name, nbuf, ndesc); | ||
1704 | |||
1705 | /* ath_desc must be a multiple of DWORDs */ | ||
1706 | if ((sizeof(struct ath_desc) % 4) != 0) { | ||
1707 | DPRINTF(sc, ATH_DBG_FATAL, "%s: ath_desc not DWORD aligned\n", | ||
1708 | __func__); | ||
1709 | ASSERT((sizeof(struct ath_desc) % 4) == 0); | ||
1710 | error = -ENOMEM; | ||
1711 | goto fail; | ||
1712 | } | ||
1713 | |||
1714 | dd->dd_name = name; | ||
1715 | dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; | ||
1716 | |||
1717 | /* | ||
1718 | * Need additional DMA memory because we can't use | ||
1719 | * descriptors that cross the 4K page boundary. Assume | ||
1720 | * one skipped descriptor per 4K page. | ||
1721 | */ | ||
1722 | if (!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
1723 | u32 ndesc_skipped = | ||
1724 | ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); | ||
1725 | u32 dma_len; | ||
1726 | |||
1727 | while (ndesc_skipped) { | ||
1728 | dma_len = ndesc_skipped * sizeof(struct ath_desc); | ||
1729 | dd->dd_desc_len += dma_len; | ||
1730 | |||
1731 | ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); | ||
1732 | }; | ||
1733 | } | ||
1734 | |||
1735 | /* allocate descriptors */ | ||
1736 | dd->dd_desc = pci_alloc_consistent(sc->pdev, | ||
1737 | dd->dd_desc_len, | ||
1738 | &dd->dd_desc_paddr); | ||
1739 | if (dd->dd_desc == NULL) { | ||
1740 | error = -ENOMEM; | ||
1741 | goto fail; | ||
1742 | } | ||
1743 | ds = dd->dd_desc; | ||
1744 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA map: %p (%u) -> %llx (%u)\n", | ||
1745 | __func__, dd->dd_name, ds, (u32) dd->dd_desc_len, | ||
1746 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | ||
1747 | |||
1748 | /* allocate buffers */ | ||
1749 | bsize = sizeof(struct ath_buf) * nbuf; | ||
1750 | bf = kmalloc(bsize, GFP_KERNEL); | ||
1751 | if (bf == NULL) { | ||
1752 | error = -ENOMEM; | ||
1753 | goto fail2; | ||
1754 | } | ||
1755 | memset(bf, 0, bsize); | ||
1756 | dd->dd_bufptr = bf; | ||
1757 | |||
1758 | INIT_LIST_HEAD(head); | ||
1759 | for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { | ||
1760 | bf->bf_desc = ds; | ||
1761 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
1762 | |||
1763 | if (!(sc->sc_ah->ah_caps.hw_caps & | ||
1764 | ATH9K_HW_CAP_4KB_SPLITTRANS)) { | ||
1765 | /* | ||
1766 | * Skip descriptor addresses which can cause 4KB | ||
1767 | * boundary crossing (addr + length) with a 32 dword | ||
1768 | * descriptor fetch. | ||
1769 | */ | ||
1770 | while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { | ||
1771 | ASSERT((caddr_t) bf->bf_desc < | ||
1772 | ((caddr_t) dd->dd_desc + | ||
1773 | dd->dd_desc_len)); | ||
1774 | |||
1775 | ds += ndesc; | ||
1776 | bf->bf_desc = ds; | ||
1777 | bf->bf_daddr = DS2PHYS(dd, ds); | ||
1778 | } | ||
1779 | } | ||
1780 | list_add_tail(&bf->list, head); | ||
1781 | } | ||
1782 | return 0; | ||
1783 | fail2: | ||
1784 | pci_free_consistent(sc->pdev, | ||
1785 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); | ||
1786 | fail: | ||
1787 | memset(dd, 0, sizeof(*dd)); | ||
1788 | return error; | ||
1789 | #undef ATH_DESC_4KB_BOUND_CHECK | ||
1790 | #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED | ||
1791 | #undef DS2PHYS | ||
1792 | } | ||
1793 | |||
1794 | void ath_descdma_cleanup(struct ath_softc *sc, | ||
1795 | struct ath_descdma *dd, | ||
1796 | struct list_head *head) | ||
1797 | { | ||
1798 | pci_free_consistent(sc->pdev, | ||
1799 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); | ||
1800 | |||
1801 | INIT_LIST_HEAD(head); | ||
1802 | kfree(dd->dd_bufptr); | ||
1803 | memset(dd, 0, sizeof(*dd)); | ||
1804 | } | ||
1805 | |||
1806 | int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) | ||
1807 | { | ||
1808 | int qnum; | ||
1809 | |||
1810 | switch (queue) { | ||
1811 | case 0: | ||
1812 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO]; | ||
1813 | break; | ||
1814 | case 1: | ||
1815 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI]; | ||
1816 | break; | ||
1817 | case 2: | ||
1818 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; | ||
1819 | break; | ||
1820 | case 3: | ||
1821 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK]; | ||
1822 | break; | ||
1823 | default: | ||
1824 | qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE]; | ||
1825 | break; | ||
1826 | } | ||
1827 | |||
1828 | return qnum; | ||
1829 | } | ||
1830 | |||
1831 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) | ||
1832 | { | ||
1833 | int qnum; | ||
1834 | |||
1835 | switch (queue) { | ||
1836 | case ATH9K_WME_AC_VO: | ||
1837 | qnum = 0; | ||
1838 | break; | ||
1839 | case ATH9K_WME_AC_VI: | ||
1840 | qnum = 1; | ||
1841 | break; | ||
1842 | case ATH9K_WME_AC_BE: | ||
1843 | qnum = 2; | ||
1844 | break; | ||
1845 | case ATH9K_WME_AC_BK: | ||
1846 | qnum = 3; | ||
1847 | break; | ||
1848 | default: | ||
1849 | qnum = -1; | ||
1850 | break; | ||
1851 | } | ||
1852 | |||
1853 | return qnum; | ||
1854 | } | ||
1855 | |||
1856 | /**********************/ | ||
1857 | /* mac80211 callbacks */ | ||
1858 | /**********************/ | ||
1859 | |||
951 | static int ath9k_start(struct ieee80211_hw *hw) | 1860 | static int ath9k_start(struct ieee80211_hw *hw) |
952 | { | 1861 | { |
953 | struct ath_softc *sc = hw->priv; | 1862 | struct ath_softc *sc = hw->priv; |
954 | struct ieee80211_channel *curchan = hw->conf.channel; | 1863 | struct ieee80211_channel *curchan = hw->conf.channel; |
955 | int error = 0, pos; | 1864 | struct ath9k_channel *init_channel; |
1865 | int error = 0, pos, status; | ||
956 | 1866 | ||
957 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with " | 1867 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with " |
958 | "initial channel: %d MHz\n", __func__, curchan->center_freq); | 1868 | "initial channel: %d MHz\n", __func__, curchan->center_freq); |
959 | 1869 | ||
960 | memset(&sc->sc_ht_info, 0, sizeof(struct ath_ht_info)); | ||
961 | |||
962 | /* setup initial channel */ | 1870 | /* setup initial channel */ |
963 | 1871 | ||
964 | pos = ath_get_channel(sc, curchan); | 1872 | pos = ath_get_channel(sc, curchan); |
965 | if (pos == -1) { | 1873 | if (pos == -1) { |
966 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); | 1874 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); |
967 | error = -EINVAL; | 1875 | error = -EINVAL; |
968 | goto exit; | 1876 | goto error; |
969 | } | 1877 | } |
970 | 1878 | ||
1879 | sc->tx_chan_width = ATH9K_HT_MACMODE_20; | ||
971 | sc->sc_ah->ah_channels[pos].chanmode = | 1880 | sc->sc_ah->ah_channels[pos].chanmode = |
972 | (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; | 1881 | (curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A; |
1882 | init_channel = &sc->sc_ah->ah_channels[pos]; | ||
1883 | |||
1884 | /* Reset SERDES registers */ | ||
1885 | ath9k_hw_configpcipowersave(sc->sc_ah, 0); | ||
973 | 1886 | ||
974 | error = ath_open(sc, &sc->sc_ah->ah_channels[pos]); | 1887 | /* |
975 | if (error) { | 1888 | * The basic interface to setting the hardware in a good |
1889 | * state is ``reset''. On return the hardware is known to | ||
1890 | * be powered up and with interrupts disabled. This must | ||
1891 | * be followed by initialization of the appropriate bits | ||
1892 | * and then setup of the interrupt mask. | ||
1893 | */ | ||
1894 | spin_lock_bh(&sc->sc_resetlock); | ||
1895 | if (!ath9k_hw_reset(sc->sc_ah, init_channel, | ||
1896 | sc->tx_chan_width, | ||
1897 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | ||
1898 | sc->sc_ht_extprotspacing, false, &status)) { | ||
976 | DPRINTF(sc, ATH_DBG_FATAL, | 1899 | DPRINTF(sc, ATH_DBG_FATAL, |
977 | "%s: Unable to complete ath_open\n", __func__); | 1900 | "%s: unable to reset hardware; hal status %u " |
978 | goto exit; | 1901 | "(freq %u flags 0x%x)\n", __func__, status, |
1902 | init_channel->channel, init_channel->channelFlags); | ||
1903 | error = -EIO; | ||
1904 | spin_unlock_bh(&sc->sc_resetlock); | ||
1905 | goto error; | ||
979 | } | 1906 | } |
1907 | spin_unlock_bh(&sc->sc_resetlock); | ||
1908 | |||
1909 | /* | ||
1910 | * This is needed only to setup initial state | ||
1911 | * but it's best done after a reset. | ||
1912 | */ | ||
1913 | ath_update_txpow(sc); | ||
1914 | |||
1915 | /* | ||
1916 | * Setup the hardware after reset: | ||
1917 | * The receive engine is set going. | ||
1918 | * Frame transmit is handled entirely | ||
1919 | * in the frame output path; there's nothing to do | ||
1920 | * here except setup the interrupt mask. | ||
1921 | */ | ||
1922 | if (ath_startrecv(sc) != 0) { | ||
1923 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1924 | "%s: unable to start recv logic\n", __func__); | ||
1925 | error = -EIO; | ||
1926 | goto error; | ||
1927 | } | ||
1928 | |||
1929 | /* Setup our intr mask. */ | ||
1930 | sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX | ||
1931 | | ATH9K_INT_RXEOL | ATH9K_INT_RXORN | ||
1932 | | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; | ||
1933 | |||
1934 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_GTT) | ||
1935 | sc->sc_imask |= ATH9K_INT_GTT; | ||
1936 | |||
1937 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) | ||
1938 | sc->sc_imask |= ATH9K_INT_CST; | ||
1939 | |||
1940 | /* | ||
1941 | * Enable MIB interrupts when there are hardware phy counters. | ||
1942 | * Note we only do this (at the moment) for station mode. | ||
1943 | */ | ||
1944 | if (ath9k_hw_phycounters(sc->sc_ah) && | ||
1945 | ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || | ||
1946 | (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))) | ||
1947 | sc->sc_imask |= ATH9K_INT_MIB; | ||
1948 | /* | ||
1949 | * Some hardware processes the TIM IE and fires an | ||
1950 | * interrupt when the TIM bit is set. For hardware | ||
1951 | * that does, if not overridden by configuration, | ||
1952 | * enable the TIM interrupt when operating as station. | ||
1953 | */ | ||
1954 | if ((sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) && | ||
1955 | (sc->sc_ah->ah_opmode == ATH9K_M_STA) && | ||
1956 | !sc->sc_config.swBeaconProcess) | ||
1957 | sc->sc_imask |= ATH9K_INT_TIM; | ||
1958 | |||
1959 | ath_setcurmode(sc, ath_chan2mode(init_channel)); | ||
1960 | |||
1961 | sc->sc_flags &= ~SC_OP_INVALID; | ||
1962 | |||
1963 | /* Disable BMISS interrupt when we're not associated */ | ||
1964 | sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | ||
1965 | ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask); | ||
980 | 1966 | ||
981 | #ifdef CONFIG_RFKILL | 1967 | ieee80211_wake_queues(sc->hw); |
1968 | |||
1969 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | ||
982 | error = ath_start_rfkill_poll(sc); | 1970 | error = ath_start_rfkill_poll(sc); |
983 | #endif | 1971 | #endif |
984 | 1972 | ||
985 | exit: | 1973 | error: |
986 | return error; | 1974 | return error; |
987 | } | 1975 | } |
988 | 1976 | ||
@@ -1049,7 +2037,30 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1049 | return; | 2037 | return; |
1050 | } | 2038 | } |
1051 | 2039 | ||
1052 | ath_stop(sc); | 2040 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Cleaning up\n", __func__); |
2041 | |||
2042 | ieee80211_stop_queues(sc->hw); | ||
2043 | |||
2044 | /* make sure h/w will not generate any interrupt | ||
2045 | * before setting the invalid flag. */ | ||
2046 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | ||
2047 | |||
2048 | if (!(sc->sc_flags & SC_OP_INVALID)) { | ||
2049 | ath_draintxq(sc, false); | ||
2050 | ath_stoprecv(sc); | ||
2051 | ath9k_hw_phy_disable(sc->sc_ah); | ||
2052 | } else | ||
2053 | sc->sc_rxlink = NULL; | ||
2054 | |||
2055 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | ||
2056 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
2057 | cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); | ||
2058 | #endif | ||
2059 | /* disable HAL and put h/w to sleep */ | ||
2060 | ath9k_hw_disable(sc->sc_ah); | ||
2061 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); | ||
2062 | |||
2063 | sc->sc_flags |= SC_OP_INVALID; | ||
1053 | 2064 | ||
1054 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); | 2065 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__); |
1055 | } | 2066 | } |
@@ -1100,10 +2111,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1100 | /* Set the device opmode */ | 2111 | /* Set the device opmode */ |
1101 | sc->sc_ah->ah_opmode = ic_opmode; | 2112 | sc->sc_ah->ah_opmode = ic_opmode; |
1102 | 2113 | ||
1103 | /* default VAP configuration */ | ||
1104 | avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE; | ||
1105 | avp->av_config.av_fixed_retryset = 0x03030303; | ||
1106 | |||
1107 | if (conf->type == NL80211_IFTYPE_AP) { | 2114 | if (conf->type == NL80211_IFTYPE_AP) { |
1108 | /* TODO: is this a suitable place to start ANI for AP mode? */ | 2115 | /* TODO: is this a suitable place to start ANI for AP mode? */ |
1109 | /* Start ANI */ | 2116 | /* Start ANI */ |
@@ -1144,39 +2151,37 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1144 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 2151 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
1145 | { | 2152 | { |
1146 | struct ath_softc *sc = hw->priv; | 2153 | struct ath_softc *sc = hw->priv; |
1147 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
1148 | struct ieee80211_conf *conf = &hw->conf; | 2154 | struct ieee80211_conf *conf = &hw->conf; |
1149 | int pos; | ||
1150 | |||
1151 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", | ||
1152 | __func__, | ||
1153 | curchan->center_freq); | ||
1154 | 2155 | ||
1155 | /* Update chainmask */ | 2156 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
1156 | ath_update_chainmask(sc, conf->ht.enabled); | 2157 | struct ieee80211_channel *curchan = hw->conf.channel; |
2158 | int pos; | ||
1157 | 2159 | ||
1158 | pos = ath_get_channel(sc, curchan); | 2160 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", |
1159 | if (pos == -1) { | 2161 | __func__, curchan->center_freq); |
1160 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); | ||
1161 | return -EINVAL; | ||
1162 | } | ||
1163 | 2162 | ||
1164 | sc->sc_ah->ah_channels[pos].chanmode = | 2163 | pos = ath_get_channel(sc, curchan); |
1165 | (curchan->band == IEEE80211_BAND_2GHZ) ? | 2164 | if (pos == -1) { |
1166 | CHANNEL_G : CHANNEL_A; | 2165 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); |
2166 | return -EINVAL; | ||
2167 | } | ||
1167 | 2168 | ||
1168 | if (sc->sc_curaid && hw->conf.ht.enabled) | 2169 | sc->tx_chan_width = ATH9K_HT_MACMODE_20; |
1169 | sc->sc_ah->ah_channels[pos].chanmode = | 2170 | sc->sc_ah->ah_channels[pos].chanmode = |
1170 | ath_get_extchanmode(sc, curchan); | 2171 | (curchan->band == IEEE80211_BAND_2GHZ) ? |
2172 | CHANNEL_G : CHANNEL_A; | ||
2173 | |||
2174 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | ||
2175 | DPRINTF(sc, ATH_DBG_FATAL, | ||
2176 | "%s: Unable to set channel\n", __func__); | ||
2177 | } | ||
2178 | |||
2179 | if (changed & IEEE80211_CONF_CHANGE_HT) | ||
2180 | ath_update_chainmask(sc, conf->ht.enabled); | ||
1171 | 2181 | ||
1172 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 2182 | if (changed & IEEE80211_CONF_CHANGE_POWER) |
1173 | sc->sc_config.txpowlimit = 2 * conf->power_level; | 2183 | sc->sc_config.txpowlimit = 2 * conf->power_level; |
1174 | 2184 | ||
1175 | /* set h/w channel */ | ||
1176 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | ||
1177 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n", | ||
1178 | __func__); | ||
1179 | |||
1180 | return 0; | 2185 | return 0; |
1181 | } | 2186 | } |
1182 | 2187 | ||
@@ -1206,9 +2211,6 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
1206 | switch (vif->type) { | 2211 | switch (vif->type) { |
1207 | case NL80211_IFTYPE_STATION: | 2212 | case NL80211_IFTYPE_STATION: |
1208 | case NL80211_IFTYPE_ADHOC: | 2213 | case NL80211_IFTYPE_ADHOC: |
1209 | /* Update ratectrl about the new state */ | ||
1210 | ath_rate_newstate(sc, avp); | ||
1211 | |||
1212 | /* Set BSSID */ | 2214 | /* Set BSSID */ |
1213 | memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN); | 2215 | memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN); |
1214 | sc->sc_curaid = 0; | 2216 | sc->sc_curaid = 0; |
@@ -1419,11 +2421,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1419 | sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; | 2421 | sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; |
1420 | } | 2422 | } |
1421 | 2423 | ||
1422 | if (changed & BSS_CHANGED_HT) { | 2424 | if (changed & BSS_CHANGED_HT) |
1423 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT\n", | ||
1424 | __func__); | ||
1425 | ath9k_ht_conf(sc, bss_conf); | 2425 | ath9k_ht_conf(sc, bss_conf); |
1426 | } | ||
1427 | 2426 | ||
1428 | if (changed & BSS_CHANGED_ASSOC) { | 2427 | if (changed & BSS_CHANGED_ASSOC) { |
1429 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n", | 2428 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n", |
@@ -1592,10 +2591,18 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1592 | if (pci_enable_device(pdev)) | 2591 | if (pci_enable_device(pdev)) |
1593 | return -EIO; | 2592 | return -EIO; |
1594 | 2593 | ||
1595 | /* XXX 32-bit addressing only */ | 2594 | ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
1596 | if (pci_set_dma_mask(pdev, 0xffffffff)) { | 2595 | |
1597 | printk(KERN_ERR "ath_pci: 32-bit DMA not available\n"); | 2596 | if (ret) { |
1598 | ret = -ENODEV; | 2597 | printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); |
2598 | goto bad; | ||
2599 | } | ||
2600 | |||
2601 | ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); | ||
2602 | |||
2603 | if (ret) { | ||
2604 | printk(KERN_ERR "ath9k: 32-bit DMA consistent " | ||
2605 | "DMA enable faled\n"); | ||
1599 | goto bad; | 2606 | goto bad; |
1600 | } | 2607 | } |
1601 | 2608 | ||
@@ -1722,7 +2729,7 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
1722 | 2729 | ||
1723 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | 2730 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); |
1724 | 2731 | ||
1725 | #ifdef CONFIG_RFKILL | 2732 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
1726 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | 2733 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
1727 | cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); | 2734 | cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll); |
1728 | #endif | 2735 | #endif |
@@ -1759,7 +2766,7 @@ static int ath_pci_resume(struct pci_dev *pdev) | |||
1759 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 2766 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
1760 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | 2767 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); |
1761 | 2768 | ||
1762 | #ifdef CONFIG_RFKILL | 2769 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
1763 | /* | 2770 | /* |
1764 | * check the h/w rfkill state on resume | 2771 | * check the h/w rfkill state on resume |
1765 | * and start the rfkill poll timer | 2772 | * and start the rfkill poll timer |
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 517992d14808..93dfea897ff2 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -15,143 +15,136 @@ | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | /* | ||
19 | * Atheros rate control algorithm | ||
20 | */ | ||
21 | |||
22 | #include "core.h" | 18 | #include "core.h" |
23 | /* FIXME: remove this include! */ | ||
24 | #include "../net/mac80211/rate.h" | ||
25 | |||
26 | static u32 tx_triglevel_max; | ||
27 | 19 | ||
28 | static struct ath_rate_table ar5416_11na_ratetable = { | 20 | static struct ath_rate_table ar5416_11na_ratetable = { |
29 | 42, | 21 | 42, |
22 | {0}, | ||
30 | { | 23 | { |
31 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | 24 | { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ |
32 | 5400, 0x0b, 0x00, 12, | 25 | 5400, 0x0b, 0x00, 12, |
33 | 0, 2, 1, 0, 0, 0, 0, 0 }, | 26 | 0, 2, 1, 0, 0, 0, 0, 0 }, |
34 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | 27 | { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ |
35 | 7800, 0x0f, 0x00, 18, | 28 | 7800, 0x0f, 0x00, 18, |
36 | 0, 3, 1, 1, 1, 1, 1, 0 }, | 29 | 0, 3, 1, 1, 1, 1, 1, 0 }, |
37 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | 30 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ |
38 | 10000, 0x0a, 0x00, 24, | 31 | 10000, 0x0a, 0x00, 24, |
39 | 2, 4, 2, 2, 2, 2, 2, 0 }, | 32 | 2, 4, 2, 2, 2, 2, 2, 0 }, |
40 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | 33 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ |
41 | 13900, 0x0e, 0x00, 36, | 34 | 13900, 0x0e, 0x00, 36, |
42 | 2, 6, 2, 3, 3, 3, 3, 0 }, | 35 | 2, 6, 2, 3, 3, 3, 3, 0 }, |
43 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | 36 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ |
44 | 17300, 0x09, 0x00, 48, | 37 | 17300, 0x09, 0x00, 48, |
45 | 4, 10, 3, 4, 4, 4, 4, 0 }, | 38 | 4, 10, 3, 4, 4, 4, 4, 0 }, |
46 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | 39 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ |
47 | 23000, 0x0d, 0x00, 72, | 40 | 23000, 0x0d, 0x00, 72, |
48 | 4, 14, 3, 5, 5, 5, 5, 0 }, | 41 | 4, 14, 3, 5, 5, 5, 5, 0 }, |
49 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | 42 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ |
50 | 27400, 0x08, 0x00, 96, | 43 | 27400, 0x08, 0x00, 96, |
51 | 4, 20, 3, 6, 6, 6, 6, 0 }, | 44 | 4, 20, 3, 6, 6, 6, 6, 0 }, |
52 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | 45 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
53 | 29300, 0x0c, 0x00, 108, | 46 | 29300, 0x0c, 0x00, 108, |
54 | 4, 23, 3, 7, 7, 7, 7, 0 }, | 47 | 4, 23, 3, 7, 7, 7, 7, 0 }, |
55 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | 48 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ |
56 | 6400, 0x80, 0x00, 0, | 49 | 6400, 0x80, 0x00, 0, |
57 | 0, 2, 3, 8, 24, 8, 24, 3216 }, | 50 | 0, 2, 3, 8, 24, 8, 24, 3216 }, |
58 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */ | 51 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ |
59 | 12700, 0x81, 0x00, 1, | 52 | 12700, 0x81, 0x00, 1, |
60 | 2, 4, 3, 9, 25, 9, 25, 6434 }, | 53 | 2, 4, 3, 9, 25, 9, 25, 6434 }, |
61 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | 54 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ |
62 | 18800, 0x82, 0x00, 2, | 55 | 18800, 0x82, 0x00, 2, |
63 | 2, 6, 3, 10, 26, 10, 26, 9650 }, | 56 | 2, 6, 3, 10, 26, 10, 26, 9650 }, |
64 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */ | 57 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ |
65 | 25000, 0x83, 0x00, 3, | 58 | 25000, 0x83, 0x00, 3, |
66 | 4, 10, 3, 11, 27, 11, 27, 12868 }, | 59 | 4, 10, 3, 11, 27, 11, 27, 12868 }, |
67 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */ | 60 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ |
68 | 36700, 0x84, 0x00, 4, | 61 | 36700, 0x84, 0x00, 4, |
69 | 4, 14, 3, 12, 28, 12, 28, 19304 }, | 62 | 4, 14, 3, 12, 28, 12, 28, 19304 }, |
70 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */ | 63 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ |
71 | 48100, 0x85, 0x00, 5, | 64 | 48100, 0x85, 0x00, 5, |
72 | 4, 20, 3, 13, 29, 13, 29, 25740 }, | 65 | 4, 20, 3, 13, 29, 13, 29, 25740 }, |
73 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | 66 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ |
74 | 53500, 0x86, 0x00, 6, | 67 | 53500, 0x86, 0x00, 6, |
75 | 4, 23, 3, 14, 30, 14, 30, 28956 }, | 68 | 4, 23, 3, 14, 30, 14, 30, 28956 }, |
76 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */ | 69 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ |
77 | 59000, 0x87, 0x00, 7, | 70 | 59000, 0x87, 0x00, 7, |
78 | 4, 25, 3, 15, 31, 15, 32, 32180 }, | 71 | 4, 25, 3, 15, 31, 15, 32, 32180 }, |
79 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */ | 72 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ |
80 | 12700, 0x88, 0x00, | 73 | 12700, 0x88, 0x00, |
81 | 8, 0, 2, 3, 16, 33, 16, 33, 6430 }, | 74 | 8, 0, 2, 3, 16, 33, 16, 33, 6430 }, |
82 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */ | 75 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ |
83 | 24800, 0x89, 0x00, 9, | 76 | 24800, 0x89, 0x00, 9, |
84 | 2, 4, 3, 17, 34, 17, 34, 12860 }, | 77 | 2, 4, 3, 17, 34, 17, 34, 12860 }, |
85 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */ | 78 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ |
86 | 36600, 0x8a, 0x00, 10, | 79 | 36600, 0x8a, 0x00, 10, |
87 | 2, 6, 3, 18, 35, 18, 35, 19300 }, | 80 | 2, 6, 3, 18, 35, 18, 35, 19300 }, |
88 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */ | 81 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ |
89 | 48100, 0x8b, 0x00, 11, | 82 | 48100, 0x8b, 0x00, 11, |
90 | 4, 10, 3, 19, 36, 19, 36, 25736 }, | 83 | 4, 10, 3, 19, 36, 19, 36, 25736 }, |
91 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */ | 84 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ |
92 | 69500, 0x8c, 0x00, 12, | 85 | 69500, 0x8c, 0x00, 12, |
93 | 4, 14, 3, 20, 37, 20, 37, 38600 }, | 86 | 4, 14, 3, 20, 37, 20, 37, 38600 }, |
94 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */ | 87 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ |
95 | 89500, 0x8d, 0x00, 13, | 88 | 89500, 0x8d, 0x00, 13, |
96 | 4, 20, 3, 21, 38, 21, 38, 51472 }, | 89 | 4, 20, 3, 21, 38, 21, 38, 51472 }, |
97 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */ | 90 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ |
98 | 98900, 0x8e, 0x00, 14, | 91 | 98900, 0x8e, 0x00, 14, |
99 | 4, 23, 3, 22, 39, 22, 39, 57890 }, | 92 | 4, 23, 3, 22, 39, 22, 39, 57890 }, |
100 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */ | 93 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ |
101 | 108300, 0x8f, 0x00, 15, | 94 | 108300, 0x8f, 0x00, 15, |
102 | 4, 25, 3, 23, 40, 23, 41, 64320 }, | 95 | 4, 25, 3, 23, 40, 23, 41, 64320 }, |
103 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | 96 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ |
104 | 13200, 0x80, 0x00, 0, | 97 | 13200, 0x80, 0x00, 0, |
105 | 0, 2, 3, 8, 24, 24, 24, 6684 }, | 98 | 0, 2, 3, 8, 24, 24, 24, 6684 }, |
106 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | 99 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ |
107 | 25900, 0x81, 0x00, 1, | 100 | 25900, 0x81, 0x00, 1, |
108 | 2, 4, 3, 9, 25, 25, 25, 13368 }, | 101 | 2, 4, 3, 9, 25, 25, 25, 13368 }, |
109 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | 102 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ |
110 | 38600, 0x82, 0x00, 2, | 103 | 38600, 0x82, 0x00, 2, |
111 | 2, 6, 3, 10, 26, 26, 26, 20052 }, | 104 | 2, 6, 3, 10, 26, 26, 26, 20052 }, |
112 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */ | 105 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ |
113 | 49800, 0x83, 0x00, 3, | 106 | 49800, 0x83, 0x00, 3, |
114 | 4, 10, 3, 11, 27, 27, 27, 26738 }, | 107 | 4, 10, 3, 11, 27, 27, 27, 26738 }, |
115 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */ | 108 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ |
116 | 72200, 0x84, 0x00, 4, | 109 | 72200, 0x84, 0x00, 4, |
117 | 4, 14, 3, 12, 28, 28, 28, 40104 }, | 110 | 4, 14, 3, 12, 28, 28, 28, 40104 }, |
118 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */ | 111 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ |
119 | 92900, 0x85, 0x00, 5, | 112 | 92900, 0x85, 0x00, 5, |
120 | 4, 20, 3, 13, 29, 29, 29, 53476 }, | 113 | 4, 20, 3, 13, 29, 29, 29, 53476 }, |
121 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | 114 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ |
122 | 102700, 0x86, 0x00, 6, | 115 | 102700, 0x86, 0x00, 6, |
123 | 4, 23, 3, 14, 30, 30, 30, 60156 }, | 116 | 4, 23, 3, 14, 30, 30, 30, 60156 }, |
124 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */ | 117 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ |
125 | 112000, 0x87, 0x00, 7, | 118 | 112000, 0x87, 0x00, 7, |
126 | 4, 25, 3, 15, 31, 32, 32, 66840 }, | 119 | 4, 25, 3, 15, 31, 32, 32, 66840 }, |
127 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | 120 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ |
128 | 122000, 0x87, 0x00, 7, | 121 | 122000, 0x87, 0x00, 7, |
129 | 4, 25, 3, 15, 31, 32, 32, 74200 }, | 122 | 4, 25, 3, 15, 31, 32, 32, 74200 }, |
130 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */ | 123 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ |
131 | 25800, 0x88, 0x00, 8, | 124 | 25800, 0x88, 0x00, 8, |
132 | 0, 2, 3, 16, 33, 33, 33, 13360 }, | 125 | 0, 2, 3, 16, 33, 33, 33, 13360 }, |
133 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */ | 126 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ |
134 | 49800, 0x89, 0x00, 9, | 127 | 49800, 0x89, 0x00, 9, |
135 | 2, 4, 3, 17, 34, 34, 34, 26720 }, | 128 | 2, 4, 3, 17, 34, 34, 34, 26720 }, |
136 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */ | 129 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ |
137 | 71900, 0x8a, 0x00, 10, | 130 | 71900, 0x8a, 0x00, 10, |
138 | 2, 6, 3, 18, 35, 35, 35, 40080 }, | 131 | 2, 6, 3, 18, 35, 35, 35, 40080 }, |
139 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */ | 132 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ |
140 | 92500, 0x8b, 0x00, 11, | 133 | 92500, 0x8b, 0x00, 11, |
141 | 4, 10, 3, 19, 36, 36, 36, 53440 }, | 134 | 4, 10, 3, 19, 36, 36, 36, 53440 }, |
142 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */ | 135 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ |
143 | 130300, 0x8c, 0x00, 12, | 136 | 130300, 0x8c, 0x00, 12, |
144 | 4, 14, 3, 20, 37, 37, 37, 80160 }, | 137 | 4, 14, 3, 20, 37, 37, 37, 80160 }, |
145 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */ | 138 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ |
146 | 162800, 0x8d, 0x00, 13, | 139 | 162800, 0x8d, 0x00, 13, |
147 | 4, 20, 3, 21, 38, 38, 38, 106880 }, | 140 | 4, 20, 3, 21, 38, 38, 38, 106880 }, |
148 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */ | 141 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ |
149 | 178200, 0x8e, 0x00, 14, | 142 | 178200, 0x8e, 0x00, 14, |
150 | 4, 23, 3, 22, 39, 39, 39, 120240 }, | 143 | 4, 23, 3, 22, 39, 39, 39, 120240 }, |
151 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */ | 144 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ |
152 | 192100, 0x8f, 0x00, 15, | 145 | 192100, 0x8f, 0x00, 15, |
153 | 4, 25, 3, 23, 40, 41, 41, 133600 }, | 146 | 4, 25, 3, 23, 40, 41, 41, 133600 }, |
154 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | 147 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ |
155 | 207000, 0x8f, 0x00, 15, | 148 | 207000, 0x8f, 0x00, 15, |
156 | 4, 25, 3, 23, 40, 41, 41, 148400 }, | 149 | 4, 25, 3, 23, 40, 41, 41, 148400 }, |
157 | }, | 150 | }, |
@@ -160,153 +153,149 @@ static struct ath_rate_table ar5416_11na_ratetable = { | |||
160 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ | 153 | WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ |
161 | }; | 154 | }; |
162 | 155 | ||
163 | /* TRUE_ALL - valid for 20/40/Legacy, | ||
164 | * TRUE - Legacy only, | ||
165 | * TRUE_20 - HT 20 only, | ||
166 | * TRUE_40 - HT 40 only */ | ||
167 | |||
168 | /* 4ms frame limit not used for NG mode. The values filled | 156 | /* 4ms frame limit not used for NG mode. The values filled |
169 | * for HT are the 64K max aggregate limit */ | 157 | * for HT are the 64K max aggregate limit */ |
170 | 158 | ||
171 | static struct ath_rate_table ar5416_11ng_ratetable = { | 159 | static struct ath_rate_table ar5416_11ng_ratetable = { |
172 | 46, | 160 | 46, |
161 | {0}, | ||
173 | { | 162 | { |
174 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 1000, /* 1 Mb */ | 163 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ |
175 | 900, 0x1b, 0x00, 2, | 164 | 900, 0x1b, 0x00, 2, |
176 | 0, 0, 1, 0, 0, 0, 0, 0 }, | 165 | 0, 0, 1, 0, 0, 0, 0, 0 }, |
177 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 2000, /* 2 Mb */ | 166 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ |
178 | 1900, 0x1a, 0x04, 4, | 167 | 1900, 0x1a, 0x04, 4, |
179 | 1, 1, 1, 1, 1, 1, 1, 0 }, | 168 | 1, 1, 1, 1, 1, 1, 1, 0 }, |
180 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ | 169 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ |
181 | 4900, 0x19, 0x04, 11, | 170 | 4900, 0x19, 0x04, 11, |
182 | 2, 2, 2, 2, 2, 2, 2, 0 }, | 171 | 2, 2, 2, 2, 2, 2, 2, 0 }, |
183 | { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 11000, /* 11 Mb */ | 172 | { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ |
184 | 8100, 0x18, 0x04, 22, | 173 | 8100, 0x18, 0x04, 22, |
185 | 3, 3, 2, 3, 3, 3, 3, 0 }, | 174 | 3, 3, 2, 3, 3, 3, 3, 0 }, |
186 | { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | 175 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ |
187 | 5400, 0x0b, 0x00, 12, | 176 | 5400, 0x0b, 0x00, 12, |
188 | 4, 2, 1, 4, 4, 4, 4, 0 }, | 177 | 4, 2, 1, 4, 4, 4, 4, 0 }, |
189 | { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | 178 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ |
190 | 7800, 0x0f, 0x00, 18, | 179 | 7800, 0x0f, 0x00, 18, |
191 | 4, 3, 1, 5, 5, 5, 5, 0 }, | 180 | 4, 3, 1, 5, 5, 5, 5, 0 }, |
192 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | 181 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ |
193 | 10100, 0x0a, 0x00, 24, | 182 | 10100, 0x0a, 0x00, 24, |
194 | 6, 4, 1, 6, 6, 6, 6, 0 }, | 183 | 6, 4, 1, 6, 6, 6, 6, 0 }, |
195 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | 184 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ |
196 | 14100, 0x0e, 0x00, 36, | 185 | 14100, 0x0e, 0x00, 36, |
197 | 6, 6, 2, 7, 7, 7, 7, 0 }, | 186 | 6, 6, 2, 7, 7, 7, 7, 0 }, |
198 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | 187 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ |
199 | 17700, 0x09, 0x00, 48, | 188 | 17700, 0x09, 0x00, 48, |
200 | 8, 10, 3, 8, 8, 8, 8, 0 }, | 189 | 8, 10, 3, 8, 8, 8, 8, 0 }, |
201 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | 190 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ |
202 | 23700, 0x0d, 0x00, 72, | 191 | 23700, 0x0d, 0x00, 72, |
203 | 8, 14, 3, 9, 9, 9, 9, 0 }, | 192 | 8, 14, 3, 9, 9, 9, 9, 0 }, |
204 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | 193 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ |
205 | 27400, 0x08, 0x00, 96, | 194 | 27400, 0x08, 0x00, 96, |
206 | 8, 20, 3, 10, 10, 10, 10, 0 }, | 195 | 8, 20, 3, 10, 10, 10, 10, 0 }, |
207 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | 196 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
208 | 30900, 0x0c, 0x00, 108, | 197 | 30900, 0x0c, 0x00, 108, |
209 | 8, 23, 3, 11, 11, 11, 11, 0 }, | 198 | 8, 23, 3, 11, 11, 11, 11, 0 }, |
210 | { FALSE, FALSE, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */ | 199 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ |
211 | 6400, 0x80, 0x00, 0, | 200 | 6400, 0x80, 0x00, 0, |
212 | 4, 2, 3, 12, 28, 12, 28, 3216 }, | 201 | 4, 2, 3, 12, 28, 12, 28, 3216 }, |
213 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */ | 202 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ |
214 | 12700, 0x81, 0x00, 1, | 203 | 12700, 0x81, 0x00, 1, |
215 | 6, 4, 3, 13, 29, 13, 29, 6434 }, | 204 | 6, 4, 3, 13, 29, 13, 29, 6434 }, |
216 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */ | 205 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ |
217 | 18800, 0x82, 0x00, 2, | 206 | 18800, 0x82, 0x00, 2, |
218 | 6, 6, 3, 14, 30, 14, 30, 9650 }, | 207 | 6, 6, 3, 14, 30, 14, 30, 9650 }, |
219 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */ | 208 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ |
220 | 25000, 0x83, 0x00, 3, | 209 | 25000, 0x83, 0x00, 3, |
221 | 8, 10, 3, 15, 31, 15, 31, 12868 }, | 210 | 8, 10, 3, 15, 31, 15, 31, 12868 }, |
222 | { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */ | 211 | { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ |
223 | 36700, 0x84, 0x00, 4, | 212 | 36700, 0x84, 0x00, 4, |
224 | 8, 14, 3, 16, 32, 16, 32, 19304 }, | 213 | 8, 14, 3, 16, 32, 16, 32, 19304 }, |
225 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */ | 214 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ |
226 | 48100, 0x85, 0x00, 5, | 215 | 48100, 0x85, 0x00, 5, |
227 | 8, 20, 3, 17, 33, 17, 33, 25740 }, | 216 | 8, 20, 3, 17, 33, 17, 33, 25740 }, |
228 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */ | 217 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ |
229 | 53500, 0x86, 0x00, 6, | 218 | 53500, 0x86, 0x00, 6, |
230 | 8, 23, 3, 18, 34, 18, 34, 28956 }, | 219 | 8, 23, 3, 18, 34, 18, 34, 28956 }, |
231 | { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */ | 220 | { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ |
232 | 59000, 0x87, 0x00, 7, | 221 | 59000, 0x87, 0x00, 7, |
233 | 8, 25, 3, 19, 35, 19, 36, 32180 }, | 222 | 8, 25, 3, 19, 35, 19, 36, 32180 }, |
234 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */ | 223 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ |
235 | 12700, 0x88, 0x00, 8, | 224 | 12700, 0x88, 0x00, 8, |
236 | 4, 2, 3, 20, 37, 20, 37, 6430 }, | 225 | 4, 2, 3, 20, 37, 20, 37, 6430 }, |
237 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */ | 226 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ |
238 | 24800, 0x89, 0x00, 9, | 227 | 24800, 0x89, 0x00, 9, |
239 | 6, 4, 3, 21, 38, 21, 38, 12860 }, | 228 | 6, 4, 3, 21, 38, 21, 38, 12860 }, |
240 | { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */ | 229 | { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ |
241 | 36600, 0x8a, 0x00, 10, | 230 | 36600, 0x8a, 0x00, 10, |
242 | 6, 6, 3, 22, 39, 22, 39, 19300 }, | 231 | 6, 6, 3, 22, 39, 22, 39, 19300 }, |
243 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */ | 232 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ |
244 | 48100, 0x8b, 0x00, 11, | 233 | 48100, 0x8b, 0x00, 11, |
245 | 8, 10, 3, 23, 40, 23, 40, 25736 }, | 234 | 8, 10, 3, 23, 40, 23, 40, 25736 }, |
246 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */ | 235 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ |
247 | 69500, 0x8c, 0x00, 12, | 236 | 69500, 0x8c, 0x00, 12, |
248 | 8, 14, 3, 24, 41, 24, 41, 38600 }, | 237 | 8, 14, 3, 24, 41, 24, 41, 38600 }, |
249 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */ | 238 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ |
250 | 89500, 0x8d, 0x00, 13, | 239 | 89500, 0x8d, 0x00, 13, |
251 | 8, 20, 3, 25, 42, 25, 42, 51472 }, | 240 | 8, 20, 3, 25, 42, 25, 42, 51472 }, |
252 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */ | 241 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ |
253 | 98900, 0x8e, 0x00, 14, | 242 | 98900, 0x8e, 0x00, 14, |
254 | 8, 23, 3, 26, 43, 26, 44, 57890 }, | 243 | 8, 23, 3, 26, 43, 26, 44, 57890 }, |
255 | { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */ | 244 | { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ |
256 | 108300, 0x8f, 0x00, 15, | 245 | 108300, 0x8f, 0x00, 15, |
257 | 8, 25, 3, 27, 44, 27, 45, 64320 }, | 246 | 8, 25, 3, 27, 44, 27, 45, 64320 }, |
258 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */ | 247 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ |
259 | 13200, 0x80, 0x00, 0, | 248 | 13200, 0x80, 0x00, 0, |
260 | 8, 2, 3, 12, 28, 28, 28, 6684 }, | 249 | 8, 2, 3, 12, 28, 28, 28, 6684 }, |
261 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */ | 250 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ |
262 | 25900, 0x81, 0x00, 1, | 251 | 25900, 0x81, 0x00, 1, |
263 | 8, 4, 3, 13, 29, 29, 29, 13368 }, | 252 | 8, 4, 3, 13, 29, 29, 29, 13368 }, |
264 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */ | 253 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ |
265 | 38600, 0x82, 0x00, 2, | 254 | 38600, 0x82, 0x00, 2, |
266 | 8, 6, 3, 14, 30, 30, 30, 20052 }, | 255 | 8, 6, 3, 14, 30, 30, 30, 20052 }, |
267 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */ | 256 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ |
268 | 49800, 0x83, 0x00, 3, | 257 | 49800, 0x83, 0x00, 3, |
269 | 8, 10, 3, 15, 31, 31, 31, 26738 }, | 258 | 8, 10, 3, 15, 31, 31, 31, 26738 }, |
270 | { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */ | 259 | { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ |
271 | 72200, 0x84, 0x00, 4, | 260 | 72200, 0x84, 0x00, 4, |
272 | 8, 14, 3, 16, 32, 32, 32, 40104 }, | 261 | 8, 14, 3, 16, 32, 32, 32, 40104 }, |
273 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */ | 262 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ |
274 | 92900, 0x85, 0x00, 5, | 263 | 92900, 0x85, 0x00, 5, |
275 | 8, 20, 3, 17, 33, 33, 33, 53476 }, | 264 | 8, 20, 3, 17, 33, 33, 33, 53476 }, |
276 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */ | 265 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ |
277 | 102700, 0x86, 0x00, 6, | 266 | 102700, 0x86, 0x00, 6, |
278 | 8, 23, 3, 18, 34, 34, 34, 60156 }, | 267 | 8, 23, 3, 18, 34, 34, 34, 60156 }, |
279 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */ | 268 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ |
280 | 112000, 0x87, 0x00, 7, | 269 | 112000, 0x87, 0x00, 7, |
281 | 8, 23, 3, 19, 35, 36, 36, 66840 }, | 270 | 8, 23, 3, 19, 35, 36, 36, 66840 }, |
282 | { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ | 271 | { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ |
283 | 122000, 0x87, 0x00, 7, | 272 | 122000, 0x87, 0x00, 7, |
284 | 8, 25, 3, 19, 35, 36, 36, 74200 }, | 273 | 8, 25, 3, 19, 35, 36, 36, 74200 }, |
285 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */ | 274 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ |
286 | 25800, 0x88, 0x00, 8, | 275 | 25800, 0x88, 0x00, 8, |
287 | 8, 2, 3, 20, 37, 37, 37, 13360 }, | 276 | 8, 2, 3, 20, 37, 37, 37, 13360 }, |
288 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */ | 277 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ |
289 | 49800, 0x89, 0x00, 9, | 278 | 49800, 0x89, 0x00, 9, |
290 | 8, 4, 3, 21, 38, 38, 38, 26720 }, | 279 | 8, 4, 3, 21, 38, 38, 38, 26720 }, |
291 | { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */ | 280 | { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ |
292 | 71900, 0x8a, 0x00, 10, | 281 | 71900, 0x8a, 0x00, 10, |
293 | 8, 6, 3, 22, 39, 39, 39, 40080 }, | 282 | 8, 6, 3, 22, 39, 39, 39, 40080 }, |
294 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */ | 283 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ |
295 | 92500, 0x8b, 0x00, 11, | 284 | 92500, 0x8b, 0x00, 11, |
296 | 8, 10, 3, 23, 40, 40, 40, 53440 }, | 285 | 8, 10, 3, 23, 40, 40, 40, 53440 }, |
297 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */ | 286 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ |
298 | 130300, 0x8c, 0x00, 12, | 287 | 130300, 0x8c, 0x00, 12, |
299 | 8, 14, 3, 24, 41, 41, 41, 80160 }, | 288 | 8, 14, 3, 24, 41, 41, 41, 80160 }, |
300 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */ | 289 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ |
301 | 162800, 0x8d, 0x00, 13, | 290 | 162800, 0x8d, 0x00, 13, |
302 | 8, 20, 3, 25, 42, 42, 42, 106880 }, | 291 | 8, 20, 3, 25, 42, 42, 42, 106880 }, |
303 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */ | 292 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ |
304 | 178200, 0x8e, 0x00, 14, | 293 | 178200, 0x8e, 0x00, 14, |
305 | 8, 23, 3, 26, 43, 43, 43, 120240 }, | 294 | 8, 23, 3, 26, 43, 43, 43, 120240 }, |
306 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */ | 295 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ |
307 | 192100, 0x8f, 0x00, 15, | 296 | 192100, 0x8f, 0x00, 15, |
308 | 8, 23, 3, 27, 44, 45, 45, 133600 }, | 297 | 8, 23, 3, 27, 44, 45, 45, 133600 }, |
309 | { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ | 298 | { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ |
310 | 207000, 0x8f, 0x00, 15, | 299 | 207000, 0x8f, 0x00, 15, |
311 | 8, 25, 3, 27, 44, 45, 45, 148400 }, | 300 | 8, 25, 3, 27, 44, 45, 45, 148400 }, |
312 | }, | 301 | }, |
@@ -317,29 +306,30 @@ static struct ath_rate_table ar5416_11ng_ratetable = { | |||
317 | 306 | ||
318 | static struct ath_rate_table ar5416_11a_ratetable = { | 307 | static struct ath_rate_table ar5416_11a_ratetable = { |
319 | 8, | 308 | 8, |
309 | {0}, | ||
320 | { | 310 | { |
321 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | 311 | { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ |
322 | 5400, 0x0b, 0x00, (0x80|12), | 312 | 5400, 0x0b, 0x00, (0x80|12), |
323 | 0, 2, 1, 0, 0 }, | 313 | 0, 2, 1, 0, 0 }, |
324 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | 314 | { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ |
325 | 7800, 0x0f, 0x00, 18, | 315 | 7800, 0x0f, 0x00, 18, |
326 | 0, 3, 1, 1, 0 }, | 316 | 0, 3, 1, 1, 0 }, |
327 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | 317 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ |
328 | 10000, 0x0a, 0x00, (0x80|24), | 318 | 10000, 0x0a, 0x00, (0x80|24), |
329 | 2, 4, 2, 2, 0 }, | 319 | 2, 4, 2, 2, 0 }, |
330 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | 320 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ |
331 | 13900, 0x0e, 0x00, 36, | 321 | 13900, 0x0e, 0x00, 36, |
332 | 2, 6, 2, 3, 0 }, | 322 | 2, 6, 2, 3, 0 }, |
333 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | 323 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ |
334 | 17300, 0x09, 0x00, (0x80|48), | 324 | 17300, 0x09, 0x00, (0x80|48), |
335 | 4, 10, 3, 4, 0 }, | 325 | 4, 10, 3, 4, 0 }, |
336 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | 326 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ |
337 | 23000, 0x0d, 0x00, 72, | 327 | 23000, 0x0d, 0x00, 72, |
338 | 4, 14, 3, 5, 0 }, | 328 | 4, 14, 3, 5, 0 }, |
339 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | 329 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ |
340 | 27400, 0x08, 0x00, 96, | 330 | 27400, 0x08, 0x00, 96, |
341 | 4, 19, 3, 6, 0 }, | 331 | 4, 19, 3, 6, 0 }, |
342 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | 332 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
343 | 29300, 0x0c, 0x00, 108, | 333 | 29300, 0x0c, 0x00, 108, |
344 | 4, 23, 3, 7, 0 }, | 334 | 4, 23, 3, 7, 0 }, |
345 | }, | 335 | }, |
@@ -348,109 +338,44 @@ static struct ath_rate_table ar5416_11a_ratetable = { | |||
348 | 0, /* Phy rates allowed initially */ | 338 | 0, /* Phy rates allowed initially */ |
349 | }; | 339 | }; |
350 | 340 | ||
351 | static struct ath_rate_table ar5416_11a_ratetable_Half = { | ||
352 | 8, | ||
353 | { | ||
354 | { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 6 Mb */ | ||
355 | 2700, 0x0b, 0x00, (0x80|6), | ||
356 | 0, 2, 1, 0, 0}, | ||
357 | { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 9 Mb */ | ||
358 | 3900, 0x0f, 0x00, 9, | ||
359 | 0, 3, 1, 1, 0 }, | ||
360 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 12 Mb */ | ||
361 | 5000, 0x0a, 0x00, (0x80|12), | ||
362 | 2, 4, 2, 2, 0 }, | ||
363 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 18 Mb */ | ||
364 | 6950, 0x0e, 0x00, 18, | ||
365 | 2, 6, 2, 3, 0 }, | ||
366 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 24 Mb */ | ||
367 | 8650, 0x09, 0x00, (0x80|24), | ||
368 | 4, 10, 3, 4, 0 }, | ||
369 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 36 Mb */ | ||
370 | 11500, 0x0d, 0x00, 36, | ||
371 | 4, 14, 3, 5, 0 }, | ||
372 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 48 Mb */ | ||
373 | 13700, 0x08, 0x00, 48, | ||
374 | 4, 19, 3, 6, 0 }, | ||
375 | { TRUE, TRUE, WLAN_PHY_OFDM, 27000, /* 54 Mb */ | ||
376 | 14650, 0x0c, 0x00, 54, | ||
377 | 4, 23, 3, 7, 0 }, | ||
378 | }, | ||
379 | 50, /* probe interval */ | ||
380 | 50, /* rssi reduce interval */ | ||
381 | 0, /* Phy rates allowed initially */ | ||
382 | }; | ||
383 | |||
384 | static struct ath_rate_table ar5416_11a_ratetable_Quarter = { | ||
385 | 8, | ||
386 | { | ||
387 | { TRUE, TRUE, WLAN_PHY_OFDM, 1500, /* 6 Mb */ | ||
388 | 1350, 0x0b, 0x00, (0x80|3), | ||
389 | 0, 2, 1, 0, 0 }, | ||
390 | { TRUE, TRUE, WLAN_PHY_OFDM, 2250, /* 9 Mb */ | ||
391 | 1950, 0x0f, 0x00, 4, | ||
392 | 0, 3, 1, 1, 0 }, | ||
393 | { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 12 Mb */ | ||
394 | 2500, 0x0a, 0x00, (0x80|6), | ||
395 | 2, 4, 2, 2, 0 }, | ||
396 | { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 18 Mb */ | ||
397 | 3475, 0x0e, 0x00, 9, | ||
398 | 2, 6, 2, 3, 0 }, | ||
399 | { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 25 Mb */ | ||
400 | 4325, 0x09, 0x00, (0x80|12), | ||
401 | 4, 10, 3, 4, 0 }, | ||
402 | { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 36 Mb */ | ||
403 | 5750, 0x0d, 0x00, 18, | ||
404 | 4, 14, 3, 5, 0 }, | ||
405 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 48 Mb */ | ||
406 | 6850, 0x08, 0x00, 24, | ||
407 | 4, 19, 3, 6, 0 }, | ||
408 | { TRUE, TRUE, WLAN_PHY_OFDM, 13500, /* 54 Mb */ | ||
409 | 7325, 0x0c, 0x00, 27, | ||
410 | 4, 23, 3, 7, 0 }, | ||
411 | }, | ||
412 | 50, /* probe interval */ | ||
413 | 50, /* rssi reduce interval */ | ||
414 | 0, /* Phy rates allowed initially */ | ||
415 | }; | ||
416 | |||
417 | static struct ath_rate_table ar5416_11g_ratetable = { | 341 | static struct ath_rate_table ar5416_11g_ratetable = { |
418 | 12, | 342 | 12, |
343 | {0}, | ||
419 | { | 344 | { |
420 | { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */ | 345 | { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ |
421 | 900, 0x1b, 0x00, 2, | 346 | 900, 0x1b, 0x00, 2, |
422 | 0, 0, 1, 0, 0 }, | 347 | 0, 0, 1, 0, 0 }, |
423 | { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */ | 348 | { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ |
424 | 1900, 0x1a, 0x04, 4, | 349 | 1900, 0x1a, 0x04, 4, |
425 | 1, 1, 1, 1, 0 }, | 350 | 1, 1, 1, 1, 0 }, |
426 | { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ | 351 | { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ |
427 | 4900, 0x19, 0x04, 11, | 352 | 4900, 0x19, 0x04, 11, |
428 | 2, 2, 2, 2, 0 }, | 353 | 2, 2, 2, 2, 0 }, |
429 | { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */ | 354 | { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ |
430 | 8100, 0x18, 0x04, 22, | 355 | 8100, 0x18, 0x04, 22, |
431 | 3, 3, 2, 3, 0 }, | 356 | 3, 3, 2, 3, 0 }, |
432 | { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */ | 357 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ |
433 | 5400, 0x0b, 0x00, 12, | 358 | 5400, 0x0b, 0x00, 12, |
434 | 4, 2, 1, 4, 0 }, | 359 | 4, 2, 1, 4, 0 }, |
435 | { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */ | 360 | { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ |
436 | 7800, 0x0f, 0x00, 18, | 361 | 7800, 0x0f, 0x00, 18, |
437 | 4, 3, 1, 5, 0 }, | 362 | 4, 3, 1, 5, 0 }, |
438 | { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */ | 363 | { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ |
439 | 10000, 0x0a, 0x00, 24, | 364 | 10000, 0x0a, 0x00, 24, |
440 | 6, 4, 1, 6, 0 }, | 365 | 6, 4, 1, 6, 0 }, |
441 | { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */ | 366 | { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ |
442 | 13900, 0x0e, 0x00, 36, | 367 | 13900, 0x0e, 0x00, 36, |
443 | 6, 6, 2, 7, 0 }, | 368 | 6, 6, 2, 7, 0 }, |
444 | { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */ | 369 | { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ |
445 | 17300, 0x09, 0x00, 48, | 370 | 17300, 0x09, 0x00, 48, |
446 | 8, 10, 3, 8, 0 }, | 371 | 8, 10, 3, 8, 0 }, |
447 | { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */ | 372 | { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ |
448 | 23000, 0x0d, 0x00, 72, | 373 | 23000, 0x0d, 0x00, 72, |
449 | 8, 14, 3, 9, 0 }, | 374 | 8, 14, 3, 9, 0 }, |
450 | { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */ | 375 | { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ |
451 | 27400, 0x08, 0x00, 96, | 376 | 27400, 0x08, 0x00, 96, |
452 | 8, 19, 3, 10, 0 }, | 377 | 8, 19, 3, 10, 0 }, |
453 | { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */ | 378 | { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ |
454 | 29300, 0x0c, 0x00, 108, | 379 | 29300, 0x0c, 0x00, 108, |
455 | 8, 23, 3, 11, 0 }, | 380 | 8, 23, 3, 11, 0 }, |
456 | }, | 381 | }, |
@@ -461,17 +386,18 @@ static struct ath_rate_table ar5416_11g_ratetable = { | |||
461 | 386 | ||
462 | static struct ath_rate_table ar5416_11b_ratetable = { | 387 | static struct ath_rate_table ar5416_11b_ratetable = { |
463 | 4, | 388 | 4, |
389 | {0}, | ||
464 | { | 390 | { |
465 | { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */ | 391 | { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ |
466 | 900, 0x1b, 0x00, (0x80|2), | 392 | 900, 0x1b, 0x00, (0x80|2), |
467 | 0, 0, 1, 0, 0 }, | 393 | 0, 0, 1, 0, 0 }, |
468 | { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */ | 394 | { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ |
469 | 1800, 0x1a, 0x04, (0x80|4), | 395 | 1800, 0x1a, 0x04, (0x80|4), |
470 | 1, 1, 1, 1, 0 }, | 396 | 1, 1, 1, 1, 0 }, |
471 | { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */ | 397 | { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ |
472 | 4300, 0x19, 0x04, (0x80|11), | 398 | 4300, 0x19, 0x04, (0x80|11), |
473 | 1, 2, 2, 2, 0 }, | 399 | 1, 2, 2, 2, 0 }, |
474 | { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */ | 400 | { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ |
475 | 7100, 0x18, 0x04, (0x80|22), | 401 | 7100, 0x18, 0x04, (0x80|22), |
476 | 1, 4, 100, 3, 0 }, | 402 | 1, 4, 100, 3, 0 }, |
477 | }, | 403 | }, |
@@ -480,48 +406,6 @@ static struct ath_rate_table ar5416_11b_ratetable = { | |||
480 | 0, /* Phy rates allowed initially */ | 406 | 0, /* Phy rates allowed initially */ |
481 | }; | 407 | }; |
482 | 408 | ||
483 | static void ar5416_attach_ratetables(struct ath_rate_softc *sc) | ||
484 | { | ||
485 | /* | ||
486 | * Attach rate tables. | ||
487 | */ | ||
488 | sc->hw_rate_table[ATH9K_MODE_11B] = &ar5416_11b_ratetable; | ||
489 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable; | ||
490 | sc->hw_rate_table[ATH9K_MODE_11G] = &ar5416_11g_ratetable; | ||
491 | |||
492 | sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable; | ||
493 | sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable; | ||
494 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] = | ||
495 | &ar5416_11na_ratetable; | ||
496 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] = | ||
497 | &ar5416_11na_ratetable; | ||
498 | sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] = | ||
499 | &ar5416_11ng_ratetable; | ||
500 | sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] = | ||
501 | &ar5416_11ng_ratetable; | ||
502 | } | ||
503 | |||
504 | static void ar5416_setquarter_ratetable(struct ath_rate_softc *sc) | ||
505 | { | ||
506 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable_Quarter; | ||
507 | return; | ||
508 | } | ||
509 | |||
510 | static void ar5416_sethalf_ratetable(struct ath_rate_softc *sc) | ||
511 | { | ||
512 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable_Half; | ||
513 | return; | ||
514 | } | ||
515 | |||
516 | static void ar5416_setfull_ratetable(struct ath_rate_softc *sc) | ||
517 | { | ||
518 | sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable; | ||
519 | return; | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | * Return the median of three numbers | ||
524 | */ | ||
525 | static inline int8_t median(int8_t a, int8_t b, int8_t c) | 409 | static inline int8_t median(int8_t a, int8_t b, int8_t c) |
526 | { | 410 | { |
527 | if (a >= b) { | 411 | if (a >= b) { |
@@ -541,68 +425,65 @@ static inline int8_t median(int8_t a, int8_t b, int8_t c) | |||
541 | } | 425 | } |
542 | } | 426 | } |
543 | 427 | ||
544 | static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, | 428 | static void ath_rc_sort_validrates(struct ath_rate_table *rate_table, |
545 | struct ath_tx_ratectrl *rate_ctrl) | 429 | struct ath_rate_priv *ath_rc_priv) |
546 | { | 430 | { |
547 | u8 i, j, idx, idx_next; | 431 | u8 i, j, idx, idx_next; |
548 | 432 | ||
549 | for (i = rate_ctrl->max_valid_rate - 1; i > 0; i--) { | 433 | for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) { |
550 | for (j = 0; j <= i-1; j++) { | 434 | for (j = 0; j <= i-1; j++) { |
551 | idx = rate_ctrl->valid_rate_index[j]; | 435 | idx = ath_rc_priv->valid_rate_index[j]; |
552 | idx_next = rate_ctrl->valid_rate_index[j+1]; | 436 | idx_next = ath_rc_priv->valid_rate_index[j+1]; |
553 | 437 | ||
554 | if (rate_table->info[idx].ratekbps > | 438 | if (rate_table->info[idx].ratekbps > |
555 | rate_table->info[idx_next].ratekbps) { | 439 | rate_table->info[idx_next].ratekbps) { |
556 | rate_ctrl->valid_rate_index[j] = idx_next; | 440 | ath_rc_priv->valid_rate_index[j] = idx_next; |
557 | rate_ctrl->valid_rate_index[j+1] = idx; | 441 | ath_rc_priv->valid_rate_index[j+1] = idx; |
558 | } | 442 | } |
559 | } | 443 | } |
560 | } | 444 | } |
561 | } | 445 | } |
562 | 446 | ||
563 | /* Access functions for valid_txrate_mask */ | 447 | static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv) |
564 | |||
565 | static void ath_rc_init_valid_txmask(struct ath_tx_ratectrl *rate_ctrl) | ||
566 | { | 448 | { |
567 | u8 i; | 449 | u8 i; |
568 | 450 | ||
569 | for (i = 0; i < rate_ctrl->rate_table_size; i++) | 451 | for (i = 0; i < ath_rc_priv->rate_table_size; i++) |
570 | rate_ctrl->valid_rate_index[i] = FALSE; | 452 | ath_rc_priv->valid_rate_index[i] = 0; |
571 | } | 453 | } |
572 | 454 | ||
573 | static inline void ath_rc_set_valid_txmask(struct ath_tx_ratectrl *rate_ctrl, | 455 | static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, |
574 | u8 index, int valid_tx_rate) | 456 | u8 index, int valid_tx_rate) |
575 | { | 457 | { |
576 | ASSERT(index <= rate_ctrl->rate_table_size); | 458 | ASSERT(index <= ath_rc_priv->rate_table_size); |
577 | rate_ctrl->valid_rate_index[index] = valid_tx_rate ? TRUE : FALSE; | 459 | ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; |
578 | } | 460 | } |
579 | 461 | ||
580 | static inline int ath_rc_isvalid_txmask(struct ath_tx_ratectrl *rate_ctrl, | 462 | static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv, |
581 | u8 index) | 463 | u8 index) |
582 | { | 464 | { |
583 | ASSERT(index <= rate_ctrl->rate_table_size); | 465 | ASSERT(index <= ath_rc_priv->rate_table_size); |
584 | return rate_ctrl->valid_rate_index[index]; | 466 | return ath_rc_priv->valid_rate_index[index]; |
585 | } | 467 | } |
586 | 468 | ||
587 | /* Iterators for valid_txrate_mask */ | 469 | static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table, |
588 | static inline int | 470 | struct ath_rate_priv *ath_rc_priv, |
589 | ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, | 471 | u8 cur_valid_txrate, |
590 | struct ath_tx_ratectrl *rate_ctrl, | 472 | u8 *next_idx) |
591 | u8 cur_valid_txrate, | ||
592 | u8 *next_idx) | ||
593 | { | 473 | { |
594 | u8 i; | 474 | u8 i; |
595 | 475 | ||
596 | for (i = 0; i < rate_ctrl->max_valid_rate - 1; i++) { | 476 | for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) { |
597 | if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) { | 477 | if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { |
598 | *next_idx = rate_ctrl->valid_rate_index[i+1]; | 478 | *next_idx = ath_rc_priv->valid_rate_index[i+1]; |
599 | return TRUE; | 479 | return 1; |
600 | } | 480 | } |
601 | } | 481 | } |
602 | 482 | ||
603 | /* No more valid rates */ | 483 | /* No more valid rates */ |
604 | *next_idx = 0; | 484 | *next_idx = 0; |
605 | return FALSE; | 485 | |
486 | return 0; | ||
606 | } | 487 | } |
607 | 488 | ||
608 | /* Return true only for single stream */ | 489 | /* Return true only for single stream */ |
@@ -610,83 +491,72 @@ ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, | |||
610 | static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) | 491 | static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) |
611 | { | 492 | { |
612 | if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG)) | 493 | if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG)) |
613 | return FALSE; | 494 | return 0; |
614 | if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) | 495 | if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) |
615 | return FALSE; | 496 | return 0; |
616 | if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) | 497 | if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) |
617 | return FALSE; | 498 | return 0; |
618 | if (!ignore_cw && WLAN_RC_PHY_HT(phy)) | 499 | if (!ignore_cw && WLAN_RC_PHY_HT(phy)) |
619 | if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) | 500 | if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) |
620 | return FALSE; | 501 | return 0; |
621 | if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG)) | 502 | if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG)) |
622 | return FALSE; | 503 | return 0; |
623 | return TRUE; | 504 | return 1; |
624 | } | 505 | } |
625 | 506 | ||
626 | static inline int | 507 | static inline int |
627 | ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table, | 508 | ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table, |
628 | struct ath_tx_ratectrl *rate_ctrl, | 509 | struct ath_rate_priv *ath_rc_priv, |
629 | u8 cur_valid_txrate, u8 *next_idx) | 510 | u8 cur_valid_txrate, u8 *next_idx) |
630 | { | 511 | { |
631 | int8_t i; | 512 | int8_t i; |
632 | 513 | ||
633 | for (i = 1; i < rate_ctrl->max_valid_rate ; i++) { | 514 | for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) { |
634 | if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) { | 515 | if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { |
635 | *next_idx = rate_ctrl->valid_rate_index[i-1]; | 516 | *next_idx = ath_rc_priv->valid_rate_index[i-1]; |
636 | return TRUE; | 517 | return 1; |
637 | } | 518 | } |
638 | } | 519 | } |
639 | return FALSE; | 520 | |
521 | return 0; | ||
640 | } | 522 | } |
641 | 523 | ||
642 | /* | 524 | static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, |
643 | * Initialize the Valid Rate Index from valid entries in Rate Table | 525 | struct ath_rate_table *rate_table, |
644 | */ | 526 | u32 capflag) |
645 | static u8 | ||
646 | ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv, | ||
647 | const struct ath_rate_table *rate_table, | ||
648 | u32 capflag) | ||
649 | { | 527 | { |
650 | struct ath_tx_ratectrl *rate_ctrl; | ||
651 | u8 i, hi = 0; | 528 | u8 i, hi = 0; |
652 | u32 valid; | 529 | u32 valid; |
653 | 530 | ||
654 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
655 | for (i = 0; i < rate_table->rate_cnt; i++) { | 531 | for (i = 0; i < rate_table->rate_cnt; i++) { |
656 | valid = (ath_rc_priv->single_stream ? | 532 | valid = (ath_rc_priv->single_stream ? |
657 | rate_table->info[i].valid_single_stream : | 533 | rate_table->info[i].valid_single_stream : |
658 | rate_table->info[i].valid); | 534 | rate_table->info[i].valid); |
659 | if (valid == TRUE) { | 535 | if (valid == 1) { |
660 | u32 phy = rate_table->info[i].phy; | 536 | u32 phy = rate_table->info[i].phy; |
661 | u8 valid_rate_count = 0; | 537 | u8 valid_rate_count = 0; |
662 | 538 | ||
663 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | 539 | if (!ath_rc_valid_phyrate(phy, capflag, 0)) |
664 | continue; | 540 | continue; |
665 | 541 | ||
666 | valid_rate_count = rate_ctrl->valid_phy_ratecnt[phy]; | 542 | valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; |
667 | 543 | ||
668 | rate_ctrl->valid_phy_rateidx[phy][valid_rate_count] = i; | 544 | ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; |
669 | rate_ctrl->valid_phy_ratecnt[phy] += 1; | 545 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; |
670 | ath_rc_set_valid_txmask(rate_ctrl, i, TRUE); | 546 | ath_rc_set_valid_txmask(ath_rc_priv, i, 1); |
671 | hi = A_MAX(hi, i); | 547 | hi = A_MAX(hi, i); |
672 | } | 548 | } |
673 | } | 549 | } |
550 | |||
674 | return hi; | 551 | return hi; |
675 | } | 552 | } |
676 | 553 | ||
677 | /* | 554 | static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, |
678 | * Initialize the Valid Rate Index from Rate Set | 555 | struct ath_rate_table *rate_table, |
679 | */ | 556 | struct ath_rateset *rateset, |
680 | static u8 | 557 | u32 capflag) |
681 | ath_rc_sib_setvalid_rates(struct ath_rate_node *ath_rc_priv, | ||
682 | const struct ath_rate_table *rate_table, | ||
683 | struct ath_rateset *rateset, | ||
684 | u32 capflag) | ||
685 | { | 558 | { |
686 | /* XXX: Clean me up and make identation friendly */ | ||
687 | u8 i, j, hi = 0; | 559 | u8 i, j, hi = 0; |
688 | struct ath_tx_ratectrl *rate_ctrl = | ||
689 | (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
690 | 560 | ||
691 | /* Use intersection of working rates and valid rates */ | 561 | /* Use intersection of working rates and valid rates */ |
692 | for (i = 0; i < rateset->rs_nrates; i++) { | 562 | for (i = 0; i < rateset->rs_nrates; i++) { |
@@ -695,196 +565,89 @@ ath_rc_sib_setvalid_rates(struct ath_rate_node *ath_rc_priv, | |||
695 | u32 valid = (ath_rc_priv->single_stream ? | 565 | u32 valid = (ath_rc_priv->single_stream ? |
696 | rate_table->info[j].valid_single_stream : | 566 | rate_table->info[j].valid_single_stream : |
697 | rate_table->info[j].valid); | 567 | rate_table->info[j].valid); |
568 | u8 rate = rateset->rs_rates[i]; | ||
569 | u8 dot11rate = rate_table->info[j].dot11rate; | ||
698 | 570 | ||
699 | /* We allow a rate only if its valid and the | 571 | /* We allow a rate only if its valid and the |
700 | * capflag matches one of the validity | 572 | * capflag matches one of the validity |
701 | * (TRUE/TRUE_20/TRUE_40) flags */ | 573 | * (VALID/VALID_20/VALID_40) flags */ |
702 | |||
703 | /* XXX: catch the negative of this branch | ||
704 | * first and then continue */ | ||
705 | if (((rateset->rs_rates[i] & 0x7F) == | ||
706 | (rate_table->info[j].dot11rate & 0x7F)) && | ||
707 | ((valid & WLAN_RC_CAP_MODE(capflag)) == | ||
708 | WLAN_RC_CAP_MODE(capflag)) && | ||
709 | !WLAN_RC_PHY_HT(phy)) { | ||
710 | 574 | ||
575 | if (((rate & 0x7F) == (dot11rate & 0x7F)) && | ||
576 | ((valid & WLAN_RC_CAP_MODE(capflag)) == | ||
577 | WLAN_RC_CAP_MODE(capflag)) && | ||
578 | !WLAN_RC_PHY_HT(phy)) { | ||
711 | u8 valid_rate_count = 0; | 579 | u8 valid_rate_count = 0; |
712 | 580 | ||
713 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | 581 | if (!ath_rc_valid_phyrate(phy, capflag, 0)) |
714 | continue; | 582 | continue; |
715 | 583 | ||
716 | valid_rate_count = | 584 | valid_rate_count = |
717 | rate_ctrl->valid_phy_ratecnt[phy]; | 585 | ath_rc_priv->valid_phy_ratecnt[phy]; |
718 | 586 | ||
719 | rate_ctrl->valid_phy_rateidx[phy] | 587 | ath_rc_priv->valid_phy_rateidx[phy] |
720 | [valid_rate_count] = j; | 588 | [valid_rate_count] = j; |
721 | rate_ctrl->valid_phy_ratecnt[phy] += 1; | 589 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; |
722 | ath_rc_set_valid_txmask(rate_ctrl, j, TRUE); | 590 | ath_rc_set_valid_txmask(ath_rc_priv, j, 1); |
723 | hi = A_MAX(hi, j); | 591 | hi = A_MAX(hi, j); |
724 | } | 592 | } |
725 | } | 593 | } |
726 | } | 594 | } |
595 | |||
727 | return hi; | 596 | return hi; |
728 | } | 597 | } |
729 | 598 | ||
730 | static u8 | 599 | static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, |
731 | ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv, | 600 | struct ath_rate_table *rate_table, |
732 | const struct ath_rate_table *rate_table, | 601 | u8 *mcs_set, u32 capflag) |
733 | u8 *mcs_set, u32 capflag) | ||
734 | { | 602 | { |
603 | struct ath_rateset *rateset = (struct ath_rateset *)mcs_set; | ||
604 | |||
735 | u8 i, j, hi = 0; | 605 | u8 i, j, hi = 0; |
736 | struct ath_tx_ratectrl *rate_ctrl = | ||
737 | (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
738 | 606 | ||
739 | /* Use intersection of working rates and valid rates */ | 607 | /* Use intersection of working rates and valid rates */ |
740 | for (i = 0; i < ((struct ath_rateset *)mcs_set)->rs_nrates; i++) { | 608 | for (i = 0; i < rateset->rs_nrates; i++) { |
741 | for (j = 0; j < rate_table->rate_cnt; j++) { | 609 | for (j = 0; j < rate_table->rate_cnt; j++) { |
742 | u32 phy = rate_table->info[j].phy; | 610 | u32 phy = rate_table->info[j].phy; |
743 | u32 valid = (ath_rc_priv->single_stream ? | 611 | u32 valid = (ath_rc_priv->single_stream ? |
744 | rate_table->info[j].valid_single_stream : | 612 | rate_table->info[j].valid_single_stream : |
745 | rate_table->info[j].valid); | 613 | rate_table->info[j].valid); |
614 | u8 rate = rateset->rs_rates[i]; | ||
615 | u8 dot11rate = rate_table->info[j].dot11rate; | ||
746 | 616 | ||
747 | if (((((struct ath_rateset *) | 617 | if (((rate & 0x7F) != (dot11rate & 0x7F)) || |
748 | mcs_set)->rs_rates[i] & 0x7F) != | ||
749 | (rate_table->info[j].dot11rate & 0x7F)) || | ||
750 | !WLAN_RC_PHY_HT(phy) || | 618 | !WLAN_RC_PHY_HT(phy) || |
751 | !WLAN_RC_PHY_HT_VALID(valid, capflag)) | 619 | !WLAN_RC_PHY_HT_VALID(valid, capflag)) |
752 | continue; | 620 | continue; |
753 | 621 | ||
754 | if (!ath_rc_valid_phyrate(phy, capflag, FALSE)) | 622 | if (!ath_rc_valid_phyrate(phy, capflag, 0)) |
755 | continue; | 623 | continue; |
756 | 624 | ||
757 | rate_ctrl->valid_phy_rateidx[phy] | 625 | ath_rc_priv->valid_phy_rateidx[phy] |
758 | [rate_ctrl->valid_phy_ratecnt[phy]] = j; | 626 | [ath_rc_priv->valid_phy_ratecnt[phy]] = j; |
759 | rate_ctrl->valid_phy_ratecnt[phy] += 1; | 627 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; |
760 | ath_rc_set_valid_txmask(rate_ctrl, j, TRUE); | 628 | ath_rc_set_valid_txmask(ath_rc_priv, j, 1); |
761 | hi = A_MAX(hi, j); | 629 | hi = A_MAX(hi, j); |
762 | } | 630 | } |
763 | } | 631 | } |
764 | return hi; | ||
765 | } | ||
766 | |||
767 | /* | ||
768 | * Attach to a device instance. Setup the public definition | ||
769 | * of how much per-node space we need and setup the private | ||
770 | * phy tables that have rate control parameters. | ||
771 | */ | ||
772 | struct ath_rate_softc *ath_rate_attach(struct ath_hal *ah) | ||
773 | { | ||
774 | struct ath_rate_softc *asc; | ||
775 | |||
776 | /* we are only in user context so we can sleep for memory */ | ||
777 | asc = kzalloc(sizeof(struct ath_rate_softc), GFP_KERNEL); | ||
778 | if (asc == NULL) | ||
779 | return NULL; | ||
780 | |||
781 | ar5416_attach_ratetables(asc); | ||
782 | |||
783 | /* Save Maximum TX Trigger Level (used for 11n) */ | ||
784 | tx_triglevel_max = ah->ah_caps.tx_triglevel_max; | ||
785 | /* return alias for ath_rate_softc * */ | ||
786 | return asc; | ||
787 | } | ||
788 | |||
789 | static struct ath_rate_node *ath_rate_node_alloc(struct ath_vap *avp, | ||
790 | struct ath_rate_softc *rsc, | ||
791 | gfp_t gfp) | ||
792 | { | ||
793 | struct ath_rate_node *anode; | ||
794 | |||
795 | anode = kzalloc(sizeof(struct ath_rate_node), gfp); | ||
796 | if (anode == NULL) | ||
797 | return NULL; | ||
798 | |||
799 | anode->avp = avp; | ||
800 | anode->asc = rsc; | ||
801 | avp->rc_node = anode; | ||
802 | |||
803 | return anode; | ||
804 | } | ||
805 | |||
806 | static void ath_rate_node_free(struct ath_rate_node *anode) | ||
807 | { | ||
808 | if (anode != NULL) | ||
809 | kfree(anode); | ||
810 | } | ||
811 | |||
812 | void ath_rate_detach(struct ath_rate_softc *asc) | ||
813 | { | ||
814 | if (asc != NULL) | ||
815 | kfree(asc); | ||
816 | } | ||
817 | |||
818 | u8 ath_rate_findrateix(struct ath_softc *sc, | ||
819 | u8 dot11rate) | ||
820 | { | ||
821 | const struct ath_rate_table *ratetable; | ||
822 | struct ath_rate_softc *rsc = sc->sc_rc; | ||
823 | int i; | ||
824 | |||
825 | ratetable = rsc->hw_rate_table[sc->sc_curmode]; | ||
826 | |||
827 | if (WARN_ON(!ratetable)) | ||
828 | return 0; | ||
829 | |||
830 | for (i = 0; i < ratetable->rate_cnt; i++) { | ||
831 | if ((ratetable->info[i].dot11rate & 0x7f) == (dot11rate & 0x7f)) | ||
832 | return i; | ||
833 | } | ||
834 | 632 | ||
835 | return 0; | 633 | return hi; |
836 | } | ||
837 | |||
838 | /* | ||
839 | * Update rate-control state on a device state change. When | ||
840 | * operating as a station this includes associate/reassociate | ||
841 | * with an AP. Otherwise this gets called, for example, when | ||
842 | * the we transition to run state when operating as an AP. | ||
843 | */ | ||
844 | void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp) | ||
845 | { | ||
846 | struct ath_rate_softc *asc = sc->sc_rc; | ||
847 | |||
848 | /* For half and quarter rate channles use different | ||
849 | * rate tables | ||
850 | */ | ||
851 | if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_HALF) | ||
852 | ar5416_sethalf_ratetable(asc); | ||
853 | else if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_QUARTER) | ||
854 | ar5416_setquarter_ratetable(asc); | ||
855 | else /* full rate */ | ||
856 | ar5416_setfull_ratetable(asc); | ||
857 | |||
858 | if (avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) { | ||
859 | asc->fixedrix = | ||
860 | sc->sc_rixmap[avp->av_config.av_fixed_rateset & 0xff]; | ||
861 | /* NB: check the fixed rate exists */ | ||
862 | if (asc->fixedrix == 0xff) | ||
863 | asc->fixedrix = IEEE80211_FIXED_RATE_NONE; | ||
864 | } else { | ||
865 | asc->fixedrix = IEEE80211_FIXED_RATE_NONE; | ||
866 | } | ||
867 | } | 634 | } |
868 | 635 | ||
869 | static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | 636 | static u8 ath_rc_ratefind_ht(struct ath_softc *sc, |
870 | struct ath_rate_node *ath_rc_priv, | 637 | struct ath_rate_priv *ath_rc_priv, |
871 | const struct ath_rate_table *rate_table, | 638 | struct ath_rate_table *rate_table, |
872 | int probe_allowed, int *is_probing, | 639 | int probe_allowed, int *is_probing, |
873 | int is_retry) | 640 | int is_retry) |
874 | { | 641 | { |
875 | u32 dt, best_thruput, this_thruput, now_msec; | 642 | u32 dt, best_thruput, this_thruput, now_msec; |
876 | u8 rate, next_rate, best_rate, maxindex, minindex; | 643 | u8 rate, next_rate, best_rate, maxindex, minindex; |
877 | int8_t rssi_last, rssi_reduce = 0, index = 0; | 644 | int8_t rssi_last, rssi_reduce = 0, index = 0; |
878 | struct ath_tx_ratectrl *rate_ctrl = NULL; | ||
879 | |||
880 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv ? | ||
881 | (ath_rc_priv) : NULL); | ||
882 | 645 | ||
883 | *is_probing = FALSE; | 646 | *is_probing = 0; |
884 | 647 | ||
885 | rssi_last = median(rate_ctrl->rssi_last, | 648 | rssi_last = median(ath_rc_priv->rssi_last, |
886 | rate_ctrl->rssi_last_prev, | 649 | ath_rc_priv->rssi_last_prev, |
887 | rate_ctrl->rssi_last_prev2); | 650 | ath_rc_priv->rssi_last_prev2); |
888 | 651 | ||
889 | /* | 652 | /* |
890 | * Age (reduce) last ack rssi based on how old it is. | 653 | * Age (reduce) last ack rssi based on how old it is. |
@@ -896,7 +659,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
896 | */ | 659 | */ |
897 | 660 | ||
898 | now_msec = jiffies_to_msecs(jiffies); | 661 | now_msec = jiffies_to_msecs(jiffies); |
899 | dt = now_msec - rate_ctrl->rssi_time; | 662 | dt = now_msec - ath_rc_priv->rssi_time; |
900 | 663 | ||
901 | if (dt >= 185) | 664 | if (dt >= 185) |
902 | rssi_reduce = 10; | 665 | rssi_reduce = 10; |
@@ -915,7 +678,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
915 | */ | 678 | */ |
916 | 679 | ||
917 | best_thruput = 0; | 680 | best_thruput = 0; |
918 | maxindex = rate_ctrl->max_valid_rate-1; | 681 | maxindex = ath_rc_priv->max_valid_rate-1; |
919 | 682 | ||
920 | minindex = 0; | 683 | minindex = 0; |
921 | best_rate = minindex; | 684 | best_rate = minindex; |
@@ -927,8 +690,8 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
927 | for (index = maxindex; index >= minindex ; index--) { | 690 | for (index = maxindex; index >= minindex ; index--) { |
928 | u8 per_thres; | 691 | u8 per_thres; |
929 | 692 | ||
930 | rate = rate_ctrl->valid_rate_index[index]; | 693 | rate = ath_rc_priv->valid_rate_index[index]; |
931 | if (rate > rate_ctrl->rate_max_phy) | 694 | if (rate > ath_rc_priv->rate_max_phy) |
932 | continue; | 695 | continue; |
933 | 696 | ||
934 | /* | 697 | /* |
@@ -942,7 +705,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
942 | * 10-15 and we would be worse off then staying | 705 | * 10-15 and we would be worse off then staying |
943 | * at the current rate. | 706 | * at the current rate. |
944 | */ | 707 | */ |
945 | per_thres = rate_ctrl->state[rate].per; | 708 | per_thres = ath_rc_priv->state[rate].per; |
946 | if (per_thres < 12) | 709 | if (per_thres < 12) |
947 | per_thres = 12; | 710 | per_thres = 12; |
948 | 711 | ||
@@ -961,41 +724,35 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
961 | * of max retries, use the min rate for the next retry | 724 | * of max retries, use the min rate for the next retry |
962 | */ | 725 | */ |
963 | if (is_retry) | 726 | if (is_retry) |
964 | rate = rate_ctrl->valid_rate_index[minindex]; | 727 | rate = ath_rc_priv->valid_rate_index[minindex]; |
965 | 728 | ||
966 | rate_ctrl->rssi_last_lookup = rssi_last; | 729 | ath_rc_priv->rssi_last_lookup = rssi_last; |
967 | 730 | ||
968 | /* | 731 | /* |
969 | * Must check the actual rate (ratekbps) to account for | 732 | * Must check the actual rate (ratekbps) to account for |
970 | * non-monoticity of 11g's rate table | 733 | * non-monoticity of 11g's rate table |
971 | */ | 734 | */ |
972 | 735 | ||
973 | if (rate >= rate_ctrl->rate_max_phy && probe_allowed) { | 736 | if (rate >= ath_rc_priv->rate_max_phy && probe_allowed) { |
974 | rate = rate_ctrl->rate_max_phy; | 737 | rate = ath_rc_priv->rate_max_phy; |
975 | 738 | ||
976 | /* Probe the next allowed phy state */ | 739 | /* Probe the next allowed phy state */ |
977 | /* FIXME:XXXX Check to make sure ratMax is checked properly */ | 740 | /* FIXME:XXXX Check to make sure ratMax is checked properly */ |
978 | if (ath_rc_get_nextvalid_txrate(rate_table, | 741 | if (ath_rc_get_nextvalid_txrate(rate_table, |
979 | rate_ctrl, rate, &next_rate) && | 742 | ath_rc_priv, rate, &next_rate) && |
980 | (now_msec - rate_ctrl->probe_time > | 743 | (now_msec - ath_rc_priv->probe_time > |
981 | rate_table->probe_interval) && | 744 | rate_table->probe_interval) && |
982 | (rate_ctrl->hw_maxretry_pktcnt >= 1)) { | 745 | (ath_rc_priv->hw_maxretry_pktcnt >= 1)) { |
983 | rate = next_rate; | 746 | rate = next_rate; |
984 | rate_ctrl->probe_rate = rate; | 747 | ath_rc_priv->probe_rate = rate; |
985 | rate_ctrl->probe_time = now_msec; | 748 | ath_rc_priv->probe_time = now_msec; |
986 | rate_ctrl->hw_maxretry_pktcnt = 0; | 749 | ath_rc_priv->hw_maxretry_pktcnt = 0; |
987 | *is_probing = TRUE; | 750 | *is_probing = 1; |
988 | } | 751 | } |
989 | } | 752 | } |
990 | 753 | ||
991 | /* | 754 | if (rate > (ath_rc_priv->rate_table_size - 1)) |
992 | * Make sure rate is not higher than the allowed maximum. | 755 | rate = ath_rc_priv->rate_table_size - 1; |
993 | * We should also enforce the min, but I suspect the min is | ||
994 | * normally 1 rather than 0 because of the rate 9 vs 6 issue | ||
995 | * in the old code. | ||
996 | */ | ||
997 | if (rate > (rate_ctrl->rate_table_size - 1)) | ||
998 | rate = rate_ctrl->rate_table_size - 1; | ||
999 | 756 | ||
1000 | ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || | 757 | ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) || |
1001 | (rate_table->info[rate].valid_single_stream && | 758 | (rate_table->info[rate].valid_single_stream && |
@@ -1004,40 +761,36 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc, | |||
1004 | return rate; | 761 | return rate; |
1005 | } | 762 | } |
1006 | 763 | ||
1007 | static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table , | 764 | static void ath_rc_rate_set_series(struct ath_rate_table *rate_table , |
1008 | struct ath_rc_series *series, | 765 | struct ieee80211_tx_rate *rate, |
1009 | u8 tries, | 766 | u8 tries, u8 rix, int rtsctsenable) |
1010 | u8 rix, | ||
1011 | int rtsctsenable) | ||
1012 | { | 767 | { |
1013 | series->tries = tries; | 768 | rate->count = tries; |
1014 | series->flags = (rtsctsenable ? ATH_RC_RTSCTS_FLAG : 0) | | 769 | rate->idx = rix; |
1015 | (WLAN_RC_PHY_DS(rate_table->info[rix].phy) ? | 770 | |
1016 | ATH_RC_DS_FLAG : 0) | | 771 | if (rtsctsenable) |
1017 | (WLAN_RC_PHY_40(rate_table->info[rix].phy) ? | 772 | rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; |
1018 | ATH_RC_CW40_FLAG : 0) | | 773 | if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) |
1019 | (WLAN_RC_PHY_SGI(rate_table->info[rix].phy) ? | 774 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
1020 | ATH_RC_SGI_FLAG : 0); | 775 | if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) |
1021 | 776 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; | |
1022 | series->rix = rate_table->info[rix].base_index; | 777 | if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) |
1023 | series->max_4ms_framelen = rate_table->info[rix].max_4ms_framelen; | 778 | rate->flags |= IEEE80211_TX_RC_MCS; |
1024 | } | 779 | } |
1025 | 780 | ||
1026 | static u8 ath_rc_rate_getidx(struct ath_softc *sc, | 781 | static u8 ath_rc_rate_getidx(struct ath_softc *sc, |
1027 | struct ath_rate_node *ath_rc_priv, | 782 | struct ath_rate_priv *ath_rc_priv, |
1028 | const struct ath_rate_table *rate_table, | 783 | struct ath_rate_table *rate_table, |
1029 | u8 rix, u16 stepdown, | 784 | u8 rix, u16 stepdown, |
1030 | u16 min_rate) | 785 | u16 min_rate) |
1031 | { | 786 | { |
1032 | u32 j; | 787 | u32 j; |
1033 | u8 nextindex; | 788 | u8 nextindex; |
1034 | struct ath_tx_ratectrl *rate_ctrl = | ||
1035 | (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
1036 | 789 | ||
1037 | if (min_rate) { | 790 | if (min_rate) { |
1038 | for (j = RATE_TABLE_SIZE; j > 0; j--) { | 791 | for (j = RATE_TABLE_SIZE; j > 0; j--) { |
1039 | if (ath_rc_get_nextlowervalid_txrate(rate_table, | 792 | if (ath_rc_get_nextlowervalid_txrate(rate_table, |
1040 | rate_ctrl, rix, &nextindex)) | 793 | ath_rc_priv, rix, &nextindex)) |
1041 | rix = nextindex; | 794 | rix = nextindex; |
1042 | else | 795 | else |
1043 | break; | 796 | break; |
@@ -1045,7 +798,7 @@ static u8 ath_rc_rate_getidx(struct ath_softc *sc, | |||
1045 | } else { | 798 | } else { |
1046 | for (j = stepdown; j > 0; j--) { | 799 | for (j = stepdown; j > 0; j--) { |
1047 | if (ath_rc_get_nextlowervalid_txrate(rate_table, | 800 | if (ath_rc_get_nextlowervalid_txrate(rate_table, |
1048 | rate_ctrl, rix, &nextindex)) | 801 | ath_rc_priv, rix, &nextindex)) |
1049 | rix = nextindex; | 802 | rix = nextindex; |
1050 | else | 803 | else |
1051 | break; | 804 | break; |
@@ -1055,41 +808,39 @@ static u8 ath_rc_rate_getidx(struct ath_softc *sc, | |||
1055 | } | 808 | } |
1056 | 809 | ||
1057 | static void ath_rc_ratefind(struct ath_softc *sc, | 810 | static void ath_rc_ratefind(struct ath_softc *sc, |
1058 | struct ath_rate_node *ath_rc_priv, | 811 | struct ath_rate_priv *ath_rc_priv, |
1059 | int num_tries, int num_rates, unsigned int rcflag, | 812 | int num_tries, int num_rates, |
1060 | struct ath_rc_series series[], int *is_probe, | 813 | struct ieee80211_tx_info *tx_info, int *is_probe, |
1061 | int is_retry) | 814 | int is_retry) |
1062 | { | 815 | { |
1063 | u8 try_per_rate = 0, i = 0, rix, nrix; | 816 | u8 try_per_rate = 0, i = 0, rix, nrix; |
1064 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | ||
1065 | struct ath_rate_table *rate_table; | 817 | struct ath_rate_table *rate_table; |
818 | struct ieee80211_tx_rate *rates = tx_info->control.rates; | ||
1066 | 819 | ||
1067 | rate_table = | 820 | rate_table = sc->hw_rate_table[sc->sc_curmode]; |
1068 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; | 821 | rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, 1, |
1069 | rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, | ||
1070 | (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0, | ||
1071 | is_probe, is_retry); | 822 | is_probe, is_retry); |
1072 | nrix = rix; | 823 | nrix = rix; |
1073 | 824 | ||
1074 | if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) { | 825 | if (*is_probe) { |
1075 | /* set one try for probe rates. For the | 826 | /* set one try for probe rates. For the |
1076 | * probes don't enable rts */ | 827 | * probes don't enable rts */ |
1077 | ath_rc_rate_set_series(rate_table, | 828 | ath_rc_rate_set_series(rate_table, |
1078 | &series[i++], 1, nrix, FALSE); | 829 | &rates[i++], 1, nrix, 0); |
1079 | 830 | ||
1080 | try_per_rate = (num_tries/num_rates); | 831 | try_per_rate = (num_tries/num_rates); |
1081 | /* Get the next tried/allowed rate. No RTS for the next series | 832 | /* Get the next tried/allowed rate. No RTS for the next series |
1082 | * after the probe rate | 833 | * after the probe rate |
1083 | */ | 834 | */ |
1084 | nrix = ath_rc_rate_getidx(sc, | 835 | nrix = ath_rc_rate_getidx(sc, |
1085 | ath_rc_priv, rate_table, nrix, 1, FALSE); | 836 | ath_rc_priv, rate_table, nrix, 1, 0); |
1086 | ath_rc_rate_set_series(rate_table, | 837 | ath_rc_rate_set_series(rate_table, |
1087 | &series[i++], try_per_rate, nrix, 0); | 838 | &rates[i++], try_per_rate, nrix, 0); |
1088 | } else { | 839 | } else { |
1089 | try_per_rate = (num_tries/num_rates); | 840 | try_per_rate = (num_tries/num_rates); |
1090 | /* Set the choosen rate. No RTS for first series entry. */ | 841 | /* Set the choosen rate. No RTS for first series entry. */ |
1091 | ath_rc_rate_set_series(rate_table, | 842 | ath_rc_rate_set_series(rate_table, |
1092 | &series[i++], try_per_rate, nrix, FALSE); | 843 | &rates[i++], try_per_rate, nrix, 0); |
1093 | } | 844 | } |
1094 | 845 | ||
1095 | /* Fill in the other rates for multirate retry */ | 846 | /* Fill in the other rates for multirate retry */ |
@@ -1099,14 +850,13 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
1099 | 850 | ||
1100 | try_num = ((i + 1) == num_rates) ? | 851 | try_num = ((i + 1) == num_rates) ? |
1101 | num_tries - (try_per_rate * i) : try_per_rate ; | 852 | num_tries - (try_per_rate * i) : try_per_rate ; |
1102 | min_rate = (((i + 1) == num_rates) && | 853 | min_rate = (((i + 1) == num_rates) && 0); |
1103 | (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0; | ||
1104 | 854 | ||
1105 | nrix = ath_rc_rate_getidx(sc, ath_rc_priv, | 855 | nrix = ath_rc_rate_getidx(sc, ath_rc_priv, |
1106 | rate_table, nrix, 1, min_rate); | 856 | rate_table, nrix, 1, min_rate); |
1107 | /* All other rates in the series have RTS enabled */ | 857 | /* All other rates in the series have RTS enabled */ |
1108 | ath_rc_rate_set_series(rate_table, | 858 | ath_rc_rate_set_series(rate_table, |
1109 | &series[i], try_num, nrix, TRUE); | 859 | &rates[i], try_num, nrix, 1); |
1110 | } | 860 | } |
1111 | 861 | ||
1112 | /* | 862 | /* |
@@ -1132,107 +882,22 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
1132 | if (i == 4 && | 882 | if (i == 4 && |
1133 | ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || | 883 | ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || |
1134 | (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { | 884 | (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { |
1135 | series[3].rix = series[2].rix; | 885 | rates[3].idx = rates[2].idx; |
1136 | series[3].flags = series[2].flags; | 886 | rates[3].flags = rates[2].flags; |
1137 | series[3].max_4ms_framelen = series[2].max_4ms_framelen; | ||
1138 | } | ||
1139 | } | ||
1140 | } | ||
1141 | |||
1142 | /* | ||
1143 | * Return the Tx rate series. | ||
1144 | */ | ||
1145 | static void ath_rate_findrate(struct ath_softc *sc, | ||
1146 | struct ath_rate_node *ath_rc_priv, | ||
1147 | int num_tries, | ||
1148 | int num_rates, | ||
1149 | unsigned int rcflag, | ||
1150 | struct ath_rc_series series[], | ||
1151 | int *is_probe, | ||
1152 | int is_retry) | ||
1153 | { | ||
1154 | struct ath_vap *avp = ath_rc_priv->avp; | ||
1155 | |||
1156 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | ||
1157 | |||
1158 | if (!num_rates || !num_tries) | ||
1159 | return; | ||
1160 | |||
1161 | if (avp->av_config.av_fixed_rateset == IEEE80211_FIXED_RATE_NONE) { | ||
1162 | ath_rc_ratefind(sc, ath_rc_priv, num_tries, num_rates, | ||
1163 | rcflag, series, is_probe, is_retry); | ||
1164 | } else { | ||
1165 | /* Fixed rate */ | ||
1166 | int idx; | ||
1167 | u8 flags; | ||
1168 | u32 rix; | ||
1169 | struct ath_rate_softc *asc = ath_rc_priv->asc; | ||
1170 | struct ath_rate_table *rate_table; | ||
1171 | |||
1172 | rate_table = (struct ath_rate_table *) | ||
1173 | asc->hw_rate_table[sc->sc_curmode]; | ||
1174 | |||
1175 | for (idx = 0; idx < 4; idx++) { | ||
1176 | unsigned int mcs; | ||
1177 | u8 series_rix = 0; | ||
1178 | |||
1179 | series[idx].tries = IEEE80211_RATE_IDX_ENTRY( | ||
1180 | avp->av_config.av_fixed_retryset, idx); | ||
1181 | |||
1182 | mcs = IEEE80211_RATE_IDX_ENTRY( | ||
1183 | avp->av_config.av_fixed_rateset, idx); | ||
1184 | |||
1185 | if (idx == 3 && (mcs & 0xf0) == 0x70) | ||
1186 | mcs = (mcs & ~0xf0)|0x80; | ||
1187 | |||
1188 | if (!(mcs & 0x80)) | ||
1189 | flags = 0; | ||
1190 | else | ||
1191 | flags = ((ath_rc_priv->ht_cap & | ||
1192 | WLAN_RC_DS_FLAG) ? | ||
1193 | ATH_RC_DS_FLAG : 0) | | ||
1194 | ((ath_rc_priv->ht_cap & | ||
1195 | WLAN_RC_40_FLAG) ? | ||
1196 | ATH_RC_CW40_FLAG : 0) | | ||
1197 | ((ath_rc_priv->ht_cap & | ||
1198 | WLAN_RC_SGI_FLAG) ? | ||
1199 | ((ath_rc_priv->ht_cap & | ||
1200 | WLAN_RC_40_FLAG) ? | ||
1201 | ATH_RC_SGI_FLAG : 0) : 0); | ||
1202 | |||
1203 | series[idx].rix = sc->sc_rixmap[mcs]; | ||
1204 | series_rix = series[idx].rix; | ||
1205 | |||
1206 | /* XXX: Give me some cleanup love */ | ||
1207 | if ((flags & ATH_RC_CW40_FLAG) && | ||
1208 | (flags & ATH_RC_SGI_FLAG)) | ||
1209 | rix = rate_table->info[series_rix].ht_index; | ||
1210 | else if (flags & ATH_RC_SGI_FLAG) | ||
1211 | rix = rate_table->info[series_rix].sgi_index; | ||
1212 | else if (flags & ATH_RC_CW40_FLAG) | ||
1213 | rix = rate_table->info[series_rix].cw40index; | ||
1214 | else | ||
1215 | rix = rate_table->info[series_rix].base_index; | ||
1216 | series[idx].max_4ms_framelen = | ||
1217 | rate_table->info[rix].max_4ms_framelen; | ||
1218 | series[idx].flags = flags; | ||
1219 | } | 887 | } |
1220 | } | 888 | } |
1221 | } | 889 | } |
1222 | 890 | ||
1223 | static void ath_rc_update_ht(struct ath_softc *sc, | 891 | static bool ath_rc_update_per(struct ath_softc *sc, |
1224 | struct ath_rate_node *ath_rc_priv, | 892 | struct ath_rate_table *rate_table, |
1225 | struct ath_tx_info_priv *info_priv, | 893 | struct ath_rate_priv *ath_rc_priv, |
1226 | int tx_rate, int xretries, int retries) | 894 | struct ath_tx_info_priv *tx_info_priv, |
895 | int tx_rate, int xretries, int retries, | ||
896 | u32 now_msec) | ||
1227 | { | 897 | { |
1228 | struct ath_tx_ratectrl *rate_ctrl; | 898 | bool state_change = false; |
1229 | u32 now_msec = jiffies_to_msecs(jiffies); | 899 | int count; |
1230 | int state_change = FALSE, rate, count; | ||
1231 | u8 last_per; | 900 | u8 last_per; |
1232 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | ||
1233 | struct ath_rate_table *rate_table = | ||
1234 | (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode]; | ||
1235 | |||
1236 | static u32 nretry_to_per_lookup[10] = { | 901 | static u32 nretry_to_per_lookup[10] = { |
1237 | 100 * 0 / 1, | 902 | 100 * 0 / 1, |
1238 | 100 * 1 / 4, | 903 | 100 * 1 / 4, |
@@ -1246,54 +911,35 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1246 | 100 * 9 / 10 | 911 | 100 * 9 / 10 |
1247 | }; | 912 | }; |
1248 | 913 | ||
1249 | if (!ath_rc_priv) | 914 | last_per = ath_rc_priv->state[tx_rate].per; |
1250 | return; | ||
1251 | |||
1252 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
1253 | |||
1254 | ASSERT(tx_rate >= 0); | ||
1255 | if (tx_rate < 0) | ||
1256 | return; | ||
1257 | |||
1258 | /* To compensate for some imbalance between ctrl and ext. channel */ | ||
1259 | |||
1260 | if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy)) | ||
1261 | info_priv->tx.ts_rssi = | ||
1262 | info_priv->tx.ts_rssi < 3 ? 0 : | ||
1263 | info_priv->tx.ts_rssi - 3; | ||
1264 | |||
1265 | last_per = rate_ctrl->state[tx_rate].per; | ||
1266 | 915 | ||
1267 | if (xretries) { | 916 | if (xretries) { |
1268 | /* Update the PER. */ | ||
1269 | if (xretries == 1) { | 917 | if (xretries == 1) { |
1270 | rate_ctrl->state[tx_rate].per += 30; | 918 | ath_rc_priv->state[tx_rate].per += 30; |
1271 | if (rate_ctrl->state[tx_rate].per > 100) | 919 | if (ath_rc_priv->state[tx_rate].per > 100) |
1272 | rate_ctrl->state[tx_rate].per = 100; | 920 | ath_rc_priv->state[tx_rate].per = 100; |
1273 | } else { | 921 | } else { |
1274 | /* xretries == 2 */ | 922 | /* xretries == 2 */ |
1275 | count = ARRAY_SIZE(nretry_to_per_lookup); | 923 | count = ARRAY_SIZE(nretry_to_per_lookup); |
1276 | if (retries >= count) | 924 | if (retries >= count) |
1277 | retries = count - 1; | 925 | retries = count - 1; |
926 | |||
1278 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | 927 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ |
1279 | rate_ctrl->state[tx_rate].per = | 928 | ath_rc_priv->state[tx_rate].per = |
1280 | (u8)(rate_ctrl->state[tx_rate].per - | 929 | (u8)(last_per - (last_per >> 3) + (100 >> 3)); |
1281 | (rate_ctrl->state[tx_rate].per >> 3) + | ||
1282 | ((100) >> 3)); | ||
1283 | } | 930 | } |
1284 | 931 | ||
1285 | /* xretries == 1 or 2 */ | 932 | /* xretries == 1 or 2 */ |
1286 | 933 | ||
1287 | if (rate_ctrl->probe_rate == tx_rate) | 934 | if (ath_rc_priv->probe_rate == tx_rate) |
1288 | rate_ctrl->probe_rate = 0; | 935 | ath_rc_priv->probe_rate = 0; |
1289 | 936 | ||
1290 | } else { /* xretries == 0 */ | 937 | } else { /* xretries == 0 */ |
1291 | /* Update the PER. */ | ||
1292 | /* Make sure it doesn't index out of array's bounds. */ | ||
1293 | count = ARRAY_SIZE(nretry_to_per_lookup); | 938 | count = ARRAY_SIZE(nretry_to_per_lookup); |
1294 | if (retries >= count) | 939 | if (retries >= count) |
1295 | retries = count - 1; | 940 | retries = count - 1; |
1296 | if (info_priv->n_bad_frames) { | 941 | |
942 | if (tx_info_priv->n_bad_frames) { | ||
1297 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) | 943 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) |
1298 | * Assuming that n_frames is not 0. The current PER | 944 | * Assuming that n_frames is not 0. The current PER |
1299 | * from the retries is 100 * retries / (retries+1), | 945 | * from the retries is 100 * retries / (retries+1), |
@@ -1306,37 +952,35 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1306 | * the above PER. The expression below is a | 952 | * the above PER. The expression below is a |
1307 | * simplified version of the sum of these two terms. | 953 | * simplified version of the sum of these two terms. |
1308 | */ | 954 | */ |
1309 | if (info_priv->n_frames > 0) | 955 | if (tx_info_priv->n_frames > 0) { |
1310 | rate_ctrl->state[tx_rate].per | 956 | int n_frames, n_bad_frames; |
1311 | = (u8) | 957 | u8 cur_per, new_per; |
1312 | (rate_ctrl->state[tx_rate].per - | 958 | |
1313 | (rate_ctrl->state[tx_rate].per >> 3) + | 959 | n_bad_frames = retries * tx_info_priv->n_frames + |
1314 | ((100*(retries*info_priv->n_frames + | 960 | tx_info_priv->n_bad_frames; |
1315 | info_priv->n_bad_frames) / | 961 | n_frames = tx_info_priv->n_frames * (retries + 1); |
1316 | (info_priv->n_frames * | 962 | cur_per = (100 * n_bad_frames / n_frames) >> 3; |
1317 | (retries+1))) >> 3)); | 963 | new_per = (u8)(last_per - (last_per >> 3) + cur_per); |
964 | ath_rc_priv->state[tx_rate].per = new_per; | ||
965 | } | ||
1318 | } else { | 966 | } else { |
1319 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ | 967 | ath_rc_priv->state[tx_rate].per = |
1320 | 968 | (u8)(last_per - (last_per >> 3) + | |
1321 | rate_ctrl->state[tx_rate].per = (u8) | 969 | (nretry_to_per_lookup[retries] >> 3)); |
1322 | (rate_ctrl->state[tx_rate].per - | ||
1323 | (rate_ctrl->state[tx_rate].per >> 3) + | ||
1324 | (nretry_to_per_lookup[retries] >> 3)); | ||
1325 | } | 970 | } |
1326 | 971 | ||
1327 | rate_ctrl->rssi_last_prev2 = rate_ctrl->rssi_last_prev; | 972 | ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev; |
1328 | rate_ctrl->rssi_last_prev = rate_ctrl->rssi_last; | 973 | ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last; |
1329 | rate_ctrl->rssi_last = info_priv->tx.ts_rssi; | 974 | ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi; |
1330 | rate_ctrl->rssi_time = now_msec; | 975 | ath_rc_priv->rssi_time = now_msec; |
1331 | 976 | ||
1332 | /* | 977 | /* |
1333 | * If we got at most one retry then increase the max rate if | 978 | * If we got at most one retry then increase the max rate if |
1334 | * this was a probe. Otherwise, ignore the probe. | 979 | * this was a probe. Otherwise, ignore the probe. |
1335 | */ | 980 | */ |
1336 | 981 | if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) { | |
1337 | if (rate_ctrl->probe_rate && rate_ctrl->probe_rate == tx_rate) { | 982 | if (retries > 0 || 2 * tx_info_priv->n_bad_frames > |
1338 | if (retries > 0 || 2 * info_priv->n_bad_frames > | 983 | tx_info_priv->n_frames) { |
1339 | info_priv->n_frames) { | ||
1340 | /* | 984 | /* |
1341 | * Since we probed with just a single attempt, | 985 | * Since we probed with just a single attempt, |
1342 | * any retries means the probe failed. Also, | 986 | * any retries means the probe failed. Also, |
@@ -1344,17 +988,18 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1344 | * the subframes were bad then also consider | 988 | * the subframes were bad then also consider |
1345 | * the probe a failure. | 989 | * the probe a failure. |
1346 | */ | 990 | */ |
1347 | rate_ctrl->probe_rate = 0; | 991 | ath_rc_priv->probe_rate = 0; |
1348 | } else { | 992 | } else { |
1349 | u8 probe_rate = 0; | 993 | u8 probe_rate = 0; |
1350 | 994 | ||
1351 | rate_ctrl->rate_max_phy = rate_ctrl->probe_rate; | 995 | ath_rc_priv->rate_max_phy = |
1352 | probe_rate = rate_ctrl->probe_rate; | 996 | ath_rc_priv->probe_rate; |
997 | probe_rate = ath_rc_priv->probe_rate; | ||
1353 | 998 | ||
1354 | if (rate_ctrl->state[probe_rate].per > 30) | 999 | if (ath_rc_priv->state[probe_rate].per > 30) |
1355 | rate_ctrl->state[probe_rate].per = 20; | 1000 | ath_rc_priv->state[probe_rate].per = 20; |
1356 | 1001 | ||
1357 | rate_ctrl->probe_rate = 0; | 1002 | ath_rc_priv->probe_rate = 0; |
1358 | 1003 | ||
1359 | /* | 1004 | /* |
1360 | * Since this probe succeeded, we allow the next | 1005 | * Since this probe succeeded, we allow the next |
@@ -1362,8 +1007,8 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1362 | * to move up faster if the probes are | 1007 | * to move up faster if the probes are |
1363 | * succesful. | 1008 | * succesful. |
1364 | */ | 1009 | */ |
1365 | rate_ctrl->probe_time = now_msec - | 1010 | ath_rc_priv->probe_time = |
1366 | rate_table->probe_interval / 2; | 1011 | now_msec - rate_table->probe_interval / 2; |
1367 | } | 1012 | } |
1368 | } | 1013 | } |
1369 | 1014 | ||
@@ -1373,74 +1018,114 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1373 | * this was because of collisions or poor signal. | 1018 | * this was because of collisions or poor signal. |
1374 | * | 1019 | * |
1375 | * Later: if rssi_ack is close to | 1020 | * Later: if rssi_ack is close to |
1376 | * rate_ctrl->state[txRate].rssi_thres and we see lots | 1021 | * ath_rc_priv->state[txRate].rssi_thres and we see lots |
1377 | * of retries, then we could increase | 1022 | * of retries, then we could increase |
1378 | * rate_ctrl->state[txRate].rssi_thres. | 1023 | * ath_rc_priv->state[txRate].rssi_thres. |
1379 | */ | 1024 | */ |
1380 | rate_ctrl->hw_maxretry_pktcnt = 0; | 1025 | ath_rc_priv->hw_maxretry_pktcnt = 0; |
1381 | } else { | 1026 | } else { |
1027 | int32_t rssi_ackAvg; | ||
1028 | int8_t rssi_thres; | ||
1029 | int8_t rssi_ack_vmin; | ||
1030 | |||
1382 | /* | 1031 | /* |
1383 | * It worked with no retries. First ignore bogus (small) | 1032 | * It worked with no retries. First ignore bogus (small) |
1384 | * rssi_ack values. | 1033 | * rssi_ack values. |
1385 | */ | 1034 | */ |
1386 | if (tx_rate == rate_ctrl->rate_max_phy && | 1035 | if (tx_rate == ath_rc_priv->rate_max_phy && |
1387 | rate_ctrl->hw_maxretry_pktcnt < 255) { | 1036 | ath_rc_priv->hw_maxretry_pktcnt < 255) { |
1388 | rate_ctrl->hw_maxretry_pktcnt++; | 1037 | ath_rc_priv->hw_maxretry_pktcnt++; |
1389 | } | 1038 | } |
1390 | 1039 | ||
1391 | if (info_priv->tx.ts_rssi >= | 1040 | if (tx_info_priv->tx.ts_rssi < |
1392 | rate_table->info[tx_rate].rssi_ack_validmin) { | 1041 | rate_table->info[tx_rate].rssi_ack_validmin) |
1393 | /* Average the rssi */ | 1042 | goto exit; |
1394 | if (tx_rate != rate_ctrl->rssi_sum_rate) { | ||
1395 | rate_ctrl->rssi_sum_rate = tx_rate; | ||
1396 | rate_ctrl->rssi_sum = | ||
1397 | rate_ctrl->rssi_sum_cnt = 0; | ||
1398 | } | ||
1399 | 1043 | ||
1400 | rate_ctrl->rssi_sum += info_priv->tx.ts_rssi; | 1044 | /* Average the rssi */ |
1401 | rate_ctrl->rssi_sum_cnt++; | 1045 | if (tx_rate != ath_rc_priv->rssi_sum_rate) { |
1402 | 1046 | ath_rc_priv->rssi_sum_rate = tx_rate; | |
1403 | if (rate_ctrl->rssi_sum_cnt > 4) { | 1047 | ath_rc_priv->rssi_sum = |
1404 | int32_t rssi_ackAvg = | 1048 | ath_rc_priv->rssi_sum_cnt = 0; |
1405 | (rate_ctrl->rssi_sum + 2) / 4; | ||
1406 | int8_t rssi_thres = | ||
1407 | rate_ctrl->state[tx_rate]. | ||
1408 | rssi_thres; | ||
1409 | int8_t rssi_ack_vmin = | ||
1410 | rate_table->info[tx_rate]. | ||
1411 | rssi_ack_validmin; | ||
1412 | |||
1413 | rate_ctrl->rssi_sum = | ||
1414 | rate_ctrl->rssi_sum_cnt = 0; | ||
1415 | |||
1416 | /* Now reduce the current | ||
1417 | * rssi threshold. */ | ||
1418 | if ((rssi_ackAvg < rssi_thres + 2) && | ||
1419 | (rssi_thres > rssi_ack_vmin)) { | ||
1420 | rate_ctrl->state[tx_rate]. | ||
1421 | rssi_thres--; | ||
1422 | } | ||
1423 | |||
1424 | state_change = TRUE; | ||
1425 | } | ||
1426 | } | 1049 | } |
1050 | |||
1051 | ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi; | ||
1052 | ath_rc_priv->rssi_sum_cnt++; | ||
1053 | |||
1054 | if (ath_rc_priv->rssi_sum_cnt < 4) | ||
1055 | goto exit; | ||
1056 | |||
1057 | rssi_ackAvg = | ||
1058 | (ath_rc_priv->rssi_sum + 2) / 4; | ||
1059 | rssi_thres = | ||
1060 | ath_rc_priv->state[tx_rate].rssi_thres; | ||
1061 | rssi_ack_vmin = | ||
1062 | rate_table->info[tx_rate].rssi_ack_validmin; | ||
1063 | |||
1064 | ath_rc_priv->rssi_sum = | ||
1065 | ath_rc_priv->rssi_sum_cnt = 0; | ||
1066 | |||
1067 | /* Now reduce the current rssi threshold */ | ||
1068 | if ((rssi_ackAvg < rssi_thres + 2) && | ||
1069 | (rssi_thres > rssi_ack_vmin)) { | ||
1070 | ath_rc_priv->state[tx_rate].rssi_thres--; | ||
1071 | } | ||
1072 | |||
1073 | state_change = true; | ||
1427 | } | 1074 | } |
1428 | } | 1075 | } |
1076 | exit: | ||
1077 | return state_change; | ||
1078 | } | ||
1079 | |||
1080 | /* Update PER, RSSI and whatever else that the code thinks it is doing. | ||
1081 | If you can make sense of all this, you really need to go out more. */ | ||
1082 | |||
1083 | static void ath_rc_update_ht(struct ath_softc *sc, | ||
1084 | struct ath_rate_priv *ath_rc_priv, | ||
1085 | struct ath_tx_info_priv *tx_info_priv, | ||
1086 | int tx_rate, int xretries, int retries) | ||
1087 | { | ||
1088 | #define CHK_RSSI(rate) \ | ||
1089 | ((ath_rc_priv->state[(rate)].rssi_thres + \ | ||
1090 | rate_table->info[(rate)].rssi_ack_deltamin) > \ | ||
1091 | ath_rc_priv->state[(rate)+1].rssi_thres) | ||
1092 | |||
1093 | u32 now_msec = jiffies_to_msecs(jiffies); | ||
1094 | int rate; | ||
1095 | u8 last_per; | ||
1096 | bool state_change = false; | ||
1097 | struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode]; | ||
1098 | int size = ath_rc_priv->rate_table_size; | ||
1099 | |||
1100 | if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) | ||
1101 | return; | ||
1102 | |||
1103 | /* To compensate for some imbalance between ctrl and ext. channel */ | ||
1104 | |||
1105 | if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy)) | ||
1106 | tx_info_priv->tx.ts_rssi = | ||
1107 | tx_info_priv->tx.ts_rssi < 3 ? 0 : | ||
1108 | tx_info_priv->tx.ts_rssi - 3; | ||
1429 | 1109 | ||
1430 | /* For all cases */ | 1110 | last_per = ath_rc_priv->state[tx_rate].per; |
1111 | |||
1112 | /* Update PER first */ | ||
1113 | state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, | ||
1114 | tx_info_priv, tx_rate, xretries, | ||
1115 | retries, now_msec); | ||
1431 | 1116 | ||
1432 | /* | 1117 | /* |
1433 | * If this rate looks bad (high PER) then stop using it for | 1118 | * If this rate looks bad (high PER) then stop using it for |
1434 | * a while (except if we are probing). | 1119 | * a while (except if we are probing). |
1435 | */ | 1120 | */ |
1436 | if (rate_ctrl->state[tx_rate].per >= 55 && tx_rate > 0 && | 1121 | if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 && |
1437 | rate_table->info[tx_rate].ratekbps <= | 1122 | rate_table->info[tx_rate].ratekbps <= |
1438 | rate_table->info[rate_ctrl->rate_max_phy].ratekbps) { | 1123 | rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { |
1439 | ath_rc_get_nextlowervalid_txrate(rate_table, rate_ctrl, | 1124 | ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv, |
1440 | (u8) tx_rate, &rate_ctrl->rate_max_phy); | 1125 | (u8)tx_rate, &ath_rc_priv->rate_max_phy); |
1441 | 1126 | ||
1442 | /* Don't probe for a little while. */ | 1127 | /* Don't probe for a little while. */ |
1443 | rate_ctrl->probe_time = now_msec; | 1128 | ath_rc_priv->probe_time = now_msec; |
1444 | } | 1129 | } |
1445 | 1130 | ||
1446 | if (state_change) { | 1131 | if (state_change) { |
@@ -1451,20 +1136,15 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1451 | * made to keep the rssi thresholds monotonically | 1136 | * made to keep the rssi thresholds monotonically |
1452 | * increasing between the CCK and OFDM rates.) | 1137 | * increasing between the CCK and OFDM rates.) |
1453 | */ | 1138 | */ |
1454 | for (rate = tx_rate; rate < | 1139 | for (rate = tx_rate; rate < size - 1; rate++) { |
1455 | rate_ctrl->rate_table_size - 1; rate++) { | ||
1456 | if (rate_table->info[rate+1].phy != | 1140 | if (rate_table->info[rate+1].phy != |
1457 | rate_table->info[tx_rate].phy) | 1141 | rate_table->info[tx_rate].phy) |
1458 | break; | 1142 | break; |
1459 | 1143 | ||
1460 | if (rate_ctrl->state[rate].rssi_thres + | 1144 | if (CHK_RSSI(rate)) { |
1461 | rate_table->info[rate].rssi_ack_deltamin > | 1145 | ath_rc_priv->state[rate+1].rssi_thres = |
1462 | rate_ctrl->state[rate+1].rssi_thres) { | 1146 | ath_rc_priv->state[rate].rssi_thres + |
1463 | rate_ctrl->state[rate+1].rssi_thres = | 1147 | rate_table->info[rate].rssi_ack_deltamin; |
1464 | rate_ctrl->state[rate]. | ||
1465 | rssi_thres + | ||
1466 | rate_table->info[rate]. | ||
1467 | rssi_ack_deltamin; | ||
1468 | } | 1148 | } |
1469 | } | 1149 | } |
1470 | 1150 | ||
@@ -1474,27 +1154,20 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1474 | rate_table->info[tx_rate].phy) | 1154 | rate_table->info[tx_rate].phy) |
1475 | break; | 1155 | break; |
1476 | 1156 | ||
1477 | if (rate_ctrl->state[rate].rssi_thres + | 1157 | if (CHK_RSSI(rate)) { |
1478 | rate_table->info[rate].rssi_ack_deltamin > | 1158 | if (ath_rc_priv->state[rate+1].rssi_thres < |
1479 | rate_ctrl->state[rate+1].rssi_thres) { | 1159 | rate_table->info[rate].rssi_ack_deltamin) |
1480 | if (rate_ctrl->state[rate+1].rssi_thres < | 1160 | ath_rc_priv->state[rate].rssi_thres = 0; |
1481 | rate_table->info[rate]. | ||
1482 | rssi_ack_deltamin) | ||
1483 | rate_ctrl->state[rate].rssi_thres = 0; | ||
1484 | else { | 1161 | else { |
1485 | rate_ctrl->state[rate].rssi_thres = | 1162 | ath_rc_priv->state[rate].rssi_thres = |
1486 | rate_ctrl->state[rate+1]. | 1163 | ath_rc_priv->state[rate+1].rssi_thres - |
1487 | rssi_thres - | 1164 | rate_table->info[rate].rssi_ack_deltamin; |
1488 | rate_table->info[rate]. | ||
1489 | rssi_ack_deltamin; | ||
1490 | } | 1165 | } |
1491 | 1166 | ||
1492 | if (rate_ctrl->state[rate].rssi_thres < | 1167 | if (ath_rc_priv->state[rate].rssi_thres < |
1493 | rate_table->info[rate]. | 1168 | rate_table->info[rate].rssi_ack_validmin) { |
1494 | rssi_ack_validmin) { | 1169 | ath_rc_priv->state[rate].rssi_thres = |
1495 | rate_ctrl->state[rate].rssi_thres = | 1170 | rate_table->info[rate].rssi_ack_validmin; |
1496 | rate_table->info[rate]. | ||
1497 | rssi_ack_validmin; | ||
1498 | } | 1171 | } |
1499 | } | 1172 | } |
1500 | } | 1173 | } |
@@ -1502,74 +1175,86 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1502 | 1175 | ||
1503 | /* Make sure the rates below this have lower PER */ | 1176 | /* Make sure the rates below this have lower PER */ |
1504 | /* Monotonicity is kept only for rates below the current rate. */ | 1177 | /* Monotonicity is kept only for rates below the current rate. */ |
1505 | if (rate_ctrl->state[tx_rate].per < last_per) { | 1178 | if (ath_rc_priv->state[tx_rate].per < last_per) { |
1506 | for (rate = tx_rate - 1; rate >= 0; rate--) { | 1179 | for (rate = tx_rate - 1; rate >= 0; rate--) { |
1507 | if (rate_table->info[rate].phy != | 1180 | if (rate_table->info[rate].phy != |
1508 | rate_table->info[tx_rate].phy) | 1181 | rate_table->info[tx_rate].phy) |
1509 | break; | 1182 | break; |
1510 | 1183 | ||
1511 | if (rate_ctrl->state[rate].per > | 1184 | if (ath_rc_priv->state[rate].per > |
1512 | rate_ctrl->state[rate+1].per) { | 1185 | ath_rc_priv->state[rate+1].per) { |
1513 | rate_ctrl->state[rate].per = | 1186 | ath_rc_priv->state[rate].per = |
1514 | rate_ctrl->state[rate+1].per; | 1187 | ath_rc_priv->state[rate+1].per; |
1515 | } | 1188 | } |
1516 | } | 1189 | } |
1517 | } | 1190 | } |
1518 | 1191 | ||
1519 | /* Maintain monotonicity for rates above the current rate */ | 1192 | /* Maintain monotonicity for rates above the current rate */ |
1520 | for (rate = tx_rate; rate < rate_ctrl->rate_table_size - 1; rate++) { | 1193 | for (rate = tx_rate; rate < size - 1; rate++) { |
1521 | if (rate_ctrl->state[rate+1].per < rate_ctrl->state[rate].per) | 1194 | if (ath_rc_priv->state[rate+1].per < |
1522 | rate_ctrl->state[rate+1].per = | 1195 | ath_rc_priv->state[rate].per) |
1523 | rate_ctrl->state[rate].per; | 1196 | ath_rc_priv->state[rate+1].per = |
1197 | ath_rc_priv->state[rate].per; | ||
1524 | } | 1198 | } |
1525 | 1199 | ||
1526 | /* Every so often, we reduce the thresholds and | 1200 | /* Every so often, we reduce the thresholds and |
1527 | * PER (different for CCK and OFDM). */ | 1201 | * PER (different for CCK and OFDM). */ |
1528 | if (now_msec - rate_ctrl->rssi_down_time >= | 1202 | if (now_msec - ath_rc_priv->rssi_down_time >= |
1529 | rate_table->rssi_reduce_interval) { | 1203 | rate_table->rssi_reduce_interval) { |
1530 | 1204 | ||
1531 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { | 1205 | for (rate = 0; rate < size; rate++) { |
1532 | if (rate_ctrl->state[rate].rssi_thres > | 1206 | if (ath_rc_priv->state[rate].rssi_thres > |
1533 | rate_table->info[rate].rssi_ack_validmin) | 1207 | rate_table->info[rate].rssi_ack_validmin) |
1534 | rate_ctrl->state[rate].rssi_thres -= 1; | 1208 | ath_rc_priv->state[rate].rssi_thres -= 1; |
1535 | } | 1209 | } |
1536 | rate_ctrl->rssi_down_time = now_msec; | 1210 | ath_rc_priv->rssi_down_time = now_msec; |
1537 | } | 1211 | } |
1538 | 1212 | ||
1539 | /* Every so often, we reduce the thresholds | 1213 | /* Every so often, we reduce the thresholds |
1540 | * and PER (different for CCK and OFDM). */ | 1214 | * and PER (different for CCK and OFDM). */ |
1541 | if (now_msec - rate_ctrl->per_down_time >= | 1215 | if (now_msec - ath_rc_priv->per_down_time >= |
1542 | rate_table->rssi_reduce_interval) { | 1216 | rate_table->rssi_reduce_interval) { |
1543 | for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) { | 1217 | for (rate = 0; rate < size; rate++) { |
1544 | rate_ctrl->state[rate].per = | 1218 | ath_rc_priv->state[rate].per = |
1545 | 7 * rate_ctrl->state[rate].per / 8; | 1219 | 7 * ath_rc_priv->state[rate].per / 8; |
1546 | } | 1220 | } |
1547 | 1221 | ||
1548 | rate_ctrl->per_down_time = now_msec; | 1222 | ath_rc_priv->per_down_time = now_msec; |
1549 | } | 1223 | } |
1224 | |||
1225 | #undef CHK_RSSI | ||
1550 | } | 1226 | } |
1551 | 1227 | ||
1552 | /* | 1228 | static int ath_rc_get_rateindex(struct ath_rate_table *rate_table, |
1553 | * This routine is called in rate control callback tx_status() to give | 1229 | struct ieee80211_tx_rate *rate) |
1554 | * the status of previous frames. | ||
1555 | */ | ||
1556 | static void ath_rc_update(struct ath_softc *sc, | ||
1557 | struct ath_rate_node *ath_rc_priv, | ||
1558 | struct ath_tx_info_priv *info_priv, int final_ts_idx, | ||
1559 | int xretries, int long_retry) | ||
1560 | { | 1230 | { |
1561 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | 1231 | int rix; |
1232 | |||
1233 | if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && | ||
1234 | (rate->flags & IEEE80211_TX_RC_SHORT_GI)) | ||
1235 | rix = rate_table->info[rate->idx].ht_index; | ||
1236 | else if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
1237 | rix = rate_table->info[rate->idx].sgi_index; | ||
1238 | else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
1239 | rix = rate_table->info[rate->idx].cw40index; | ||
1240 | else | ||
1241 | rix = rate_table->info[rate->idx].base_index; | ||
1242 | |||
1243 | return rix; | ||
1244 | } | ||
1245 | |||
1246 | static void ath_rc_tx_status(struct ath_softc *sc, | ||
1247 | struct ath_rate_priv *ath_rc_priv, | ||
1248 | struct ieee80211_tx_info *tx_info, | ||
1249 | int final_ts_idx, int xretries, int long_retry) | ||
1250 | { | ||
1251 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
1562 | struct ath_rate_table *rate_table; | 1252 | struct ath_rate_table *rate_table; |
1563 | struct ath_tx_ratectrl *rate_ctrl; | 1253 | struct ieee80211_tx_rate *rates = tx_info->status.rates; |
1564 | struct ath_rc_series rcs[4]; | ||
1565 | u8 flags; | 1254 | u8 flags; |
1566 | u32 series = 0, rix; | 1255 | u32 i = 0, rix; |
1567 | 1256 | ||
1568 | memcpy(rcs, info_priv->rcs, 4 * sizeof(rcs[0])); | 1257 | rate_table = sc->hw_rate_table[sc->sc_curmode]; |
1569 | rate_table = (struct ath_rate_table *) | ||
1570 | asc->hw_rate_table[sc->sc_curmode]; | ||
1571 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
1572 | ASSERT(rcs[0].tries != 0); | ||
1573 | 1258 | ||
1574 | /* | 1259 | /* |
1575 | * If the first rate is not the final index, there | 1260 | * If the first rate is not the final index, there |
@@ -1577,32 +1262,22 @@ static void ath_rc_update(struct ath_softc *sc, | |||
1577 | */ | 1262 | */ |
1578 | if (final_ts_idx != 0) { | 1263 | if (final_ts_idx != 0) { |
1579 | /* Process intermediate rates that failed.*/ | 1264 | /* Process intermediate rates that failed.*/ |
1580 | for (series = 0; series < final_ts_idx ; series++) { | 1265 | for (i = 0; i < final_ts_idx ; i++) { |
1581 | if (rcs[series].tries != 0) { | 1266 | if (rates[i].count != 0 && (rates[i].idx >= 0)) { |
1582 | flags = rcs[series].flags; | 1267 | flags = rates[i].flags; |
1268 | |||
1583 | /* If HT40 and we have switched mode from | 1269 | /* If HT40 and we have switched mode from |
1584 | * 40 to 20 => don't update */ | 1270 | * 40 to 20 => don't update */ |
1585 | if ((flags & ATH_RC_CW40_FLAG) && | 1271 | |
1586 | (rate_ctrl->rc_phy_mode != | 1272 | if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && |
1587 | (flags & ATH_RC_CW40_FLAG))) | 1273 | (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) |
1588 | return; | 1274 | return; |
1589 | if ((flags & ATH_RC_CW40_FLAG) && | 1275 | |
1590 | (flags & ATH_RC_SGI_FLAG)) | 1276 | rix = ath_rc_get_rateindex(rate_table, &rates[i]); |
1591 | rix = rate_table->info[ | ||
1592 | rcs[series].rix].ht_index; | ||
1593 | else if (flags & ATH_RC_SGI_FLAG) | ||
1594 | rix = rate_table->info[ | ||
1595 | rcs[series].rix].sgi_index; | ||
1596 | else if (flags & ATH_RC_CW40_FLAG) | ||
1597 | rix = rate_table->info[ | ||
1598 | rcs[series].rix].cw40index; | ||
1599 | else | ||
1600 | rix = rate_table->info[ | ||
1601 | rcs[series].rix].base_index; | ||
1602 | ath_rc_update_ht(sc, ath_rc_priv, | 1277 | ath_rc_update_ht(sc, ath_rc_priv, |
1603 | info_priv, rix, | 1278 | tx_info_priv, rix, |
1604 | xretries ? 1 : 2, | 1279 | xretries ? 1 : 2, |
1605 | rcs[series].tries); | 1280 | rates[i].count); |
1606 | } | 1281 | } |
1607 | } | 1282 | } |
1608 | } else { | 1283 | } else { |
@@ -1612,240 +1287,110 @@ static void ath_rc_update(struct ath_softc *sc, | |||
1612 | * Treating it as an excessive retry penalizes the rate | 1287 | * Treating it as an excessive retry penalizes the rate |
1613 | * inordinately. | 1288 | * inordinately. |
1614 | */ | 1289 | */ |
1615 | if (rcs[0].tries == 1 && xretries == 1) | 1290 | if (rates[0].count == 1 && xretries == 1) |
1616 | xretries = 2; | 1291 | xretries = 2; |
1617 | } | 1292 | } |
1618 | 1293 | ||
1619 | flags = rcs[series].flags; | 1294 | flags = rates[i].flags; |
1620 | /* If HT40 and we have switched mode from 40 to 20 => don't update */ | ||
1621 | if ((flags & ATH_RC_CW40_FLAG) && | ||
1622 | (rate_ctrl->rc_phy_mode != (flags & ATH_RC_CW40_FLAG))) | ||
1623 | return; | ||
1624 | |||
1625 | if ((flags & ATH_RC_CW40_FLAG) && (flags & ATH_RC_SGI_FLAG)) | ||
1626 | rix = rate_table->info[rcs[series].rix].ht_index; | ||
1627 | else if (flags & ATH_RC_SGI_FLAG) | ||
1628 | rix = rate_table->info[rcs[series].rix].sgi_index; | ||
1629 | else if (flags & ATH_RC_CW40_FLAG) | ||
1630 | rix = rate_table->info[rcs[series].rix].cw40index; | ||
1631 | else | ||
1632 | rix = rate_table->info[rcs[series].rix].base_index; | ||
1633 | |||
1634 | ath_rc_update_ht(sc, ath_rc_priv, info_priv, rix, | ||
1635 | xretries, long_retry); | ||
1636 | } | ||
1637 | |||
1638 | /* | ||
1639 | * Process a tx descriptor for a completed transmit (success or failure). | ||
1640 | */ | ||
1641 | static void ath_rate_tx_complete(struct ath_softc *sc, | ||
1642 | struct ath_node *an, | ||
1643 | struct ath_rate_node *rc_priv, | ||
1644 | struct ath_tx_info_priv *info_priv) | ||
1645 | { | ||
1646 | int final_ts_idx = info_priv->tx.ts_rateindex; | ||
1647 | int tx_status = 0, is_underrun = 0; | ||
1648 | struct ath_vap *avp; | ||
1649 | 1295 | ||
1650 | avp = rc_priv->avp; | 1296 | /* If HT40 and we have switched mode from 40 to 20 => don't update */ |
1651 | if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) || | 1297 | if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && |
1652 | (info_priv->tx.ts_status & ATH9K_TXERR_FILT)) | 1298 | (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) { |
1653 | return; | 1299 | return; |
1654 | |||
1655 | if (info_priv->tx.ts_rssi > 0) { | ||
1656 | ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi, | ||
1657 | info_priv->tx.ts_rssi); | ||
1658 | } | 1300 | } |
1659 | 1301 | ||
1660 | /* | 1302 | rix = ath_rc_get_rateindex(rate_table, &rates[i]); |
1661 | * If underrun error is seen assume it as an excessive retry only | 1303 | ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix, |
1662 | * if prefetch trigger level have reached the max (0x3f for 5416) | 1304 | xretries, long_retry); |
1663 | * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY | ||
1664 | * times. This affects how ratectrl updates PER for the failed rate. | ||
1665 | */ | ||
1666 | if (info_priv->tx.ts_flags & | ||
1667 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) && | ||
1668 | ((sc->sc_ah->ah_txTrigLevel) >= tx_triglevel_max)) { | ||
1669 | tx_status = 1; | ||
1670 | is_underrun = 1; | ||
1671 | } | ||
1672 | |||
1673 | if ((info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) || | ||
1674 | (info_priv->tx.ts_status & ATH9K_TXERR_FIFO)) | ||
1675 | tx_status = 1; | ||
1676 | |||
1677 | ath_rc_update(sc, rc_priv, info_priv, final_ts_idx, tx_status, | ||
1678 | (is_underrun) ? ATH_11N_TXMAXTRY : | ||
1679 | info_priv->tx.ts_longretry); | ||
1680 | } | 1305 | } |
1681 | 1306 | ||
1682 | /* | 1307 | static void ath_rc_init(struct ath_softc *sc, |
1683 | * Update the SIB's rate control information | 1308 | struct ath_rate_priv *ath_rc_priv, |
1684 | * | 1309 | struct ieee80211_supported_band *sband, |
1685 | * This should be called when the supported rates change | 1310 | struct ieee80211_sta *sta) |
1686 | * (e.g. SME operation, wireless mode change) | ||
1687 | * | ||
1688 | * It will determine which rates are valid for use. | ||
1689 | */ | ||
1690 | static void ath_rc_sib_update(struct ath_softc *sc, | ||
1691 | struct ath_rate_node *ath_rc_priv, | ||
1692 | u32 capflag, int keep_state, | ||
1693 | struct ath_rateset *negotiated_rates, | ||
1694 | struct ath_rateset *negotiated_htrates) | ||
1695 | { | 1311 | { |
1696 | struct ath_rate_table *rate_table = NULL; | 1312 | struct ath_rate_table *rate_table = NULL; |
1697 | struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc; | 1313 | struct ath_rateset *rateset = &ath_rc_priv->neg_rates; |
1698 | struct ath_rateset *rateset = negotiated_rates; | 1314 | u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; |
1699 | u8 *ht_mcs = (u8 *)negotiated_htrates; | ||
1700 | struct ath_tx_ratectrl *rate_ctrl = | ||
1701 | (struct ath_tx_ratectrl *)ath_rc_priv; | ||
1702 | u8 i, j, k, hi = 0, hthi = 0; | 1315 | u8 i, j, k, hi = 0, hthi = 0; |
1703 | 1316 | ||
1704 | rate_table = (struct ath_rate_table *) | 1317 | rate_table = sc->hw_rate_table[sc->sc_curmode]; |
1705 | asc->hw_rate_table[sc->sc_curmode]; | 1318 | |
1319 | if (sta->ht_cap.ht_supported) { | ||
1320 | if (sband->band == IEEE80211_BAND_2GHZ) | ||
1321 | rate_table = sc->hw_rate_table[ATH9K_MODE_11NG_HT20]; | ||
1322 | else | ||
1323 | rate_table = sc->hw_rate_table[ATH9K_MODE_11NA_HT20]; | ||
1324 | |||
1325 | ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG); | ||
1326 | |||
1327 | if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | ||
1328 | ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG; | ||
1329 | } | ||
1706 | 1330 | ||
1707 | /* Initial rate table size. Will change depending | 1331 | /* Initial rate table size. Will change depending |
1708 | * on the working rate set */ | 1332 | * on the working rate set */ |
1709 | rate_ctrl->rate_table_size = MAX_TX_RATE_TBL; | 1333 | ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; |
1710 | 1334 | ||
1711 | /* Initialize thresholds according to the global rate table */ | 1335 | /* Initialize thresholds according to the global rate table */ |
1712 | for (i = 0 ; (i < rate_ctrl->rate_table_size) && (!keep_state); i++) { | 1336 | for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { |
1713 | rate_ctrl->state[i].rssi_thres = | 1337 | ath_rc_priv->state[i].rssi_thres = |
1714 | rate_table->info[i].rssi_ack_validmin; | 1338 | rate_table->info[i].rssi_ack_validmin; |
1715 | rate_ctrl->state[i].per = 0; | 1339 | ath_rc_priv->state[i].per = 0; |
1716 | } | 1340 | } |
1717 | 1341 | ||
1718 | /* Determine the valid rates */ | 1342 | /* Determine the valid rates */ |
1719 | ath_rc_init_valid_txmask(rate_ctrl); | 1343 | ath_rc_init_valid_txmask(ath_rc_priv); |
1720 | 1344 | ||
1721 | for (i = 0; i < WLAN_RC_PHY_MAX; i++) { | 1345 | for (i = 0; i < WLAN_RC_PHY_MAX; i++) { |
1722 | for (j = 0; j < MAX_TX_RATE_PHY; j++) | 1346 | for (j = 0; j < MAX_TX_RATE_PHY; j++) |
1723 | rate_ctrl->valid_phy_rateidx[i][j] = 0; | 1347 | ath_rc_priv->valid_phy_rateidx[i][j] = 0; |
1724 | rate_ctrl->valid_phy_ratecnt[i] = 0; | 1348 | ath_rc_priv->valid_phy_ratecnt[i] = 0; |
1725 | } | 1349 | } |
1726 | rate_ctrl->rc_phy_mode = (capflag & WLAN_RC_40_FLAG); | 1350 | ath_rc_priv->rc_phy_mode = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG); |
1727 | 1351 | ||
1728 | /* Set stream capability */ | 1352 | /* Set stream capability */ |
1729 | ath_rc_priv->single_stream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1; | 1353 | ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1; |
1730 | 1354 | ||
1731 | if (!rateset->rs_nrates) { | 1355 | if (!rateset->rs_nrates) { |
1732 | /* No working rate, just initialize valid rates */ | 1356 | /* No working rate, just initialize valid rates */ |
1733 | hi = ath_rc_sib_init_validrates(ath_rc_priv, rate_table, | 1357 | hi = ath_rc_init_validrates(ath_rc_priv, rate_table, |
1734 | capflag); | 1358 | ath_rc_priv->ht_cap); |
1735 | } else { | 1359 | } else { |
1736 | /* Use intersection of working rates and valid rates */ | 1360 | /* Use intersection of working rates and valid rates */ |
1737 | hi = ath_rc_sib_setvalid_rates(ath_rc_priv, rate_table, | 1361 | hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table, |
1738 | rateset, capflag); | 1362 | rateset, ath_rc_priv->ht_cap); |
1739 | if (capflag & WLAN_RC_HT_FLAG) { | 1363 | if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) { |
1740 | hthi = ath_rc_sib_setvalid_htrates(ath_rc_priv, | 1364 | hthi = ath_rc_setvalid_htrates(ath_rc_priv, |
1741 | rate_table, | 1365 | rate_table, |
1742 | ht_mcs, | 1366 | ht_mcs, |
1743 | capflag); | 1367 | ath_rc_priv->ht_cap); |
1744 | } | 1368 | } |
1745 | hi = A_MAX(hi, hthi); | 1369 | hi = A_MAX(hi, hthi); |
1746 | } | 1370 | } |
1747 | 1371 | ||
1748 | rate_ctrl->rate_table_size = hi + 1; | 1372 | ath_rc_priv->rate_table_size = hi + 1; |
1749 | rate_ctrl->rate_max_phy = 0; | 1373 | ath_rc_priv->rate_max_phy = 0; |
1750 | ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL); | 1374 | ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); |
1751 | 1375 | ||
1752 | for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { | 1376 | for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { |
1753 | for (j = 0; j < rate_ctrl->valid_phy_ratecnt[i]; j++) { | 1377 | for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) { |
1754 | rate_ctrl->valid_rate_index[k++] = | 1378 | ath_rc_priv->valid_rate_index[k++] = |
1755 | rate_ctrl->valid_phy_rateidx[i][j]; | 1379 | ath_rc_priv->valid_phy_rateidx[i][j]; |
1756 | } | 1380 | } |
1757 | 1381 | ||
1758 | if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, TRUE) | 1382 | if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) |
1759 | || !rate_ctrl->valid_phy_ratecnt[i]) | 1383 | || !ath_rc_priv->valid_phy_ratecnt[i]) |
1760 | continue; | 1384 | continue; |
1761 | 1385 | ||
1762 | rate_ctrl->rate_max_phy = rate_ctrl->valid_phy_rateidx[i][j-1]; | 1386 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1]; |
1763 | } | ||
1764 | ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL); | ||
1765 | ASSERT(k <= MAX_TX_RATE_TBL); | ||
1766 | |||
1767 | rate_ctrl->max_valid_rate = k; | ||
1768 | /* | ||
1769 | * Some third party vendors don't send the supported rate series in | ||
1770 | * order. So sorting to make sure its in order, otherwise our RateFind | ||
1771 | * Algo will select wrong rates | ||
1772 | */ | ||
1773 | ath_rc_sort_validrates(rate_table, rate_ctrl); | ||
1774 | rate_ctrl->rate_max_phy = rate_ctrl->valid_rate_index[k-4]; | ||
1775 | } | ||
1776 | |||
1777 | /* | ||
1778 | * Update rate-control state on station associate/reassociate. | ||
1779 | */ | ||
1780 | static int ath_rate_newassoc(struct ath_softc *sc, | ||
1781 | struct ath_rate_node *ath_rc_priv, | ||
1782 | unsigned int capflag, | ||
1783 | struct ath_rateset *negotiated_rates, | ||
1784 | struct ath_rateset *negotiated_htrates) | ||
1785 | { | ||
1786 | |||
1787 | |||
1788 | ath_rc_priv->ht_cap = | ||
1789 | ((capflag & ATH_RC_DS_FLAG) ? WLAN_RC_DS_FLAG : 0) | | ||
1790 | ((capflag & ATH_RC_SGI_FLAG) ? WLAN_RC_SGI_FLAG : 0) | | ||
1791 | ((capflag & ATH_RC_HT_FLAG) ? WLAN_RC_HT_FLAG : 0) | | ||
1792 | ((capflag & ATH_RC_CW40_FLAG) ? WLAN_RC_40_FLAG : 0); | ||
1793 | |||
1794 | ath_rc_sib_update(sc, ath_rc_priv, ath_rc_priv->ht_cap, 0, | ||
1795 | negotiated_rates, negotiated_htrates); | ||
1796 | |||
1797 | return 0; | ||
1798 | } | ||
1799 | |||
1800 | /* | ||
1801 | * This routine is called to initialize the rate control parameters | ||
1802 | * in the SIB. It is called initially during system initialization | ||
1803 | * or when a station is associated with the AP. | ||
1804 | */ | ||
1805 | static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv) | ||
1806 | { | ||
1807 | struct ath_tx_ratectrl *rate_ctrl; | ||
1808 | |||
1809 | rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv); | ||
1810 | rate_ctrl->rssi_down_time = jiffies_to_msecs(jiffies); | ||
1811 | } | ||
1812 | |||
1813 | |||
1814 | static void ath_setup_rates(struct ath_softc *sc, | ||
1815 | struct ieee80211_supported_band *sband, | ||
1816 | struct ieee80211_sta *sta, | ||
1817 | struct ath_rate_node *rc_priv) | ||
1818 | |||
1819 | { | ||
1820 | int i, j = 0; | ||
1821 | |||
1822 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | ||
1823 | |||
1824 | for (i = 0; i < sband->n_bitrates; i++) { | ||
1825 | if (sta->supp_rates[sband->band] & BIT(i)) { | ||
1826 | rc_priv->neg_rates.rs_rates[j] | ||
1827 | = (sband->bitrates[i].bitrate * 2) / 10; | ||
1828 | j++; | ||
1829 | } | ||
1830 | } | ||
1831 | rc_priv->neg_rates.rs_nrates = j; | ||
1832 | } | ||
1833 | |||
1834 | void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv) | ||
1835 | { | ||
1836 | struct ath_softc *sc = hw->priv; | ||
1837 | u32 capflag = 0; | ||
1838 | |||
1839 | if (hw->conf.ht.enabled) { | ||
1840 | capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG; | ||
1841 | if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040) | ||
1842 | capflag |= ATH_RC_CW40_FLAG; | ||
1843 | } | 1387 | } |
1388 | ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); | ||
1389 | ASSERT(k <= RATE_TABLE_SIZE); | ||
1844 | 1390 | ||
1845 | ath_rate_newassoc(sc, rc_priv, capflag, | 1391 | ath_rc_priv->max_valid_rate = k; |
1846 | &rc_priv->neg_rates, | 1392 | ath_rc_sort_validrates(rate_table, ath_rc_priv); |
1847 | &rc_priv->neg_ht_rates); | 1393 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; |
1848 | |||
1849 | } | 1394 | } |
1850 | 1395 | ||
1851 | /* Rate Control callbacks */ | 1396 | /* Rate Control callbacks */ |
@@ -1854,27 +1399,48 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1854 | struct sk_buff *skb) | 1399 | struct sk_buff *skb) |
1855 | { | 1400 | { |
1856 | struct ath_softc *sc = priv; | 1401 | struct ath_softc *sc = priv; |
1857 | struct ath_tx_info_priv *tx_info_priv; | 1402 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
1858 | struct ath_node *an; | 1403 | struct ath_tx_info_priv *tx_info_priv = NULL; |
1859 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1404 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1860 | struct ieee80211_hdr *hdr; | 1405 | struct ieee80211_hdr *hdr; |
1406 | int final_ts_idx, tx_status = 0, is_underrun = 0; | ||
1861 | __le16 fc; | 1407 | __le16 fc; |
1862 | 1408 | ||
1863 | hdr = (struct ieee80211_hdr *)skb->data; | 1409 | hdr = (struct ieee80211_hdr *)skb->data; |
1864 | fc = hdr->frame_control; | 1410 | fc = hdr->frame_control; |
1865 | /* XXX: UGLY HACK!! */ | 1411 | tx_info_priv = ATH_TX_INFO_PRIV(tx_info); |
1866 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; | 1412 | final_ts_idx = tx_info_priv->tx.ts_rateindex; |
1867 | 1413 | ||
1868 | an = (struct ath_node *)sta->drv_priv; | 1414 | if (!priv_sta || !ieee80211_is_data(fc) || |
1415 | !tx_info_priv->update_rc) | ||
1416 | goto exit; | ||
1869 | 1417 | ||
1870 | if (tx_info_priv == NULL) | 1418 | if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT) |
1871 | return; | 1419 | goto exit; |
1872 | 1420 | ||
1873 | if (an && priv_sta && ieee80211_is_data(fc)) | 1421 | /* |
1874 | ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv); | 1422 | * If underrun error is seen assume it as an excessive retry only |
1423 | * if prefetch trigger level have reached the max (0x3f for 5416) | ||
1424 | * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY | ||
1425 | * times. This affects how ratectrl updates PER for the failed rate. | ||
1426 | */ | ||
1427 | if (tx_info_priv->tx.ts_flags & | ||
1428 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) && | ||
1429 | ((sc->sc_ah->ah_txTrigLevel) >= ath_rc_priv->tx_triglevel_max)) { | ||
1430 | tx_status = 1; | ||
1431 | is_underrun = 1; | ||
1432 | } | ||
1433 | |||
1434 | if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) || | ||
1435 | (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO)) | ||
1436 | tx_status = 1; | ||
1875 | 1437 | ||
1438 | ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, | ||
1439 | (is_underrun) ? ATH_11N_TXMAXTRY : | ||
1440 | tx_info_priv->tx.ts_longretry); | ||
1441 | |||
1442 | exit: | ||
1876 | kfree(tx_info_priv); | 1443 | kfree(tx_info_priv); |
1877 | tx_info->control.vif = NULL; | ||
1878 | } | 1444 | } |
1879 | 1445 | ||
1880 | static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | 1446 | static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, |
@@ -1885,55 +1451,29 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
1885 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1451 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1886 | struct ath_softc *sc = priv; | 1452 | struct ath_softc *sc = priv; |
1887 | struct ieee80211_hw *hw = sc->hw; | 1453 | struct ieee80211_hw *hw = sc->hw; |
1888 | struct ath_tx_info_priv *tx_info_priv; | 1454 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
1889 | struct ath_rate_node *ath_rc_priv = priv_sta; | ||
1890 | struct ath_node *an; | ||
1891 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1455 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1892 | int is_probe = FALSE; | 1456 | int is_probe = 0; |
1893 | s8 lowest_idx; | ||
1894 | __le16 fc = hdr->frame_control; | 1457 | __le16 fc = hdr->frame_control; |
1895 | u8 *qc, tid; | ||
1896 | |||
1897 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | ||
1898 | 1458 | ||
1899 | /* allocate driver private area of tx_info, XXX: UGLY HACK! */ | ||
1900 | tx_info->control.vif = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); | ||
1901 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; | ||
1902 | ASSERT(tx_info_priv != NULL); | ||
1903 | |||
1904 | lowest_idx = rate_lowest_index(sband, sta); | ||
1905 | tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; | ||
1906 | /* lowest rate for management and multicast/broadcast frames */ | 1459 | /* lowest rate for management and multicast/broadcast frames */ |
1907 | if (!ieee80211_is_data(fc) || | 1460 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) { |
1908 | is_multicast_ether_addr(hdr->addr1) || !sta) { | 1461 | tx_info->control.rates[0].idx = rate_lowest_index(sband, sta); |
1909 | tx_info->control.rates[0].idx = lowest_idx; | 1462 | tx_info->control.rates[0].count = |
1463 | is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY; | ||
1910 | return; | 1464 | return; |
1911 | } | 1465 | } |
1912 | 1466 | ||
1913 | /* Find tx rate for unicast frames */ | 1467 | /* Find tx rate for unicast frames */ |
1914 | ath_rate_findrate(sc, ath_rc_priv, | 1468 | ath_rc_ratefind(sc, ath_rc_priv, ATH_11N_TXMAXTRY, 4, |
1915 | ATH_11N_TXMAXTRY, 4, | 1469 | tx_info, &is_probe, false); |
1916 | ATH_RC_PROBE_ALLOWED, | ||
1917 | tx_info_priv->rcs, | ||
1918 | &is_probe, | ||
1919 | false); | ||
1920 | #if 0 | ||
1921 | if (is_probe) | ||
1922 | sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate; | ||
1923 | #endif | ||
1924 | |||
1925 | /* Ratecontrol sometimes returns invalid rate index */ | ||
1926 | if (tx_info_priv->rcs[0].rix != 0xff) | ||
1927 | ath_rc_priv->prev_data_rix = tx_info_priv->rcs[0].rix; | ||
1928 | else | ||
1929 | tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix; | ||
1930 | |||
1931 | tx_info->control.rates[0].idx = tx_info_priv->rcs[0].rix; | ||
1932 | 1470 | ||
1933 | /* Check if aggregation has to be enabled for this tid */ | 1471 | /* Check if aggregation has to be enabled for this tid */ |
1934 | |||
1935 | if (hw->conf.ht.enabled) { | 1472 | if (hw->conf.ht.enabled) { |
1936 | if (ieee80211_is_data_qos(fc)) { | 1473 | if (ieee80211_is_data_qos(fc)) { |
1474 | u8 *qc, tid; | ||
1475 | struct ath_node *an; | ||
1476 | |||
1937 | qc = ieee80211_get_qos_ctl(hdr); | 1477 | qc = ieee80211_get_qos_ctl(hdr); |
1938 | tid = qc[0] & 0xf; | 1478 | tid = qc[0] & 0xf; |
1939 | an = (struct ath_node *)sta->drv_priv; | 1479 | an = (struct ath_node *)sta->drv_priv; |
@@ -1948,14 +1488,20 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1948 | struct ieee80211_sta *sta, void *priv_sta) | 1488 | struct ieee80211_sta *sta, void *priv_sta) |
1949 | { | 1489 | { |
1950 | struct ath_softc *sc = priv; | 1490 | struct ath_softc *sc = priv; |
1951 | struct ath_rate_node *ath_rc_priv = priv_sta; | 1491 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
1952 | int i, j = 0; | 1492 | int i, j = 0; |
1953 | 1493 | ||
1954 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | 1494 | for (i = 0; i < sband->n_bitrates; i++) { |
1495 | if (sta->supp_rates[sband->band] & BIT(i)) { | ||
1496 | ath_rc_priv->neg_rates.rs_rates[j] | ||
1497 | = (sband->bitrates[i].bitrate * 2) / 10; | ||
1498 | j++; | ||
1499 | } | ||
1500 | } | ||
1501 | ath_rc_priv->neg_rates.rs_nrates = j; | ||
1955 | 1502 | ||
1956 | ath_setup_rates(sc, sband, sta, ath_rc_priv); | ||
1957 | if (sta->ht_cap.ht_supported) { | 1503 | if (sta->ht_cap.ht_supported) { |
1958 | for (i = 0; i < 77; i++) { | 1504 | for (i = 0, j = 0; i < 77; i++) { |
1959 | if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) | 1505 | if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) |
1960 | ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; | 1506 | ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; |
1961 | if (j == ATH_RATE_MAX) | 1507 | if (j == ATH_RATE_MAX) |
@@ -1963,14 +1509,12 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1963 | } | 1509 | } |
1964 | ath_rc_priv->neg_ht_rates.rs_nrates = j; | 1510 | ath_rc_priv->neg_ht_rates.rs_nrates = j; |
1965 | } | 1511 | } |
1966 | ath_rc_node_update(sc->hw, priv_sta); | 1512 | |
1513 | ath_rc_init(sc, priv_sta, sband, sta); | ||
1967 | } | 1514 | } |
1968 | 1515 | ||
1969 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 1516 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
1970 | { | 1517 | { |
1971 | struct ath_softc *sc = hw->priv; | ||
1972 | |||
1973 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | ||
1974 | return hw->priv; | 1518 | return hw->priv; |
1975 | } | 1519 | } |
1976 | 1520 | ||
@@ -1981,26 +1525,19 @@ static void ath_rate_free(void *priv) | |||
1981 | 1525 | ||
1982 | static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) | 1526 | static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) |
1983 | { | 1527 | { |
1984 | struct ieee80211_vif *vif; | ||
1985 | struct ath_softc *sc = priv; | 1528 | struct ath_softc *sc = priv; |
1986 | struct ath_vap *avp; | 1529 | struct ath_rate_priv *rate_priv; |
1987 | struct ath_rate_node *rate_priv; | ||
1988 | |||
1989 | DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); | ||
1990 | |||
1991 | vif = sc->sc_vaps[0]; | ||
1992 | ASSERT(vif); | ||
1993 | |||
1994 | avp = (void *)vif->drv_priv; | ||
1995 | 1530 | ||
1996 | rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp); | 1531 | rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); |
1997 | if (!rate_priv) { | 1532 | if (!rate_priv) { |
1998 | DPRINTF(sc, ATH_DBG_FATAL, | 1533 | DPRINTF(sc, ATH_DBG_FATAL, |
1999 | "%s: Unable to allocate private rc structure\n", | 1534 | "%s: Unable to allocate private rc structure\n", |
2000 | __func__); | 1535 | __func__); |
2001 | return NULL; | 1536 | return NULL; |
2002 | } | 1537 | } |
2003 | ath_rc_sib_init(rate_priv); | 1538 | |
1539 | rate_priv->rssi_down_time = jiffies_to_msecs(jiffies); | ||
1540 | rate_priv->tx_triglevel_max = sc->sc_ah->ah_caps.tx_triglevel_max; | ||
2004 | 1541 | ||
2005 | return rate_priv; | 1542 | return rate_priv; |
2006 | } | 1543 | } |
@@ -2008,11 +1545,8 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp | |||
2008 | static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, | 1545 | static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, |
2009 | void *priv_sta) | 1546 | void *priv_sta) |
2010 | { | 1547 | { |
2011 | struct ath_rate_node *rate_priv = priv_sta; | 1548 | struct ath_rate_priv *rate_priv = priv_sta; |
2012 | struct ath_softc *sc = priv; | 1549 | kfree(rate_priv); |
2013 | |||
2014 | DPRINTF(sc, ATH_DBG_RATE, "%s", __func__); | ||
2015 | ath_rate_node_free(rate_priv); | ||
2016 | } | 1550 | } |
2017 | 1551 | ||
2018 | static struct rate_control_ops ath_rate_ops = { | 1552 | static struct rate_control_ops ath_rate_ops = { |
@@ -2027,6 +1561,63 @@ static struct rate_control_ops ath_rate_ops = { | |||
2027 | .free_sta = ath_rate_free_sta, | 1561 | .free_sta = ath_rate_free_sta, |
2028 | }; | 1562 | }; |
2029 | 1563 | ||
1564 | static void ath_setup_rate_table(struct ath_softc *sc, | ||
1565 | struct ath_rate_table *rate_table) | ||
1566 | { | ||
1567 | int i; | ||
1568 | |||
1569 | for (i = 0; i < 256; i++) | ||
1570 | rate_table->rateCodeToIndex[i] = (u8)-1; | ||
1571 | |||
1572 | for (i = 0; i < rate_table->rate_cnt; i++) { | ||
1573 | u8 code = rate_table->info[i].ratecode; | ||
1574 | u8 cix = rate_table->info[i].ctrl_rate; | ||
1575 | u8 sh = rate_table->info[i].short_preamble; | ||
1576 | |||
1577 | rate_table->rateCodeToIndex[code] = i; | ||
1578 | rate_table->rateCodeToIndex[code | sh] = i; | ||
1579 | |||
1580 | rate_table->info[i].lpAckDuration = | ||
1581 | ath9k_hw_computetxtime(sc->sc_ah, rate_table, | ||
1582 | WLAN_CTRL_FRAME_SIZE, | ||
1583 | cix, | ||
1584 | false); | ||
1585 | rate_table->info[i].spAckDuration = | ||
1586 | ath9k_hw_computetxtime(sc->sc_ah, rate_table, | ||
1587 | WLAN_CTRL_FRAME_SIZE, | ||
1588 | cix, | ||
1589 | true); | ||
1590 | } | ||
1591 | } | ||
1592 | |||
1593 | void ath_rate_attach(struct ath_softc *sc) | ||
1594 | { | ||
1595 | sc->hw_rate_table[ATH9K_MODE_11B] = | ||
1596 | &ar5416_11b_ratetable; | ||
1597 | sc->hw_rate_table[ATH9K_MODE_11A] = | ||
1598 | &ar5416_11a_ratetable; | ||
1599 | sc->hw_rate_table[ATH9K_MODE_11G] = | ||
1600 | &ar5416_11g_ratetable; | ||
1601 | sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = | ||
1602 | &ar5416_11na_ratetable; | ||
1603 | sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = | ||
1604 | &ar5416_11ng_ratetable; | ||
1605 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] = | ||
1606 | &ar5416_11na_ratetable; | ||
1607 | sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] = | ||
1608 | &ar5416_11na_ratetable; | ||
1609 | sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] = | ||
1610 | &ar5416_11ng_ratetable; | ||
1611 | sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] = | ||
1612 | &ar5416_11ng_ratetable; | ||
1613 | |||
1614 | ath_setup_rate_table(sc, &ar5416_11b_ratetable); | ||
1615 | ath_setup_rate_table(sc, &ar5416_11a_ratetable); | ||
1616 | ath_setup_rate_table(sc, &ar5416_11g_ratetable); | ||
1617 | ath_setup_rate_table(sc, &ar5416_11na_ratetable); | ||
1618 | ath_setup_rate_table(sc, &ar5416_11ng_ratetable); | ||
1619 | } | ||
1620 | |||
2030 | int ath_rate_control_register(void) | 1621 | int ath_rate_control_register(void) |
2031 | { | 1622 | { |
2032 | return ieee80211_rate_control_register(&ath_rate_ops); | 1623 | return ieee80211_rate_control_register(&ath_rate_ops); |
@@ -2036,4 +1627,3 @@ void ath_rate_control_unregister(void) | |||
2036 | { | 1627 | { |
2037 | ieee80211_rate_control_unregister(&ath_rate_ops); | 1628 | ieee80211_rate_control_unregister(&ath_rate_ops); |
2038 | } | 1629 | } |
2039 | |||
diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h index 6671097fad72..97c60d12e8aa 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath9k/rc.h | |||
@@ -20,83 +20,24 @@ | |||
20 | #define RC_H | 20 | #define RC_H |
21 | 21 | ||
22 | #include "ath9k.h" | 22 | #include "ath9k.h" |
23 | /* | ||
24 | * Interface definitions for transmit rate control modules for the | ||
25 | * Atheros driver. | ||
26 | * | ||
27 | * A rate control module is responsible for choosing the transmit rate | ||
28 | * for each data frame. Management+control frames are always sent at | ||
29 | * a fixed rate. | ||
30 | * | ||
31 | * Only one module may be present at a time; the driver references | ||
32 | * rate control interfaces by symbol name. If multiple modules are | ||
33 | * to be supported we'll need to switch to a registration-based scheme | ||
34 | * as is currently done, for example, for authentication modules. | ||
35 | * | ||
36 | * An instance of the rate control module is attached to each device | ||
37 | * at attach time and detached when the device is destroyed. The module | ||
38 | * may associate data with each device and each node (station). Both | ||
39 | * sets of storage are opaque except for the size of the per-node storage | ||
40 | * which must be provided when the module is attached. | ||
41 | * | ||
42 | * The rate control module is notified for each state transition and | ||
43 | * station association/reassociation. Otherwise it is queried for a | ||
44 | * rate for each outgoing frame and provided status from each transmitted | ||
45 | * frame. Any ancillary processing is the responsibility of the module | ||
46 | * (e.g. if periodic processing is required then the module should setup | ||
47 | * it's own timer). | ||
48 | * | ||
49 | * In addition to the transmit rate for each frame the module must also | ||
50 | * indicate the number of attempts to make at the specified rate. If this | ||
51 | * number is != ATH_TXMAXTRY then an additional callback is made to setup | ||
52 | * additional transmit state. The rate control code is assumed to write | ||
53 | * this additional data directly to the transmit descriptor. | ||
54 | */ | ||
55 | 23 | ||
56 | struct ath_softc; | 24 | struct ath_softc; |
57 | 25 | ||
58 | #define TRUE 1 | 26 | #define ATH_RATE_MAX 30 |
59 | #define FALSE 0 | 27 | #define RATE_TABLE_SIZE 64 |
28 | #define MAX_TX_RATE_PHY 48 | ||
60 | 29 | ||
61 | #define ATH_RATE_MAX 30 | 30 | /* VALID_ALL - valid for 20/40/Legacy, |
31 | * VALID - Legacy only, | ||
32 | * VALID_20 - HT 20 only, | ||
33 | * VALID_40 - HT 40 only */ | ||
62 | 34 | ||
63 | enum ieee80211_fixed_rate_mode { | 35 | #define INVALID 0x0 |
64 | IEEE80211_FIXED_RATE_NONE = 0, | 36 | #define VALID 0x1 |
65 | IEEE80211_FIXED_RATE_MCS = 1 /* HT rates */ | 37 | #define VALID_20 0x2 |
66 | }; | 38 | #define VALID_40 0x4 |
67 | 39 | #define VALID_2040 (VALID_20|VALID_40) | |
68 | /* | 40 | #define VALID_ALL (VALID_2040|VALID) |
69 | * Use the hal os glue code to get ms time | ||
70 | */ | ||
71 | #define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8))) | ||
72 | |||
73 | #define WLAN_PHY_HT_20_SS WLAN_RC_PHY_HT_20_SS | ||
74 | #define WLAN_PHY_HT_20_DS WLAN_RC_PHY_HT_20_DS | ||
75 | #define WLAN_PHY_HT_20_DS_HGI WLAN_RC_PHY_HT_20_DS_HGI | ||
76 | #define WLAN_PHY_HT_40_SS WLAN_RC_PHY_HT_40_SS | ||
77 | #define WLAN_PHY_HT_40_SS_HGI WLAN_RC_PHY_HT_40_SS_HGI | ||
78 | #define WLAN_PHY_HT_40_DS WLAN_RC_PHY_HT_40_DS | ||
79 | #define WLAN_PHY_HT_40_DS_HGI WLAN_RC_PHY_HT_40_DS_HGI | ||
80 | |||
81 | #define WLAN_PHY_OFDM PHY_OFDM | ||
82 | #define WLAN_PHY_CCK PHY_CCK | ||
83 | |||
84 | #define TRUE_20 0x2 | ||
85 | #define TRUE_40 0x4 | ||
86 | #define TRUE_2040 (TRUE_20|TRUE_40) | ||
87 | #define TRUE_ALL (TRUE_2040|TRUE) | ||
88 | |||
89 | enum { | ||
90 | WLAN_RC_PHY_HT_20_SS = 4, | ||
91 | WLAN_RC_PHY_HT_20_DS, | ||
92 | WLAN_RC_PHY_HT_40_SS, | ||
93 | WLAN_RC_PHY_HT_40_DS, | ||
94 | WLAN_RC_PHY_HT_20_SS_HGI, | ||
95 | WLAN_RC_PHY_HT_20_DS_HGI, | ||
96 | WLAN_RC_PHY_HT_40_SS_HGI, | ||
97 | WLAN_RC_PHY_HT_40_DS_HGI, | ||
98 | WLAN_RC_PHY_MAX | ||
99 | }; | ||
100 | 41 | ||
101 | #define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ | 42 | #define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ |
102 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ | 43 | || (_phy == WLAN_RC_PHY_HT_40_DS) \ |
@@ -113,26 +54,22 @@ enum { | |||
113 | 54 | ||
114 | #define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) | 55 | #define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) |
115 | 56 | ||
116 | /* Returns the capflag mode */ | ||
117 | #define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \ | 57 | #define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \ |
118 | (capflag & WLAN_RC_40_FLAG) ? TRUE_40 : TRUE_20 : TRUE)) | 58 | (capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID)) |
119 | 59 | ||
120 | /* Return TRUE if flag supports HT20 && client supports HT20 or | 60 | /* Return TRUE if flag supports HT20 && client supports HT20 or |
121 | * return TRUE if flag supports HT40 && client supports HT40. | 61 | * return TRUE if flag supports HT40 && client supports HT40. |
122 | * This is used becos some rates overlap between HT20/HT40. | 62 | * This is used becos some rates overlap between HT20/HT40. |
123 | */ | 63 | */ |
124 | 64 | #define WLAN_RC_PHY_HT_VALID(flag, capflag) \ | |
125 | #define WLAN_RC_PHY_HT_VALID(flag, capflag) (((flag & TRUE_20) && !(capflag \ | 65 | (((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \ |
126 | & WLAN_RC_40_FLAG)) || ((flag & TRUE_40) && \ | 66 | ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG))) |
127 | (capflag & WLAN_RC_40_FLAG))) | ||
128 | 67 | ||
129 | #define WLAN_RC_DS_FLAG (0x01) | 68 | #define WLAN_RC_DS_FLAG (0x01) |
130 | #define WLAN_RC_40_FLAG (0x02) | 69 | #define WLAN_RC_40_FLAG (0x02) |
131 | #define WLAN_RC_SGI_FLAG (0x04) | 70 | #define WLAN_RC_SGI_FLAG (0x04) |
132 | #define WLAN_RC_HT_FLAG (0x08) | 71 | #define WLAN_RC_HT_FLAG (0x08) |
133 | 72 | ||
134 | #define RATE_TABLE_SIZE 64 | ||
135 | |||
136 | /** | 73 | /** |
137 | * struct ath_rate_table - Rate Control table | 74 | * struct ath_rate_table - Rate Control table |
138 | * @valid: valid for use in rate control | 75 | * @valid: valid for use in rate control |
@@ -149,10 +86,11 @@ enum { | |||
149 | * @max_4ms_framelen: maximum frame length(bytes) for tx duration | 86 | * @max_4ms_framelen: maximum frame length(bytes) for tx duration |
150 | * @probe_interval: interval for rate control to probe for other rates | 87 | * @probe_interval: interval for rate control to probe for other rates |
151 | * @rssi_reduce_interval: interval for rate control to reduce rssi | 88 | * @rssi_reduce_interval: interval for rate control to reduce rssi |
152 | * @initial_ratemax: initial ratemax value used in ath_rc_sib_update() | 89 | * @initial_ratemax: initial ratemax value |
153 | */ | 90 | */ |
154 | struct ath_rate_table { | 91 | struct ath_rate_table { |
155 | int rate_cnt; | 92 | int rate_cnt; |
93 | u8 rateCodeToIndex[256]; | ||
156 | struct { | 94 | struct { |
157 | int valid; | 95 | int valid; |
158 | int valid_single_stream; | 96 | int valid_single_stream; |
@@ -170,42 +108,26 @@ struct ath_rate_table { | |||
170 | u8 sgi_index; | 108 | u8 sgi_index; |
171 | u8 ht_index; | 109 | u8 ht_index; |
172 | u32 max_4ms_framelen; | 110 | u32 max_4ms_framelen; |
111 | u16 lpAckDuration; | ||
112 | u16 spAckDuration; | ||
173 | } info[RATE_TABLE_SIZE]; | 113 | } info[RATE_TABLE_SIZE]; |
174 | u32 probe_interval; | 114 | u32 probe_interval; |
175 | u32 rssi_reduce_interval; | 115 | u32 rssi_reduce_interval; |
176 | u8 initial_ratemax; | 116 | u8 initial_ratemax; |
177 | }; | 117 | }; |
178 | 118 | ||
179 | #define ATH_RC_PROBE_ALLOWED 0x00000001 | ||
180 | #define ATH_RC_MINRATE_LASTRATE 0x00000002 | ||
181 | |||
182 | struct ath_rc_series { | ||
183 | u8 rix; | ||
184 | u8 tries; | ||
185 | u8 flags; | ||
186 | u32 max_4ms_framelen; | ||
187 | }; | ||
188 | |||
189 | /* rcs_flags definition */ | ||
190 | #define ATH_RC_DS_FLAG 0x01 | ||
191 | #define ATH_RC_CW40_FLAG 0x02 /* CW 40 */ | ||
192 | #define ATH_RC_SGI_FLAG 0x04 /* Short Guard Interval */ | ||
193 | #define ATH_RC_HT_FLAG 0x08 /* HT */ | ||
194 | #define ATH_RC_RTSCTS_FLAG 0x10 /* RTS-CTS */ | ||
195 | |||
196 | /* | ||
197 | * State structures for new rate adaptation code | ||
198 | */ | ||
199 | #define MAX_TX_RATE_TBL 64 | ||
200 | #define MAX_TX_RATE_PHY 48 | ||
201 | |||
202 | struct ath_tx_ratectrl_state { | 119 | struct ath_tx_ratectrl_state { |
203 | int8_t rssi_thres; /* required rssi for this rate (dB) */ | 120 | int8_t rssi_thres; /* required rssi for this rate (dB) */ |
204 | u8 per; /* recent estimate of packet error rate (%) */ | 121 | u8 per; /* recent estimate of packet error rate (%) */ |
205 | }; | 122 | }; |
206 | 123 | ||
124 | struct ath_rateset { | ||
125 | u8 rs_nrates; | ||
126 | u8 rs_rates[ATH_RATE_MAX]; | ||
127 | }; | ||
128 | |||
207 | /** | 129 | /** |
208 | * struct ath_tx_ratectrl - TX Rate control Information | 130 | * struct ath_rate_priv - Rate Control priv data |
209 | * @state: RC state | 131 | * @state: RC state |
210 | * @rssi_last: last ACK rssi | 132 | * @rssi_last: last ACK rssi |
211 | * @rssi_last_lookup: last ACK rssi used for lookup | 133 | * @rssi_last_lookup: last ACK rssi used for lookup |
@@ -224,9 +146,13 @@ struct ath_tx_ratectrl_state { | |||
224 | * @valid_phy_ratecnt: valid rate count | 146 | * @valid_phy_ratecnt: valid rate count |
225 | * @rate_max_phy: phy index for the max rate | 147 | * @rate_max_phy: phy index for the max rate |
226 | * @probe_interval: interval for ratectrl to probe for other rates | 148 | * @probe_interval: interval for ratectrl to probe for other rates |
149 | * @prev_data_rix: rate idx of last data frame | ||
150 | * @ht_cap: HT capabilities | ||
151 | * @single_stream: When TRUE, only single TX stream possible | ||
152 | * @neg_rates: Negotatied rates | ||
153 | * @neg_ht_rates: Negotiated HT rates | ||
227 | */ | 154 | */ |
228 | struct ath_tx_ratectrl { | 155 | struct ath_rate_priv { |
229 | struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL]; | ||
230 | int8_t rssi_last; | 156 | int8_t rssi_last; |
231 | int8_t rssi_last_lookup; | 157 | int8_t rssi_last_lookup; |
232 | int8_t rssi_last_prev; | 158 | int8_t rssi_last_prev; |
@@ -236,89 +162,40 @@ struct ath_tx_ratectrl { | |||
236 | int32_t rssi_sum; | 162 | int32_t rssi_sum; |
237 | u8 rate_table_size; | 163 | u8 rate_table_size; |
238 | u8 probe_rate; | 164 | u8 probe_rate; |
239 | u32 rssi_time; | ||
240 | u32 rssi_down_time; | ||
241 | u32 probe_time; | ||
242 | u8 hw_maxretry_pktcnt; | 165 | u8 hw_maxretry_pktcnt; |
243 | u8 max_valid_rate; | 166 | u8 max_valid_rate; |
244 | u8 valid_rate_index[MAX_TX_RATE_TBL]; | 167 | u8 valid_rate_index[RATE_TABLE_SIZE]; |
245 | u32 per_down_time; | 168 | u8 ht_cap; |
246 | 169 | u8 single_stream; | |
247 | /* 11n state */ | ||
248 | u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; | 170 | u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; |
249 | u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL]; | 171 | u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; |
250 | u8 rc_phy_mode; | 172 | u8 rc_phy_mode; |
251 | u8 rate_max_phy; | 173 | u8 rate_max_phy; |
174 | u32 rssi_time; | ||
175 | u32 rssi_down_time; | ||
176 | u32 probe_time; | ||
177 | u32 per_down_time; | ||
252 | u32 probe_interval; | 178 | u32 probe_interval; |
253 | }; | ||
254 | |||
255 | struct ath_rateset { | ||
256 | u8 rs_nrates; | ||
257 | u8 rs_rates[ATH_RATE_MAX]; | ||
258 | }; | ||
259 | |||
260 | /* per-device state */ | ||
261 | struct ath_rate_softc { | ||
262 | /* phy tables that contain rate control data */ | ||
263 | const void *hw_rate_table[ATH9K_MODE_MAX]; | ||
264 | |||
265 | /* -1 or index of fixed rate */ | ||
266 | int fixedrix; | ||
267 | }; | ||
268 | |||
269 | /* per-node state */ | ||
270 | struct ath_rate_node { | ||
271 | struct ath_tx_ratectrl tx_ratectrl; | ||
272 | |||
273 | /* rate idx of last data frame */ | ||
274 | u32 prev_data_rix; | 179 | u32 prev_data_rix; |
275 | 180 | u32 tx_triglevel_max; | |
276 | /* ht capabilities */ | 181 | struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE]; |
277 | u8 ht_cap; | ||
278 | |||
279 | /* When TRUE, only single stream Tx possible */ | ||
280 | u8 single_stream; | ||
281 | |||
282 | /* Negotiated rates */ | ||
283 | struct ath_rateset neg_rates; | 182 | struct ath_rateset neg_rates; |
284 | |||
285 | /* Negotiated HT rates */ | ||
286 | struct ath_rateset neg_ht_rates; | 183 | struct ath_rateset neg_ht_rates; |
287 | |||
288 | struct ath_rate_softc *asc; | 184 | struct ath_rate_softc *asc; |
289 | struct ath_vap *avp; | ||
290 | }; | 185 | }; |
291 | 186 | ||
292 | /* Driver data of ieee80211_tx_info */ | ||
293 | struct ath_tx_info_priv { | 187 | struct ath_tx_info_priv { |
294 | struct ath_rc_series rcs[4]; | ||
295 | struct ath_tx_status tx; | 188 | struct ath_tx_status tx; |
296 | int n_frames; | 189 | int n_frames; |
297 | int n_bad_frames; | 190 | int n_bad_frames; |
298 | u8 min_rate; | 191 | bool update_rc; |
299 | }; | 192 | }; |
300 | 193 | ||
301 | /* | 194 | #define ATH_TX_INFO_PRIV(tx_info) \ |
302 | * Attach/detach a rate control module. | 195 | ((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0])) |
303 | */ | ||
304 | struct ath_rate_softc *ath_rate_attach(struct ath_hal *ah); | ||
305 | void ath_rate_detach(struct ath_rate_softc *asc); | ||
306 | |||
307 | /* | ||
308 | * Update/reset rate control state for 802.11 state transitions. | ||
309 | * Important mostly as the analog to ath_rate_newassoc when operating | ||
310 | * in station mode. | ||
311 | */ | ||
312 | void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv); | ||
313 | void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp); | ||
314 | |||
315 | /* | ||
316 | * Return rate index for given Dot11 Rate. | ||
317 | */ | ||
318 | u8 ath_rate_findrateix(struct ath_softc *sc, | ||
319 | u8 dot11_rate); | ||
320 | 196 | ||
321 | /* Routines to register/unregister rate control algorithm */ | 197 | void ath_rate_attach(struct ath_softc *sc); |
198 | u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate); | ||
322 | int ath_rate_control_register(void); | 199 | int ath_rate_control_register(void); |
323 | void ath_rate_control_unregister(void); | 200 | void ath_rate_control_unregister(void); |
324 | 201 | ||
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 2d72ac19fada..743ad228b833 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c | |||
@@ -14,10 +14,6 @@ | |||
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 | /* | ||
18 | * Implementation of receive path. | ||
19 | */ | ||
20 | |||
21 | #include "core.h" | 17 | #include "core.h" |
22 | 18 | ||
23 | /* | 19 | /* |
@@ -27,10 +23,7 @@ | |||
27 | * MAC acknowledges BA status as long as it copies frames to host | 23 | * MAC acknowledges BA status as long as it copies frames to host |
28 | * buffer (or rx fifo). This can incorrectly acknowledge packets | 24 | * buffer (or rx fifo). This can incorrectly acknowledge packets |
29 | * to a sender if last desc is self-linked. | 25 | * to a sender if last desc is self-linked. |
30 | * | ||
31 | * NOTE: Caller should hold the rxbuf lock. | ||
32 | */ | 26 | */ |
33 | |||
34 | static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | 27 | static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) |
35 | { | 28 | { |
36 | struct ath_hal *ah = sc->sc_ah; | 29 | struct ath_hal *ah = sc->sc_ah; |
@@ -40,19 +33,17 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
40 | ATH_RXBUF_RESET(bf); | 33 | ATH_RXBUF_RESET(bf); |
41 | 34 | ||
42 | ds = bf->bf_desc; | 35 | ds = bf->bf_desc; |
43 | ds->ds_link = 0; /* link to null */ | 36 | ds->ds_link = 0; /* link to null */ |
44 | ds->ds_data = bf->bf_buf_addr; | 37 | ds->ds_data = bf->bf_buf_addr; |
45 | 38 | ||
46 | /* XXX For RADAR? | 39 | /* virtual addr of the beginning of the buffer. */ |
47 | * virtual addr of the beginning of the buffer. */ | ||
48 | skb = bf->bf_mpdu; | 40 | skb = bf->bf_mpdu; |
49 | ASSERT(skb != NULL); | 41 | ASSERT(skb != NULL); |
50 | ds->ds_vdata = skb->data; | 42 | ds->ds_vdata = skb->data; |
51 | 43 | ||
52 | /* setup rx descriptors */ | 44 | /* setup rx descriptors */ |
53 | ath9k_hw_setuprxdesc(ah, | 45 | ath9k_hw_setuprxdesc(ah, ds, |
54 | ds, | 46 | skb_tailroom(skb), /* buffer size */ |
55 | skb_tailroom(skb), /* buffer size */ | ||
56 | 0); | 47 | 0); |
57 | 48 | ||
58 | if (sc->sc_rxlink == NULL) | 49 | if (sc->sc_rxlink == NULL) |
@@ -64,8 +55,29 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
64 | ath9k_hw_rxena(ah); | 55 | ath9k_hw_rxena(ah); |
65 | } | 56 | } |
66 | 57 | ||
67 | static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, | 58 | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) |
68 | u32 len) | 59 | { |
60 | /* XXX block beacon interrupts */ | ||
61 | ath9k_hw_setantenna(sc->sc_ah, antenna); | ||
62 | sc->sc_defant = antenna; | ||
63 | sc->sc_rxotherant = 0; | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Extend 15-bit time stamp from rx descriptor to | ||
68 | * a full 64-bit TSF using the current h/w TSF. | ||
69 | */ | ||
70 | static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) | ||
71 | { | ||
72 | u64 tsf; | ||
73 | |||
74 | tsf = ath9k_hw_gettsf64(sc->sc_ah); | ||
75 | if ((tsf & 0x7fff) < rstamp) | ||
76 | tsf -= 0x8000; | ||
77 | return (tsf & ~0x7fff) | rstamp; | ||
78 | } | ||
79 | |||
80 | static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len) | ||
69 | { | 81 | { |
70 | struct sk_buff *skb; | 82 | struct sk_buff *skb; |
71 | u32 off; | 83 | u32 off; |
@@ -91,59 +103,133 @@ static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, | |||
91 | return skb; | 103 | return skb; |
92 | } | 104 | } |
93 | 105 | ||
94 | static void ath_rx_requeue(struct ath_softc *sc, struct sk_buff *skb) | 106 | static int ath_rate2idx(struct ath_softc *sc, int rate) |
95 | { | 107 | { |
96 | struct ath_buf *bf = ATH_RX_CONTEXT(skb)->ctx_rxbuf; | 108 | int i = 0, cur_band, n_rates; |
109 | struct ieee80211_hw *hw = sc->hw; | ||
97 | 110 | ||
98 | ASSERT(bf != NULL); | 111 | cur_band = hw->conf.channel->band; |
112 | n_rates = sc->sbands[cur_band].n_bitrates; | ||
99 | 113 | ||
100 | spin_lock_bh(&sc->sc_rxbuflock); | 114 | for (i = 0; i < n_rates; i++) { |
101 | if (bf->bf_status & ATH_BUFSTATUS_STALE) { | 115 | if (sc->sbands[cur_band].bitrates[i].bitrate == rate) |
102 | /* | 116 | break; |
103 | * This buffer is still held for hw acess. | ||
104 | * Mark it as free to be re-queued it later. | ||
105 | */ | ||
106 | bf->bf_status |= ATH_BUFSTATUS_FREE; | ||
107 | } else { | ||
108 | /* XXX: we probably never enter here, remove after | ||
109 | * verification */ | ||
110 | list_add_tail(&bf->list, &sc->sc_rxbuf); | ||
111 | ath_rx_buf_link(sc, bf); | ||
112 | } | 117 | } |
113 | spin_unlock_bh(&sc->sc_rxbuflock); | 118 | |
119 | /* | ||
120 | * NB:mac80211 validates rx rate index against the supported legacy rate | ||
121 | * index only (should be done against ht rates also), return the highest | ||
122 | * legacy rate index for rx rate which does not match any one of the | ||
123 | * supported basic and extended rates to make mac80211 happy. | ||
124 | * The following hack will be cleaned up once the issue with | ||
125 | * the rx rate index validation in mac80211 is fixed. | ||
126 | */ | ||
127 | if (i == n_rates) | ||
128 | return n_rates - 1; | ||
129 | |||
130 | return i; | ||
114 | } | 131 | } |
115 | 132 | ||
116 | /* | 133 | /* |
117 | * The skb indicated to upper stack won't be returned to us. | 134 | * For Decrypt or Demic errors, we only mark packet status here and always push |
118 | * So we have to allocate a new one and queue it by ourselves. | 135 | * up the frame up to let mac80211 handle the actual error case, be it no |
136 | * decryption key or real decryption error. This let us keep statistics there. | ||
119 | */ | 137 | */ |
120 | static int ath_rx_indicate(struct ath_softc *sc, | 138 | static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, |
121 | struct sk_buff *skb, | 139 | struct ieee80211_rx_status *rx_status, bool *decrypt_error, |
122 | struct ath_recv_status *status, | 140 | struct ath_softc *sc) |
123 | u16 keyix) | ||
124 | { | 141 | { |
125 | struct ath_buf *bf = ATH_RX_CONTEXT(skb)->ctx_rxbuf; | 142 | struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode]; |
126 | struct sk_buff *nskb; | 143 | struct ieee80211_hdr *hdr; |
127 | int type; | 144 | int ratekbps, rix; |
128 | 145 | u8 ratecode; | |
129 | /* indicate frame to the stack, which will free the old skb. */ | 146 | __le16 fc; |
130 | type = _ath_rx_indicate(sc, skb, status, keyix); | 147 | |
131 | 148 | hdr = (struct ieee80211_hdr *)skb->data; | |
132 | /* allocate a new skb and queue it to for H/W processing */ | 149 | fc = hdr->frame_control; |
133 | nskb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize); | 150 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); |
134 | if (nskb != NULL) { | ||
135 | bf->bf_mpdu = nskb; | ||
136 | bf->bf_buf_addr = pci_map_single(sc->pdev, nskb->data, | ||
137 | skb_end_pointer(nskb) - nskb->head, | ||
138 | PCI_DMA_FROMDEVICE); | ||
139 | bf->bf_dmacontext = bf->bf_buf_addr; | ||
140 | ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf; | ||
141 | 151 | ||
142 | /* queue the new wbuf to H/W */ | 152 | if (ds->ds_rxstat.rs_more) { |
143 | ath_rx_requeue(sc, nskb); | 153 | /* |
154 | * Frame spans multiple descriptors; this cannot happen yet | ||
155 | * as we don't support jumbograms. If not in monitor mode, | ||
156 | * discard the frame. Enable this if you want to see | ||
157 | * error frames in Monitor mode. | ||
158 | */ | ||
159 | if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR) | ||
160 | goto rx_next; | ||
161 | } else if (ds->ds_rxstat.rs_status != 0) { | ||
162 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) | ||
163 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
164 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) | ||
165 | goto rx_next; | ||
166 | |||
167 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) { | ||
168 | *decrypt_error = true; | ||
169 | } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) { | ||
170 | if (ieee80211_is_ctl(fc)) | ||
171 | /* | ||
172 | * Sometimes, we get invalid | ||
173 | * MIC failures on valid control frames. | ||
174 | * Remove these mic errors. | ||
175 | */ | ||
176 | ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC; | ||
177 | else | ||
178 | rx_status->flag |= RX_FLAG_MMIC_ERROR; | ||
179 | } | ||
180 | /* | ||
181 | * Reject error frames with the exception of | ||
182 | * decryption and MIC failures. For monitor mode, | ||
183 | * we also ignore the CRC error. | ||
184 | */ | ||
185 | if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) { | ||
186 | if (ds->ds_rxstat.rs_status & | ||
187 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | ||
188 | ATH9K_RXERR_CRC)) | ||
189 | goto rx_next; | ||
190 | } else { | ||
191 | if (ds->ds_rxstat.rs_status & | ||
192 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { | ||
193 | goto rx_next; | ||
194 | } | ||
195 | } | ||
144 | } | 196 | } |
145 | 197 | ||
146 | return type; | 198 | ratecode = ds->ds_rxstat.rs_rate; |
199 | rix = rate_table->rateCodeToIndex[ratecode]; | ||
200 | ratekbps = rate_table->info[rix].ratekbps; | ||
201 | |||
202 | /* HT rate */ | ||
203 | if (ratecode & 0x80) { | ||
204 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) | ||
205 | ratekbps = (ratekbps * 27) / 13; | ||
206 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI) | ||
207 | ratekbps = (ratekbps * 10) / 9; | ||
208 | } | ||
209 | |||
210 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); | ||
211 | rx_status->band = sc->hw->conf.channel->band; | ||
212 | rx_status->freq = sc->hw->conf.channel->center_freq; | ||
213 | rx_status->noise = sc->sc_ani.sc_noise_floor; | ||
214 | rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi; | ||
215 | rx_status->rate_idx = ath_rate2idx(sc, (ratekbps / 100)); | ||
216 | rx_status->antenna = ds->ds_rxstat.rs_antenna; | ||
217 | |||
218 | /* at 45 you will be able to use MCS 15 reliably. A more elaborate | ||
219 | * scheme can be used here but it requires tables of SNR/throughput for | ||
220 | * each possible mode used. */ | ||
221 | rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45; | ||
222 | |||
223 | /* rssi can be more than 45 though, anything above that | ||
224 | * should be considered at 100% */ | ||
225 | if (rx_status->qual > 100) | ||
226 | rx_status->qual = 100; | ||
227 | |||
228 | rx_status->flag |= RX_FLAG_TSFT; | ||
229 | |||
230 | return 1; | ||
231 | rx_next: | ||
232 | return 0; | ||
147 | } | 233 | } |
148 | 234 | ||
149 | static void ath_opmode_init(struct ath_softc *sc) | 235 | static void ath_opmode_init(struct ath_softc *sc) |
@@ -185,12 +271,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
185 | sc->sc_flags &= ~SC_OP_RXFLUSH; | 271 | sc->sc_flags &= ~SC_OP_RXFLUSH; |
186 | spin_lock_init(&sc->sc_rxbuflock); | 272 | spin_lock_init(&sc->sc_rxbuflock); |
187 | 273 | ||
188 | /* | ||
189 | * Cisco's VPN software requires that drivers be able to | ||
190 | * receive encapsulated frames that are larger than the MTU. | ||
191 | * Since we can't be sure how large a frame we'll get, setup | ||
192 | * to handle the larges on possible. | ||
193 | */ | ||
194 | sc->sc_rxbufsize = roundup(IEEE80211_MAX_MPDU_LEN, | 274 | sc->sc_rxbufsize = roundup(IEEE80211_MAX_MPDU_LEN, |
195 | min(sc->sc_cachelsz, | 275 | min(sc->sc_cachelsz, |
196 | (u16)64)); | 276 | (u16)64)); |
@@ -209,8 +289,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
209 | break; | 289 | break; |
210 | } | 290 | } |
211 | 291 | ||
212 | /* Pre-allocate a wbuf for each rx buffer */ | ||
213 | |||
214 | list_for_each_entry(bf, &sc->sc_rxbuf, list) { | 292 | list_for_each_entry(bf, &sc->sc_rxbuf, list) { |
215 | skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize); | 293 | skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize); |
216 | if (skb == NULL) { | 294 | if (skb == NULL) { |
@@ -223,7 +301,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
223 | skb_end_pointer(skb) - skb->head, | 301 | skb_end_pointer(skb) - skb->head, |
224 | PCI_DMA_FROMDEVICE); | 302 | PCI_DMA_FROMDEVICE); |
225 | bf->bf_dmacontext = bf->bf_buf_addr; | 303 | bf->bf_dmacontext = bf->bf_buf_addr; |
226 | ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf; | ||
227 | } | 304 | } |
228 | sc->sc_rxlink = NULL; | 305 | sc->sc_rxlink = NULL; |
229 | 306 | ||
@@ -235,8 +312,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
235 | return error; | 312 | return error; |
236 | } | 313 | } |
237 | 314 | ||
238 | /* Reclaim all rx queue resources */ | ||
239 | |||
240 | void ath_rx_cleanup(struct ath_softc *sc) | 315 | void ath_rx_cleanup(struct ath_softc *sc) |
241 | { | 316 | { |
242 | struct sk_buff *skb; | 317 | struct sk_buff *skb; |
@@ -248,8 +323,6 @@ void ath_rx_cleanup(struct ath_softc *sc) | |||
248 | dev_kfree_skb(skb); | 323 | dev_kfree_skb(skb); |
249 | } | 324 | } |
250 | 325 | ||
251 | /* cleanup rx descriptors */ | ||
252 | |||
253 | if (sc->sc_rxdma.dd_desc_len != 0) | 326 | if (sc->sc_rxdma.dd_desc_len != 0) |
254 | ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); | 327 | ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf); |
255 | } | 328 | } |
@@ -297,20 +370,19 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
297 | } | 370 | } |
298 | 371 | ||
299 | if (sc->sc_ah->ah_opmode == ATH9K_M_STA || | 372 | if (sc->sc_ah->ah_opmode == ATH9K_M_STA || |
300 | sc->sc_ah->ah_opmode == ATH9K_M_IBSS) | 373 | sc->sc_ah->ah_opmode == ATH9K_M_IBSS) |
301 | rfilt |= ATH9K_RX_FILTER_BEACON; | 374 | rfilt |= ATH9K_RX_FILTER_BEACON; |
302 | 375 | ||
303 | /* If in HOSTAP mode, want to enable reception of PSPOLL frames | 376 | /* If in HOSTAP mode, want to enable reception of PSPOLL frames |
304 | & beacon frames */ | 377 | & beacon frames */ |
305 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) | 378 | if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) |
306 | rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL); | 379 | rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL); |
380 | |||
307 | return rfilt; | 381 | return rfilt; |
308 | 382 | ||
309 | #undef RX_FILTER_PRESERVE | 383 | #undef RX_FILTER_PRESERVE |
310 | } | 384 | } |
311 | 385 | ||
312 | /* Enable the receive h/w following a reset. */ | ||
313 | |||
314 | int ath_startrecv(struct ath_softc *sc) | 386 | int ath_startrecv(struct ath_softc *sc) |
315 | { | 387 | { |
316 | struct ath_hal *ah = sc->sc_ah; | 388 | struct ath_hal *ah = sc->sc_ah; |
@@ -322,21 +394,6 @@ int ath_startrecv(struct ath_softc *sc) | |||
322 | 394 | ||
323 | sc->sc_rxlink = NULL; | 395 | sc->sc_rxlink = NULL; |
324 | list_for_each_entry_safe(bf, tbf, &sc->sc_rxbuf, list) { | 396 | list_for_each_entry_safe(bf, tbf, &sc->sc_rxbuf, list) { |
325 | if (bf->bf_status & ATH_BUFSTATUS_STALE) { | ||
326 | /* restarting h/w, no need for holding descriptors */ | ||
327 | bf->bf_status &= ~ATH_BUFSTATUS_STALE; | ||
328 | /* | ||
329 | * Upper layer may not be done with the frame yet so | ||
330 | * we can't just re-queue it to hardware. Remove it | ||
331 | * from h/w queue. It'll be re-queued when upper layer | ||
332 | * returns the frame and ath_rx_requeue_mpdu is called. | ||
333 | */ | ||
334 | if (!(bf->bf_status & ATH_BUFSTATUS_FREE)) { | ||
335 | list_del(&bf->list); | ||
336 | continue; | ||
337 | } | ||
338 | } | ||
339 | /* chain descriptors */ | ||
340 | ath_rx_buf_link(sc, bf); | 397 | ath_rx_buf_link(sc, bf); |
341 | } | 398 | } |
342 | 399 | ||
@@ -346,120 +403,69 @@ int ath_startrecv(struct ath_softc *sc) | |||
346 | 403 | ||
347 | bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list); | 404 | bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list); |
348 | ath9k_hw_putrxbuf(ah, bf->bf_daddr); | 405 | ath9k_hw_putrxbuf(ah, bf->bf_daddr); |
349 | ath9k_hw_rxena(ah); /* enable recv descriptors */ | 406 | ath9k_hw_rxena(ah); |
350 | 407 | ||
351 | start_recv: | 408 | start_recv: |
352 | spin_unlock_bh(&sc->sc_rxbuflock); | 409 | spin_unlock_bh(&sc->sc_rxbuflock); |
353 | ath_opmode_init(sc); /* set filters, etc. */ | 410 | ath_opmode_init(sc); |
354 | ath9k_hw_startpcureceive(ah); /* re-enable PCU/DMA engine */ | 411 | ath9k_hw_startpcureceive(ah); |
412 | |||
355 | return 0; | 413 | return 0; |
356 | } | 414 | } |
357 | 415 | ||
358 | /* Disable the receive h/w in preparation for a reset. */ | ||
359 | |||
360 | bool ath_stoprecv(struct ath_softc *sc) | 416 | bool ath_stoprecv(struct ath_softc *sc) |
361 | { | 417 | { |
362 | struct ath_hal *ah = sc->sc_ah; | 418 | struct ath_hal *ah = sc->sc_ah; |
363 | u64 tsf; | ||
364 | bool stopped; | 419 | bool stopped; |
365 | 420 | ||
366 | ath9k_hw_stoppcurecv(ah); /* disable PCU */ | 421 | ath9k_hw_stoppcurecv(ah); |
367 | ath9k_hw_setrxfilter(ah, 0); /* clear recv filter */ | 422 | ath9k_hw_setrxfilter(ah, 0); |
368 | stopped = ath9k_hw_stopdmarecv(ah); /* disable DMA engine */ | 423 | stopped = ath9k_hw_stopdmarecv(ah); |
369 | mdelay(3); /* 3ms is long enough for 1 frame */ | 424 | mdelay(3); /* 3ms is long enough for 1 frame */ |
370 | tsf = ath9k_hw_gettsf64(ah); | 425 | sc->sc_rxlink = NULL; |
371 | sc->sc_rxlink = NULL; /* just in case */ | 426 | |
372 | return stopped; | 427 | return stopped; |
373 | } | 428 | } |
374 | 429 | ||
375 | /* Flush receive queue */ | ||
376 | |||
377 | void ath_flushrecv(struct ath_softc *sc) | 430 | void ath_flushrecv(struct ath_softc *sc) |
378 | { | 431 | { |
379 | /* | ||
380 | * ath_rx_tasklet may be used to handle rx interrupt and flush receive | ||
381 | * queue at the same time. Use a lock to serialize the access of rx | ||
382 | * queue. | ||
383 | * ath_rx_tasklet cannot hold the spinlock while indicating packets. | ||
384 | * Instead, do not claim the spinlock but check for a flush in | ||
385 | * progress (see references to sc_rxflush) | ||
386 | */ | ||
387 | spin_lock_bh(&sc->sc_rxflushlock); | 432 | spin_lock_bh(&sc->sc_rxflushlock); |
388 | sc->sc_flags |= SC_OP_RXFLUSH; | 433 | sc->sc_flags |= SC_OP_RXFLUSH; |
389 | |||
390 | ath_rx_tasklet(sc, 1); | 434 | ath_rx_tasklet(sc, 1); |
391 | |||
392 | sc->sc_flags &= ~SC_OP_RXFLUSH; | 435 | sc->sc_flags &= ~SC_OP_RXFLUSH; |
393 | spin_unlock_bh(&sc->sc_rxflushlock); | 436 | spin_unlock_bh(&sc->sc_rxflushlock); |
394 | } | 437 | } |
395 | 438 | ||
396 | /* Process receive queue, as well as LED, etc. */ | ||
397 | |||
398 | int ath_rx_tasklet(struct ath_softc *sc, int flush) | 439 | int ath_rx_tasklet(struct ath_softc *sc, int flush) |
399 | { | 440 | { |
400 | #define PA2DESC(_sc, _pa) \ | 441 | #define PA2DESC(_sc, _pa) \ |
401 | ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \ | 442 | ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \ |
402 | ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr))) | 443 | ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr))) |
403 | 444 | ||
404 | struct ath_buf *bf, *bf_held = NULL; | 445 | struct ath_buf *bf; |
405 | struct ath_desc *ds; | 446 | struct ath_desc *ds; |
406 | struct ieee80211_hdr *hdr; | 447 | struct sk_buff *skb = NULL, *requeue_skb; |
407 | struct sk_buff *skb = NULL; | 448 | struct ieee80211_rx_status rx_status; |
408 | struct ath_recv_status rx_status; | ||
409 | struct ath_hal *ah = sc->sc_ah; | 449 | struct ath_hal *ah = sc->sc_ah; |
410 | int type, rx_processed = 0; | 450 | struct ieee80211_hdr *hdr; |
411 | u32 phyerr; | 451 | int hdrlen, padsize, retval; |
412 | u8 chainreset = 0; | 452 | bool decrypt_error = false; |
413 | int retval; | 453 | u8 keyix; |
414 | __le16 fc; | 454 | |
455 | spin_lock_bh(&sc->sc_rxbuflock); | ||
415 | 456 | ||
416 | do { | 457 | do { |
417 | /* If handling rx interrupt and flush is in progress => exit */ | 458 | /* If handling rx interrupt and flush is in progress => exit */ |
418 | if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) | 459 | if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) |
419 | break; | 460 | break; |
420 | 461 | ||
421 | spin_lock_bh(&sc->sc_rxbuflock); | ||
422 | if (list_empty(&sc->sc_rxbuf)) { | 462 | if (list_empty(&sc->sc_rxbuf)) { |
423 | sc->sc_rxlink = NULL; | 463 | sc->sc_rxlink = NULL; |
424 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
425 | break; | 464 | break; |
426 | } | 465 | } |
427 | 466 | ||
428 | bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list); | 467 | bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list); |
429 | |||
430 | /* | ||
431 | * There is a race condition that BH gets scheduled after sw | ||
432 | * writes RxE and before hw re-load the last descriptor to get | ||
433 | * the newly chained one. Software must keep the last DONE | ||
434 | * descriptor as a holding descriptor - software does so by | ||
435 | * marking it with the STALE flag. | ||
436 | */ | ||
437 | if (bf->bf_status & ATH_BUFSTATUS_STALE) { | ||
438 | bf_held = bf; | ||
439 | if (list_is_last(&bf_held->list, &sc->sc_rxbuf)) { | ||
440 | /* | ||
441 | * The holding descriptor is the last | ||
442 | * descriptor in queue. It's safe to | ||
443 | * remove the last holding descriptor | ||
444 | * in BH context. | ||
445 | */ | ||
446 | list_del(&bf_held->list); | ||
447 | bf_held->bf_status &= ~ATH_BUFSTATUS_STALE; | ||
448 | sc->sc_rxlink = NULL; | ||
449 | |||
450 | if (bf_held->bf_status & ATH_BUFSTATUS_FREE) { | ||
451 | list_add_tail(&bf_held->list, | ||
452 | &sc->sc_rxbuf); | ||
453 | ath_rx_buf_link(sc, bf_held); | ||
454 | } | ||
455 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
456 | break; | ||
457 | } | ||
458 | bf = list_entry(bf->list.next, struct ath_buf, list); | ||
459 | } | ||
460 | |||
461 | ds = bf->bf_desc; | 468 | ds = bf->bf_desc; |
462 | ++rx_processed; | ||
463 | 469 | ||
464 | /* | 470 | /* |
465 | * Must provide the virtual address of the current | 471 | * Must provide the virtual address of the current |
@@ -472,8 +478,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
472 | * on. All this is necessary because of our use of | 478 | * on. All this is necessary because of our use of |
473 | * a self-linked list to avoid rx overruns. | 479 | * a self-linked list to avoid rx overruns. |
474 | */ | 480 | */ |
475 | retval = ath9k_hw_rxprocdesc(ah, | 481 | retval = ath9k_hw_rxprocdesc(ah, ds, |
476 | ds, | ||
477 | bf->bf_daddr, | 482 | bf->bf_daddr, |
478 | PA2DESC(sc, ds->ds_link), | 483 | PA2DESC(sc, ds->ds_link), |
479 | 0); | 484 | 0); |
@@ -482,7 +487,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
482 | struct ath_desc *tds; | 487 | struct ath_desc *tds; |
483 | 488 | ||
484 | if (list_is_last(&bf->list, &sc->sc_rxbuf)) { | 489 | if (list_is_last(&bf->list, &sc->sc_rxbuf)) { |
485 | spin_unlock_bh(&sc->sc_rxbuflock); | 490 | sc->sc_rxlink = NULL; |
486 | break; | 491 | break; |
487 | } | 492 | } |
488 | 493 | ||
@@ -500,215 +505,87 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
500 | */ | 505 | */ |
501 | 506 | ||
502 | tds = tbf->bf_desc; | 507 | tds = tbf->bf_desc; |
503 | retval = ath9k_hw_rxprocdesc(ah, | 508 | retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr, |
504 | tds, tbf->bf_daddr, | 509 | PA2DESC(sc, tds->ds_link), 0); |
505 | PA2DESC(sc, tds->ds_link), 0); | ||
506 | if (retval == -EINPROGRESS) { | 510 | if (retval == -EINPROGRESS) { |
507 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
508 | break; | 511 | break; |
509 | } | 512 | } |
510 | } | 513 | } |
511 | 514 | ||
512 | /* XXX: we do not support frames spanning | ||
513 | * multiple descriptors */ | ||
514 | bf->bf_status |= ATH_BUFSTATUS_DONE; | ||
515 | |||
516 | skb = bf->bf_mpdu; | 515 | skb = bf->bf_mpdu; |
517 | if (skb == NULL) { /* XXX ??? can this happen */ | 516 | if (!skb) |
518 | spin_unlock_bh(&sc->sc_rxbuflock); | ||
519 | continue; | 517 | continue; |
520 | } | ||
521 | /* | ||
522 | * Now we know it's a completed frame, we can indicate the | ||
523 | * frame. Remove the previous holding descriptor and leave | ||
524 | * this one in the queue as the new holding descriptor. | ||
525 | */ | ||
526 | if (bf_held) { | ||
527 | list_del(&bf_held->list); | ||
528 | bf_held->bf_status &= ~ATH_BUFSTATUS_STALE; | ||
529 | if (bf_held->bf_status & ATH_BUFSTATUS_FREE) { | ||
530 | list_add_tail(&bf_held->list, &sc->sc_rxbuf); | ||
531 | /* try to requeue this descriptor */ | ||
532 | ath_rx_buf_link(sc, bf_held); | ||
533 | } | ||
534 | } | ||
535 | 518 | ||
536 | bf->bf_status |= ATH_BUFSTATUS_STALE; | ||
537 | bf_held = bf; | ||
538 | /* | 519 | /* |
539 | * Release the lock here in case ieee80211_input() return | 520 | * If we're asked to flush receive queue, directly |
540 | * the frame immediately by calling ath_rx_mpdu_requeue(). | 521 | * chain it back at the queue without processing it. |
541 | */ | 522 | */ |
542 | spin_unlock_bh(&sc->sc_rxbuflock); | 523 | if (flush) |
524 | goto requeue; | ||
543 | 525 | ||
544 | if (flush) { | 526 | if (!ds->ds_rxstat.rs_datalen) |
545 | /* | 527 | goto requeue; |
546 | * If we're asked to flush receive queue, directly | ||
547 | * chain it back at the queue without processing it. | ||
548 | */ | ||
549 | goto rx_next; | ||
550 | } | ||
551 | 528 | ||
552 | hdr = (struct ieee80211_hdr *)skb->data; | 529 | /* The status portion of the descriptor could get corrupted. */ |
553 | fc = hdr->frame_control; | 530 | if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen) |
554 | memset(&rx_status, 0, sizeof(struct ath_recv_status)); | 531 | goto requeue; |
555 | 532 | ||
556 | if (ds->ds_rxstat.rs_more) { | 533 | if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc)) |
557 | /* | 534 | goto requeue; |
558 | * Frame spans multiple descriptors; this | ||
559 | * cannot happen yet as we don't support | ||
560 | * jumbograms. If not in monitor mode, | ||
561 | * discard the frame. | ||
562 | */ | ||
563 | #ifndef ERROR_FRAMES | ||
564 | /* | ||
565 | * Enable this if you want to see | ||
566 | * error frames in Monitor mode. | ||
567 | */ | ||
568 | if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR) | ||
569 | goto rx_next; | ||
570 | #endif | ||
571 | /* fall thru for monitor mode handling... */ | ||
572 | } else if (ds->ds_rxstat.rs_status != 0) { | ||
573 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) | ||
574 | rx_status.flags |= ATH_RX_FCS_ERROR; | ||
575 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) { | ||
576 | phyerr = ds->ds_rxstat.rs_phyerr & 0x1f; | ||
577 | goto rx_next; | ||
578 | } | ||
579 | 535 | ||
580 | if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) { | 536 | /* Ensure we always have an skb to requeue once we are done |
581 | /* | 537 | * processing the current buffer's skb */ |
582 | * Decrypt error. We only mark packet status | 538 | requeue_skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize); |
583 | * here and always push up the frame up to let | ||
584 | * mac80211 handle the actual error case, be | ||
585 | * it no decryption key or real decryption | ||
586 | * error. This let us keep statistics there. | ||
587 | */ | ||
588 | rx_status.flags |= ATH_RX_DECRYPT_ERROR; | ||
589 | } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) { | ||
590 | /* | ||
591 | * Demic error. We only mark frame status here | ||
592 | * and always push up the frame up to let | ||
593 | * mac80211 handle the actual error case. This | ||
594 | * let us keep statistics there. Hardware may | ||
595 | * post a false-positive MIC error. | ||
596 | */ | ||
597 | if (ieee80211_is_ctl(fc)) | ||
598 | /* | ||
599 | * Sometimes, we get invalid | ||
600 | * MIC failures on valid control frames. | ||
601 | * Remove these mic errors. | ||
602 | */ | ||
603 | ds->ds_rxstat.rs_status &= | ||
604 | ~ATH9K_RXERR_MIC; | ||
605 | else | ||
606 | rx_status.flags |= ATH_RX_MIC_ERROR; | ||
607 | } | ||
608 | /* | ||
609 | * Reject error frames with the exception of | ||
610 | * decryption and MIC failures. For monitor mode, | ||
611 | * we also ignore the CRC error. | ||
612 | */ | ||
613 | if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) { | ||
614 | if (ds->ds_rxstat.rs_status & | ||
615 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | ||
616 | ATH9K_RXERR_CRC)) | ||
617 | goto rx_next; | ||
618 | } else { | ||
619 | if (ds->ds_rxstat.rs_status & | ||
620 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { | ||
621 | goto rx_next; | ||
622 | } | ||
623 | } | ||
624 | } | ||
625 | /* | ||
626 | * The status portion of the descriptor could get corrupted. | ||
627 | */ | ||
628 | if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen) | ||
629 | goto rx_next; | ||
630 | /* | ||
631 | * Sync and unmap the frame. At this point we're | ||
632 | * committed to passing the sk_buff somewhere so | ||
633 | * clear buf_skb; this means a new sk_buff must be | ||
634 | * allocated when the rx descriptor is setup again | ||
635 | * to receive another frame. | ||
636 | */ | ||
637 | skb_put(skb, ds->ds_rxstat.rs_datalen); | ||
638 | skb->protocol = cpu_to_be16(ETH_P_CONTROL); | ||
639 | rx_status.tsf = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); | ||
640 | rx_status.rateieee = | ||
641 | sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate; | ||
642 | rx_status.rateKbps = | ||
643 | sc->sc_hwmap[ds->ds_rxstat.rs_rate].rateKbps; | ||
644 | rx_status.ratecode = ds->ds_rxstat.rs_rate; | ||
645 | |||
646 | /* HT rate */ | ||
647 | if (rx_status.ratecode & 0x80) { | ||
648 | /* TODO - add table to avoid division */ | ||
649 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) { | ||
650 | rx_status.flags |= ATH_RX_40MHZ; | ||
651 | rx_status.rateKbps = | ||
652 | (rx_status.rateKbps * 27) / 13; | ||
653 | } | ||
654 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI) | ||
655 | rx_status.rateKbps = | ||
656 | (rx_status.rateKbps * 10) / 9; | ||
657 | else | ||
658 | rx_status.flags |= ATH_RX_SHORT_GI; | ||
659 | } | ||
660 | 539 | ||
661 | /* sc_noise_floor is only available when the station | 540 | /* If there is no memory we ignore the current RX'd frame, |
662 | attaches to an AP, so we use a default value | 541 | * tell hardware it can give us a new frame using the old |
663 | if we are not yet attached. */ | 542 | * skb and put it at the tail of the sc->sc_rxbuf list for |
664 | rx_status.abs_rssi = | 543 | * processing. */ |
665 | ds->ds_rxstat.rs_rssi + sc->sc_ani.sc_noise_floor; | 544 | if (!requeue_skb) |
545 | goto requeue; | ||
666 | 546 | ||
667 | pci_dma_sync_single_for_cpu(sc->pdev, | 547 | /* Sync and unmap the frame */ |
668 | bf->bf_buf_addr, | 548 | pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr, |
669 | skb_tailroom(skb), | 549 | skb_tailroom(skb), |
670 | PCI_DMA_FROMDEVICE); | 550 | PCI_DMA_FROMDEVICE); |
671 | pci_unmap_single(sc->pdev, | 551 | pci_unmap_single(sc->pdev, bf->bf_buf_addr, |
672 | bf->bf_buf_addr, | ||
673 | sc->sc_rxbufsize, | 552 | sc->sc_rxbufsize, |
674 | PCI_DMA_FROMDEVICE); | 553 | PCI_DMA_FROMDEVICE); |
675 | 554 | ||
676 | /* XXX: Ah! make me more readable, use a helper */ | 555 | skb_put(skb, ds->ds_rxstat.rs_datalen); |
677 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { | 556 | skb->protocol = cpu_to_be16(ETH_P_CONTROL); |
678 | if (ds->ds_rxstat.rs_moreaggr == 0) { | 557 | |
679 | rx_status.rssictl[0] = | 558 | /* see if any padding is done by the hw and remove it */ |
680 | ds->ds_rxstat.rs_rssi_ctl0; | 559 | hdr = (struct ieee80211_hdr *)skb->data; |
681 | rx_status.rssictl[1] = | 560 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
682 | ds->ds_rxstat.rs_rssi_ctl1; | 561 | |
683 | rx_status.rssictl[2] = | 562 | if (hdrlen & 3) { |
684 | ds->ds_rxstat.rs_rssi_ctl2; | 563 | padsize = hdrlen % 4; |
685 | rx_status.rssi = ds->ds_rxstat.rs_rssi; | 564 | memmove(skb->data + padsize, skb->data, hdrlen); |
686 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) { | 565 | skb_pull(skb, padsize); |
687 | rx_status.rssiextn[0] = | ||
688 | ds->ds_rxstat.rs_rssi_ext0; | ||
689 | rx_status.rssiextn[1] = | ||
690 | ds->ds_rxstat.rs_rssi_ext1; | ||
691 | rx_status.rssiextn[2] = | ||
692 | ds->ds_rxstat.rs_rssi_ext2; | ||
693 | rx_status.flags |= | ||
694 | ATH_RX_RSSI_EXTN_VALID; | ||
695 | } | ||
696 | rx_status.flags |= ATH_RX_RSSI_VALID | | ||
697 | ATH_RX_CHAIN_RSSI_VALID; | ||
698 | } | ||
699 | } else { | ||
700 | /* | ||
701 | * Need to insert the "combined" rssi into the | ||
702 | * status structure for upper layer processing | ||
703 | */ | ||
704 | rx_status.rssi = ds->ds_rxstat.rs_rssi; | ||
705 | rx_status.flags |= ATH_RX_RSSI_VALID; | ||
706 | } | 566 | } |
707 | 567 | ||
708 | /* Pass frames up to the stack. */ | 568 | keyix = ds->ds_rxstat.rs_keyix; |
709 | 569 | ||
710 | type = ath_rx_indicate(sc, skb, | 570 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { |
711 | &rx_status, ds->ds_rxstat.rs_keyix); | 571 | rx_status.flag |= RX_FLAG_DECRYPTED; |
572 | } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) | ||
573 | && !decrypt_error && skb->len >= hdrlen + 4) { | ||
574 | keyix = skb->data[hdrlen + 3] >> 6; | ||
575 | |||
576 | if (test_bit(keyix, sc->sc_keymap)) | ||
577 | rx_status.flag |= RX_FLAG_DECRYPTED; | ||
578 | } | ||
579 | |||
580 | /* Send the frame to mac80211 */ | ||
581 | __ieee80211_rx(sc->hw, skb, &rx_status); | ||
582 | |||
583 | /* We will now give hardware our shiny new allocated skb */ | ||
584 | bf->bf_mpdu = requeue_skb; | ||
585 | bf->bf_buf_addr = pci_map_single(sc->pdev, requeue_skb->data, | ||
586 | sc->sc_rxbufsize, | ||
587 | PCI_DMA_FROMDEVICE); | ||
588 | bf->bf_dmacontext = bf->bf_buf_addr; | ||
712 | 589 | ||
713 | /* | 590 | /* |
714 | * change the default rx antenna if rx diversity chooses the | 591 | * change the default rx antenna if rx diversity chooses the |
@@ -716,37 +593,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
716 | */ | 593 | */ |
717 | if (sc->sc_defant != ds->ds_rxstat.rs_antenna) { | 594 | if (sc->sc_defant != ds->ds_rxstat.rs_antenna) { |
718 | if (++sc->sc_rxotherant >= 3) | 595 | if (++sc->sc_rxotherant >= 3) |
719 | ath_setdefantenna(sc, | 596 | ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna); |
720 | ds->ds_rxstat.rs_antenna); | ||
721 | } else { | 597 | } else { |
722 | sc->sc_rxotherant = 0; | 598 | sc->sc_rxotherant = 0; |
723 | } | 599 | } |
600 | requeue: | ||
601 | list_move_tail(&bf->list, &sc->sc_rxbuf); | ||
602 | ath_rx_buf_link(sc, bf); | ||
603 | } while (1); | ||
724 | 604 | ||
725 | #ifdef CONFIG_SLOW_ANT_DIV | 605 | spin_unlock_bh(&sc->sc_rxbuflock); |
726 | if ((rx_status.flags & ATH_RX_RSSI_VALID) && | ||
727 | ieee80211_is_beacon(fc)) { | ||
728 | ath_slow_ant_div(&sc->sc_antdiv, hdr, &ds->ds_rxstat); | ||
729 | } | ||
730 | #endif | ||
731 | /* | ||
732 | * For frames successfully indicated, the buffer will be | ||
733 | * returned to us by upper layers by calling | ||
734 | * ath_rx_mpdu_requeue, either synchronusly or asynchronously. | ||
735 | * So we don't want to do it here in this loop. | ||
736 | */ | ||
737 | continue; | ||
738 | |||
739 | rx_next: | ||
740 | bf->bf_status |= ATH_BUFSTATUS_FREE; | ||
741 | } while (TRUE); | ||
742 | |||
743 | if (chainreset) { | ||
744 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
745 | "%s: Reset rx chain mask. " | ||
746 | "Do internal reset\n", __func__); | ||
747 | ASSERT(flush == 0); | ||
748 | ath_reset(sc, false); | ||
749 | } | ||
750 | 606 | ||
751 | return 0; | 607 | return 0; |
752 | #undef PA2DESC | 608 | #undef PA2DESC |
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 8937728b0301..413fbdd38ab6 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -14,10 +14,6 @@ | |||
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 | /* | ||
18 | * Implementation of transmit path. | ||
19 | */ | ||
20 | |||
21 | #include "core.h" | 17 | #include "core.h" |
22 | 18 | ||
23 | #define BITS_PER_BYTE 8 | 19 | #define BITS_PER_BYTE 8 |
@@ -106,21 +102,35 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
106 | ath9k_hw_txstart(ah, txq->axq_qnum); | 102 | ath9k_hw_txstart(ah, txq->axq_qnum); |
107 | } | 103 | } |
108 | 104 | ||
109 | /* Get transmit rate index using rate in Kbps */ | 105 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |
110 | 106 | struct ath_xmit_status *tx_status) | |
111 | static int ath_tx_findindex(const struct ath9k_rate_table *rt, int rate) | ||
112 | { | 107 | { |
113 | int i; | 108 | struct ieee80211_hw *hw = sc->hw; |
114 | int ndx = 0; | 109 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
110 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
115 | 111 | ||
116 | for (i = 0; i < rt->rateCount; i++) { | 112 | DPRINTF(sc, ATH_DBG_XMIT, |
117 | if (rt->info[i].rateKbps == rate) { | 113 | "%s: TX complete: skb: %p\n", __func__, skb); |
118 | ndx = i; | 114 | |
119 | break; | 115 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || |
120 | } | 116 | tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { |
117 | kfree(tx_info_priv); | ||
118 | tx_info->rate_driver_data[0] = NULL; | ||
121 | } | 119 | } |
122 | 120 | ||
123 | return ndx; | 121 | if (tx_status->flags & ATH_TX_BAR) { |
122 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | ||
123 | tx_status->flags &= ~ATH_TX_BAR; | ||
124 | } | ||
125 | |||
126 | if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { | ||
127 | /* Frame was ACKed */ | ||
128 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | ||
129 | } | ||
130 | |||
131 | tx_info->status.rates[0].count = tx_status->retries + 1; | ||
132 | |||
133 | ieee80211_tx_status(hw, skb); | ||
124 | } | 134 | } |
125 | 135 | ||
126 | /* Check if it's okay to send out aggregates */ | 136 | /* Check if it's okay to send out aggregates */ |
@@ -137,6 +147,19 @@ static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno) | |||
137 | return 0; | 147 | return 0; |
138 | } | 148 | } |
139 | 149 | ||
150 | static void ath_get_beaconconfig(struct ath_softc *sc, int if_id, | ||
151 | struct ath_beacon_config *conf) | ||
152 | { | ||
153 | struct ieee80211_hw *hw = sc->hw; | ||
154 | |||
155 | /* fill in beacon config data */ | ||
156 | |||
157 | conf->beacon_interval = hw->conf.beacon_int; | ||
158 | conf->listen_interval = 100; | ||
159 | conf->dtim_count = 1; | ||
160 | conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval; | ||
161 | } | ||
162 | |||
140 | /* Calculate Atheros packet type from IEEE80211 packet header */ | 163 | /* Calculate Atheros packet type from IEEE80211 packet header */ |
141 | 164 | ||
142 | static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) | 165 | static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) |
@@ -162,26 +185,23 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) | |||
162 | return htype; | 185 | return htype; |
163 | } | 186 | } |
164 | 187 | ||
165 | static bool check_min_rate(struct sk_buff *skb) | 188 | static bool is_pae(struct sk_buff *skb) |
166 | { | 189 | { |
167 | struct ieee80211_hdr *hdr; | 190 | struct ieee80211_hdr *hdr; |
168 | bool use_minrate = false; | ||
169 | __le16 fc; | 191 | __le16 fc; |
170 | 192 | ||
171 | hdr = (struct ieee80211_hdr *)skb->data; | 193 | hdr = (struct ieee80211_hdr *)skb->data; |
172 | fc = hdr->frame_control; | 194 | fc = hdr->frame_control; |
173 | 195 | ||
174 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) { | 196 | if (ieee80211_is_data(fc)) { |
175 | use_minrate = true; | ||
176 | } else if (ieee80211_is_data(fc)) { | ||
177 | if (ieee80211_is_nullfunc(fc) || | 197 | if (ieee80211_is_nullfunc(fc) || |
178 | /* Port Access Entity (IEEE 802.1X) */ | 198 | /* Port Access Entity (IEEE 802.1X) */ |
179 | (skb->protocol == cpu_to_be16(ETH_P_PAE))) { | 199 | (skb->protocol == cpu_to_be16(ETH_P_PAE))) { |
180 | use_minrate = true; | 200 | return true; |
181 | } | 201 | } |
182 | } | 202 | } |
183 | 203 | ||
184 | return use_minrate; | 204 | return false; |
185 | } | 205 | } |
186 | 206 | ||
187 | static int get_hw_crypto_keytype(struct sk_buff *skb) | 207 | static int get_hw_crypto_keytype(struct sk_buff *skb) |
@@ -200,56 +220,6 @@ static int get_hw_crypto_keytype(struct sk_buff *skb) | |||
200 | return ATH9K_KEY_TYPE_CLEAR; | 220 | return ATH9K_KEY_TYPE_CLEAR; |
201 | } | 221 | } |
202 | 222 | ||
203 | static void setup_rate_retries(struct ath_softc *sc, struct sk_buff *skb) | ||
204 | { | ||
205 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
206 | struct ath_tx_info_priv *tx_info_priv; | ||
207 | struct ath_rc_series *rcs; | ||
208 | struct ieee80211_hdr *hdr; | ||
209 | const struct ath9k_rate_table *rt; | ||
210 | bool use_minrate; | ||
211 | __le16 fc; | ||
212 | u8 rix; | ||
213 | |||
214 | rt = sc->sc_currates; | ||
215 | BUG_ON(!rt); | ||
216 | |||
217 | hdr = (struct ieee80211_hdr *)skb->data; | ||
218 | fc = hdr->frame_control; | ||
219 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; /* HACK */ | ||
220 | rcs = tx_info_priv->rcs; | ||
221 | |||
222 | /* Check if min rates have to be used */ | ||
223 | use_minrate = check_min_rate(skb); | ||
224 | |||
225 | if (ieee80211_is_data(fc) && !use_minrate) { | ||
226 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
227 | rcs[0].rix = | ||
228 | ath_tx_findindex(rt, tx_info_priv->min_rate); | ||
229 | /* mcast packets are not re-tried */ | ||
230 | rcs[0].tries = 1; | ||
231 | } | ||
232 | } else { | ||
233 | /* for management and control frames, | ||
234 | or for NULL and EAPOL frames */ | ||
235 | if (use_minrate) | ||
236 | rcs[0].rix = ath_rate_findrateix(sc, tx_info_priv->min_rate); | ||
237 | else | ||
238 | rcs[0].rix = 0; | ||
239 | rcs[0].tries = ATH_MGT_TXMAXTRY; | ||
240 | } | ||
241 | |||
242 | rix = rcs[0].rix; | ||
243 | |||
244 | if (ieee80211_has_morefrags(fc) || | ||
245 | (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { | ||
246 | rcs[1].tries = rcs[2].tries = rcs[3].tries = 0; | ||
247 | rcs[1].rix = rcs[2].rix = rcs[3].rix = 0; | ||
248 | /* reset tries but keep rate index */ | ||
249 | rcs[0].tries = ATH_TXMAXTRY; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /* Called only when tx aggregation is enabled and HT is supported */ | 223 | /* Called only when tx aggregation is enabled and HT is supported */ |
254 | 224 | ||
255 | static void assign_aggr_tid_seqno(struct sk_buff *skb, | 225 | static void assign_aggr_tid_seqno(struct sk_buff *skb, |
@@ -278,7 +248,7 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb, | |||
278 | 248 | ||
279 | /* Get seqno */ | 249 | /* Get seqno */ |
280 | 250 | ||
281 | if (ieee80211_is_data(fc) && !check_min_rate(skb)) { | 251 | if (ieee80211_is_data(fc) && !is_pae(skb)) { |
282 | /* For HT capable stations, we save tidno for later use. | 252 | /* For HT capable stations, we save tidno for later use. |
283 | * We also override seqno set by upper layer with the one | 253 | * We also override seqno set by upper layer with the one |
284 | * in tx aggregation state. | 254 | * in tx aggregation state. |
@@ -523,27 +493,23 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
523 | * width - 0 for 20 MHz, 1 for 40 MHz | 493 | * width - 0 for 20 MHz, 1 for 40 MHz |
524 | * half_gi - to use 4us v/s 3.6 us for symbol time | 494 | * half_gi - to use 4us v/s 3.6 us for symbol time |
525 | */ | 495 | */ |
526 | |||
527 | static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, | 496 | static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, |
528 | int width, int half_gi, bool shortPreamble) | 497 | int width, int half_gi, bool shortPreamble) |
529 | { | 498 | { |
530 | const struct ath9k_rate_table *rt = sc->sc_currates; | 499 | struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode]; |
531 | u32 nbits, nsymbits, duration, nsymbols; | 500 | u32 nbits, nsymbits, duration, nsymbols; |
532 | u8 rc; | 501 | u8 rc; |
533 | int streams, pktlen; | 502 | int streams, pktlen; |
534 | 503 | ||
535 | pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; | 504 | pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; |
536 | rc = rt->info[rix].rateCode; | 505 | rc = rate_table->info[rix].ratecode; |
537 | 506 | ||
538 | /* | 507 | /* for legacy rates, use old function to compute packet duration */ |
539 | * for legacy rates, use old function to compute packet duration | ||
540 | */ | ||
541 | if (!IS_HT_RATE(rc)) | 508 | if (!IS_HT_RATE(rc)) |
542 | return ath9k_hw_computetxtime(sc->sc_ah, rt, pktlen, rix, | 509 | return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen, |
543 | shortPreamble); | 510 | rix, shortPreamble); |
544 | /* | 511 | |
545 | * find number of symbols: PLCP + data | 512 | /* find number of symbols: PLCP + data */ |
546 | */ | ||
547 | nbits = (pktlen << 3) + OFDM_PLCP_BITS; | 513 | nbits = (pktlen << 3) + OFDM_PLCP_BITS; |
548 | nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; | 514 | nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; |
549 | nsymbols = (nbits + nsymbits - 1) / nsymbits; | 515 | nsymbols = (nbits + nsymbits - 1) / nsymbits; |
@@ -553,9 +519,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, | |||
553 | else | 519 | else |
554 | duration = SYMBOL_TIME_HALFGI(nsymbols); | 520 | duration = SYMBOL_TIME_HALFGI(nsymbols); |
555 | 521 | ||
556 | /* | 522 | /* addup duration for legacy/ht training and signal fields */ |
557 | * addup duration for legacy/ht training and signal fields | ||
558 | */ | ||
559 | streams = HT_RC_2_STREAMS(rc); | 523 | streams = HT_RC_2_STREAMS(rc); |
560 | duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); | 524 | duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); |
561 | 525 | ||
@@ -567,179 +531,125 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, | |||
567 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | 531 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) |
568 | { | 532 | { |
569 | struct ath_hal *ah = sc->sc_ah; | 533 | struct ath_hal *ah = sc->sc_ah; |
570 | const struct ath9k_rate_table *rt; | 534 | struct ath_rate_table *rt; |
571 | struct ath_desc *ds = bf->bf_desc; | 535 | struct ath_desc *ds = bf->bf_desc; |
572 | struct ath_desc *lastds = bf->bf_lastbf->bf_desc; | 536 | struct ath_desc *lastds = bf->bf_lastbf->bf_desc; |
573 | struct ath9k_11n_rate_series series[4]; | 537 | struct ath9k_11n_rate_series series[4]; |
538 | struct sk_buff *skb; | ||
539 | struct ieee80211_tx_info *tx_info; | ||
540 | struct ieee80211_tx_rate *rates; | ||
541 | struct ieee80211_hdr *hdr; | ||
574 | int i, flags, rtsctsena = 0; | 542 | int i, flags, rtsctsena = 0; |
575 | u32 ctsduration = 0; | 543 | u32 ctsduration = 0; |
576 | u8 rix = 0, cix, ctsrate = 0; | 544 | u8 rix = 0, cix, ctsrate = 0; |
577 | struct ath_node *an = NULL; | 545 | __le16 fc; |
578 | struct sk_buff *skb; | 546 | |
579 | struct ieee80211_tx_info *tx_info; | 547 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); |
580 | 548 | ||
581 | skb = (struct sk_buff *)bf->bf_mpdu; | 549 | skb = (struct sk_buff *)bf->bf_mpdu; |
550 | hdr = (struct ieee80211_hdr *)skb->data; | ||
551 | fc = hdr->frame_control; | ||
582 | tx_info = IEEE80211_SKB_CB(skb); | 552 | tx_info = IEEE80211_SKB_CB(skb); |
553 | rates = tx_info->control.rates; | ||
583 | 554 | ||
584 | if (tx_info->control.sta) | 555 | if (ieee80211_has_morefrags(fc) || |
585 | an = (struct ath_node *)tx_info->control.sta->drv_priv; | 556 | (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { |
557 | rates[1].count = rates[2].count = rates[3].count = 0; | ||
558 | rates[1].idx = rates[2].idx = rates[3].idx = 0; | ||
559 | rates[0].count = ATH_TXMAXTRY; | ||
560 | } | ||
586 | 561 | ||
587 | /* | 562 | /* get the cix for the lowest valid rix */ |
588 | * get the cix for the lowest valid rix. | 563 | rt = sc->hw_rate_table[sc->sc_curmode]; |
589 | */ | 564 | for (i = 3; i >= 0; i--) { |
590 | rt = sc->sc_currates; | 565 | if (rates[i].count && (rates[i].idx >= 0)) { |
591 | for (i = 4; i--;) { | 566 | rix = rates[i].idx; |
592 | if (bf->bf_rcs[i].tries) { | ||
593 | rix = bf->bf_rcs[i].rix; | ||
594 | break; | 567 | break; |
595 | } | 568 | } |
596 | } | 569 | } |
570 | |||
597 | flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)); | 571 | flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)); |
598 | cix = rt->info[rix].controlRate; | 572 | cix = rt->info[rix].ctrl_rate; |
599 | 573 | ||
600 | /* | 574 | /* |
601 | * If 802.11g protection is enabled, determine whether | 575 | * If 802.11g protection is enabled, determine whether to use RTS/CTS or |
602 | * to use RTS/CTS or just CTS. Note that this is only | 576 | * just CTS. Note that this is only done for OFDM/HT unicast frames. |
603 | * done for OFDM/HT unicast frames. | ||
604 | */ | 577 | */ |
605 | if (sc->sc_protmode != PROT_M_NONE && | 578 | if (sc->sc_protmode != PROT_M_NONE && !(bf->bf_flags & ATH9K_TXDESC_NOACK) |
606 | (rt->info[rix].phy == PHY_OFDM || | 579 | && (rt->info[rix].phy == WLAN_RC_PHY_OFDM || |
607 | rt->info[rix].phy == PHY_HT) && | 580 | WLAN_RC_PHY_HT(rt->info[rix].phy))) { |
608 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | ||
609 | if (sc->sc_protmode == PROT_M_RTSCTS) | 581 | if (sc->sc_protmode == PROT_M_RTSCTS) |
610 | flags = ATH9K_TXDESC_RTSENA; | 582 | flags = ATH9K_TXDESC_RTSENA; |
611 | else if (sc->sc_protmode == PROT_M_CTSONLY) | 583 | else if (sc->sc_protmode == PROT_M_CTSONLY) |
612 | flags = ATH9K_TXDESC_CTSENA; | 584 | flags = ATH9K_TXDESC_CTSENA; |
613 | 585 | ||
614 | cix = rt->info[sc->sc_protrix].controlRate; | 586 | cix = rt->info[sc->sc_protrix].ctrl_rate; |
615 | rtsctsena = 1; | 587 | rtsctsena = 1; |
616 | } | 588 | } |
617 | 589 | ||
618 | /* For 11n, the default behavior is to enable RTS for | 590 | /* For 11n, the default behavior is to enable RTS for hw retried frames. |
619 | * hw retried frames. We enable the global flag here and | 591 | * We enable the global flag here and let rate series flags determine |
620 | * let rate series flags determine which rates will actually | 592 | * which rates will actually use RTS. |
621 | * use RTS. | ||
622 | */ | 593 | */ |
623 | if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) { | 594 | if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) { |
624 | /* | 595 | /* 802.11g protection not needed, use our default behavior */ |
625 | * 802.11g protection not needed, use our default behavior | ||
626 | */ | ||
627 | if (!rtsctsena) | 596 | if (!rtsctsena) |
628 | flags = ATH9K_TXDESC_RTSENA; | 597 | flags = ATH9K_TXDESC_RTSENA; |
629 | } | 598 | } |
630 | 599 | ||
631 | /* | 600 | /* Set protection if aggregate protection on */ |
632 | * Set protection if aggregate protection on | ||
633 | */ | ||
634 | if (sc->sc_config.ath_aggr_prot && | 601 | if (sc->sc_config.ath_aggr_prot && |
635 | (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { | 602 | (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { |
636 | flags = ATH9K_TXDESC_RTSENA; | 603 | flags = ATH9K_TXDESC_RTSENA; |
637 | cix = rt->info[sc->sc_protrix].controlRate; | 604 | cix = rt->info[sc->sc_protrix].ctrl_rate; |
638 | rtsctsena = 1; | 605 | rtsctsena = 1; |
639 | } | 606 | } |
640 | 607 | ||
641 | /* | 608 | /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ |
642 | * For AR5416 - RTS cannot be followed by a frame larger than 8K. | 609 | if (bf_isaggr(bf) && (bf->bf_al > ah->ah_caps.rts_aggr_limit)) |
643 | */ | ||
644 | if (bf_isaggr(bf) && (bf->bf_al > ah->ah_caps.rts_aggr_limit)) { | ||
645 | /* | ||
646 | * Ensure that in the case of SM Dynamic power save | ||
647 | * while we are bursting the second aggregate the | ||
648 | * RTS is cleared. | ||
649 | */ | ||
650 | flags &= ~(ATH9K_TXDESC_RTSENA); | 610 | flags &= ~(ATH9K_TXDESC_RTSENA); |
651 | } | ||
652 | |||
653 | /* | ||
654 | * CTS transmit rate is derived from the transmit rate | ||
655 | * by looking in the h/w rate table. We must also factor | ||
656 | * in whether or not a short preamble is to be used. | ||
657 | * NB: cix is set above where RTS/CTS is enabled | ||
658 | */ | ||
659 | BUG_ON(cix == 0xff); | ||
660 | ctsrate = rt->info[cix].rateCode | | ||
661 | (bf_isshpreamble(bf) ? rt->info[cix].shortPreamble : 0); | ||
662 | 611 | ||
663 | /* | 612 | /* |
664 | * Setup HAL rate series | 613 | * CTS transmit rate is derived from the transmit rate by looking in the |
614 | * h/w rate table. We must also factor in whether or not a short | ||
615 | * preamble is to be used. NB: cix is set above where RTS/CTS is enabled | ||
665 | */ | 616 | */ |
666 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); | 617 | ctsrate = rt->info[cix].ratecode | |
618 | (bf_isshpreamble(bf) ? rt->info[cix].short_preamble : 0); | ||
667 | 619 | ||
668 | for (i = 0; i < 4; i++) { | 620 | for (i = 0; i < 4; i++) { |
669 | if (!bf->bf_rcs[i].tries) | 621 | if (!rates[i].count || (rates[i].idx < 0)) |
670 | continue; | 622 | continue; |
671 | 623 | ||
672 | rix = bf->bf_rcs[i].rix; | 624 | rix = rates[i].idx; |
673 | 625 | ||
674 | series[i].Rate = rt->info[rix].rateCode | | 626 | series[i].Rate = rt->info[rix].ratecode | |
675 | (bf_isshpreamble(bf) ? rt->info[rix].shortPreamble : 0); | 627 | (bf_isshpreamble(bf) ? rt->info[rix].short_preamble : 0); |
676 | 628 | ||
677 | series[i].Tries = bf->bf_rcs[i].tries; | 629 | series[i].Tries = rates[i].count; |
678 | 630 | ||
679 | series[i].RateFlags = ( | 631 | series[i].RateFlags = ( |
680 | (bf->bf_rcs[i].flags & ATH_RC_RTSCTS_FLAG) ? | 632 | (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) ? |
681 | ATH9K_RATESERIES_RTS_CTS : 0) | | 633 | ATH9K_RATESERIES_RTS_CTS : 0) | |
682 | ((bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) ? | 634 | ((rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? |
683 | ATH9K_RATESERIES_2040 : 0) | | 635 | ATH9K_RATESERIES_2040 : 0) | |
684 | ((bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG) ? | 636 | ((rates[i].flags & IEEE80211_TX_RC_SHORT_GI) ? |
685 | ATH9K_RATESERIES_HALFGI : 0); | 637 | ATH9K_RATESERIES_HALFGI : 0); |
686 | 638 | ||
687 | series[i].PktDuration = ath_pkt_duration(sc, rix, bf, | 639 | series[i].PktDuration = ath_pkt_duration(sc, rix, bf, |
688 | (bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0, | 640 | (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0, |
689 | (bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG), | 641 | (rates[i].flags & IEEE80211_TX_RC_SHORT_GI), |
690 | bf_isshpreamble(bf)); | 642 | bf_isshpreamble(bf)); |
691 | 643 | ||
692 | if (bf_isht(bf) && an) | 644 | series[i].ChSel = sc->sc_tx_chainmask; |
693 | series[i].ChSel = ath_chainmask_sel_logic(sc, an); | ||
694 | else | ||
695 | series[i].ChSel = sc->sc_tx_chainmask; | ||
696 | 645 | ||
697 | if (rtsctsena) | 646 | if (rtsctsena) |
698 | series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; | 647 | series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; |
699 | } | 648 | } |
700 | 649 | ||
701 | /* | 650 | /* set dur_update_en for l-sig computation except for PS-Poll frames */ |
702 | * For non-HT devices, calculate RTS/CTS duration in software | 651 | ath9k_hw_set11n_ratescenario(ah, ds, lastds, !bf_ispspoll(bf), |
703 | * and disable multi-rate retry. | 652 | ctsrate, ctsduration, |
704 | */ | ||
705 | if (flags && !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)) { | ||
706 | /* | ||
707 | * Compute the transmit duration based on the frame | ||
708 | * size and the size of an ACK frame. We call into the | ||
709 | * HAL to do the computation since it depends on the | ||
710 | * characteristics of the actual PHY being used. | ||
711 | * | ||
712 | * NB: CTS is assumed the same size as an ACK so we can | ||
713 | * use the precalculated ACK durations. | ||
714 | */ | ||
715 | if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */ | ||
716 | ctsduration += bf_isshpreamble(bf) ? | ||
717 | rt->info[cix].spAckDuration : | ||
718 | rt->info[cix].lpAckDuration; | ||
719 | } | ||
720 | |||
721 | ctsduration += series[0].PktDuration; | ||
722 | |||
723 | if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */ | ||
724 | ctsduration += bf_isshpreamble(bf) ? | ||
725 | rt->info[rix].spAckDuration : | ||
726 | rt->info[rix].lpAckDuration; | ||
727 | } | ||
728 | |||
729 | /* | ||
730 | * Disable multi-rate retry when using RTS/CTS by clearing | ||
731 | * series 1, 2 and 3. | ||
732 | */ | ||
733 | memset(&series[1], 0, sizeof(struct ath9k_11n_rate_series) * 3); | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | * set dur_update_en for l-sig computation except for PS-Poll frames | ||
738 | */ | ||
739 | ath9k_hw_set11n_ratescenario(ah, ds, lastds, | ||
740 | !bf_ispspoll(bf), | ||
741 | ctsrate, | ||
742 | ctsduration, | ||
743 | series, 4, flags); | 653 | series, 4, flags); |
744 | 654 | ||
745 | if (sc->sc_config.ath_aggr_prot && flags) | 655 | if (sc->sc_config.ath_aggr_prot && flags) |
@@ -750,29 +660,18 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
750 | * Function to send a normal HT (non-AMPDU) frame | 660 | * Function to send a normal HT (non-AMPDU) frame |
751 | * NB: must be called with txq lock held | 661 | * NB: must be called with txq lock held |
752 | */ | 662 | */ |
753 | |||
754 | static int ath_tx_send_normal(struct ath_softc *sc, | 663 | static int ath_tx_send_normal(struct ath_softc *sc, |
755 | struct ath_txq *txq, | 664 | struct ath_txq *txq, |
756 | struct ath_atx_tid *tid, | 665 | struct ath_atx_tid *tid, |
757 | struct list_head *bf_head) | 666 | struct list_head *bf_head) |
758 | { | 667 | { |
759 | struct ath_buf *bf; | 668 | struct ath_buf *bf; |
760 | struct sk_buff *skb; | ||
761 | struct ieee80211_tx_info *tx_info; | ||
762 | struct ath_tx_info_priv *tx_info_priv; | ||
763 | 669 | ||
764 | BUG_ON(list_empty(bf_head)); | 670 | BUG_ON(list_empty(bf_head)); |
765 | 671 | ||
766 | bf = list_first_entry(bf_head, struct ath_buf, list); | 672 | bf = list_first_entry(bf_head, struct ath_buf, list); |
767 | bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */ | 673 | bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */ |
768 | 674 | ||
769 | skb = (struct sk_buff *)bf->bf_mpdu; | ||
770 | tx_info = IEEE80211_SKB_CB(skb); | ||
771 | |||
772 | /* XXX: HACK! */ | ||
773 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; | ||
774 | memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); | ||
775 | |||
776 | /* update starting sequence number for subsequent ADDBA request */ | 675 | /* update starting sequence number for subsequent ADDBA request */ |
777 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | 676 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); |
778 | 677 | ||
@@ -1051,18 +950,37 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
1051 | return; | 950 | return; |
1052 | } | 951 | } |
1053 | 952 | ||
953 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad) | ||
954 | { | ||
955 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | ||
956 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
957 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
958 | |||
959 | tx_info_priv->update_rc = false; | ||
960 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | ||
961 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
962 | |||
963 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | ||
964 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | ||
965 | if (bf_isdata(bf)) { | ||
966 | memcpy(&tx_info_priv->tx, &ds->ds_txstat, | ||
967 | sizeof(tx_info_priv->tx)); | ||
968 | tx_info_priv->n_frames = bf->bf_nframes; | ||
969 | tx_info_priv->n_bad_frames = nbad; | ||
970 | tx_info_priv->update_rc = true; | ||
971 | } | ||
972 | } | ||
973 | } | ||
974 | |||
1054 | /* Process completed xmit descriptors from the specified queue */ | 975 | /* Process completed xmit descriptors from the specified queue */ |
1055 | 976 | ||
1056 | static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | 977 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) |
1057 | { | 978 | { |
1058 | struct ath_hal *ah = sc->sc_ah; | 979 | struct ath_hal *ah = sc->sc_ah; |
1059 | struct ath_buf *bf, *lastbf, *bf_held = NULL; | 980 | struct ath_buf *bf, *lastbf, *bf_held = NULL; |
1060 | struct list_head bf_head; | 981 | struct list_head bf_head; |
1061 | struct ath_desc *ds, *tmp_ds; | 982 | struct ath_desc *ds; |
1062 | struct sk_buff *skb; | 983 | int txok, nbad = 0; |
1063 | struct ieee80211_tx_info *tx_info; | ||
1064 | struct ath_tx_info_priv *tx_info_priv; | ||
1065 | int nacked, txok, nbad = 0, isrifs = 0; | ||
1066 | int status; | 984 | int status; |
1067 | 985 | ||
1068 | DPRINTF(sc, ATH_DBG_QUEUE, | 986 | DPRINTF(sc, ATH_DBG_QUEUE, |
@@ -1070,7 +988,6 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1070 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), | 988 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), |
1071 | txq->axq_link); | 989 | txq->axq_link); |
1072 | 990 | ||
1073 | nacked = 0; | ||
1074 | for (;;) { | 991 | for (;;) { |
1075 | spin_lock_bh(&txq->axq_lock); | 992 | spin_lock_bh(&txq->axq_lock); |
1076 | if (list_empty(&txq->axq_q)) { | 993 | if (list_empty(&txq->axq_q)) { |
@@ -1160,30 +1077,8 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1160 | } else { | 1077 | } else { |
1161 | nbad = ath_tx_num_badfrms(sc, bf, txok); | 1078 | nbad = ath_tx_num_badfrms(sc, bf, txok); |
1162 | } | 1079 | } |
1163 | skb = bf->bf_mpdu; | 1080 | |
1164 | tx_info = IEEE80211_SKB_CB(skb); | 1081 | ath_tx_rc_status(bf, ds, nbad); |
1165 | |||
1166 | /* XXX: HACK! */ | ||
1167 | tx_info_priv = (struct ath_tx_info_priv *) tx_info->control.vif; | ||
1168 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | ||
1169 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
1170 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | ||
1171 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | ||
1172 | if (ds->ds_txstat.ts_status == 0) | ||
1173 | nacked++; | ||
1174 | |||
1175 | if (bf_isdata(bf)) { | ||
1176 | if (isrifs) | ||
1177 | tmp_ds = bf->bf_rifslast->bf_desc; | ||
1178 | else | ||
1179 | tmp_ds = ds; | ||
1180 | memcpy(&tx_info_priv->tx, | ||
1181 | &tmp_ds->ds_txstat, | ||
1182 | sizeof(tx_info_priv->tx)); | ||
1183 | tx_info_priv->n_frames = bf->bf_nframes; | ||
1184 | tx_info_priv->n_bad_frames = nbad; | ||
1185 | } | ||
1186 | } | ||
1187 | 1082 | ||
1188 | /* | 1083 | /* |
1189 | * Complete this transmit unit | 1084 | * Complete this transmit unit |
@@ -1214,7 +1109,6 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1214 | ath_txq_schedule(sc, txq); | 1109 | ath_txq_schedule(sc, txq); |
1215 | spin_unlock_bh(&txq->axq_lock); | 1110 | spin_unlock_bh(&txq->axq_lock); |
1216 | } | 1111 | } |
1217 | return nacked; | ||
1218 | } | 1112 | } |
1219 | 1113 | ||
1220 | static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq) | 1114 | static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq) |
@@ -1254,7 +1148,7 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx) | |||
1254 | spin_lock_bh(&sc->sc_resetlock); | 1148 | spin_lock_bh(&sc->sc_resetlock); |
1255 | if (!ath9k_hw_reset(ah, | 1149 | if (!ath9k_hw_reset(ah, |
1256 | sc->sc_ah->ah_curchan, | 1150 | sc->sc_ah->ah_curchan, |
1257 | sc->sc_ht_info.tx_chan_width, | 1151 | sc->tx_chan_width, |
1258 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, | 1152 | sc->sc_tx_chainmask, sc->sc_rx_chainmask, |
1259 | sc->sc_ht_extprotspacing, true, &status)) { | 1153 | sc->sc_ht_extprotspacing, true, &status)) { |
1260 | 1154 | ||
@@ -1307,9 +1201,6 @@ static int ath_tx_send_ampdu(struct ath_softc *sc, | |||
1307 | struct ath_tx_control *txctl) | 1201 | struct ath_tx_control *txctl) |
1308 | { | 1202 | { |
1309 | struct ath_buf *bf; | 1203 | struct ath_buf *bf; |
1310 | struct sk_buff *skb; | ||
1311 | struct ieee80211_tx_info *tx_info; | ||
1312 | struct ath_tx_info_priv *tx_info_priv; | ||
1313 | 1204 | ||
1314 | BUG_ON(list_empty(bf_head)); | 1205 | BUG_ON(list_empty(bf_head)); |
1315 | 1206 | ||
@@ -1335,12 +1226,6 @@ static int ath_tx_send_ampdu(struct ath_softc *sc, | |||
1335 | return 0; | 1226 | return 0; |
1336 | } | 1227 | } |
1337 | 1228 | ||
1338 | skb = (struct sk_buff *)bf->bf_mpdu; | ||
1339 | tx_info = IEEE80211_SKB_CB(skb); | ||
1340 | /* XXX: HACK! */ | ||
1341 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; | ||
1342 | memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); | ||
1343 | |||
1344 | /* Add sub-frame to BAW */ | 1229 | /* Add sub-frame to BAW */ |
1345 | ath_tx_addto_baw(sc, tid, bf); | 1230 | ath_tx_addto_baw(sc, tid, bf); |
1346 | 1231 | ||
@@ -1362,9 +1247,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc, | |||
1362 | struct ath_buf *bf, | 1247 | struct ath_buf *bf, |
1363 | struct ath_atx_tid *tid) | 1248 | struct ath_atx_tid *tid) |
1364 | { | 1249 | { |
1365 | const struct ath9k_rate_table *rt = sc->sc_currates; | 1250 | struct ath_rate_table *rate_table = sc->hw_rate_table[sc->sc_curmode]; |
1366 | struct sk_buff *skb; | 1251 | struct sk_buff *skb; |
1367 | struct ieee80211_tx_info *tx_info; | 1252 | struct ieee80211_tx_info *tx_info; |
1253 | struct ieee80211_tx_rate *rates; | ||
1368 | struct ath_tx_info_priv *tx_info_priv; | 1254 | struct ath_tx_info_priv *tx_info_priv; |
1369 | u32 max_4ms_framelen, frame_length; | 1255 | u32 max_4ms_framelen, frame_length; |
1370 | u16 aggr_limit, legacy = 0, maxampdu; | 1256 | u16 aggr_limit, legacy = 0, maxampdu; |
@@ -1372,10 +1258,9 @@ static u32 ath_lookup_rate(struct ath_softc *sc, | |||
1372 | 1258 | ||
1373 | skb = (struct sk_buff *)bf->bf_mpdu; | 1259 | skb = (struct sk_buff *)bf->bf_mpdu; |
1374 | tx_info = IEEE80211_SKB_CB(skb); | 1260 | tx_info = IEEE80211_SKB_CB(skb); |
1375 | tx_info_priv = (struct ath_tx_info_priv *) | 1261 | rates = tx_info->control.rates; |
1376 | tx_info->control.vif; /* XXX: HACK! */ | 1262 | tx_info_priv = |
1377 | memcpy(bf->bf_rcs, | 1263 | (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; |
1378 | tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); | ||
1379 | 1264 | ||
1380 | /* | 1265 | /* |
1381 | * Find the lowest frame length among the rate series that will have a | 1266 | * Find the lowest frame length among the rate series that will have a |
@@ -1385,14 +1270,14 @@ static u32 ath_lookup_rate(struct ath_softc *sc, | |||
1385 | max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; | 1270 | max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; |
1386 | 1271 | ||
1387 | for (i = 0; i < 4; i++) { | 1272 | for (i = 0; i < 4; i++) { |
1388 | if (bf->bf_rcs[i].tries) { | 1273 | if (rates[i].count) { |
1389 | frame_length = bf->bf_rcs[i].max_4ms_framelen; | 1274 | if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) { |
1390 | |||
1391 | if (rt->info[bf->bf_rcs[i].rix].phy != PHY_HT) { | ||
1392 | legacy = 1; | 1275 | legacy = 1; |
1393 | break; | 1276 | break; |
1394 | } | 1277 | } |
1395 | 1278 | ||
1279 | frame_length = | ||
1280 | rate_table->info[rates[i].idx].max_4ms_framelen; | ||
1396 | max_4ms_framelen = min(max_4ms_framelen, frame_length); | 1281 | max_4ms_framelen = min(max_4ms_framelen, frame_length); |
1397 | } | 1282 | } |
1398 | } | 1283 | } |
@@ -1431,7 +1316,9 @@ static int ath_compute_num_delims(struct ath_softc *sc, | |||
1431 | struct ath_buf *bf, | 1316 | struct ath_buf *bf, |
1432 | u16 frmlen) | 1317 | u16 frmlen) |
1433 | { | 1318 | { |
1434 | const struct ath9k_rate_table *rt = sc->sc_currates; | 1319 | struct ath_rate_table *rt = sc->hw_rate_table[sc->sc_curmode]; |
1320 | struct sk_buff *skb = bf->bf_mpdu; | ||
1321 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1435 | u32 nsymbits, nsymbols, mpdudensity; | 1322 | u32 nsymbits, nsymbols, mpdudensity; |
1436 | u16 minlen; | 1323 | u16 minlen; |
1437 | u8 rc, flags, rix; | 1324 | u8 rc, flags, rix; |
@@ -1464,11 +1351,11 @@ static int ath_compute_num_delims(struct ath_softc *sc, | |||
1464 | if (mpdudensity == 0) | 1351 | if (mpdudensity == 0) |
1465 | return ndelim; | 1352 | return ndelim; |
1466 | 1353 | ||
1467 | rix = bf->bf_rcs[0].rix; | 1354 | rix = tx_info->control.rates[0].idx; |
1468 | flags = bf->bf_rcs[0].flags; | 1355 | flags = tx_info->control.rates[0].flags; |
1469 | rc = rt->info[rix].rateCode; | 1356 | rc = rt->info[rix].ratecode; |
1470 | width = (flags & ATH_RC_CW40_FLAG) ? 1 : 0; | 1357 | width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; |
1471 | half_gi = (flags & ATH_RC_SGI_FLAG) ? 1 : 0; | 1358 | half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; |
1472 | 1359 | ||
1473 | if (half_gi) | 1360 | if (half_gi) |
1474 | nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); | 1361 | nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); |
@@ -1510,7 +1397,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
1510 | u16 aggr_limit = 0, al = 0, bpad = 0, | 1397 | u16 aggr_limit = 0, al = 0, bpad = 0, |
1511 | al_delta, h_baw = tid->baw_size / 2; | 1398 | al_delta, h_baw = tid->baw_size / 2; |
1512 | enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; | 1399 | enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; |
1513 | int prev_al = 0, is_ds_rate = 0; | 1400 | int prev_al = 0; |
1514 | INIT_LIST_HEAD(&bf_head); | 1401 | INIT_LIST_HEAD(&bf_head); |
1515 | 1402 | ||
1516 | BUG_ON(list_empty(&tid->buf_q)); | 1403 | BUG_ON(list_empty(&tid->buf_q)); |
@@ -1531,11 +1418,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
1531 | if (!rl) { | 1418 | if (!rl) { |
1532 | aggr_limit = ath_lookup_rate(sc, bf, tid); | 1419 | aggr_limit = ath_lookup_rate(sc, bf, tid); |
1533 | rl = 1; | 1420 | rl = 1; |
1534 | /* | ||
1535 | * Is rate dual stream | ||
1536 | */ | ||
1537 | is_ds_rate = | ||
1538 | (bf->bf_rcs[0].flags & ATH_RC_DS_FLAG) ? 1 : 0; | ||
1539 | } | 1421 | } |
1540 | 1422 | ||
1541 | /* | 1423 | /* |
@@ -1772,20 +1654,19 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc, | |||
1772 | } | 1654 | } |
1773 | 1655 | ||
1774 | static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, | 1656 | static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, |
1775 | struct sk_buff *skb, struct scatterlist *sg, | 1657 | struct sk_buff *skb, |
1776 | struct ath_tx_control *txctl) | 1658 | struct ath_tx_control *txctl) |
1777 | { | 1659 | { |
1778 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1660 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1779 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1661 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1780 | struct ath_tx_info_priv *tx_info_priv; | 1662 | struct ath_tx_info_priv *tx_info_priv; |
1781 | struct ath_rc_series *rcs; | ||
1782 | int hdrlen; | 1663 | int hdrlen; |
1783 | __le16 fc; | 1664 | __le16 fc; |
1784 | 1665 | ||
1785 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; | 1666 | tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_KERNEL); |
1667 | tx_info->rate_driver_data[0] = tx_info_priv; | ||
1786 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1668 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
1787 | fc = hdr->frame_control; | 1669 | fc = hdr->frame_control; |
1788 | rcs = tx_info_priv->rcs; | ||
1789 | 1670 | ||
1790 | ATH_TXBUF_RESET(bf); | 1671 | ATH_TXBUF_RESET(bf); |
1791 | 1672 | ||
@@ -1805,7 +1686,7 @@ static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, | |||
1805 | (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? | 1686 | (sc->sc_flags & SC_OP_PREAMBLE_SHORT) ? |
1806 | (bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) : | 1687 | (bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) : |
1807 | (bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE); | 1688 | (bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE); |
1808 | (sc->hw->conf.ht.enabled && | 1689 | (sc->hw->conf.ht.enabled && !is_pae(skb) && |
1809 | (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) ? | 1690 | (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) ? |
1810 | (bf->bf_state.bf_type |= BUF_HT) : | 1691 | (bf->bf_state.bf_type |= BUF_HT) : |
1811 | (bf->bf_state.bf_type &= ~BUF_HT); | 1692 | (bf->bf_state.bf_type &= ~BUF_HT); |
@@ -1823,15 +1704,6 @@ static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, | |||
1823 | bf->bf_keyix = ATH9K_TXKEYIX_INVALID; | 1704 | bf->bf_keyix = ATH9K_TXKEYIX_INVALID; |
1824 | } | 1705 | } |
1825 | 1706 | ||
1826 | /* Rate series */ | ||
1827 | |||
1828 | setup_rate_retries(sc, skb); | ||
1829 | |||
1830 | bf->bf_rcs[0] = rcs[0]; | ||
1831 | bf->bf_rcs[1] = rcs[1]; | ||
1832 | bf->bf_rcs[2] = rcs[2]; | ||
1833 | bf->bf_rcs[3] = rcs[3]; | ||
1834 | |||
1835 | /* Assign seqno, tidno */ | 1707 | /* Assign seqno, tidno */ |
1836 | 1708 | ||
1837 | if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR)) | 1709 | if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR)) |
@@ -1847,7 +1719,6 @@ static void ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf, | |||
1847 | 1719 | ||
1848 | /* FIXME: tx power */ | 1720 | /* FIXME: tx power */ |
1849 | static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | 1721 | static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, |
1850 | struct scatterlist *sg, u32 n_sg, | ||
1851 | struct ath_tx_control *txctl) | 1722 | struct ath_tx_control *txctl) |
1852 | { | 1723 | { |
1853 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | 1724 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; |
@@ -1876,10 +1747,10 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1876 | bf->bf_keyix, bf->bf_keytype, bf->bf_flags); | 1747 | bf->bf_keyix, bf->bf_keytype, bf->bf_flags); |
1877 | 1748 | ||
1878 | ath9k_hw_filltxdesc(ah, ds, | 1749 | ath9k_hw_filltxdesc(ah, ds, |
1879 | sg_dma_len(sg), /* segment length */ | 1750 | skb->len, /* segment length */ |
1880 | true, /* first segment */ | 1751 | true, /* first segment */ |
1881 | (n_sg == 1) ? true : false, /* last segment */ | 1752 | true, /* last segment */ |
1882 | ds); /* first descriptor */ | 1753 | ds); /* first descriptor */ |
1883 | 1754 | ||
1884 | bf->bf_lastfrm = bf; | 1755 | bf->bf_lastfrm = bf; |
1885 | 1756 | ||
@@ -1919,7 +1790,6 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, | |||
1919 | struct ath_tx_control *txctl) | 1790 | struct ath_tx_control *txctl) |
1920 | { | 1791 | { |
1921 | struct ath_buf *bf; | 1792 | struct ath_buf *bf; |
1922 | struct scatterlist sg; | ||
1923 | 1793 | ||
1924 | /* Check if a tx buffer is available */ | 1794 | /* Check if a tx buffer is available */ |
1925 | 1795 | ||
@@ -1930,15 +1800,8 @@ int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb, | |||
1930 | return -1; | 1800 | return -1; |
1931 | } | 1801 | } |
1932 | 1802 | ||
1933 | ath_tx_setup_buffer(sc, bf, skb, &sg, txctl); | 1803 | ath_tx_setup_buffer(sc, bf, skb, txctl); |
1934 | 1804 | ath_tx_start_dma(sc, bf, txctl); | |
1935 | /* Setup S/G */ | ||
1936 | |||
1937 | memset(&sg, 0, sizeof(struct scatterlist)); | ||
1938 | sg_dma_address(&sg) = bf->bf_dmacontext; | ||
1939 | sg_dma_len(&sg) = skb->len; | ||
1940 | |||
1941 | ath_tx_start_dma(sc, bf, &sg, 1, txctl); | ||
1942 | 1805 | ||
1943 | return 0; | 1806 | return 0; |
1944 | } | 1807 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h index 1daa3f05a775..7dea1552a906 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h | |||
@@ -107,7 +107,7 @@ static inline int __iwl3945_poll_bit(const char *f, u32 l, | |||
107 | int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout); | 107 | int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout); |
108 | IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", | 108 | IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", |
109 | addr, bits, mask, | 109 | addr, bits, mask, |
110 | unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l); | 110 | unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l); |
111 | return ret; | 111 | return ret; |
112 | } | 112 | } |
113 | #define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \ | 113 | #define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 7187925bd0d5..2a924c10ff93 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -886,7 +886,6 @@ struct iwl3945_priv { | |||
886 | struct work_struct report_work; | 886 | struct work_struct report_work; |
887 | struct work_struct request_scan; | 887 | struct work_struct request_scan; |
888 | struct work_struct beacon_update; | 888 | struct work_struct beacon_update; |
889 | struct work_struct set_monitor; | ||
890 | 889 | ||
891 | struct tasklet_struct irq_tasklet; | 890 | struct tasklet_struct irq_tasklet; |
892 | 891 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index c43cf2f072cd..ab0b40531989 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -53,6 +53,7 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); | |||
53 | * is not compatible with earlier drivers. | 53 | * is not compatible with earlier drivers. |
54 | * This number will also appear in << 8 position of 1st dword of uCode file */ | 54 | * This number will also appear in << 8 position of 1st dword of uCode file */ |
55 | #define IWL4965_UCODE_API "-2" | 55 | #define IWL4965_UCODE_API "-2" |
56 | #define IWL4965_MODULE_FIRMWARE "iwlwifi-4965" IWL4965_UCODE_API ".ucode" | ||
56 | 57 | ||
57 | 58 | ||
58 | /* module parameters */ | 59 | /* module parameters */ |
@@ -661,7 +662,7 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, | |||
661 | int txq_id = txq->q.id; | 662 | int txq_id = txq->q.id; |
662 | 663 | ||
663 | /* Find out whether to activate Tx queue */ | 664 | /* Find out whether to activate Tx queue */ |
664 | int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0; | 665 | int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; |
665 | 666 | ||
666 | /* Set up and activate */ | 667 | /* Set up and activate */ |
667 | iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id), | 668 | iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id), |
@@ -691,9 +692,10 @@ static const u16 default_queue_to_tx_fifo[] = { | |||
691 | static int iwl4965_alive_notify(struct iwl_priv *priv) | 692 | static int iwl4965_alive_notify(struct iwl_priv *priv) |
692 | { | 693 | { |
693 | u32 a; | 694 | u32 a; |
694 | int i = 0; | ||
695 | unsigned long flags; | 695 | unsigned long flags; |
696 | int ret; | 696 | int ret; |
697 | int i, chan; | ||
698 | u32 reg_val; | ||
697 | 699 | ||
698 | spin_lock_irqsave(&priv->lock, flags); | 700 | spin_lock_irqsave(&priv->lock, flags); |
699 | 701 | ||
@@ -717,6 +719,17 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
717 | iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, | 719 | iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, |
718 | priv->scd_bc_tbls.dma >> 10); | 720 | priv->scd_bc_tbls.dma >> 10); |
719 | 721 | ||
722 | /* Enable DMA channel */ | ||
723 | for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++) | ||
724 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
725 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
726 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
727 | |||
728 | /* Update FH chicken bits */ | ||
729 | reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); | ||
730 | iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, | ||
731 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
732 | |||
720 | /* Disable chain mode for all queues */ | 733 | /* Disable chain mode for all queues */ |
721 | iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); | 734 | iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); |
722 | 735 | ||
@@ -747,7 +760,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv) | |||
747 | (1 << priv->hw_params.max_txq_num) - 1); | 760 | (1 << priv->hw_params.max_txq_num) - 1); |
748 | 761 | ||
749 | /* Activate all Tx DMA/FIFO channels */ | 762 | /* Activate all Tx DMA/FIFO channels */ |
750 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); | 763 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6)); |
751 | 764 | ||
752 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); | 765 | iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); |
753 | 766 | ||
@@ -1909,7 +1922,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
1909 | ra_tid = BUILD_RAxTID(sta_id, tid); | 1922 | ra_tid = BUILD_RAxTID(sta_id, tid); |
1910 | 1923 | ||
1911 | /* Modify device's station table to Tx this TID */ | 1924 | /* Modify device's station table to Tx this TID */ |
1912 | iwl_sta_modify_enable_tid_tx(priv, sta_id, tid); | 1925 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); |
1913 | 1926 | ||
1914 | spin_lock_irqsave(&priv->lock, flags); | 1927 | spin_lock_irqsave(&priv->lock, flags); |
1915 | ret = iwl_grab_nic_access(priv); | 1928 | ret = iwl_grab_nic_access(priv); |
@@ -2025,7 +2038,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
2025 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 2038 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); |
2026 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 2039 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
2027 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 2040 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
2028 | info->flags |= iwl_is_tx_success(status)? | 2041 | info->flags |= iwl_is_tx_success(status) ? |
2029 | IEEE80211_TX_STAT_ACK : 0; | 2042 | IEEE80211_TX_STAT_ACK : 0; |
2030 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 2043 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); |
2031 | /* FIXME: code repetition end */ | 2044 | /* FIXME: code repetition end */ |
@@ -2322,7 +2335,7 @@ static struct iwl_ops iwl4965_ops = { | |||
2322 | 2335 | ||
2323 | struct iwl_cfg iwl4965_agn_cfg = { | 2336 | struct iwl_cfg iwl4965_agn_cfg = { |
2324 | .name = "4965AGN", | 2337 | .name = "4965AGN", |
2325 | .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode", | 2338 | .fw_name = IWL4965_MODULE_FIRMWARE, |
2326 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 2339 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
2327 | .eeprom_size = IWL4965_EEPROM_IMG_SIZE, | 2340 | .eeprom_size = IWL4965_EEPROM_IMG_SIZE, |
2328 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, | 2341 | .eeprom_ver = EEPROM_4965_EEPROM_VERSION, |
@@ -2332,7 +2345,7 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2332 | }; | 2345 | }; |
2333 | 2346 | ||
2334 | /* Module firmware */ | 2347 | /* Module firmware */ |
2335 | MODULE_FIRMWARE("iwlwifi-4965" IWL4965_UCODE_API ".ucode"); | 2348 | MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE); |
2336 | 2349 | ||
2337 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); | 2350 | module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); |
2338 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); | 2351 | MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ee3613db3132..a738886b434f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -475,6 +475,9 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv, | |||
475 | case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: | 475 | case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: |
476 | index = IWL_CALIB_TX_IQ_PERD; | 476 | index = IWL_CALIB_TX_IQ_PERD; |
477 | break; | 477 | break; |
478 | case IWL_PHY_CALIBRATE_BASE_BAND_CMD: | ||
479 | index = IWL_CALIB_BASE_BAND; | ||
480 | break; | ||
478 | default: | 481 | default: |
479 | IWL_ERROR("Unknown calibration notification %d\n", | 482 | IWL_ERROR("Unknown calibration notification %d\n", |
480 | hdr->op_code); | 483 | hdr->op_code); |
@@ -697,9 +700,10 @@ static int iwl5000_send_wimax_coex(struct iwl_priv *priv) | |||
697 | static int iwl5000_alive_notify(struct iwl_priv *priv) | 700 | static int iwl5000_alive_notify(struct iwl_priv *priv) |
698 | { | 701 | { |
699 | u32 a; | 702 | u32 a; |
700 | int i = 0; | ||
701 | unsigned long flags; | 703 | unsigned long flags; |
702 | int ret; | 704 | int ret; |
705 | int i, chan; | ||
706 | u32 reg_val; | ||
703 | 707 | ||
704 | spin_lock_irqsave(&priv->lock, flags); | 708 | spin_lock_irqsave(&priv->lock, flags); |
705 | 709 | ||
@@ -722,6 +726,18 @@ static int iwl5000_alive_notify(struct iwl_priv *priv) | |||
722 | 726 | ||
723 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, | 727 | iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, |
724 | priv->scd_bc_tbls.dma >> 10); | 728 | priv->scd_bc_tbls.dma >> 10); |
729 | |||
730 | /* Enable DMA channel */ | ||
731 | for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) | ||
732 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), | ||
733 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
734 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
735 | |||
736 | /* Update FH chicken bits */ | ||
737 | reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); | ||
738 | iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, | ||
739 | reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); | ||
740 | |||
725 | iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, | 741 | iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, |
726 | IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); | 742 | IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); |
727 | iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); | 743 | iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); |
@@ -841,8 +857,9 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |||
841 | priv->hw_params.calib_init_cfg = | 857 | priv->hw_params.calib_init_cfg = |
842 | BIT(IWL_CALIB_XTAL) | | 858 | BIT(IWL_CALIB_XTAL) | |
843 | BIT(IWL_CALIB_LO) | | 859 | BIT(IWL_CALIB_LO) | |
844 | BIT(IWL_CALIB_TX_IQ) | | 860 | BIT(IWL_CALIB_TX_IQ) | |
845 | BIT(IWL_CALIB_TX_IQ_PERD); | 861 | BIT(IWL_CALIB_TX_IQ_PERD) | |
862 | BIT(IWL_CALIB_BASE_BAND); | ||
846 | break; | 863 | break; |
847 | case CSR_HW_REV_TYPE_5150: | 864 | case CSR_HW_REV_TYPE_5150: |
848 | priv->hw_params.calib_init_cfg = 0; | 865 | priv->hw_params.calib_init_cfg = 0; |
@@ -969,7 +986,7 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, | |||
969 | ra_tid = BUILD_RAxTID(sta_id, tid); | 986 | ra_tid = BUILD_RAxTID(sta_id, tid); |
970 | 987 | ||
971 | /* Modify device's station table to Tx this TID */ | 988 | /* Modify device's station table to Tx this TID */ |
972 | iwl_sta_modify_enable_tid_tx(priv, sta_id, tid); | 989 | iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); |
973 | 990 | ||
974 | spin_lock_irqsave(&priv->lock, flags); | 991 | spin_lock_irqsave(&priv->lock, flags); |
975 | ret = iwl_grab_nic_access(priv); | 992 | ret = iwl_grab_nic_access(priv); |
@@ -1111,7 +1128,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | |||
1111 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 1128 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); |
1112 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1129 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1113 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1130 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1114 | info->flags |= iwl_is_tx_success(status)? | 1131 | info->flags |= iwl_is_tx_success(status) ? |
1115 | IEEE80211_TX_STAT_ACK : 0; | 1132 | IEEE80211_TX_STAT_ACK : 0; |
1116 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 1133 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); |
1117 | 1134 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 0332805cc630..3a2b81291d86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -281,10 +281,9 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, | |||
281 | u32 time_diff; | 281 | u32 time_diff; |
282 | s32 index; | 282 | s32 index; |
283 | struct iwl_traffic_load *tl = NULL; | 283 | struct iwl_traffic_load *tl = NULL; |
284 | __le16 fc = hdr->frame_control; | ||
285 | u8 tid; | 284 | u8 tid; |
286 | 285 | ||
287 | if (ieee80211_is_data_qos(fc)) { | 286 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
288 | u8 *qc = ieee80211_get_qos_ctl(hdr); | 287 | u8 *qc = ieee80211_get_qos_ctl(hdr); |
289 | tid = qc[0] & 0xf; | 288 | tid = qc[0] & 0xf; |
290 | } else | 289 | } else |
@@ -773,7 +772,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
773 | int status; | 772 | int status; |
774 | u8 retries; | 773 | u8 retries; |
775 | int rs_index, index = 0; | 774 | int rs_index, index = 0; |
776 | struct iwl_lq_sta *lq_sta; | 775 | struct iwl_lq_sta *lq_sta = priv_sta; |
777 | struct iwl_link_quality_cmd *table; | 776 | struct iwl_link_quality_cmd *table; |
778 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 777 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
779 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 778 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
@@ -785,12 +784,12 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
785 | struct iwl_scale_tbl_info tbl_type; | 784 | struct iwl_scale_tbl_info tbl_type; |
786 | struct iwl_scale_tbl_info *curr_tbl, *search_tbl; | 785 | struct iwl_scale_tbl_info *curr_tbl, *search_tbl; |
787 | u8 active_index = 0; | 786 | u8 active_index = 0; |
788 | __le16 fc = hdr->frame_control; | ||
789 | s32 tpt = 0; | 787 | s32 tpt = 0; |
790 | 788 | ||
791 | IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n"); | 789 | IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n"); |
792 | 790 | ||
793 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) | 791 | if (!ieee80211_is_data(hdr->frame_control) || |
792 | is_multicast_ether_addr(hdr->addr1)) | ||
794 | return; | 793 | return; |
795 | 794 | ||
796 | /* This packet was aggregated but doesn't carry rate scale info */ | 795 | /* This packet was aggregated but doesn't carry rate scale info */ |
@@ -803,8 +802,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
803 | if (retries > 15) | 802 | if (retries > 15) |
804 | retries = 15; | 803 | retries = 15; |
805 | 804 | ||
806 | lq_sta = (struct iwl_lq_sta *)priv_sta; | ||
807 | |||
808 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 805 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
809 | !lq_sta->ibss_sta_added) | 806 | !lq_sta->ibss_sta_added) |
810 | goto out; | 807 | goto out; |
@@ -1675,7 +1672,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1675 | int high_tpt = IWL_INVALID_VALUE; | 1672 | int high_tpt = IWL_INVALID_VALUE; |
1676 | u32 fail_count; | 1673 | u32 fail_count; |
1677 | s8 scale_action = 0; | 1674 | s8 scale_action = 0; |
1678 | __le16 fc; | ||
1679 | u16 rate_mask; | 1675 | u16 rate_mask; |
1680 | u8 update_lq = 0; | 1676 | u8 update_lq = 0; |
1681 | struct iwl_scale_tbl_info *tbl, *tbl1; | 1677 | struct iwl_scale_tbl_info *tbl, *tbl1; |
@@ -1690,13 +1686,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
1690 | 1686 | ||
1691 | IWL_DEBUG_RATE("rate scale calculate new rate for skb\n"); | 1687 | IWL_DEBUG_RATE("rate scale calculate new rate for skb\n"); |
1692 | 1688 | ||
1693 | fc = hdr->frame_control; | 1689 | /* Send management frames and broadcast/multicast data using |
1694 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) { | 1690 | * lowest rate. */ |
1695 | /* Send management frames and broadcast/multicast data using | 1691 | /* TODO: this could probably be improved.. */ |
1696 | * lowest rate. */ | 1692 | if (!ieee80211_is_data(hdr->frame_control) || |
1697 | /* TODO: this could probably be improved.. */ | 1693 | is_multicast_ether_addr(hdr->addr1)) |
1698 | return; | 1694 | return; |
1699 | } | ||
1700 | 1695 | ||
1701 | if (!sta || !lq_sta) | 1696 | if (!sta || !lq_sta) |
1702 | return; | 1697 | return; |
@@ -2095,29 +2090,26 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2095 | struct ieee80211_tx_rate_control *txrc) | 2090 | struct ieee80211_tx_rate_control *txrc) |
2096 | { | 2091 | { |
2097 | 2092 | ||
2098 | int i; | ||
2099 | struct sk_buff *skb = txrc->skb; | 2093 | struct sk_buff *skb = txrc->skb; |
2100 | struct ieee80211_supported_band *sband = txrc->sband; | 2094 | struct ieee80211_supported_band *sband = txrc->sband; |
2101 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2095 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2102 | struct ieee80211_conf *conf = &priv->hw->conf; | 2096 | struct ieee80211_conf *conf = &priv->hw->conf; |
2103 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 2097 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
2104 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2098 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2105 | __le16 fc; | 2099 | struct iwl_lq_sta *lq_sta = priv_sta; |
2106 | struct iwl_lq_sta *lq_sta; | 2100 | int rate_idx; |
2107 | 2101 | ||
2108 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); | 2102 | IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); |
2109 | 2103 | ||
2110 | /* Send management frames and broadcast/multicast data using lowest | 2104 | /* Send management frames and broadcast/multicast data using lowest |
2111 | * rate. */ | 2105 | * rate. */ |
2112 | fc = hdr->frame_control; | 2106 | if (!ieee80211_is_data(hdr->frame_control) || |
2113 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || | 2107 | is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) { |
2114 | !sta || !priv_sta) { | ||
2115 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | 2108 | info->control.rates[0].idx = rate_lowest_index(sband, sta); |
2116 | return; | 2109 | return; |
2117 | } | 2110 | } |
2118 | 2111 | ||
2119 | lq_sta = (struct iwl_lq_sta *)priv_sta; | 2112 | rate_idx = lq_sta->last_txrate_idx; |
2120 | i = lq_sta->last_txrate_idx; | ||
2121 | 2113 | ||
2122 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && | 2114 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && |
2123 | !lq_sta->ibss_sta_added) { | 2115 | !lq_sta->ibss_sta_added) { |
@@ -2137,14 +2129,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2137 | } | 2129 | } |
2138 | } | 2130 | } |
2139 | 2131 | ||
2140 | if ((i < 0) || (i > IWL_RATE_COUNT)) { | 2132 | if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT) |
2141 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | 2133 | rate_idx = rate_lowest_index(sband, sta); |
2142 | return; | 2134 | else if (sband->band == IEEE80211_BAND_5GHZ) |
2143 | } | 2135 | rate_idx -= IWL_FIRST_OFDM_RATE; |
2144 | 2136 | ||
2145 | if (sband->band == IEEE80211_BAND_5GHZ) | 2137 | info->control.rates[0].idx = rate_idx; |
2146 | i -= IWL_FIRST_OFDM_RATE; | ||
2147 | info->control.rates[0].idx = i; | ||
2148 | } | 2138 | } |
2149 | 2139 | ||
2150 | static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, | 2140 | static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, |
@@ -2525,7 +2515,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, | |||
2525 | for (i = 0; i < LQ_SIZE; i++) { | 2515 | for (i = 0; i < LQ_SIZE; i++) { |
2526 | desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n" | 2516 | desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n" |
2527 | "rate=0x%X\n", | 2517 | "rate=0x%X\n", |
2528 | lq_sta->active_tbl == i?"*":"x", | 2518 | lq_sta->active_tbl == i ? "*" : "x", |
2529 | lq_sta->lq_info[i].lq_type, | 2519 | lq_sta->lq_info[i].lq_type, |
2530 | lq_sta->lq_info[i].is_SGI, | 2520 | lq_sta->lq_info[i].is_SGI, |
2531 | lq_sta->lq_info[i].is_fat, | 2521 | lq_sta->lq_info[i].is_fat, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8fa4f7a2dc1a..c8ce84a1eef4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -466,9 +466,9 @@ static u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) | |||
466 | 466 | ||
467 | /* Set rate mask*/ | 467 | /* Set rate mask*/ |
468 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) | 468 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) |
469 | rate_mask = priv->active_rate_basic & 0xF; | 469 | rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; |
470 | else | 470 | else |
471 | rate_mask = priv->active_rate_basic & 0xFF0; | 471 | rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; |
472 | 472 | ||
473 | /* Find lowest valid rate */ | 473 | /* Find lowest valid rate */ |
474 | for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; | 474 | for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; |
@@ -1492,7 +1492,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1492 | hw_rf_kill = 1; | 1492 | hw_rf_kill = 1; |
1493 | 1493 | ||
1494 | IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n", | 1494 | IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n", |
1495 | hw_rf_kill ? "disable radio":"enable radio"); | 1495 | hw_rf_kill ? "disable radio" : "enable radio"); |
1496 | 1496 | ||
1497 | /* driver only loads ucode once setting the interface up. | 1497 | /* driver only loads ucode once setting the interface up. |
1498 | * the driver as well won't allow loading if RFKILL is set | 1498 | * the driver as well won't allow loading if RFKILL is set |
@@ -2224,27 +2224,6 @@ static void iwl_bg_rf_kill(struct work_struct *work) | |||
2224 | iwl_rfkill_set_hw_state(priv); | 2224 | iwl_rfkill_set_hw_state(priv); |
2225 | } | 2225 | } |
2226 | 2226 | ||
2227 | static void iwl_bg_set_monitor(struct work_struct *work) | ||
2228 | { | ||
2229 | struct iwl_priv *priv = container_of(work, | ||
2230 | struct iwl_priv, set_monitor); | ||
2231 | int ret; | ||
2232 | |||
2233 | IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n"); | ||
2234 | |||
2235 | mutex_lock(&priv->mutex); | ||
2236 | |||
2237 | ret = iwl_set_mode(priv, NL80211_IFTYPE_MONITOR); | ||
2238 | if (ret) { | ||
2239 | if (ret == -EAGAIN) | ||
2240 | IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n"); | ||
2241 | else | ||
2242 | IWL_ERROR("iwl_set_mode() failed ret = %d\n", ret); | ||
2243 | } | ||
2244 | |||
2245 | mutex_unlock(&priv->mutex); | ||
2246 | } | ||
2247 | |||
2248 | static void iwl_bg_run_time_calib_work(struct work_struct *work) | 2227 | static void iwl_bg_run_time_calib_work(struct work_struct *work) |
2249 | { | 2228 | { |
2250 | struct iwl_priv *priv = container_of(work, struct iwl_priv, | 2229 | struct iwl_priv *priv = container_of(work, struct iwl_priv, |
@@ -2890,16 +2869,43 @@ static void iwl_configure_filter(struct ieee80211_hw *hw, | |||
2890 | int mc_count, struct dev_addr_list *mc_list) | 2869 | int mc_count, struct dev_addr_list *mc_list) |
2891 | { | 2870 | { |
2892 | struct iwl_priv *priv = hw->priv; | 2871 | struct iwl_priv *priv = hw->priv; |
2872 | __le32 *filter_flags = &priv->staging_rxon.filter_flags; | ||
2873 | |||
2874 | IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", | ||
2875 | changed_flags, *total_flags); | ||
2893 | 2876 | ||
2894 | if (changed_flags & (*total_flags) & FIF_OTHER_BSS) { | 2877 | if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { |
2895 | IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", | 2878 | if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) |
2896 | NL80211_IFTYPE_MONITOR, | 2879 | *filter_flags |= RXON_FILTER_PROMISC_MSK; |
2897 | changed_flags, *total_flags); | 2880 | else |
2898 | /* queue work 'cuz mac80211 is holding a lock which | 2881 | *filter_flags &= ~RXON_FILTER_PROMISC_MSK; |
2899 | * prevents us from issuing (synchronous) f/w cmds */ | 2882 | } |
2900 | queue_work(priv->workqueue, &priv->set_monitor); | 2883 | if (changed_flags & FIF_ALLMULTI) { |
2884 | if (*total_flags & FIF_ALLMULTI) | ||
2885 | *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK; | ||
2886 | else | ||
2887 | *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK; | ||
2888 | } | ||
2889 | if (changed_flags & FIF_CONTROL) { | ||
2890 | if (*total_flags & FIF_CONTROL) | ||
2891 | *filter_flags |= RXON_FILTER_CTL2HOST_MSK; | ||
2892 | else | ||
2893 | *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK; | ||
2894 | } | ||
2895 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | ||
2896 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | ||
2897 | *filter_flags |= RXON_FILTER_BCON_AWARE_MSK; | ||
2898 | else | ||
2899 | *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK; | ||
2901 | } | 2900 | } |
2902 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | | 2901 | |
2902 | /* We avoid iwl_commit_rxon here to commit the new filter flags | ||
2903 | * since mac80211 will call ieee80211_hw_config immediately. | ||
2904 | * (mc_list is not supported at this time). Otherwise, we need to | ||
2905 | * queue a background iwl_commit_rxon work. | ||
2906 | */ | ||
2907 | |||
2908 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | | ||
2903 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | 2909 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; |
2904 | } | 2910 | } |
2905 | 2911 | ||
@@ -3058,49 +3064,11 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, | |||
3058 | struct ieee80211_key_conf *keyconf, const u8 *addr, | 3064 | struct ieee80211_key_conf *keyconf, const u8 *addr, |
3059 | u32 iv32, u16 *phase1key) | 3065 | u32 iv32, u16 *phase1key) |
3060 | { | 3066 | { |
3061 | struct iwl_priv *priv = hw->priv; | ||
3062 | u8 sta_id = IWL_INVALID_STATION; | ||
3063 | unsigned long flags; | ||
3064 | __le16 key_flags = 0; | ||
3065 | int i; | ||
3066 | 3067 | ||
3068 | struct iwl_priv *priv = hw->priv; | ||
3067 | IWL_DEBUG_MAC80211("enter\n"); | 3069 | IWL_DEBUG_MAC80211("enter\n"); |
3068 | 3070 | ||
3069 | sta_id = iwl_find_station(priv, addr); | 3071 | iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key); |
3070 | if (sta_id == IWL_INVALID_STATION) { | ||
3071 | IWL_DEBUG_MAC80211("leave - %pM not in station map.\n", | ||
3072 | addr); | ||
3073 | return; | ||
3074 | } | ||
3075 | |||
3076 | if (iwl_scan_cancel(priv)) { | ||
3077 | /* cancel scan failed, just live w/ bad key and rely | ||
3078 | briefly on SW decryption */ | ||
3079 | return; | ||
3080 | } | ||
3081 | |||
3082 | key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); | ||
3083 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | ||
3084 | key_flags &= ~STA_KEY_FLG_INVALID; | ||
3085 | |||
3086 | if (sta_id == priv->hw_params.bcast_sta_id) | ||
3087 | key_flags |= STA_KEY_MULTICAST_MSK; | ||
3088 | |||
3089 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
3090 | |||
3091 | priv->stations[sta_id].sta.key.key_flags = key_flags; | ||
3092 | priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; | ||
3093 | |||
3094 | for (i = 0; i < 5; i++) | ||
3095 | priv->stations[sta_id].sta.key.tkip_rx_ttak[i] = | ||
3096 | cpu_to_le16(phase1key[i]); | ||
3097 | |||
3098 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | ||
3099 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
3100 | |||
3101 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
3102 | |||
3103 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
3104 | 3072 | ||
3105 | IWL_DEBUG_MAC80211("leave\n"); | 3073 | IWL_DEBUG_MAC80211("leave\n"); |
3106 | } | 3074 | } |
@@ -3239,10 +3207,10 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3239 | switch (action) { | 3207 | switch (action) { |
3240 | case IEEE80211_AMPDU_RX_START: | 3208 | case IEEE80211_AMPDU_RX_START: |
3241 | IWL_DEBUG_HT("start Rx\n"); | 3209 | IWL_DEBUG_HT("start Rx\n"); |
3242 | return iwl_rx_agg_start(priv, sta->addr, tid, *ssn); | 3210 | return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); |
3243 | case IEEE80211_AMPDU_RX_STOP: | 3211 | case IEEE80211_AMPDU_RX_STOP: |
3244 | IWL_DEBUG_HT("stop Rx\n"); | 3212 | IWL_DEBUG_HT("stop Rx\n"); |
3245 | return iwl_rx_agg_stop(priv, sta->addr, tid); | 3213 | return iwl_sta_rx_agg_stop(priv, sta->addr, tid); |
3246 | case IEEE80211_AMPDU_TX_START: | 3214 | case IEEE80211_AMPDU_TX_START: |
3247 | IWL_DEBUG_HT("start Tx\n"); | 3215 | IWL_DEBUG_HT("start Tx\n"); |
3248 | return iwl_tx_agg_start(priv, sta->addr, tid, ssn); | 3216 | return iwl_tx_agg_start(priv, sta->addr, tid, ssn); |
@@ -3256,6 +3224,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | |||
3256 | } | 3224 | } |
3257 | return 0; | 3225 | return 0; |
3258 | } | 3226 | } |
3227 | |||
3259 | static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, | 3228 | static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, |
3260 | struct ieee80211_tx_queue_stats *stats) | 3229 | struct ieee80211_tx_queue_stats *stats) |
3261 | { | 3230 | { |
@@ -3694,7 +3663,8 @@ static ssize_t show_power_level(struct device *d, | |||
3694 | break; | 3663 | break; |
3695 | } | 3664 | } |
3696 | 3665 | ||
3697 | p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO)?"fixed":"auto"); | 3666 | p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ? |
3667 | "fixed" : "auto"); | ||
3698 | p += sprintf(p, "\tINDEX:%d", level); | 3668 | p += sprintf(p, "\tINDEX:%d", level); |
3699 | p += sprintf(p, "\n"); | 3669 | p += sprintf(p, "\n"); |
3700 | return p - buf + 1; | 3670 | return p - buf + 1; |
@@ -3832,7 +3802,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3832 | INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); | 3802 | INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); |
3833 | INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill); | 3803 | INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill); |
3834 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); | 3804 | INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); |
3835 | INIT_WORK(&priv->set_monitor, iwl_bg_set_monitor); | ||
3836 | INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); | 3805 | INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); |
3837 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); | 3806 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); |
3838 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); | 3807 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 8bd4d087d4e2..6aa332bebc5f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "iwl-io.h" | 37 | #include "iwl-io.h" |
38 | #include "iwl-rfkill.h" | 38 | #include "iwl-rfkill.h" |
39 | #include "iwl-power.h" | 39 | #include "iwl-power.h" |
40 | #include "iwl-sta.h" | ||
40 | 41 | ||
41 | 42 | ||
42 | MODULE_DESCRIPTION("iwl core"); | 43 | MODULE_DESCRIPTION("iwl core"); |
@@ -237,28 +238,6 @@ int iwl_hw_nic_init(struct iwl_priv *priv) | |||
237 | } | 238 | } |
238 | EXPORT_SYMBOL(iwl_hw_nic_init); | 239 | EXPORT_SYMBOL(iwl_hw_nic_init); |
239 | 240 | ||
240 | /** | ||
241 | * iwl_clear_stations_table - Clear the driver's station table | ||
242 | * | ||
243 | * NOTE: This does not clear or otherwise alter the device's station table. | ||
244 | */ | ||
245 | void iwl_clear_stations_table(struct iwl_priv *priv) | ||
246 | { | ||
247 | unsigned long flags; | ||
248 | |||
249 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
250 | |||
251 | if (iwl_is_alive(priv) && | ||
252 | !test_bit(STATUS_EXIT_PENDING, &priv->status) && | ||
253 | iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL)) | ||
254 | IWL_ERROR("Couldn't clear the station table\n"); | ||
255 | |||
256 | priv->num_stations = 0; | ||
257 | memset(priv->stations, 0, sizeof(priv->stations)); | ||
258 | |||
259 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
260 | } | ||
261 | EXPORT_SYMBOL(iwl_clear_stations_table); | ||
262 | 241 | ||
263 | void iwl_reset_qos(struct iwl_priv *priv) | 242 | void iwl_reset_qos(struct iwl_priv *priv) |
264 | { | 243 | { |
@@ -832,6 +811,9 @@ int iwl_setup_mac(struct iwl_priv *priv) | |||
832 | BIT(NL80211_IFTYPE_AP) | | 811 | BIT(NL80211_IFTYPE_AP) | |
833 | BIT(NL80211_IFTYPE_STATION) | | 812 | BIT(NL80211_IFTYPE_STATION) | |
834 | BIT(NL80211_IFTYPE_ADHOC); | 813 | BIT(NL80211_IFTYPE_ADHOC); |
814 | |||
815 | hw->wiphy->fw_handles_regulatory = true; | ||
816 | |||
835 | /* Default value; 4 EDCA QOS priorities */ | 817 | /* Default value; 4 EDCA QOS priorities */ |
836 | hw->queues = 4; | 818 | hw->queues = 4; |
837 | /* queues to support 11n aggregation */ | 819 | /* queues to support 11n aggregation */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index ff966b8a0c6d..82bf263b6f5a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -182,7 +182,6 @@ struct iwl_cfg { | |||
182 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, | 182 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, |
183 | struct ieee80211_ops *hw_ops); | 183 | struct ieee80211_ops *hw_ops); |
184 | void iwl_hw_detect(struct iwl_priv *priv); | 184 | void iwl_hw_detect(struct iwl_priv *priv); |
185 | void iwl_clear_stations_table(struct iwl_priv *priv); | ||
186 | void iwl_reset_qos(struct iwl_priv *priv); | 185 | void iwl_reset_qos(struct iwl_priv *priv); |
187 | void iwl_set_rxon_chain(struct iwl_priv *priv); | 186 | void iwl_set_rxon_chain(struct iwl_priv *priv); |
188 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); | 187 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); |
@@ -206,8 +205,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | |||
206 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 205 | void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
207 | void iwl_rx_replenish(struct iwl_priv *priv); | 206 | void iwl_rx_replenish(struct iwl_priv *priv); |
208 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 207 | int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
209 | int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn); | ||
210 | int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); | ||
211 | int iwl_rx_queue_restock(struct iwl_priv *priv); | 208 | int iwl_rx_queue_restock(struct iwl_priv *priv); |
212 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); | 209 | int iwl_rx_queue_space(const struct iwl_rx_queue *q); |
213 | void iwl_rx_allocate(struct iwl_priv *priv); | 210 | void iwl_rx_allocate(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index bd3df55e4953..4da988e0eae0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -574,11 +574,6 @@ struct iwl_hw_params { | |||
574 | * iwl4965_mac_ <-- mac80211 callback | 574 | * iwl4965_mac_ <-- mac80211 callback |
575 | * | 575 | * |
576 | ****************************************************************************/ | 576 | ****************************************************************************/ |
577 | struct iwl_addsta_cmd; | ||
578 | extern int iwl_send_add_sta(struct iwl_priv *priv, | ||
579 | struct iwl_addsta_cmd *sta, u8 flags); | ||
580 | extern u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, | ||
581 | int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info); | ||
582 | extern void iwl_update_chain_flags(struct iwl_priv *priv); | 577 | extern void iwl_update_chain_flags(struct iwl_priv *priv); |
583 | extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src); | 578 | extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src); |
584 | extern const u8 iwl_bcast_addr[ETH_ALEN]; | 579 | extern const u8 iwl_bcast_addr[ETH_ALEN]; |
@@ -700,6 +695,7 @@ enum iwl_calib { | |||
700 | IWL_CALIB_LO, | 695 | IWL_CALIB_LO, |
701 | IWL_CALIB_TX_IQ, | 696 | IWL_CALIB_TX_IQ, |
702 | IWL_CALIB_TX_IQ_PERD, | 697 | IWL_CALIB_TX_IQ_PERD, |
698 | IWL_CALIB_BASE_BAND, | ||
703 | IWL_CALIB_MAX | 699 | IWL_CALIB_MAX |
704 | }; | 700 | }; |
705 | 701 | ||
@@ -990,7 +986,6 @@ struct iwl_priv { | |||
990 | struct work_struct report_work; | 986 | struct work_struct report_work; |
991 | struct work_struct request_scan; | 987 | struct work_struct request_scan; |
992 | struct work_struct beacon_update; | 988 | struct work_struct beacon_update; |
993 | struct work_struct set_monitor; | ||
994 | 989 | ||
995 | struct tasklet_struct irq_tasklet; | 990 | struct tasklet_struct irq_tasklet; |
996 | 991 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index e46300c28a8f..c3dadb03701c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h | |||
@@ -72,7 +72,7 @@ | |||
72 | * Addresses are offsets from device's PCI hardware base address. | 72 | * Addresses are offsets from device's PCI hardware base address. |
73 | */ | 73 | */ |
74 | #define FH_MEM_LOWER_BOUND (0x1000) | 74 | #define FH_MEM_LOWER_BOUND (0x1000) |
75 | #define FH_MEM_UPPER_BOUND (0x1EF0) | 75 | #define FH_MEM_UPPER_BOUND (0x2000) |
76 | 76 | ||
77 | /** | 77 | /** |
78 | * Keep-Warm (KW) buffer base address. | 78 | * Keep-Warm (KW) buffer base address. |
@@ -268,6 +268,8 @@ | |||
268 | 268 | ||
269 | #define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME (0x00008000) | 269 | #define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME (0x00008000) |
270 | 270 | ||
271 | #define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ | ||
272 | |||
271 | 273 | ||
272 | /** | 274 | /** |
273 | * Rx Shared Status Registers (RSSR) | 275 | * Rx Shared Status Registers (RSSR) |
@@ -294,6 +296,13 @@ | |||
294 | 296 | ||
295 | #define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 | 297 | #define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 |
296 | 298 | ||
299 | /* TFDB Area - TFDs buffer table */ | ||
300 | #define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF) | ||
301 | #define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900) | ||
302 | #define FH_TFDIB_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x958) | ||
303 | #define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl)) | ||
304 | #define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4) | ||
305 | |||
297 | /** | 306 | /** |
298 | * Transmit DMA Channel Control/Status Registers (TCSR) | 307 | * Transmit DMA Channel Control/Status Registers (TCSR) |
299 | * | 308 | * |
@@ -323,6 +332,7 @@ | |||
323 | #define FH49_TCSR_CHNL_NUM (7) | 332 | #define FH49_TCSR_CHNL_NUM (7) |
324 | #define FH50_TCSR_CHNL_NUM (8) | 333 | #define FH50_TCSR_CHNL_NUM (8) |
325 | 334 | ||
335 | /* TCSR: tx_config register values */ | ||
326 | #define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \ | 336 | #define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \ |
327 | (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl)) | 337 | (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl)) |
328 | #define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \ | 338 | #define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \ |
@@ -379,31 +389,18 @@ | |||
379 | (FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \ | 389 | (FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \ |
380 | FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl)) | 390 | FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl)) |
381 | 391 | ||
382 | |||
383 | |||
384 | #define FH_REGS_LOWER_BOUND (0x1000) | ||
385 | #define FH_REGS_UPPER_BOUND (0x2000) | ||
386 | |||
387 | /* Tx service channels */ | 392 | /* Tx service channels */ |
388 | #define FH_SRVC_CHNL (9) | 393 | #define FH_SRVC_CHNL (9) |
389 | #define FH_SRVC_LOWER_BOUND (FH_REGS_LOWER_BOUND + 0x9C8) | 394 | #define FH_SRVC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9C8) |
390 | #define FH_SRVC_UPPER_BOUND (FH_REGS_LOWER_BOUND + 0x9D0) | 395 | #define FH_SRVC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0) |
391 | #define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \ | 396 | #define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \ |
392 | (FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4) | 397 | (FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4) |
393 | 398 | ||
394 | /* TFDB Area - TFDs buffer table */ | 399 | #define FH_TX_CHICKEN_BITS_REG (FH_MEM_LOWER_BOUND + 0xE98) |
395 | #define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF) | 400 | /* Instruct FH to increment the retry count of a packet when |
396 | #define FH_TFDIB_LOWER_BOUND (FH_REGS_LOWER_BOUND + 0x900) | 401 | * it is brought from the memory to TX-FIFO |
397 | #define FH_TFDIB_UPPER_BOUND (FH_REGS_LOWER_BOUND + 0x958) | 402 | */ |
398 | #define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl)) | 403 | #define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002) |
399 | #define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4) | ||
400 | |||
401 | /* TCSR: tx_config register values */ | ||
402 | #define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ | ||
403 | |||
404 | #define TFD_QUEUE_SIZE_MAX (256) | ||
405 | #define TFD_QUEUE_SIZE_BC_DUP (64) | ||
406 | #define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP) | ||
407 | 404 | ||
408 | /** | 405 | /** |
409 | * struct iwl_rb_status - reseve buffer status | 406 | * struct iwl_rb_status - reseve buffer status |
@@ -423,9 +420,10 @@ struct iwl_rb_status { | |||
423 | } __attribute__ ((packed)); | 420 | } __attribute__ ((packed)); |
424 | 421 | ||
425 | 422 | ||
426 | 423 | #define TFD_QUEUE_SIZE_MAX (256) | |
424 | #define TFD_QUEUE_SIZE_BC_DUP (64) | ||
425 | #define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP) | ||
427 | #define IWL_TX_DMA_MASK DMA_BIT_MASK(36) | 426 | #define IWL_TX_DMA_MASK DMA_BIT_MASK(36) |
428 | |||
429 | #define IWL_NUM_OF_TBS 20 | 427 | #define IWL_NUM_OF_TBS 20 |
430 | 428 | ||
431 | static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr) | 429 | static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr) |
@@ -440,7 +438,7 @@ static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr) | |||
440 | * @lo: low [31:0] portion of the dma address of TX buffer | 438 | * @lo: low [31:0] portion of the dma address of TX buffer |
441 | * every even is unaligned on 16 bit boundary | 439 | * every even is unaligned on 16 bit boundary |
442 | * @hi_n_len 0-3 [35:32] portion of dma | 440 | * @hi_n_len 0-3 [35:32] portion of dma |
443 | * 4-16 length of the tx buffer | 441 | * 4-15 length of the tx buffer |
444 | */ | 442 | */ |
445 | struct iwl_tfd_tb { | 443 | struct iwl_tfd_tb { |
446 | __le32 lo; | 444 | __le32 lo; |
@@ -453,7 +451,8 @@ struct iwl_tfd_tb { | |||
453 | * Transmit Frame Descriptor (TFD) | 451 | * Transmit Frame Descriptor (TFD) |
454 | * | 452 | * |
455 | * @ __reserved1[3] reserved | 453 | * @ __reserved1[3] reserved |
456 | * @ num_tbs 0-5 number of active tbs | 454 | * @ num_tbs 0-4 number of active tbs |
455 | * 5 reserved | ||
457 | * 6-7 padding (not used) | 456 | * 6-7 padding (not used) |
458 | * @ tbs[20] transmit frame buffer descriptors | 457 | * @ tbs[20] transmit frame buffer descriptors |
459 | * @ __pad padding | 458 | * @ __pad padding |
@@ -473,8 +472,6 @@ struct iwl_tfd_tb { | |||
473 | * Tx frame, up to 8 KBytes in size. | 472 | * Tx frame, up to 8 KBytes in size. |
474 | * | 473 | * |
475 | * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx. | 474 | * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx. |
476 | * | ||
477 | * Bit fields in the control dword (val0): | ||
478 | */ | 475 | */ |
479 | struct iwl_tfd { | 476 | struct iwl_tfd { |
480 | u8 __reserved1[3]; | 477 | u8 __reserved1[3]; |
@@ -485,6 +482,6 @@ struct iwl_tfd { | |||
485 | 482 | ||
486 | 483 | ||
487 | /* Keep Warm Size */ | 484 | /* Keep Warm Size */ |
488 | #define IWL_KW_SIZE 0x1000 /*4k */ | 485 | #define IWL_KW_SIZE 0x1000 /* 4k */ |
489 | 486 | ||
490 | #endif /* !__iwl_fh_h__ */ | 487 | #endif /* !__iwl_fh_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 8300f3d00a06..0008a35232b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include "iwl-core.h" | 36 | #include "iwl-core.h" |
37 | 37 | ||
38 | 38 | ||
39 | #define IWL_CMD(x) case x : return #x | 39 | #define IWL_CMD(x) case x: return #x |
40 | 40 | ||
41 | const char *get_cmd_string(u8 cmd) | 41 | const char *get_cmd_string(u8 cmd) |
42 | { | 42 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 40e0050b7536..bc10435d96e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -109,7 +109,7 @@ static inline int __iwl_poll_bit(const char *f, u32 l, | |||
109 | int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout); | 109 | int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout); |
110 | IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", | 110 | IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", |
111 | addr, bits, mask, | 111 | addr, bits, mask, |
112 | unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l); | 112 | unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l); |
113 | return ret; | 113 | return ret; |
114 | } | 114 | } |
115 | #define iwl_poll_bit(priv, addr, bits, mask, timeout) \ | 115 | #define iwl_poll_bit(priv, addr, bits, mask, timeout) \ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 876afd4cab9e..8d2b73e194da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -499,49 +499,6 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
499 | } | 499 | } |
500 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); | 500 | EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); |
501 | 501 | ||
502 | int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn) | ||
503 | { | ||
504 | unsigned long flags; | ||
505 | int sta_id; | ||
506 | |||
507 | sta_id = iwl_find_station(priv, addr); | ||
508 | if (sta_id == IWL_INVALID_STATION) | ||
509 | return -ENXIO; | ||
510 | |||
511 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
512 | priv->stations[sta_id].sta.station_flags_msk = 0; | ||
513 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; | ||
514 | priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; | ||
515 | priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); | ||
516 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
517 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
518 | |||
519 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | ||
520 | CMD_ASYNC); | ||
521 | } | ||
522 | EXPORT_SYMBOL(iwl_rx_agg_start); | ||
523 | |||
524 | int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) | ||
525 | { | ||
526 | unsigned long flags; | ||
527 | int sta_id; | ||
528 | |||
529 | sta_id = iwl_find_station(priv, addr); | ||
530 | if (sta_id == IWL_INVALID_STATION) | ||
531 | return -ENXIO; | ||
532 | |||
533 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
534 | priv->stations[sta_id].sta.station_flags_msk = 0; | ||
535 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; | ||
536 | priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; | ||
537 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
538 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
539 | |||
540 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | ||
541 | CMD_ASYNC); | ||
542 | } | ||
543 | EXPORT_SYMBOL(iwl_rx_agg_stop); | ||
544 | |||
545 | 502 | ||
546 | /* Calculate noise level, based on measurements during network silence just | 503 | /* Calculate noise level, based on measurements during network silence just |
547 | * before arriving beacon. This measurement can be done only if we know | 504 | * before arriving beacon. This measurement can be done only if we know |
@@ -1017,38 +974,6 @@ static inline int iwl_calc_rssi(struct iwl_priv *priv, | |||
1017 | } | 974 | } |
1018 | 975 | ||
1019 | 976 | ||
1020 | static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | ||
1021 | { | ||
1022 | unsigned long flags; | ||
1023 | |||
1024 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1025 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; | ||
1026 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; | ||
1027 | priv->stations[sta_id].sta.sta.modify_mask = 0; | ||
1028 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1029 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1030 | |||
1031 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1032 | } | ||
1033 | |||
1034 | static void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) | ||
1035 | { | ||
1036 | /* FIXME: need locking over ps_status ??? */ | ||
1037 | u8 sta_id = iwl_find_station(priv, addr); | ||
1038 | |||
1039 | if (sta_id != IWL_INVALID_STATION) { | ||
1040 | u8 sta_awake = priv->stations[sta_id]. | ||
1041 | ps_status == STA_PS_STATUS_WAKE; | ||
1042 | |||
1043 | if (sta_awake && ps_bit) | ||
1044 | priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; | ||
1045 | else if (!sta_awake && !ps_bit) { | ||
1046 | iwl_sta_modify_ps_wake(priv, sta_id); | ||
1047 | priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; | ||
1048 | } | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | /* This is necessary only for a number of statistics, see the caller. */ | 977 | /* This is necessary only for a number of statistics, see the caller. */ |
1053 | static int iwl_is_network_packet(struct iwl_priv *priv, | 978 | static int iwl_is_network_packet(struct iwl_priv *priv, |
1054 | struct ieee80211_hdr *header) | 979 | struct ieee80211_hdr *header) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 0c5f1221b8f3..f86a8ca2aa3b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -132,7 +132,7 @@ static int iwl_add_sta_callback(struct iwl_priv *priv, | |||
132 | return 1; | 132 | return 1; |
133 | } | 133 | } |
134 | 134 | ||
135 | int iwl_send_add_sta(struct iwl_priv *priv, | 135 | static int iwl_send_add_sta(struct iwl_priv *priv, |
136 | struct iwl_addsta_cmd *sta, u8 flags) | 136 | struct iwl_addsta_cmd *sta, u8 flags) |
137 | { | 137 | { |
138 | struct iwl_rx_packet *res = NULL; | 138 | struct iwl_rx_packet *res = NULL; |
@@ -180,7 +180,6 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
180 | 180 | ||
181 | return ret; | 181 | return ret; |
182 | } | 182 | } |
183 | EXPORT_SYMBOL(iwl_send_add_sta); | ||
184 | 183 | ||
185 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, | 184 | static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, |
186 | struct ieee80211_sta_ht_cap *sta_ht_inf) | 185 | struct ieee80211_sta_ht_cap *sta_ht_inf) |
@@ -464,6 +463,29 @@ out: | |||
464 | } | 463 | } |
465 | EXPORT_SYMBOL(iwl_remove_station); | 464 | EXPORT_SYMBOL(iwl_remove_station); |
466 | 465 | ||
466 | /** | ||
467 | * iwl_clear_stations_table - Clear the driver's station table | ||
468 | * | ||
469 | * NOTE: This does not clear or otherwise alter the device's station table. | ||
470 | */ | ||
471 | void iwl_clear_stations_table(struct iwl_priv *priv) | ||
472 | { | ||
473 | unsigned long flags; | ||
474 | |||
475 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
476 | |||
477 | if (iwl_is_alive(priv) && | ||
478 | !test_bit(STATUS_EXIT_PENDING, &priv->status) && | ||
479 | iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL)) | ||
480 | IWL_ERROR("Couldn't clear the station table\n"); | ||
481 | |||
482 | priv->num_stations = 0; | ||
483 | memset(priv->stations, 0, sizeof(priv->stations)); | ||
484 | |||
485 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
486 | } | ||
487 | EXPORT_SYMBOL(iwl_clear_stations_table); | ||
488 | |||
467 | static int iwl_get_free_ucode_key_index(struct iwl_priv *priv) | 489 | static int iwl_get_free_ucode_key_index(struct iwl_priv *priv) |
468 | { | 490 | { |
469 | int i; | 491 | int i; |
@@ -703,6 +725,55 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | |||
703 | return ret; | 725 | return ret; |
704 | } | 726 | } |
705 | 727 | ||
728 | void iwl_update_tkip_key(struct iwl_priv *priv, | ||
729 | struct ieee80211_key_conf *keyconf, | ||
730 | const u8 *addr, u32 iv32, u16 *phase1key) | ||
731 | { | ||
732 | u8 sta_id = IWL_INVALID_STATION; | ||
733 | unsigned long flags; | ||
734 | __le16 key_flags = 0; | ||
735 | int i; | ||
736 | DECLARE_MAC_BUF(mac); | ||
737 | |||
738 | sta_id = iwl_find_station(priv, addr); | ||
739 | if (sta_id == IWL_INVALID_STATION) { | ||
740 | IWL_DEBUG_MAC80211("leave - %pM not in station map.\n", | ||
741 | addr); | ||
742 | return; | ||
743 | } | ||
744 | |||
745 | if (iwl_scan_cancel(priv)) { | ||
746 | /* cancel scan failed, just live w/ bad key and rely | ||
747 | briefly on SW decryption */ | ||
748 | return; | ||
749 | } | ||
750 | |||
751 | key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); | ||
752 | key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); | ||
753 | key_flags &= ~STA_KEY_FLG_INVALID; | ||
754 | |||
755 | if (sta_id == priv->hw_params.bcast_sta_id) | ||
756 | key_flags |= STA_KEY_MULTICAST_MSK; | ||
757 | |||
758 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
759 | |||
760 | priv->stations[sta_id].sta.key.key_flags = key_flags; | ||
761 | priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; | ||
762 | |||
763 | for (i = 0; i < 5; i++) | ||
764 | priv->stations[sta_id].sta.key.tkip_rx_ttak[i] = | ||
765 | cpu_to_le16(phase1key[i]); | ||
766 | |||
767 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; | ||
768 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
769 | |||
770 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
771 | |||
772 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
773 | |||
774 | } | ||
775 | EXPORT_SYMBOL(iwl_update_tkip_key); | ||
776 | |||
706 | int iwl_remove_dynamic_key(struct iwl_priv *priv, | 777 | int iwl_remove_dynamic_key(struct iwl_priv *priv, |
707 | struct ieee80211_key_conf *keyconf, | 778 | struct ieee80211_key_conf *keyconf, |
708 | u8 sta_id) | 779 | u8 sta_id) |
@@ -989,9 +1060,9 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | |||
989 | EXPORT_SYMBOL(iwl_get_sta_id); | 1060 | EXPORT_SYMBOL(iwl_get_sta_id); |
990 | 1061 | ||
991 | /** | 1062 | /** |
992 | * iwl_sta_modify_enable_tid_tx - Enable Tx for this TID in station table | 1063 | * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table |
993 | */ | 1064 | */ |
994 | void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid) | 1065 | void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) |
995 | { | 1066 | { |
996 | unsigned long flags; | 1067 | unsigned long flags; |
997 | 1068 | ||
@@ -1004,5 +1075,81 @@ void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid) | |||
1004 | 1075 | ||
1005 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1076 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1006 | } | 1077 | } |
1007 | EXPORT_SYMBOL(iwl_sta_modify_enable_tid_tx); | 1078 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); |
1079 | |||
1080 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, | ||
1081 | const u8 *addr, int tid, u16 ssn) | ||
1082 | { | ||
1083 | unsigned long flags; | ||
1084 | int sta_id; | ||
1085 | |||
1086 | sta_id = iwl_find_station(priv, addr); | ||
1087 | if (sta_id == IWL_INVALID_STATION) | ||
1088 | return -ENXIO; | ||
1089 | |||
1090 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1091 | priv->stations[sta_id].sta.station_flags_msk = 0; | ||
1092 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; | ||
1093 | priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; | ||
1094 | priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); | ||
1095 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1096 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1097 | |||
1098 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | ||
1099 | CMD_ASYNC); | ||
1100 | } | ||
1101 | EXPORT_SYMBOL(iwl_sta_rx_agg_start); | ||
1102 | |||
1103 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) | ||
1104 | { | ||
1105 | unsigned long flags; | ||
1106 | int sta_id; | ||
1107 | |||
1108 | sta_id = iwl_find_station(priv, addr); | ||
1109 | if (sta_id == IWL_INVALID_STATION) | ||
1110 | return -ENXIO; | ||
1111 | |||
1112 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1113 | priv->stations[sta_id].sta.station_flags_msk = 0; | ||
1114 | priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; | ||
1115 | priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; | ||
1116 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1117 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1118 | |||
1119 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | ||
1120 | CMD_ASYNC); | ||
1121 | } | ||
1122 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); | ||
1123 | |||
1124 | static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | ||
1125 | { | ||
1126 | unsigned long flags; | ||
1127 | |||
1128 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1129 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; | ||
1130 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; | ||
1131 | priv->stations[sta_id].sta.sta.modify_mask = 0; | ||
1132 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1133 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1134 | |||
1135 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | ||
1136 | } | ||
1137 | |||
1138 | void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) | ||
1139 | { | ||
1140 | /* FIXME: need locking over ps_status ??? */ | ||
1141 | u8 sta_id = iwl_find_station(priv, addr); | ||
1142 | |||
1143 | if (sta_id != IWL_INVALID_STATION) { | ||
1144 | u8 sta_awake = priv->stations[sta_id]. | ||
1145 | ps_status == STA_PS_STATUS_WAKE; | ||
1146 | |||
1147 | if (sta_awake && ps_bit) | ||
1148 | priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; | ||
1149 | else if (!sta_awake && !ps_bit) { | ||
1150 | iwl_sta_modify_ps_wake(priv, sta_id); | ||
1151 | priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; | ||
1152 | } | ||
1153 | } | ||
1154 | } | ||
1008 | 1155 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 221b93e670a6..7b98ea4dfbc0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -47,9 +47,21 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, | |||
47 | struct ieee80211_key_conf *key, u8 sta_id); | 47 | struct ieee80211_key_conf *key, u8 sta_id); |
48 | int iwl_remove_dynamic_key(struct iwl_priv *priv, | 48 | int iwl_remove_dynamic_key(struct iwl_priv *priv, |
49 | struct ieee80211_key_conf *key, u8 sta_id); | 49 | struct ieee80211_key_conf *key, u8 sta_id); |
50 | void iwl_update_tkip_key(struct iwl_priv *priv, | ||
51 | struct ieee80211_key_conf *keyconf, | ||
52 | const u8 *addr, u32 iv32, u16 *phase1key); | ||
53 | |||
50 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap); | 54 | int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap); |
51 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap); | 55 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap); |
56 | void iwl_clear_stations_table(struct iwl_priv *priv); | ||
52 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); | 57 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); |
53 | void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid); | ||
54 | int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); | 58 | int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); |
59 | u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, | ||
60 | int is_ap, u8 flags, | ||
61 | struct ieee80211_sta_ht_cap *ht_info); | ||
62 | void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); | ||
63 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, | ||
64 | const u8 *addr, int tid, u16 ssn); | ||
65 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); | ||
66 | void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr); | ||
55 | #endif /* __iwl_sta_h__ */ | 67 | #endif /* __iwl_sta_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 166f0001e01d..e045dfeaa1fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -449,11 +449,6 @@ static int iwl_hw_tx_queue_init(struct iwl_priv *priv, | |||
449 | iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), | 449 | iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), |
450 | txq->q.dma_addr >> 8); | 450 | txq->q.dma_addr >> 8); |
451 | 451 | ||
452 | /* Enable DMA channel, using same id as for TFD queue */ | ||
453 | iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), | ||
454 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | | ||
455 | FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); | ||
456 | |||
457 | iwl_release_nic_access(priv); | 452 | iwl_release_nic_access(priv); |
458 | spin_unlock_irqrestore(&priv->lock, flags); | 453 | spin_unlock_irqrestore(&priv->lock, flags); |
459 | 454 | ||
@@ -587,8 +582,6 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
587 | iwl_release_nic_access(priv); | 582 | iwl_release_nic_access(priv); |
588 | spin_unlock_irqrestore(&priv->lock, flags); | 583 | spin_unlock_irqrestore(&priv->lock, flags); |
589 | 584 | ||
590 | |||
591 | |||
592 | /* Alloc and init all Tx queues, including the command queue (#4) */ | 585 | /* Alloc and init all Tx queues, including the command queue (#4) */ |
593 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | 586 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
594 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? | 587 | slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? |
@@ -618,11 +611,9 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
618 | */ | 611 | */ |
619 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | 612 | void iwl_txq_ctx_stop(struct iwl_priv *priv) |
620 | { | 613 | { |
621 | |||
622 | int txq_id; | 614 | int txq_id; |
623 | unsigned long flags; | 615 | unsigned long flags; |
624 | 616 | ||
625 | |||
626 | /* Turn off all Tx DMA fifos */ | 617 | /* Turn off all Tx DMA fifos */ |
627 | spin_lock_irqsave(&priv->lock, flags); | 618 | spin_lock_irqsave(&priv->lock, flags); |
628 | if (iwl_grab_nic_access(priv)) { | 619 | if (iwl_grab_nic_access(priv)) { |
@@ -1498,7 +1489,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, | |||
1498 | ack = bitmap & (1ULL << i); | 1489 | ack = bitmap & (1ULL << i); |
1499 | successes += !!ack; | 1490 | successes += !!ack; |
1500 | IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", | 1491 | IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", |
1501 | ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff, | 1492 | ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, |
1502 | agg->start_idx + i); | 1493 | agg->start_idx + i); |
1503 | } | 1494 | } |
1504 | 1495 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3344841b7662..69fda64c6503 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -519,7 +519,7 @@ static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) | |||
519 | 519 | ||
520 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 520 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
521 | 521 | ||
522 | #define IWL_CMD(x) case x : return #x | 522 | #define IWL_CMD(x) case x: return #x |
523 | 523 | ||
524 | static const char *get_cmd_string(u8 cmd) | 524 | static const char *get_cmd_string(u8 cmd) |
525 | { | 525 | { |
@@ -1425,9 +1425,9 @@ static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv) | |||
1425 | 1425 | ||
1426 | /* Set rate mask*/ | 1426 | /* Set rate mask*/ |
1427 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) | 1427 | if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) |
1428 | rate_mask = priv->active_rate_basic & 0xF; | 1428 | rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; |
1429 | else | 1429 | else |
1430 | rate_mask = priv->active_rate_basic & 0xFF0; | 1430 | rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; |
1431 | 1431 | ||
1432 | for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; | 1432 | for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; |
1433 | i = iwl3945_rates[i].next_ieee) { | 1433 | i = iwl3945_rates[i].next_ieee) { |
@@ -4320,7 +4320,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) | |||
4320 | 4320 | ||
4321 | IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR, | 4321 | IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR, |
4322 | "RF_KILL bit toggled to %s.\n", | 4322 | "RF_KILL bit toggled to %s.\n", |
4323 | hw_rf_kill ? "disable radio":"enable radio"); | 4323 | hw_rf_kill ? "disable radio" : "enable radio"); |
4324 | 4324 | ||
4325 | /* Queue restart only if RF_KILL switch was set to "kill" | 4325 | /* Queue restart only if RF_KILL switch was set to "kill" |
4326 | * when we loaded driver, and is now set to "enable". | 4326 | * when we loaded driver, and is now set to "enable". |
@@ -5996,24 +5996,6 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) | |||
5996 | iwl3945_rfkill_set_hw_state(priv); | 5996 | iwl3945_rfkill_set_hw_state(priv); |
5997 | } | 5997 | } |
5998 | 5998 | ||
5999 | static void iwl3945_bg_set_monitor(struct work_struct *work) | ||
6000 | { | ||
6001 | struct iwl3945_priv *priv = container_of(work, | ||
6002 | struct iwl3945_priv, set_monitor); | ||
6003 | |||
6004 | IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n"); | ||
6005 | |||
6006 | mutex_lock(&priv->mutex); | ||
6007 | |||
6008 | if (!iwl3945_is_ready(priv)) | ||
6009 | IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n"); | ||
6010 | else | ||
6011 | if (iwl3945_set_mode(priv, NL80211_IFTYPE_MONITOR) != 0) | ||
6012 | IWL_ERROR("iwl3945_set_mode() failed\n"); | ||
6013 | |||
6014 | mutex_unlock(&priv->mutex); | ||
6015 | } | ||
6016 | |||
6017 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) | 5999 | #define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) |
6018 | 6000 | ||
6019 | static void iwl3945_bg_scan_check(struct work_struct *data) | 6001 | static void iwl3945_bg_scan_check(struct work_struct *data) |
@@ -6339,10 +6321,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv) | |||
6339 | 6321 | ||
6340 | case NL80211_IFTYPE_ADHOC: | 6322 | case NL80211_IFTYPE_ADHOC: |
6341 | 6323 | ||
6342 | /* clear out the station table */ | 6324 | priv->assoc_id = 1; |
6343 | iwl3945_clear_stations_table(priv); | ||
6344 | |||
6345 | iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0); | ||
6346 | iwl3945_add_station(priv, priv->bssid, 0, 0); | 6325 | iwl3945_add_station(priv, priv->bssid, 0, 0); |
6347 | iwl3945_sync_sta(priv, IWL_STA_ID, | 6326 | iwl3945_sync_sta(priv, IWL_STA_ID, |
6348 | (priv->band == IEEE80211_BAND_5GHZ) ? | 6327 | (priv->band == IEEE80211_BAND_5GHZ) ? |
@@ -6830,16 +6809,43 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw, | |||
6830 | int mc_count, struct dev_addr_list *mc_list) | 6809 | int mc_count, struct dev_addr_list *mc_list) |
6831 | { | 6810 | { |
6832 | struct iwl3945_priv *priv = hw->priv; | 6811 | struct iwl3945_priv *priv = hw->priv; |
6812 | __le32 *filter_flags = &priv->staging_rxon.filter_flags; | ||
6813 | |||
6814 | IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n", | ||
6815 | changed_flags, *total_flags); | ||
6833 | 6816 | ||
6834 | if (changed_flags & (*total_flags) & FIF_OTHER_BSS) { | 6817 | if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { |
6835 | IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n", | 6818 | if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) |
6836 | NL80211_IFTYPE_MONITOR, | 6819 | *filter_flags |= RXON_FILTER_PROMISC_MSK; |
6837 | changed_flags, *total_flags); | 6820 | else |
6838 | /* queue work 'cuz mac80211 is holding a lock which | 6821 | *filter_flags &= ~RXON_FILTER_PROMISC_MSK; |
6839 | * prevents us from issuing (synchronous) f/w cmds */ | 6822 | } |
6840 | queue_work(priv->workqueue, &priv->set_monitor); | 6823 | if (changed_flags & FIF_ALLMULTI) { |
6824 | if (*total_flags & FIF_ALLMULTI) | ||
6825 | *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK; | ||
6826 | else | ||
6827 | *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK; | ||
6841 | } | 6828 | } |
6842 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | | 6829 | if (changed_flags & FIF_CONTROL) { |
6830 | if (*total_flags & FIF_CONTROL) | ||
6831 | *filter_flags |= RXON_FILTER_CTL2HOST_MSK; | ||
6832 | else | ||
6833 | *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK; | ||
6834 | } | ||
6835 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | ||
6836 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | ||
6837 | *filter_flags |= RXON_FILTER_BCON_AWARE_MSK; | ||
6838 | else | ||
6839 | *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK; | ||
6840 | } | ||
6841 | |||
6842 | /* We avoid iwl_commit_rxon here to commit the new filter flags | ||
6843 | * since mac80211 will call ieee80211_hw_config immediately. | ||
6844 | * (mc_list is not supported at this time). Otherwise, we need to | ||
6845 | * queue a background iwl_commit_rxon work. | ||
6846 | */ | ||
6847 | |||
6848 | *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | | ||
6843 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; | 6849 | FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; |
6844 | } | 6850 | } |
6845 | 6851 | ||
@@ -7715,7 +7721,6 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv) | |||
7715 | INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan); | 7721 | INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan); |
7716 | INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill); | 7722 | INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill); |
7717 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); | 7723 | INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); |
7718 | INIT_WORK(&priv->set_monitor, iwl3945_bg_set_monitor); | ||
7719 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); | 7724 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); |
7720 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); | 7725 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); |
7721 | INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check); | 7726 | INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check); |
@@ -7787,6 +7792,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7787 | struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); | 7792 | struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); |
7788 | unsigned long flags; | 7793 | unsigned long flags; |
7789 | 7794 | ||
7795 | /*********************** | ||
7796 | * 1. Allocating HW data | ||
7797 | * ********************/ | ||
7798 | |||
7790 | /* Disabling hardware scan means that mac80211 will perform scans | 7799 | /* Disabling hardware scan means that mac80211 will perform scans |
7791 | * "the hard way", rather than using device's scan. */ | 7800 | * "the hard way", rather than using device's scan. */ |
7792 | if (iwl3945_param_disable_hw_scan) { | 7801 | if (iwl3945_param_disable_hw_scan) { |
@@ -7810,27 +7819,24 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7810 | err = -ENOMEM; | 7819 | err = -ENOMEM; |
7811 | goto out; | 7820 | goto out; |
7812 | } | 7821 | } |
7813 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
7814 | 7822 | ||
7815 | hw->rate_control_algorithm = "iwl-3945-rs"; | 7823 | SET_IEEE80211_DEV(hw, &pdev->dev); |
7816 | hw->sta_data_size = sizeof(struct iwl3945_sta_priv); | ||
7817 | 7824 | ||
7818 | IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); | ||
7819 | priv = hw->priv; | 7825 | priv = hw->priv; |
7820 | priv->hw = hw; | 7826 | priv->hw = hw; |
7821 | |||
7822 | priv->pci_dev = pdev; | 7827 | priv->pci_dev = pdev; |
7823 | priv->cfg = cfg; | 7828 | priv->cfg = cfg; |
7824 | 7829 | ||
7830 | IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); | ||
7831 | hw->rate_control_algorithm = "iwl-3945-rs"; | ||
7832 | hw->sta_data_size = sizeof(struct iwl3945_sta_priv); | ||
7833 | |||
7825 | /* Select antenna (may be helpful if only one antenna is connected) */ | 7834 | /* Select antenna (may be helpful if only one antenna is connected) */ |
7826 | priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna; | 7835 | priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna; |
7827 | #ifdef CONFIG_IWL3945_DEBUG | 7836 | #ifdef CONFIG_IWL3945_DEBUG |
7828 | iwl3945_debug_level = iwl3945_param_debug; | 7837 | iwl3945_debug_level = iwl3945_param_debug; |
7829 | atomic_set(&priv->restrict_refcnt, 0); | 7838 | atomic_set(&priv->restrict_refcnt, 0); |
7830 | #endif | 7839 | #endif |
7831 | priv->retry_rate = 1; | ||
7832 | |||
7833 | priv->ibss_beacon = NULL; | ||
7834 | 7840 | ||
7835 | /* Tell mac80211 our characteristics */ | 7841 | /* Tell mac80211 our characteristics */ |
7836 | hw->flags = IEEE80211_HW_SIGNAL_DBM | | 7842 | hw->flags = IEEE80211_HW_SIGNAL_DBM | |
@@ -7841,17 +7847,14 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7841 | BIT(NL80211_IFTYPE_STATION) | | 7847 | BIT(NL80211_IFTYPE_STATION) | |
7842 | BIT(NL80211_IFTYPE_ADHOC); | 7848 | BIT(NL80211_IFTYPE_ADHOC); |
7843 | 7849 | ||
7850 | hw->wiphy->fw_handles_regulatory = true; | ||
7851 | |||
7844 | /* 4 EDCA QOS priorities */ | 7852 | /* 4 EDCA QOS priorities */ |
7845 | hw->queues = 4; | 7853 | hw->queues = 4; |
7846 | 7854 | ||
7847 | spin_lock_init(&priv->lock); | 7855 | /*************************** |
7848 | spin_lock_init(&priv->power_data.lock); | 7856 | * 2. Initializing PCI bus |
7849 | spin_lock_init(&priv->sta_lock); | 7857 | * *************************/ |
7850 | spin_lock_init(&priv->hcmd_lock); | ||
7851 | |||
7852 | INIT_LIST_HEAD(&priv->free_frames); | ||
7853 | |||
7854 | mutex_init(&priv->mutex); | ||
7855 | if (pci_enable_device(pdev)) { | 7858 | if (pci_enable_device(pdev)) { |
7856 | err = -ENODEV; | 7859 | err = -ENODEV; |
7857 | goto out_ieee80211_free_hw; | 7860 | goto out_ieee80211_free_hw; |
@@ -7859,14 +7862,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7859 | 7862 | ||
7860 | pci_set_master(pdev); | 7863 | pci_set_master(pdev); |
7861 | 7864 | ||
7862 | /* Clear the driver's (not device's) station table */ | ||
7863 | iwl3945_clear_stations_table(priv); | ||
7864 | |||
7865 | priv->data_retry_limit = -1; | ||
7866 | priv->ieee_channels = NULL; | ||
7867 | priv->ieee_rates = NULL; | ||
7868 | priv->band = IEEE80211_BAND_2GHZ; | ||
7869 | |||
7870 | err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | 7865 | err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); |
7871 | if (!err) | 7866 | if (!err) |
7872 | err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); | 7867 | err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); |
@@ -7880,10 +7875,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7880 | if (err) | 7875 | if (err) |
7881 | goto out_pci_disable_device; | 7876 | goto out_pci_disable_device; |
7882 | 7877 | ||
7883 | /* We disable the RETRY_TIMEOUT register (0x41) to keep | 7878 | /*********************** |
7884 | * PCI Tx retries from interfering with C3 CPU state */ | 7879 | * 3. Read REV Register |
7885 | pci_write_config_byte(pdev, 0x41, 0x00); | 7880 | * ********************/ |
7886 | |||
7887 | priv->hw_base = pci_iomap(pdev, 0, 0); | 7881 | priv->hw_base = pci_iomap(pdev, 0, 0); |
7888 | if (!priv->hw_base) { | 7882 | if (!priv->hw_base) { |
7889 | err = -ENODEV; | 7883 | err = -ENODEV; |
@@ -7894,25 +7888,70 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7894 | (unsigned long long) pci_resource_len(pdev, 0)); | 7888 | (unsigned long long) pci_resource_len(pdev, 0)); |
7895 | IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base); | 7889 | IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base); |
7896 | 7890 | ||
7897 | /* Initialize module parameter values here */ | 7891 | /* We disable the RETRY_TIMEOUT register (0x41) to keep |
7892 | * PCI Tx retries from interfering with C3 CPU state */ | ||
7893 | pci_write_config_byte(pdev, 0x41, 0x00); | ||
7898 | 7894 | ||
7899 | /* Disable radio (SW RF KILL) via parameter when loading driver */ | 7895 | /* nic init */ |
7900 | if (iwl3945_param_disable) { | 7896 | iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS, |
7901 | set_bit(STATUS_RF_KILL_SW, &priv->status); | 7897 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); |
7902 | IWL_DEBUG_INFO("Radio disabled.\n"); | ||
7903 | } | ||
7904 | 7898 | ||
7905 | priv->iw_mode = NL80211_IFTYPE_STATION; | 7899 | iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); |
7900 | err = iwl3945_poll_bit(priv, CSR_GP_CNTRL, | ||
7901 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
7902 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
7903 | if (err < 0) { | ||
7904 | IWL_DEBUG_INFO("Failed to init the card\n"); | ||
7905 | goto out_remove_sysfs; | ||
7906 | } | ||
7906 | 7907 | ||
7907 | printk(KERN_INFO DRV_NAME | 7908 | /*********************** |
7908 | ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); | 7909 | * 4. Read EEPROM |
7910 | * ********************/ | ||
7911 | /* Read the EEPROM */ | ||
7912 | err = iwl3945_eeprom_init(priv); | ||
7913 | if (err) { | ||
7914 | IWL_ERROR("Unable to init EEPROM\n"); | ||
7915 | goto out_remove_sysfs; | ||
7916 | } | ||
7917 | /* MAC Address location in EEPROM same for 3945/4965 */ | ||
7918 | get_eeprom_mac(priv, priv->mac_addr); | ||
7919 | IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr); | ||
7920 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); | ||
7909 | 7921 | ||
7922 | /*********************** | ||
7923 | * 5. Setup HW Constants | ||
7924 | * ********************/ | ||
7910 | /* Device-specific setup */ | 7925 | /* Device-specific setup */ |
7911 | if (iwl3945_hw_set_hw_setting(priv)) { | 7926 | if (iwl3945_hw_set_hw_setting(priv)) { |
7912 | IWL_ERROR("failed to set hw settings\n"); | 7927 | IWL_ERROR("failed to set hw settings\n"); |
7913 | goto out_iounmap; | 7928 | goto out_iounmap; |
7914 | } | 7929 | } |
7915 | 7930 | ||
7931 | /*********************** | ||
7932 | * 6. Setup priv | ||
7933 | * ********************/ | ||
7934 | priv->retry_rate = 1; | ||
7935 | priv->ibss_beacon = NULL; | ||
7936 | |||
7937 | spin_lock_init(&priv->lock); | ||
7938 | spin_lock_init(&priv->power_data.lock); | ||
7939 | spin_lock_init(&priv->sta_lock); | ||
7940 | spin_lock_init(&priv->hcmd_lock); | ||
7941 | |||
7942 | INIT_LIST_HEAD(&priv->free_frames); | ||
7943 | mutex_init(&priv->mutex); | ||
7944 | |||
7945 | /* Clear the driver's (not device's) station table */ | ||
7946 | iwl3945_clear_stations_table(priv); | ||
7947 | |||
7948 | priv->data_retry_limit = -1; | ||
7949 | priv->ieee_channels = NULL; | ||
7950 | priv->ieee_rates = NULL; | ||
7951 | priv->band = IEEE80211_BAND_2GHZ; | ||
7952 | |||
7953 | priv->iw_mode = NL80211_IFTYPE_STATION; | ||
7954 | |||
7916 | if (iwl3945_param_qos_enable) | 7955 | if (iwl3945_param_qos_enable) |
7917 | priv->qos_data.qos_enable = 1; | 7956 | priv->qos_data.qos_enable = 1; |
7918 | 7957 | ||
@@ -7921,70 +7960,76 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7921 | priv->qos_data.qos_active = 0; | 7960 | priv->qos_data.qos_active = 0; |
7922 | priv->qos_data.qos_cap.val = 0; | 7961 | priv->qos_data.qos_cap.val = 0; |
7923 | 7962 | ||
7924 | iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); | ||
7925 | iwl3945_setup_deferred_work(priv); | ||
7926 | iwl3945_setup_rx_handlers(priv); | ||
7927 | 7963 | ||
7928 | priv->rates_mask = IWL_RATES_MASK; | 7964 | priv->rates_mask = IWL_RATES_MASK; |
7929 | /* If power management is turned on, default to AC mode */ | 7965 | /* If power management is turned on, default to AC mode */ |
7930 | priv->power_mode = IWL_POWER_AC; | 7966 | priv->power_mode = IWL_POWER_AC; |
7931 | priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; | 7967 | priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; |
7932 | 7968 | ||
7933 | spin_lock_irqsave(&priv->lock, flags); | 7969 | err = iwl3945_init_channel_map(priv); |
7934 | iwl3945_disable_interrupts(priv); | ||
7935 | spin_unlock_irqrestore(&priv->lock, flags); | ||
7936 | |||
7937 | err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); | ||
7938 | if (err) { | 7970 | if (err) { |
7939 | IWL_ERROR("failed to create sysfs device attributes\n"); | 7971 | IWL_ERROR("initializing regulatory failed: %d\n", err); |
7940 | goto out_release_irq; | 7972 | goto out_release_irq; |
7941 | } | 7973 | } |
7942 | 7974 | ||
7943 | /* nic init */ | 7975 | err = iwl3945_init_geos(priv); |
7944 | iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS, | ||
7945 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | ||
7946 | |||
7947 | iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | ||
7948 | err = iwl3945_poll_bit(priv, CSR_GP_CNTRL, | ||
7949 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | ||
7950 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | ||
7951 | if (err < 0) { | ||
7952 | IWL_DEBUG_INFO("Failed to init the card\n"); | ||
7953 | goto out_remove_sysfs; | ||
7954 | } | ||
7955 | /* Read the EEPROM */ | ||
7956 | err = iwl3945_eeprom_init(priv); | ||
7957 | if (err) { | 7976 | if (err) { |
7958 | IWL_ERROR("Unable to init EEPROM\n"); | 7977 | IWL_ERROR("initializing geos failed: %d\n", err); |
7959 | goto out_remove_sysfs; | 7978 | goto out_free_channel_map; |
7960 | } | 7979 | } |
7961 | /* MAC Address location in EEPROM same for 3945/4965 */ | ||
7962 | get_eeprom_mac(priv, priv->mac_addr); | ||
7963 | IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr); | ||
7964 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); | ||
7965 | 7980 | ||
7966 | err = iwl3945_init_channel_map(priv); | 7981 | printk(KERN_INFO DRV_NAME |
7967 | if (err) { | 7982 | ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); |
7968 | IWL_ERROR("initializing regulatory failed: %d\n", err); | 7983 | |
7969 | goto out_remove_sysfs; | 7984 | /*********************************** |
7985 | * 7. Initialize Module Parameters | ||
7986 | * **********************************/ | ||
7987 | |||
7988 | /* Initialize module parameter values here */ | ||
7989 | /* Disable radio (SW RF KILL) via parameter when loading driver */ | ||
7990 | if (iwl3945_param_disable) { | ||
7991 | set_bit(STATUS_RF_KILL_SW, &priv->status); | ||
7992 | IWL_DEBUG_INFO("Radio disabled.\n"); | ||
7970 | } | 7993 | } |
7971 | 7994 | ||
7972 | err = iwl3945_init_geos(priv); | 7995 | |
7996 | /*********************** | ||
7997 | * 8. Setup Services | ||
7998 | * ********************/ | ||
7999 | |||
8000 | spin_lock_irqsave(&priv->lock, flags); | ||
8001 | iwl3945_disable_interrupts(priv); | ||
8002 | spin_unlock_irqrestore(&priv->lock, flags); | ||
8003 | |||
8004 | err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); | ||
7973 | if (err) { | 8005 | if (err) { |
7974 | IWL_ERROR("initializing geos failed: %d\n", err); | 8006 | IWL_ERROR("failed to create sysfs device attributes\n"); |
7975 | goto out_free_channel_map; | 8007 | goto out_free_geos; |
7976 | } | 8008 | } |
7977 | 8009 | ||
8010 | iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); | ||
8011 | iwl3945_setup_deferred_work(priv); | ||
8012 | iwl3945_setup_rx_handlers(priv); | ||
8013 | |||
8014 | /*********************** | ||
8015 | * 9. Conclude | ||
8016 | * ********************/ | ||
8017 | pci_save_state(pdev); | ||
8018 | pci_disable_device(pdev); | ||
8019 | |||
8020 | /********************************* | ||
8021 | * 10. Setup and Register mac80211 | ||
8022 | * *******************************/ | ||
8023 | |||
7978 | err = ieee80211_register_hw(priv->hw); | 8024 | err = ieee80211_register_hw(priv->hw); |
7979 | if (err) { | 8025 | if (err) { |
7980 | IWL_ERROR("Failed to register network device (error %d)\n", err); | 8026 | IWL_ERROR("Failed to register network device (error %d)\n", err); |
7981 | goto out_free_geos; | 8027 | goto out_remove_sysfs; |
7982 | } | 8028 | } |
7983 | 8029 | ||
7984 | priv->hw->conf.beacon_int = 100; | 8030 | priv->hw->conf.beacon_int = 100; |
7985 | priv->mac80211_registered = 1; | 8031 | priv->mac80211_registered = 1; |
7986 | pci_save_state(pdev); | 8032 | |
7987 | pci_disable_device(pdev); | ||
7988 | 8033 | ||
7989 | err = iwl3945_rfkill_init(priv); | 8034 | err = iwl3945_rfkill_init(priv); |
7990 | if (err) | 8035 | if (err) |
@@ -7993,12 +8038,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
7993 | 8038 | ||
7994 | return 0; | 8039 | return 0; |
7995 | 8040 | ||
8041 | out_remove_sysfs: | ||
8042 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | ||
7996 | out_free_geos: | 8043 | out_free_geos: |
7997 | iwl3945_free_geos(priv); | 8044 | iwl3945_free_geos(priv); |
7998 | out_free_channel_map: | 8045 | out_free_channel_map: |
7999 | iwl3945_free_channel_map(priv); | 8046 | iwl3945_free_channel_map(priv); |
8000 | out_remove_sysfs: | 8047 | |
8001 | sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); | ||
8002 | 8048 | ||
8003 | out_release_irq: | 8049 | out_release_irq: |
8004 | destroy_workqueue(priv->workqueue); | 8050 | destroy_workqueue(priv->workqueue); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index d8b5cf389405..530648b39935 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -452,9 +452,9 @@ static int mac80211_hwsim_config_interface(struct ieee80211_hw *hw, | |||
452 | hwsim_check_magic(vif); | 452 | hwsim_check_magic(vif); |
453 | if (conf->changed & IEEE80211_IFCC_BSSID) { | 453 | if (conf->changed & IEEE80211_IFCC_BSSID) { |
454 | DECLARE_MAC_BUF(mac); | 454 | DECLARE_MAC_BUF(mac); |
455 | printk(KERN_DEBUG "%s:%s: BSSID changed: %s\n", | 455 | printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n", |
456 | wiphy_name(hw->wiphy), __func__, | 456 | wiphy_name(hw->wiphy), __func__, |
457 | print_mac(mac, conf->bssid)); | 457 | conf->bssid); |
458 | memcpy(vp->bssid, conf->bssid, ETH_ALEN); | 458 | memcpy(vp->bssid, conf->bssid, ETH_ALEN); |
459 | } | 459 | } |
460 | return 0; | 460 | return 0; |
@@ -612,9 +612,8 @@ static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) | |||
612 | if (!vp->assoc) | 612 | if (!vp->assoc) |
613 | return; | 613 | return; |
614 | 614 | ||
615 | printk(KERN_DEBUG "%s:%s: send PS-Poll to %s for aid %d\n", | 615 | printk(KERN_DEBUG "%s:%s: send PS-Poll to %pM for aid %d\n", |
616 | wiphy_name(data->hw->wiphy), __func__, | 616 | wiphy_name(data->hw->wiphy), __func__, vp->bssid, vp->aid); |
617 | print_mac(buf, vp->bssid), vp->aid); | ||
618 | 617 | ||
619 | skb = dev_alloc_skb(sizeof(*pspoll)); | 618 | skb = dev_alloc_skb(sizeof(*pspoll)); |
620 | if (!skb) | 619 | if (!skb) |
@@ -644,9 +643,8 @@ static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, | |||
644 | if (!vp->assoc) | 643 | if (!vp->assoc) |
645 | return; | 644 | return; |
646 | 645 | ||
647 | printk(KERN_DEBUG "%s:%s: send data::nullfunc to %s ps=%d\n", | 646 | printk(KERN_DEBUG "%s:%s: send data::nullfunc to %pM ps=%d\n", |
648 | wiphy_name(data->hw->wiphy), __func__, | 647 | wiphy_name(data->hw->wiphy), __func__, vp->bssid, ps); |
649 | print_mac(buf, vp->bssid), ps); | ||
650 | 648 | ||
651 | skb = dev_alloc_skb(sizeof(*hdr)); | 649 | skb = dev_alloc_skb(sizeof(*hdr)); |
652 | if (!skb) | 650 | if (!skb) |
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index fd9263980d69..171bfa03868e 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c | |||
@@ -84,6 +84,7 @@ | |||
84 | #include <linux/etherdevice.h> | 84 | #include <linux/etherdevice.h> |
85 | #include <linux/ethtool.h> | 85 | #include <linux/ethtool.h> |
86 | #include <linux/firmware.h> | 86 | #include <linux/firmware.h> |
87 | #include <linux/suspend.h> | ||
87 | #include <linux/if_arp.h> | 88 | #include <linux/if_arp.h> |
88 | #include <linux/wireless.h> | 89 | #include <linux/wireless.h> |
89 | #include <linux/ieee80211.h> | 90 | #include <linux/ieee80211.h> |
@@ -431,9 +432,9 @@ struct fw_info { | |||
431 | }; | 432 | }; |
432 | 433 | ||
433 | const static struct fw_info orinoco_fw[] = { | 434 | const static struct fw_info orinoco_fw[] = { |
434 | { "", "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 }, | 435 | { NULL, "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 }, |
435 | { "", "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 }, | 436 | { NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 }, |
436 | { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 512 } | 437 | { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 } |
437 | }; | 438 | }; |
438 | 439 | ||
439 | /* Structure used to access fields in FW | 440 | /* Structure used to access fields in FW |
@@ -487,18 +488,17 @@ orinoco_dl_firmware(struct orinoco_private *priv, | |||
487 | if (err) | 488 | if (err) |
488 | goto free; | 489 | goto free; |
489 | 490 | ||
490 | if (priv->cached_fw) | 491 | if (!priv->cached_fw) { |
491 | fw_entry = priv->cached_fw; | ||
492 | else { | ||
493 | err = request_firmware(&fw_entry, firmware, priv->dev); | 492 | err = request_firmware(&fw_entry, firmware, priv->dev); |
493 | |||
494 | if (err) { | 494 | if (err) { |
495 | printk(KERN_ERR "%s: Cannot find firmware %s\n", | 495 | printk(KERN_ERR "%s: Cannot find firmware %s\n", |
496 | dev->name, firmware); | 496 | dev->name, firmware); |
497 | err = -ENOENT; | 497 | err = -ENOENT; |
498 | goto free; | 498 | goto free; |
499 | } | 499 | } |
500 | priv->cached_fw = fw_entry; | 500 | } else |
501 | } | 501 | fw_entry = priv->cached_fw; |
502 | 502 | ||
503 | hdr = (const struct orinoco_fw_header *) fw_entry->data; | 503 | hdr = (const struct orinoco_fw_header *) fw_entry->data; |
504 | 504 | ||
@@ -540,11 +540,9 @@ orinoco_dl_firmware(struct orinoco_private *priv, | |||
540 | dev->name, hermes_present(hw)); | 540 | dev->name, hermes_present(hw)); |
541 | 541 | ||
542 | abort: | 542 | abort: |
543 | /* In case of error, assume firmware was bogus and release it */ | 543 | /* If we requested the firmware, release it. */ |
544 | if (err) { | 544 | if (!priv->cached_fw) |
545 | priv->cached_fw = NULL; | ||
546 | release_firmware(fw_entry); | 545 | release_firmware(fw_entry); |
547 | } | ||
548 | 546 | ||
549 | free: | 547 | free: |
550 | kfree(pda); | 548 | kfree(pda); |
@@ -648,34 +646,41 @@ symbol_dl_firmware(struct orinoco_private *priv, | |||
648 | int ret; | 646 | int ret; |
649 | const struct firmware *fw_entry; | 647 | const struct firmware *fw_entry; |
650 | 648 | ||
651 | if (request_firmware(&fw_entry, fw->pri_fw, | 649 | if (!priv->cached_pri_fw) { |
652 | priv->dev) != 0) { | 650 | if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) { |
653 | printk(KERN_ERR "%s: Cannot find firmware: %s\n", | 651 | printk(KERN_ERR "%s: Cannot find firmware: %s\n", |
654 | dev->name, fw->pri_fw); | 652 | dev->name, fw->pri_fw); |
655 | return -ENOENT; | 653 | return -ENOENT; |
656 | } | 654 | } |
655 | } else | ||
656 | fw_entry = priv->cached_pri_fw; | ||
657 | 657 | ||
658 | /* Load primary firmware */ | 658 | /* Load primary firmware */ |
659 | ret = symbol_dl_image(priv, fw, fw_entry->data, | 659 | ret = symbol_dl_image(priv, fw, fw_entry->data, |
660 | fw_entry->data + fw_entry->size, 0); | 660 | fw_entry->data + fw_entry->size, 0); |
661 | release_firmware(fw_entry); | 661 | |
662 | if (!priv->cached_pri_fw) | ||
663 | release_firmware(fw_entry); | ||
662 | if (ret) { | 664 | if (ret) { |
663 | printk(KERN_ERR "%s: Primary firmware download failed\n", | 665 | printk(KERN_ERR "%s: Primary firmware download failed\n", |
664 | dev->name); | 666 | dev->name); |
665 | return ret; | 667 | return ret; |
666 | } | 668 | } |
667 | 669 | ||
668 | if (request_firmware(&fw_entry, fw->sta_fw, | 670 | if (!priv->cached_fw) { |
669 | priv->dev) != 0) { | 671 | if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) { |
670 | printk(KERN_ERR "%s: Cannot find firmware: %s\n", | 672 | printk(KERN_ERR "%s: Cannot find firmware: %s\n", |
671 | dev->name, fw->sta_fw); | 673 | dev->name, fw->sta_fw); |
672 | return -ENOENT; | 674 | return -ENOENT; |
673 | } | 675 | } |
676 | } else | ||
677 | fw_entry = priv->cached_fw; | ||
674 | 678 | ||
675 | /* Load secondary firmware */ | 679 | /* Load secondary firmware */ |
676 | ret = symbol_dl_image(priv, fw, fw_entry->data, | 680 | ret = symbol_dl_image(priv, fw, fw_entry->data, |
677 | fw_entry->data + fw_entry->size, 1); | 681 | fw_entry->data + fw_entry->size, 1); |
678 | release_firmware(fw_entry); | 682 | if (!priv->cached_fw) |
683 | release_firmware(fw_entry); | ||
679 | if (ret) { | 684 | if (ret) { |
680 | printk(KERN_ERR "%s: Secondary firmware download failed\n", | 685 | printk(KERN_ERR "%s: Secondary firmware download failed\n", |
681 | dev->name); | 686 | dev->name); |
@@ -708,6 +713,45 @@ static int orinoco_download(struct orinoco_private *priv) | |||
708 | return err; | 713 | return err; |
709 | } | 714 | } |
710 | 715 | ||
716 | #if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) | ||
717 | static void orinoco_cache_fw(struct orinoco_private *priv, int ap) | ||
718 | { | ||
719 | const struct firmware *fw_entry = NULL; | ||
720 | const char *pri_fw; | ||
721 | const char *fw; | ||
722 | |||
723 | pri_fw = orinoco_fw[priv->firmware_type].pri_fw; | ||
724 | if (ap) | ||
725 | fw = orinoco_fw[priv->firmware_type].ap_fw; | ||
726 | else | ||
727 | fw = orinoco_fw[priv->firmware_type].sta_fw; | ||
728 | |||
729 | if (pri_fw) { | ||
730 | if (request_firmware(&fw_entry, pri_fw, priv->dev) == 0) | ||
731 | priv->cached_pri_fw = fw_entry; | ||
732 | } | ||
733 | |||
734 | if (fw) { | ||
735 | if (request_firmware(&fw_entry, fw, priv->dev) == 0) | ||
736 | priv->cached_fw = fw_entry; | ||
737 | } | ||
738 | } | ||
739 | |||
740 | static void orinoco_uncache_fw(struct orinoco_private *priv) | ||
741 | { | ||
742 | if (priv->cached_pri_fw) | ||
743 | release_firmware(priv->cached_pri_fw); | ||
744 | if (priv->cached_fw) | ||
745 | release_firmware(priv->cached_fw); | ||
746 | |||
747 | priv->cached_pri_fw = NULL; | ||
748 | priv->cached_fw = NULL; | ||
749 | } | ||
750 | #else | ||
751 | #define orinoco_cache_fw(priv, ap) | ||
752 | #define orinoco_uncache_fw(priv) | ||
753 | #endif | ||
754 | |||
711 | /********************************************************************/ | 755 | /********************************************************************/ |
712 | /* Device methods */ | 756 | /* Device methods */ |
713 | /********************************************************************/ | 757 | /********************************************************************/ |
@@ -809,7 +853,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) | |||
809 | wstats->qual.qual = (int)le16_to_cpu(cq.qual); | 853 | wstats->qual.qual = (int)le16_to_cpu(cq.qual); |
810 | wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; | 854 | wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; |
811 | wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; | 855 | wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; |
812 | wstats->qual.updated = 7; | 856 | wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; |
813 | } | 857 | } |
814 | } | 858 | } |
815 | 859 | ||
@@ -1168,7 +1212,7 @@ static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, | |||
1168 | wstats.level = level - 0x95; | 1212 | wstats.level = level - 0x95; |
1169 | wstats.noise = noise - 0x95; | 1213 | wstats.noise = noise - 0x95; |
1170 | wstats.qual = (level > noise) ? (level - noise) : 0; | 1214 | wstats.qual = (level > noise) ? (level - noise) : 0; |
1171 | wstats.updated = 7; | 1215 | wstats.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; |
1172 | /* Update spy records */ | 1216 | /* Update spy records */ |
1173 | wireless_spy_update(dev, mac, &wstats); | 1217 | wireless_spy_update(dev, mac, &wstats); |
1174 | } | 1218 | } |
@@ -3062,6 +3106,50 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id) | |||
3062 | } | 3106 | } |
3063 | 3107 | ||
3064 | /********************************************************************/ | 3108 | /********************************************************************/ |
3109 | /* Power management */ | ||
3110 | /********************************************************************/ | ||
3111 | #if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_HERMES_CACHE_FW_ON_INIT) | ||
3112 | static int orinoco_pm_notifier(struct notifier_block *notifier, | ||
3113 | unsigned long pm_event, | ||
3114 | void *unused) | ||
3115 | { | ||
3116 | struct orinoco_private *priv = container_of(notifier, | ||
3117 | struct orinoco_private, | ||
3118 | pm_notifier); | ||
3119 | |||
3120 | /* All we need to do is cache the firmware before suspend, and | ||
3121 | * release it when we come out. | ||
3122 | * | ||
3123 | * Only need to do this if we're downloading firmware. */ | ||
3124 | if (!priv->do_fw_download) | ||
3125 | return NOTIFY_DONE; | ||
3126 | |||
3127 | switch (pm_event) { | ||
3128 | case PM_HIBERNATION_PREPARE: | ||
3129 | case PM_SUSPEND_PREPARE: | ||
3130 | orinoco_cache_fw(priv, 0); | ||
3131 | break; | ||
3132 | |||
3133 | case PM_POST_RESTORE: | ||
3134 | /* Restore from hibernation failed. We need to clean | ||
3135 | * up in exactly the same way, so fall through. */ | ||
3136 | case PM_POST_HIBERNATION: | ||
3137 | case PM_POST_SUSPEND: | ||
3138 | orinoco_uncache_fw(priv); | ||
3139 | break; | ||
3140 | |||
3141 | case PM_RESTORE_PREPARE: | ||
3142 | default: | ||
3143 | break; | ||
3144 | } | ||
3145 | |||
3146 | return NOTIFY_DONE; | ||
3147 | } | ||
3148 | #else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */ | ||
3149 | #define orinoco_pm_notifier NULL | ||
3150 | #endif | ||
3151 | |||
3152 | /********************************************************************/ | ||
3065 | /* Initialization */ | 3153 | /* Initialization */ |
3066 | /********************************************************************/ | 3154 | /********************************************************************/ |
3067 | 3155 | ||
@@ -3304,6 +3392,10 @@ static int orinoco_init(struct net_device *dev) | |||
3304 | } | 3392 | } |
3305 | 3393 | ||
3306 | if (priv->do_fw_download) { | 3394 | if (priv->do_fw_download) { |
3395 | #ifdef CONFIG_HERMES_CACHE_FW_ON_INIT | ||
3396 | orinoco_cache_fw(priv, 0); | ||
3397 | #endif | ||
3398 | |||
3307 | err = orinoco_download(priv); | 3399 | err = orinoco_download(priv); |
3308 | if (err) | 3400 | if (err) |
3309 | priv->do_fw_download = 0; | 3401 | priv->do_fw_download = 0; |
@@ -3540,8 +3632,13 @@ struct net_device | |||
3540 | netif_carrier_off(dev); | 3632 | netif_carrier_off(dev); |
3541 | priv->last_linkstatus = 0xffff; | 3633 | priv->last_linkstatus = 0xffff; |
3542 | 3634 | ||
3635 | priv->cached_pri_fw = NULL; | ||
3543 | priv->cached_fw = NULL; | 3636 | priv->cached_fw = NULL; |
3544 | 3637 | ||
3638 | /* Register PM notifiers */ | ||
3639 | priv->pm_notifier.notifier_call = orinoco_pm_notifier; | ||
3640 | register_pm_notifier(&priv->pm_notifier); | ||
3641 | |||
3545 | return dev; | 3642 | return dev; |
3546 | } | 3643 | } |
3547 | 3644 | ||
@@ -3553,9 +3650,10 @@ void free_orinocodev(struct net_device *dev) | |||
3553 | * when we call tasklet_kill it will run one final time, | 3650 | * when we call tasklet_kill it will run one final time, |
3554 | * emptying the list */ | 3651 | * emptying the list */ |
3555 | tasklet_kill(&priv->rx_tasklet); | 3652 | tasklet_kill(&priv->rx_tasklet); |
3556 | if (priv->cached_fw) | 3653 | |
3557 | release_firmware(priv->cached_fw); | 3654 | unregister_pm_notifier(&priv->pm_notifier); |
3558 | priv->cached_fw = NULL; | 3655 | orinoco_uncache_fw(priv); |
3656 | |||
3559 | priv->wpa_ie_len = 0; | 3657 | priv->wpa_ie_len = 0; |
3560 | kfree(priv->wpa_ie); | 3658 | kfree(priv->wpa_ie); |
3561 | orinoco_mic_free(priv); | 3659 | orinoco_mic_free(priv); |
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h index 8c2953834923..00750c8ba7db 100644 --- a/drivers/net/wireless/orinoco/orinoco.h +++ b/drivers/net/wireless/orinoco/orinoco.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #define DRIVER_VERSION "0.15" | 10 | #define DRIVER_VERSION "0.15" |
11 | 11 | ||
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/suspend.h> | ||
13 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
14 | #include <linux/wireless.h> | 15 | #include <linux/wireless.h> |
15 | #include <net/iw_handler.h> | 16 | #include <net/iw_handler.h> |
@@ -167,8 +168,11 @@ struct orinoco_private { | |||
167 | unsigned int tkip_cm_active:1; | 168 | unsigned int tkip_cm_active:1; |
168 | unsigned int key_mgmt:3; | 169 | unsigned int key_mgmt:3; |
169 | 170 | ||
170 | /* Cached in memory firmware to use in ->resume */ | 171 | /* Cached in memory firmware to use during ->resume. */ |
172 | const struct firmware *cached_pri_fw; | ||
171 | const struct firmware *cached_fw; | 173 | const struct firmware *cached_fw; |
174 | |||
175 | struct notifier_block pm_notifier; | ||
172 | }; | 176 | }; |
173 | 177 | ||
174 | #ifdef ORINOCO_DEBUG | 178 | #ifdef ORINOCO_DEBUG |
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index 0bae3dcf9d50..a2764764c1c0 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c | |||
@@ -450,10 +450,29 @@ spectrum_cs_resume(struct pcmcia_device *link) | |||
450 | { | 450 | { |
451 | struct net_device *dev = link->priv; | 451 | struct net_device *dev = link->priv; |
452 | struct orinoco_private *priv = netdev_priv(dev); | 452 | struct orinoco_private *priv = netdev_priv(dev); |
453 | unsigned long flags; | ||
454 | int err; | ||
455 | |||
456 | err = orinoco_reinit_firmware(dev); | ||
457 | if (err) { | ||
458 | printk(KERN_ERR "%s: Error %d re-initializing firmware\n", | ||
459 | dev->name, err); | ||
460 | return -EIO; | ||
461 | } | ||
462 | |||
463 | spin_lock_irqsave(&priv->lock, flags); | ||
453 | 464 | ||
454 | netif_device_attach(dev); | 465 | netif_device_attach(dev); |
455 | priv->hw_unavailable--; | 466 | priv->hw_unavailable--; |
456 | schedule_work(&priv->reset_work); | 467 | |
468 | if (priv->open && !priv->hw_unavailable) { | ||
469 | err = __orinoco_up(dev); | ||
470 | if (err) | ||
471 | printk(KERN_ERR "%s: Error %d restarting card\n", | ||
472 | dev->name, err); | ||
473 | } | ||
474 | |||
475 | spin_unlock_irqrestore(&priv->lock, flags); | ||
457 | 476 | ||
458 | return 0; | 477 | return 0; |
459 | } | 478 | } |
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index b585ff65e0e4..491ab96c7b67 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h | |||
@@ -102,6 +102,9 @@ struct p54_common { | |||
102 | unsigned int output_power; | 102 | unsigned int output_power; |
103 | u32 tsf_low32; | 103 | u32 tsf_low32; |
104 | u32 tsf_high32; | 104 | u32 tsf_high32; |
105 | u64 basic_rate_mask; | ||
106 | u16 wakeup_timer; | ||
107 | u16 aid; | ||
105 | struct ieee80211_tx_queue_stats tx_stats[8]; | 108 | struct ieee80211_tx_queue_stats tx_stats[8]; |
106 | struct p54_edcf_queue_param qos_params[8]; | 109 | struct p54_edcf_queue_param qos_params[8]; |
107 | struct ieee80211_low_level_stats stats; | 110 | struct ieee80211_low_level_stats stats; |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 1796b8c6c5b8..602392628e4e 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -530,6 +530,8 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
530 | rx_status.noise = priv->noise; | 530 | rx_status.noise = priv->noise; |
531 | /* XX correct? */ | 531 | /* XX correct? */ |
532 | rx_status.qual = (100 * hdr->rssi) / 127; | 532 | rx_status.qual = (100 * hdr->rssi) / 127; |
533 | if (hdr->rate & 0x10) | ||
534 | rx_status.flag |= RX_FLAG_SHORTPRE; | ||
533 | rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ? | 535 | rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ? |
534 | hdr->rate : (hdr->rate - 4)) & 0xf; | 536 | hdr->rate : (hdr->rate - 4)) & 0xf; |
535 | rx_status.freq = freq; | 537 | rx_status.freq = freq; |
@@ -576,7 +578,7 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
576 | unsigned long flags; | 578 | unsigned long flags; |
577 | u32 freed = 0, last_addr = priv->rx_start; | 579 | u32 freed = 0, last_addr = priv->rx_start; |
578 | 580 | ||
579 | if (!skb || !dev) | 581 | if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue))) |
580 | return; | 582 | return; |
581 | 583 | ||
582 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | 584 | spin_lock_irqsave(&priv->tx_queue.lock, flags); |
@@ -1058,6 +1060,7 @@ static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
1058 | break; | 1060 | break; |
1059 | case NL80211_IFTYPE_AP: | 1061 | case NL80211_IFTYPE_AP: |
1060 | case NL80211_IFTYPE_ADHOC: | 1062 | case NL80211_IFTYPE_ADHOC: |
1063 | case NL80211_IFTYPE_MESH_POINT: | ||
1061 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { | 1064 | if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { |
1062 | *aid = 0; | 1065 | *aid = 0; |
1063 | *queue = 3; | 1066 | *queue = 3; |
@@ -1198,7 +1201,10 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1198 | txhdr->key_type = 0; | 1201 | txhdr->key_type = 0; |
1199 | txhdr->key_len = 0; | 1202 | txhdr->key_len = 0; |
1200 | txhdr->hw_queue = queue; | 1203 | txhdr->hw_queue = queue; |
1201 | txhdr->backlog = 32; | 1204 | if (current_queue) |
1205 | txhdr->backlog = current_queue->len; | ||
1206 | else | ||
1207 | txhdr->backlog = 0; | ||
1202 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); | 1208 | memset(txhdr->durations, 0, sizeof(txhdr->durations)); |
1203 | txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? | 1209 | txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? |
1204 | 2 : info->antenna_sel_tx - 1; | 1210 | 2 : info->antenna_sel_tx - 1; |
@@ -1243,20 +1249,20 @@ static int p54_setup_mac(struct ieee80211_hw *dev, u16 mode, const u8 *bssid) | |||
1243 | setup->rx_antenna = priv->rx_antenna; | 1249 | setup->rx_antenna = priv->rx_antenna; |
1244 | setup->rx_align = 0; | 1250 | setup->rx_align = 0; |
1245 | if (priv->fw_var < 0x500) { | 1251 | if (priv->fw_var < 0x500) { |
1246 | setup->v1.basic_rate_mask = cpu_to_le32(0x15f); | 1252 | setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); |
1247 | memset(setup->v1.rts_rates, 0, 8); | 1253 | memset(setup->v1.rts_rates, 0, 8); |
1248 | setup->v1.rx_addr = cpu_to_le32(priv->rx_end); | 1254 | setup->v1.rx_addr = cpu_to_le32(priv->rx_end); |
1249 | setup->v1.max_rx = cpu_to_le16(priv->rx_mtu); | 1255 | setup->v1.max_rx = cpu_to_le16(priv->rx_mtu); |
1250 | setup->v1.rxhw = cpu_to_le16(priv->rxhw); | 1256 | setup->v1.rxhw = cpu_to_le16(priv->rxhw); |
1251 | setup->v1.wakeup_timer = cpu_to_le16(500); | 1257 | setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer); |
1252 | setup->v1.unalloc0 = cpu_to_le16(0); | 1258 | setup->v1.unalloc0 = cpu_to_le16(0); |
1253 | } else { | 1259 | } else { |
1254 | setup->v2.rx_addr = cpu_to_le32(priv->rx_end); | 1260 | setup->v2.rx_addr = cpu_to_le32(priv->rx_end); |
1255 | setup->v2.max_rx = cpu_to_le16(priv->rx_mtu); | 1261 | setup->v2.max_rx = cpu_to_le16(priv->rx_mtu); |
1256 | setup->v2.rxhw = cpu_to_le16(priv->rxhw); | 1262 | setup->v2.rxhw = cpu_to_le16(priv->rxhw); |
1257 | setup->v2.timer = cpu_to_le16(1000); | 1263 | setup->v2.timer = cpu_to_le16(priv->wakeup_timer); |
1258 | setup->v2.truncate = cpu_to_le16(48896); | 1264 | setup->v2.truncate = cpu_to_le16(48896); |
1259 | setup->v2.basic_rate_mask = cpu_to_le32(0x15f); | 1265 | setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); |
1260 | setup->v2.sbss_offset = 0; | 1266 | setup->v2.sbss_offset = 0; |
1261 | setup->v2.mcast_window = 0; | 1267 | setup->v2.mcast_window = 0; |
1262 | setup->v2.rx_rssi_threshold = 0; | 1268 | setup->v2.rx_rssi_threshold = 0; |
@@ -1342,7 +1348,7 @@ static int p54_set_freq(struct ieee80211_hw *dev, u16 frequency) | |||
1342 | } else { | 1348 | } else { |
1343 | chan->v2.rssical_mul = cpu_to_le16(130); | 1349 | chan->v2.rssical_mul = cpu_to_le16(130); |
1344 | chan->v2.rssical_add = cpu_to_le16(0xfe70); | 1350 | chan->v2.rssical_add = cpu_to_le16(0xfe70); |
1345 | chan->v2.basic_rate_mask = cpu_to_le32(0x15f); | 1351 | chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); |
1346 | memset(chan->v2.rts_rates, 0, 8); | 1352 | memset(chan->v2.rts_rates, 0, 8); |
1347 | } | 1353 | } |
1348 | priv->tx(dev, skb, 1); | 1354 | priv->tx(dev, skb, 1); |
@@ -1518,16 +1524,24 @@ static int p54_start(struct ieee80211_hw *dev) | |||
1518 | 1524 | ||
1519 | mutex_lock(&priv->conf_mutex); | 1525 | mutex_lock(&priv->conf_mutex); |
1520 | err = priv->open(dev); | 1526 | err = priv->open(dev); |
1521 | if (!err) | 1527 | if (err) |
1522 | priv->mode = NL80211_IFTYPE_MONITOR; | 1528 | goto out; |
1523 | P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47); | 1529 | P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47); |
1524 | P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94); | 1530 | P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94); |
1525 | P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0); | 1531 | P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0); |
1526 | P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0); | 1532 | P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0); |
1527 | err = p54_set_edcf(dev); | 1533 | err = p54_set_edcf(dev); |
1528 | if (!err) | 1534 | if (err) |
1529 | err = p54_init_stats(dev); | 1535 | goto out; |
1536 | err = p54_init_stats(dev); | ||
1537 | if (err) | ||
1538 | goto out; | ||
1539 | err = p54_setup_mac(dev, P54_FILTER_TYPE_NONE, NULL); | ||
1540 | if (err) | ||
1541 | goto out; | ||
1542 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1530 | 1543 | ||
1544 | out: | ||
1531 | mutex_unlock(&priv->conf_mutex); | 1545 | mutex_unlock(&priv->conf_mutex); |
1532 | return err; | 1546 | return err; |
1533 | } | 1547 | } |
@@ -1547,7 +1561,6 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
1547 | while ((skb = skb_dequeue(&priv->tx_queue))) | 1561 | while ((skb = skb_dequeue(&priv->tx_queue))) |
1548 | kfree_skb(skb); | 1562 | kfree_skb(skb); |
1549 | 1563 | ||
1550 | kfree(priv->cached_beacon); | ||
1551 | priv->cached_beacon = NULL; | 1564 | priv->cached_beacon = NULL; |
1552 | priv->stop(dev); | 1565 | priv->stop(dev); |
1553 | priv->tsf_high32 = priv->tsf_low32 = 0; | 1566 | priv->tsf_high32 = priv->tsf_low32 = 0; |
@@ -1570,6 +1583,7 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
1570 | case NL80211_IFTYPE_STATION: | 1583 | case NL80211_IFTYPE_STATION: |
1571 | case NL80211_IFTYPE_ADHOC: | 1584 | case NL80211_IFTYPE_ADHOC: |
1572 | case NL80211_IFTYPE_AP: | 1585 | case NL80211_IFTYPE_AP: |
1586 | case NL80211_IFTYPE_MESH_POINT: | ||
1573 | priv->mode = conf->type; | 1587 | priv->mode = conf->type; |
1574 | break; | 1588 | break; |
1575 | default: | 1589 | default: |
@@ -1589,6 +1603,7 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
1589 | p54_setup_mac(dev, P54_FILTER_TYPE_AP, priv->mac_addr); | 1603 | p54_setup_mac(dev, P54_FILTER_TYPE_AP, priv->mac_addr); |
1590 | break; | 1604 | break; |
1591 | case NL80211_IFTYPE_ADHOC: | 1605 | case NL80211_IFTYPE_ADHOC: |
1606 | case NL80211_IFTYPE_MESH_POINT: | ||
1592 | p54_setup_mac(dev, P54_FILTER_TYPE_IBSS, NULL); | 1607 | p54_setup_mac(dev, P54_FILTER_TYPE_IBSS, NULL); |
1593 | break; | 1608 | break; |
1594 | default: | 1609 | default: |
@@ -1653,6 +1668,7 @@ static int p54_config_interface(struct ieee80211_hw *dev, | |||
1653 | break; | 1668 | break; |
1654 | case NL80211_IFTYPE_AP: | 1669 | case NL80211_IFTYPE_AP: |
1655 | case NL80211_IFTYPE_ADHOC: | 1670 | case NL80211_IFTYPE_ADHOC: |
1671 | case NL80211_IFTYPE_MESH_POINT: | ||
1656 | memcpy(priv->bssid, conf->bssid, ETH_ALEN); | 1672 | memcpy(priv->bssid, conf->bssid, ETH_ALEN); |
1657 | ret = p54_set_freq(dev, dev->conf.channel->center_freq); | 1673 | ret = p54_set_freq(dev, dev->conf.channel->center_freq); |
1658 | if (ret) | 1674 | if (ret) |
@@ -1712,10 +1728,9 @@ static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue, | |||
1712 | if ((params) && !(queue > 4)) { | 1728 | if ((params) && !(queue > 4)) { |
1713 | P54_SET_QUEUE(priv->qos_params[queue], params->aifs, | 1729 | P54_SET_QUEUE(priv->qos_params[queue], params->aifs, |
1714 | params->cw_min, params->cw_max, params->txop); | 1730 | params->cw_min, params->cw_max, params->txop); |
1731 | ret = p54_set_edcf(dev); | ||
1715 | } else | 1732 | } else |
1716 | ret = -EINVAL; | 1733 | ret = -EINVAL; |
1717 | if (!ret) | ||
1718 | ret = p54_set_edcf(dev); | ||
1719 | mutex_unlock(&priv->conf_mutex); | 1734 | mutex_unlock(&priv->conf_mutex); |
1720 | return ret; | 1735 | return ret; |
1721 | } | 1736 | } |
@@ -1792,6 +1807,24 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, | |||
1792 | priv->use_short_slot = info->use_short_slot; | 1807 | priv->use_short_slot = info->use_short_slot; |
1793 | p54_set_edcf(dev); | 1808 | p54_set_edcf(dev); |
1794 | } | 1809 | } |
1810 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
1811 | if (dev->conf.channel->band == IEEE80211_BAND_5GHZ) | ||
1812 | priv->basic_rate_mask = (info->basic_rates << 4); | ||
1813 | else | ||
1814 | priv->basic_rate_mask = info->basic_rates; | ||
1815 | p54_setup_mac(dev, priv->mac_mode, priv->bssid); | ||
1816 | if (priv->fw_var >= 0x500) | ||
1817 | p54_set_freq(dev, dev->conf.channel->center_freq); | ||
1818 | } | ||
1819 | if (changed & BSS_CHANGED_ASSOC) { | ||
1820 | if (info->assoc) { | ||
1821 | priv->aid = info->aid; | ||
1822 | priv->wakeup_timer = info->beacon_int * | ||
1823 | info->dtim_period * 5; | ||
1824 | p54_setup_mac(dev, priv->mac_mode, priv->bssid); | ||
1825 | } | ||
1826 | } | ||
1827 | |||
1795 | } | 1828 | } |
1796 | 1829 | ||
1797 | static const struct ieee80211_ops p54_ops = { | 1830 | static const struct ieee80211_ops p54_ops = { |
@@ -1821,14 +1854,16 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
1821 | 1854 | ||
1822 | priv = dev->priv; | 1855 | priv = dev->priv; |
1823 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | 1856 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; |
1857 | priv->basic_rate_mask = 0x15f; | ||
1824 | skb_queue_head_init(&priv->tx_queue); | 1858 | skb_queue_head_init(&priv->tx_queue); |
1825 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 1859 | dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
1826 | IEEE80211_HW_SIGNAL_DBM | | 1860 | IEEE80211_HW_SIGNAL_DBM | |
1827 | IEEE80211_HW_NOISE_DBM; | 1861 | IEEE80211_HW_NOISE_DBM; |
1828 | 1862 | ||
1829 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION | | 1863 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1830 | NL80211_IFTYPE_ADHOC | | 1864 | BIT(NL80211_IFTYPE_ADHOC) | |
1831 | NL80211_IFTYPE_AP); | 1865 | BIT(NL80211_IFTYPE_AP) | |
1866 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
1832 | 1867 | ||
1833 | dev->channel_change_time = 1000; /* TODO: find actual value */ | 1868 | dev->channel_change_time = 1000; /* TODO: find actual value */ |
1834 | priv->tx_stats[0].limit = 1; /* Beacon queue */ | 1869 | priv->tx_stats[0].limit = 1; /* Beacon queue */ |
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 8c8793cb2d79..3419f16be938 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h | |||
@@ -259,7 +259,7 @@ enum p54_rx_decrypt_status { | |||
259 | P54_DECRYPT_NOCKIPMIC, | 259 | P54_DECRYPT_NOCKIPMIC, |
260 | P54_DECRYPT_FAIL_WEP, | 260 | P54_DECRYPT_FAIL_WEP, |
261 | P54_DECRYPT_FAIL_TKIP, | 261 | P54_DECRYPT_FAIL_TKIP, |
262 | P54_DECRYPT_FAIL_MICAHEL, | 262 | P54_DECRYPT_FAIL_MICHAEL, |
263 | P54_DECRYPT_FAIL_CKIPKP, | 263 | P54_DECRYPT_FAIL_CKIPKP, |
264 | P54_DECRYPT_FAIL_CKIPMIC, | 264 | P54_DECRYPT_FAIL_CKIPMIC, |
265 | P54_DECRYPT_FAIL_AESCCMP | 265 | P54_DECRYPT_FAIL_AESCCMP |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index c4a868ae6d6b..d21c509325fe 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(pci, p54p_table); | |||
47 | static int p54p_upload_firmware(struct ieee80211_hw *dev) | 47 | static int p54p_upload_firmware(struct ieee80211_hw *dev) |
48 | { | 48 | { |
49 | struct p54p_priv *priv = dev->priv; | 49 | struct p54p_priv *priv = dev->priv; |
50 | const struct firmware *fw_entry = NULL; | ||
51 | __le32 reg; | 50 | __le32 reg; |
52 | int err; | 51 | int err; |
53 | __le32 *data; | 52 | __le32 *data; |
@@ -73,23 +72,15 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev) | |||
73 | P54P_WRITE(ctrl_stat, reg); | 72 | P54P_WRITE(ctrl_stat, reg); |
74 | wmb(); | 73 | wmb(); |
75 | 74 | ||
76 | err = request_firmware(&fw_entry, "isl3886pci", &priv->pdev->dev); | 75 | /* wait for the firmware to reset properly */ |
77 | if (err) { | 76 | mdelay(10); |
78 | printk(KERN_ERR "%s (p54pci): cannot find firmware " | ||
79 | "(isl3886pci)\n", pci_name(priv->pdev)); | ||
80 | err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev); | ||
81 | if (err) | ||
82 | return err; | ||
83 | } | ||
84 | 77 | ||
85 | err = p54_parse_firmware(dev, fw_entry); | 78 | err = p54_parse_firmware(dev, priv->firmware); |
86 | if (err) { | 79 | if (err) |
87 | release_firmware(fw_entry); | ||
88 | return err; | 80 | return err; |
89 | } | ||
90 | 81 | ||
91 | data = (__le32 *) fw_entry->data; | 82 | data = (__le32 *) priv->firmware->data; |
92 | remains = fw_entry->size; | 83 | remains = priv->firmware->size; |
93 | device_addr = ISL38XX_DEV_FIRMWARE_ADDR; | 84 | device_addr = ISL38XX_DEV_FIRMWARE_ADDR; |
94 | while (remains) { | 85 | while (remains) { |
95 | u32 i = 0; | 86 | u32 i = 0; |
@@ -107,8 +98,6 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev) | |||
107 | P54P_READ(int_enable); | 98 | P54P_READ(int_enable); |
108 | } | 99 | } |
109 | 100 | ||
110 | release_firmware(fw_entry); | ||
111 | |||
112 | reg = P54P_READ(ctrl_stat); | 101 | reg = P54P_READ(ctrl_stat); |
113 | reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); | 102 | reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); |
114 | reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); | 103 | reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); |
@@ -500,15 +489,14 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
500 | if (mem_len < sizeof(struct p54p_csr)) { | 489 | if (mem_len < sizeof(struct p54p_csr)) { |
501 | printk(KERN_ERR "%s (p54pci): Too short PCI resources\n", | 490 | printk(KERN_ERR "%s (p54pci): Too short PCI resources\n", |
502 | pci_name(pdev)); | 491 | pci_name(pdev)); |
503 | pci_disable_device(pdev); | 492 | goto err_disable_dev; |
504 | return err; | ||
505 | } | 493 | } |
506 | 494 | ||
507 | err = pci_request_regions(pdev, "p54pci"); | 495 | err = pci_request_regions(pdev, "p54pci"); |
508 | if (err) { | 496 | if (err) { |
509 | printk(KERN_ERR "%s (p54pci): Cannot obtain PCI resources\n", | 497 | printk(KERN_ERR "%s (p54pci): Cannot obtain PCI resources\n", |
510 | pci_name(pdev)); | 498 | pci_name(pdev)); |
511 | return err; | 499 | goto err_disable_dev; |
512 | } | 500 | } |
513 | 501 | ||
514 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || | 502 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || |
@@ -561,6 +549,17 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
561 | spin_lock_init(&priv->lock); | 549 | spin_lock_init(&priv->lock); |
562 | tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); | 550 | tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); |
563 | 551 | ||
552 | err = request_firmware(&priv->firmware, "isl3886pci", | ||
553 | &priv->pdev->dev); | ||
554 | if (err) { | ||
555 | printk(KERN_ERR "%s (p54pci): cannot find firmware " | ||
556 | "(isl3886pci)\n", pci_name(priv->pdev)); | ||
557 | err = request_firmware(&priv->firmware, "isl3886", | ||
558 | &priv->pdev->dev); | ||
559 | if (err) | ||
560 | goto err_free_common; | ||
561 | } | ||
562 | |||
564 | err = p54p_open(dev); | 563 | err = p54p_open(dev); |
565 | if (err) | 564 | if (err) |
566 | goto err_free_common; | 565 | goto err_free_common; |
@@ -579,6 +578,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
579 | return 0; | 578 | return 0; |
580 | 579 | ||
581 | err_free_common: | 580 | err_free_common: |
581 | release_firmware(priv->firmware); | ||
582 | p54_free_common(dev); | 582 | p54_free_common(dev); |
583 | pci_free_consistent(pdev, sizeof(*priv->ring_control), | 583 | pci_free_consistent(pdev, sizeof(*priv->ring_control), |
584 | priv->ring_control, priv->ring_control_dma); | 584 | priv->ring_control, priv->ring_control_dma); |
@@ -592,6 +592,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev, | |||
592 | 592 | ||
593 | err_free_reg: | 593 | err_free_reg: |
594 | pci_release_regions(pdev); | 594 | pci_release_regions(pdev); |
595 | err_disable_dev: | ||
595 | pci_disable_device(pdev); | 596 | pci_disable_device(pdev); |
596 | return err; | 597 | return err; |
597 | } | 598 | } |
@@ -606,6 +607,7 @@ static void __devexit p54p_remove(struct pci_dev *pdev) | |||
606 | 607 | ||
607 | ieee80211_unregister_hw(dev); | 608 | ieee80211_unregister_hw(dev); |
608 | priv = dev->priv; | 609 | priv = dev->priv; |
610 | release_firmware(priv->firmware); | ||
609 | pci_free_consistent(pdev, sizeof(*priv->ring_control), | 611 | pci_free_consistent(pdev, sizeof(*priv->ring_control), |
610 | priv->ring_control, priv->ring_control_dma); | 612 | priv->ring_control, priv->ring_control_dma); |
611 | p54_free_common(dev); | 613 | p54_free_common(dev); |
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h index 4a6778070afc..fbb683953fb2 100644 --- a/drivers/net/wireless/p54/p54pci.h +++ b/drivers/net/wireless/p54/p54pci.h | |||
@@ -93,7 +93,7 @@ struct p54p_priv { | |||
93 | struct pci_dev *pdev; | 93 | struct pci_dev *pdev; |
94 | struct p54p_csr __iomem *map; | 94 | struct p54p_csr __iomem *map; |
95 | struct tasklet_struct rx_tasklet; | 95 | struct tasklet_struct rx_tasklet; |
96 | 96 | const struct firmware *firmware; | |
97 | spinlock_t lock; | 97 | spinlock_t lock; |
98 | struct p54p_ring_control *ring_control; | 98 | struct p54p_ring_control *ring_control; |
99 | dma_addr_t ring_control_dma; | 99 | dma_addr_t ring_control_dma; |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 78fca1bcc544..6a977679124d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -49,20 +49,10 @@ | |||
49 | * the access attempt is considered to have failed, | 49 | * the access attempt is considered to have failed, |
50 | * and we will print an error. | 50 | * and we will print an error. |
51 | */ | 51 | */ |
52 | static u32 rt2400pci_bbp_check(struct rt2x00_dev *rt2x00dev) | 52 | #define WAIT_FOR_BBP(__dev, __reg) \ |
53 | { | 53 | rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) |
54 | u32 reg; | 54 | #define WAIT_FOR_RF(__dev, __reg) \ |
55 | unsigned int i; | 55 | rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) |
56 | |||
57 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
58 | rt2x00pci_register_read(rt2x00dev, BBPCSR, ®); | ||
59 | if (!rt2x00_get_field32(reg, BBPCSR_BUSY)) | ||
60 | break; | ||
61 | udelay(REGISTER_BUSY_DELAY); | ||
62 | } | ||
63 | |||
64 | return reg; | ||
65 | } | ||
66 | 56 | ||
67 | static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, | 57 | static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, |
68 | const unsigned int word, const u8 value) | 58 | const unsigned int word, const u8 value) |
@@ -72,31 +62,20 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
72 | mutex_lock(&rt2x00dev->csr_mutex); | 62 | mutex_lock(&rt2x00dev->csr_mutex); |
73 | 63 | ||
74 | /* | 64 | /* |
75 | * Wait until the BBP becomes ready. | 65 | * Wait until the BBP becomes available, afterwards we |
66 | * can safely write the new data into the register. | ||
76 | */ | 67 | */ |
77 | reg = rt2400pci_bbp_check(rt2x00dev); | 68 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
78 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) | 69 | reg = 0; |
79 | goto exit_fail; | 70 | rt2x00_set_field32(®, BBPCSR_VALUE, value); |
80 | 71 | rt2x00_set_field32(®, BBPCSR_REGNUM, word); | |
81 | /* | 72 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); |
82 | * Write the data into the BBP. | 73 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); |
83 | */ | 74 | |
84 | reg = 0; | 75 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); |
85 | rt2x00_set_field32(®, BBPCSR_VALUE, value); | 76 | } |
86 | rt2x00_set_field32(®, BBPCSR_REGNUM, word); | ||
87 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | ||
88 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); | ||
89 | |||
90 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | ||
91 | |||
92 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
93 | |||
94 | return; | ||
95 | 77 | ||
96 | exit_fail: | ||
97 | mutex_unlock(&rt2x00dev->csr_mutex); | 78 | mutex_unlock(&rt2x00dev->csr_mutex); |
98 | |||
99 | ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n"); | ||
100 | } | 79 | } |
101 | 80 | ||
102 | static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, | 81 | static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -107,75 +86,55 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
107 | mutex_lock(&rt2x00dev->csr_mutex); | 86 | mutex_lock(&rt2x00dev->csr_mutex); |
108 | 87 | ||
109 | /* | 88 | /* |
110 | * Wait until the BBP becomes ready. | 89 | * Wait until the BBP becomes available, afterwards we |
90 | * can safely write the read request into the register. | ||
91 | * After the data has been written, we wait until hardware | ||
92 | * returns the correct value, if at any time the register | ||
93 | * doesn't become available in time, reg will be 0xffffffff | ||
94 | * which means we return 0xff to the caller. | ||
111 | */ | 95 | */ |
112 | reg = rt2400pci_bbp_check(rt2x00dev); | 96 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
113 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) | 97 | reg = 0; |
114 | goto exit_fail; | 98 | rt2x00_set_field32(®, BBPCSR_REGNUM, word); |
99 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | ||
100 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); | ||
115 | 101 | ||
116 | /* | 102 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); |
117 | * Write the request into the BBP. | ||
118 | */ | ||
119 | reg = 0; | ||
120 | rt2x00_set_field32(®, BBPCSR_REGNUM, word); | ||
121 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | ||
122 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); | ||
123 | 103 | ||
124 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | 104 | WAIT_FOR_BBP(rt2x00dev, ®); |
125 | 105 | } | |
126 | /* | ||
127 | * Wait until the BBP becomes ready. | ||
128 | */ | ||
129 | reg = rt2400pci_bbp_check(rt2x00dev); | ||
130 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) | ||
131 | goto exit_fail; | ||
132 | 106 | ||
133 | *value = rt2x00_get_field32(reg, BBPCSR_VALUE); | 107 | *value = rt2x00_get_field32(reg, BBPCSR_VALUE); |
134 | 108 | ||
135 | mutex_unlock(&rt2x00dev->csr_mutex); | 109 | mutex_unlock(&rt2x00dev->csr_mutex); |
136 | |||
137 | return; | ||
138 | |||
139 | exit_fail: | ||
140 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
141 | |||
142 | ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); | ||
143 | *value = 0xff; | ||
144 | } | 110 | } |
145 | 111 | ||
146 | static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, | 112 | static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, |
147 | const unsigned int word, const u32 value) | 113 | const unsigned int word, const u32 value) |
148 | { | 114 | { |
149 | u32 reg; | 115 | u32 reg; |
150 | unsigned int i; | ||
151 | 116 | ||
152 | if (!word) | 117 | if (!word) |
153 | return; | 118 | return; |
154 | 119 | ||
155 | mutex_lock(&rt2x00dev->csr_mutex); | 120 | mutex_lock(&rt2x00dev->csr_mutex); |
156 | 121 | ||
157 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 122 | /* |
158 | rt2x00pci_register_read(rt2x00dev, RFCSR, ®); | 123 | * Wait until the RF becomes available, afterwards we |
159 | if (!rt2x00_get_field32(reg, RFCSR_BUSY)) | 124 | * can safely write the new data into the register. |
160 | goto rf_write; | 125 | */ |
161 | udelay(REGISTER_BUSY_DELAY); | 126 | if (WAIT_FOR_RF(rt2x00dev, ®)) { |
127 | reg = 0; | ||
128 | rt2x00_set_field32(®, RFCSR_VALUE, value); | ||
129 | rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); | ||
130 | rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); | ||
131 | rt2x00_set_field32(®, RFCSR_BUSY, 1); | ||
132 | |||
133 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); | ||
134 | rt2x00_rf_write(rt2x00dev, word, value); | ||
162 | } | 135 | } |
163 | 136 | ||
164 | mutex_unlock(&rt2x00dev->csr_mutex); | 137 | mutex_unlock(&rt2x00dev->csr_mutex); |
165 | ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n"); | ||
166 | return; | ||
167 | |||
168 | rf_write: | ||
169 | reg = 0; | ||
170 | rt2x00_set_field32(®, RFCSR_VALUE, value); | ||
171 | rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); | ||
172 | rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); | ||
173 | rt2x00_set_field32(®, RFCSR_BUSY, 1); | ||
174 | |||
175 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); | ||
176 | rt2x00_rf_write(rt2x00dev, word, value); | ||
177 | |||
178 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
179 | } | 138 | } |
180 | 139 | ||
181 | static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 140 | static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 972b5a5c3864..d3bc218ec85c 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -49,20 +49,10 @@ | |||
49 | * the access attempt is considered to have failed, | 49 | * the access attempt is considered to have failed, |
50 | * and we will print an error. | 50 | * and we will print an error. |
51 | */ | 51 | */ |
52 | static u32 rt2500pci_bbp_check(struct rt2x00_dev *rt2x00dev) | 52 | #define WAIT_FOR_BBP(__dev, __reg) \ |
53 | { | 53 | rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) |
54 | u32 reg; | 54 | #define WAIT_FOR_RF(__dev, __reg) \ |
55 | unsigned int i; | 55 | rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) |
56 | |||
57 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
58 | rt2x00pci_register_read(rt2x00dev, BBPCSR, ®); | ||
59 | if (!rt2x00_get_field32(reg, BBPCSR_BUSY)) | ||
60 | break; | ||
61 | udelay(REGISTER_BUSY_DELAY); | ||
62 | } | ||
63 | |||
64 | return reg; | ||
65 | } | ||
66 | 56 | ||
67 | static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, | 57 | static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, |
68 | const unsigned int word, const u8 value) | 58 | const unsigned int word, const u8 value) |
@@ -72,31 +62,20 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
72 | mutex_lock(&rt2x00dev->csr_mutex); | 62 | mutex_lock(&rt2x00dev->csr_mutex); |
73 | 63 | ||
74 | /* | 64 | /* |
75 | * Wait until the BBP becomes ready. | 65 | * Wait until the BBP becomes available, afterwards we |
66 | * can safely write the new data into the register. | ||
76 | */ | 67 | */ |
77 | reg = rt2500pci_bbp_check(rt2x00dev); | 68 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
78 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) | 69 | reg = 0; |
79 | goto exit_fail; | 70 | rt2x00_set_field32(®, BBPCSR_VALUE, value); |
80 | 71 | rt2x00_set_field32(®, BBPCSR_REGNUM, word); | |
81 | /* | 72 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); |
82 | * Write the data into the BBP. | 73 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); |
83 | */ | 74 | |
84 | reg = 0; | 75 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); |
85 | rt2x00_set_field32(®, BBPCSR_VALUE, value); | 76 | } |
86 | rt2x00_set_field32(®, BBPCSR_REGNUM, word); | ||
87 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | ||
88 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); | ||
89 | |||
90 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | ||
91 | |||
92 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
93 | |||
94 | return; | ||
95 | 77 | ||
96 | exit_fail: | ||
97 | mutex_unlock(&rt2x00dev->csr_mutex); | 78 | mutex_unlock(&rt2x00dev->csr_mutex); |
98 | |||
99 | ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n"); | ||
100 | } | 79 | } |
101 | 80 | ||
102 | static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, | 81 | static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -107,75 +86,55 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
107 | mutex_lock(&rt2x00dev->csr_mutex); | 86 | mutex_lock(&rt2x00dev->csr_mutex); |
108 | 87 | ||
109 | /* | 88 | /* |
110 | * Wait until the BBP becomes ready. | 89 | * Wait until the BBP becomes available, afterwards we |
90 | * can safely write the read request into the register. | ||
91 | * After the data has been written, we wait until hardware | ||
92 | * returns the correct value, if at any time the register | ||
93 | * doesn't become available in time, reg will be 0xffffffff | ||
94 | * which means we return 0xff to the caller. | ||
111 | */ | 95 | */ |
112 | reg = rt2500pci_bbp_check(rt2x00dev); | 96 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
113 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) | 97 | reg = 0; |
114 | goto exit_fail; | 98 | rt2x00_set_field32(®, BBPCSR_REGNUM, word); |
99 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | ||
100 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); | ||
115 | 101 | ||
116 | /* | 102 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); |
117 | * Write the request into the BBP. | ||
118 | */ | ||
119 | reg = 0; | ||
120 | rt2x00_set_field32(®, BBPCSR_REGNUM, word); | ||
121 | rt2x00_set_field32(®, BBPCSR_BUSY, 1); | ||
122 | rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); | ||
123 | 103 | ||
124 | rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); | 104 | WAIT_FOR_BBP(rt2x00dev, ®); |
125 | 105 | } | |
126 | /* | ||
127 | * Wait until the BBP becomes ready. | ||
128 | */ | ||
129 | reg = rt2500pci_bbp_check(rt2x00dev); | ||
130 | if (rt2x00_get_field32(reg, BBPCSR_BUSY)) | ||
131 | goto exit_fail; | ||
132 | 106 | ||
133 | *value = rt2x00_get_field32(reg, BBPCSR_VALUE); | 107 | *value = rt2x00_get_field32(reg, BBPCSR_VALUE); |
134 | 108 | ||
135 | mutex_unlock(&rt2x00dev->csr_mutex); | 109 | mutex_unlock(&rt2x00dev->csr_mutex); |
136 | |||
137 | return; | ||
138 | |||
139 | exit_fail: | ||
140 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
141 | |||
142 | ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n"); | ||
143 | *value = 0xff; | ||
144 | } | 110 | } |
145 | 111 | ||
146 | static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, | 112 | static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, |
147 | const unsigned int word, const u32 value) | 113 | const unsigned int word, const u32 value) |
148 | { | 114 | { |
149 | u32 reg; | 115 | u32 reg; |
150 | unsigned int i; | ||
151 | 116 | ||
152 | if (!word) | 117 | if (!word) |
153 | return; | 118 | return; |
154 | 119 | ||
155 | mutex_lock(&rt2x00dev->csr_mutex); | 120 | mutex_lock(&rt2x00dev->csr_mutex); |
156 | 121 | ||
157 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 122 | /* |
158 | rt2x00pci_register_read(rt2x00dev, RFCSR, ®); | 123 | * Wait until the RF becomes available, afterwards we |
159 | if (!rt2x00_get_field32(reg, RFCSR_BUSY)) | 124 | * can safely write the new data into the register. |
160 | goto rf_write; | 125 | */ |
161 | udelay(REGISTER_BUSY_DELAY); | 126 | if (WAIT_FOR_RF(rt2x00dev, ®)) { |
127 | reg = 0; | ||
128 | rt2x00_set_field32(®, RFCSR_VALUE, value); | ||
129 | rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); | ||
130 | rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); | ||
131 | rt2x00_set_field32(®, RFCSR_BUSY, 1); | ||
132 | |||
133 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); | ||
134 | rt2x00_rf_write(rt2x00dev, word, value); | ||
162 | } | 135 | } |
163 | 136 | ||
164 | mutex_unlock(&rt2x00dev->csr_mutex); | 137 | mutex_unlock(&rt2x00dev->csr_mutex); |
165 | ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n"); | ||
166 | return; | ||
167 | |||
168 | rf_write: | ||
169 | reg = 0; | ||
170 | rt2x00_set_field32(®, RFCSR_VALUE, value); | ||
171 | rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); | ||
172 | rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); | ||
173 | rt2x00_set_field32(®, RFCSR_BUSY, 1); | ||
174 | |||
175 | rt2x00pci_register_write(rt2x00dev, RFCSR, reg); | ||
176 | rt2x00_rf_write(rt2x00dev, word, value); | ||
177 | |||
178 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
179 | } | 138 | } |
180 | 139 | ||
181 | static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 140 | static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index e6bae4ae4c47..0447e93306ad 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -57,7 +57,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, | |||
57 | __le16 reg; | 57 | __le16 reg; |
58 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | 58 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, |
59 | USB_VENDOR_REQUEST_IN, offset, | 59 | USB_VENDOR_REQUEST_IN, offset, |
60 | ®, sizeof(u16), REGISTER_TIMEOUT); | 60 | ®, sizeof(reg), REGISTER_TIMEOUT); |
61 | *value = le16_to_cpu(reg); | 61 | *value = le16_to_cpu(reg); |
62 | } | 62 | } |
63 | 63 | ||
@@ -68,7 +68,7 @@ static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev, | |||
68 | __le16 reg; | 68 | __le16 reg; |
69 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, | 69 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, |
70 | USB_VENDOR_REQUEST_IN, offset, | 70 | USB_VENDOR_REQUEST_IN, offset, |
71 | ®, sizeof(u16), REGISTER_TIMEOUT); | 71 | ®, sizeof(reg), REGISTER_TIMEOUT); |
72 | *value = le16_to_cpu(reg); | 72 | *value = le16_to_cpu(reg); |
73 | } | 73 | } |
74 | 74 | ||
@@ -89,7 +89,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, | |||
89 | __le16 reg = cpu_to_le16(value); | 89 | __le16 reg = cpu_to_le16(value); |
90 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | 90 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, |
91 | USB_VENDOR_REQUEST_OUT, offset, | 91 | USB_VENDOR_REQUEST_OUT, offset, |
92 | ®, sizeof(u16), REGISTER_TIMEOUT); | 92 | ®, sizeof(reg), REGISTER_TIMEOUT); |
93 | } | 93 | } |
94 | 94 | ||
95 | static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, | 95 | static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, |
@@ -99,7 +99,7 @@ static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, | |||
99 | __le16 reg = cpu_to_le16(value); | 99 | __le16 reg = cpu_to_le16(value); |
100 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, | 100 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, |
101 | USB_VENDOR_REQUEST_OUT, offset, | 101 | USB_VENDOR_REQUEST_OUT, offset, |
102 | ®, sizeof(u16), REGISTER_TIMEOUT); | 102 | ®, sizeof(reg), REGISTER_TIMEOUT); |
103 | } | 103 | } |
104 | 104 | ||
105 | static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | 105 | static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, |
@@ -112,21 +112,32 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | |||
112 | REGISTER_TIMEOUT16(length)); | 112 | REGISTER_TIMEOUT16(length)); |
113 | } | 113 | } |
114 | 114 | ||
115 | static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev) | 115 | static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, |
116 | const unsigned int offset, | ||
117 | struct rt2x00_field16 field, | ||
118 | u16 *reg) | ||
116 | { | 119 | { |
117 | u16 reg; | ||
118 | unsigned int i; | 120 | unsigned int i; |
119 | 121 | ||
120 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 122 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
121 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, ®); | 123 | rt2500usb_register_read_lock(rt2x00dev, offset, reg); |
122 | if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY)) | 124 | if (!rt2x00_get_field16(*reg, field)) |
123 | break; | 125 | return 1; |
124 | udelay(REGISTER_BUSY_DELAY); | 126 | udelay(REGISTER_BUSY_DELAY); |
125 | } | 127 | } |
126 | 128 | ||
127 | return reg; | 129 | ERROR(rt2x00dev, "Indirect register access failed: " |
130 | "offset=0x%.08x, value=0x%.08x\n", offset, *reg); | ||
131 | *reg = ~0; | ||
132 | |||
133 | return 0; | ||
128 | } | 134 | } |
129 | 135 | ||
136 | #define WAIT_FOR_BBP(__dev, __reg) \ | ||
137 | rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg)) | ||
138 | #define WAIT_FOR_RF(__dev, __reg) \ | ||
139 | rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg)) | ||
140 | |||
130 | static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, | 141 | static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, |
131 | const unsigned int word, const u8 value) | 142 | const unsigned int word, const u8 value) |
132 | { | 143 | { |
@@ -135,30 +146,19 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
135 | mutex_lock(&rt2x00dev->csr_mutex); | 146 | mutex_lock(&rt2x00dev->csr_mutex); |
136 | 147 | ||
137 | /* | 148 | /* |
138 | * Wait until the BBP becomes ready. | 149 | * Wait until the BBP becomes available, afterwards we |
139 | */ | 150 | * can safely write the new data into the register. |
140 | reg = rt2500usb_bbp_check(rt2x00dev); | ||
141 | if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) | ||
142 | goto exit_fail; | ||
143 | |||
144 | /* | ||
145 | * Write the data into the BBP. | ||
146 | */ | 151 | */ |
147 | reg = 0; | 152 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
148 | rt2x00_set_field16(®, PHY_CSR7_DATA, value); | 153 | reg = 0; |
149 | rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); | 154 | rt2x00_set_field16(®, PHY_CSR7_DATA, value); |
150 | rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); | 155 | rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); |
151 | 156 | rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); | |
152 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); | ||
153 | |||
154 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
155 | 157 | ||
156 | return; | 158 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); |
159 | } | ||
157 | 160 | ||
158 | exit_fail: | ||
159 | mutex_unlock(&rt2x00dev->csr_mutex); | 161 | mutex_unlock(&rt2x00dev->csr_mutex); |
160 | |||
161 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); | ||
162 | } | 162 | } |
163 | 163 | ||
164 | static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, | 164 | static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -169,77 +169,57 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
169 | mutex_lock(&rt2x00dev->csr_mutex); | 169 | mutex_lock(&rt2x00dev->csr_mutex); |
170 | 170 | ||
171 | /* | 171 | /* |
172 | * Wait until the BBP becomes ready. | 172 | * Wait until the BBP becomes available, afterwards we |
173 | */ | 173 | * can safely write the read request into the register. |
174 | reg = rt2500usb_bbp_check(rt2x00dev); | 174 | * After the data has been written, we wait until hardware |
175 | if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) | 175 | * returns the correct value, if at any time the register |
176 | goto exit_fail; | 176 | * doesn't become available in time, reg will be 0xffffffff |
177 | 177 | * which means we return 0xff to the caller. | |
178 | /* | ||
179 | * Write the request into the BBP. | ||
180 | */ | 178 | */ |
181 | reg = 0; | 179 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
182 | rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); | 180 | reg = 0; |
183 | rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); | 181 | rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); |
182 | rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); | ||
184 | 183 | ||
185 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); | 184 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); |
186 | 185 | ||
187 | /* | 186 | if (WAIT_FOR_BBP(rt2x00dev, ®)) |
188 | * Wait until the BBP becomes ready. | 187 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); |
189 | */ | 188 | } |
190 | reg = rt2500usb_bbp_check(rt2x00dev); | ||
191 | if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) | ||
192 | goto exit_fail; | ||
193 | 189 | ||
194 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); | ||
195 | *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); | 190 | *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); |
196 | 191 | ||
197 | mutex_unlock(&rt2x00dev->csr_mutex); | 192 | mutex_unlock(&rt2x00dev->csr_mutex); |
198 | |||
199 | return; | ||
200 | |||
201 | exit_fail: | ||
202 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
203 | |||
204 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); | ||
205 | *value = 0xff; | ||
206 | } | 193 | } |
207 | 194 | ||
208 | static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, | 195 | static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, |
209 | const unsigned int word, const u32 value) | 196 | const unsigned int word, const u32 value) |
210 | { | 197 | { |
211 | u16 reg; | 198 | u16 reg; |
212 | unsigned int i; | ||
213 | 199 | ||
214 | if (!word) | 200 | if (!word) |
215 | return; | 201 | return; |
216 | 202 | ||
217 | mutex_lock(&rt2x00dev->csr_mutex); | 203 | mutex_lock(&rt2x00dev->csr_mutex); |
218 | 204 | ||
219 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 205 | /* |
220 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®); | 206 | * Wait until the RF becomes available, afterwards we |
221 | if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY)) | 207 | * can safely write the new data into the register. |
222 | goto rf_write; | 208 | */ |
223 | udelay(REGISTER_BUSY_DELAY); | 209 | if (WAIT_FOR_RF(rt2x00dev, ®)) { |
224 | } | 210 | reg = 0; |
225 | 211 | rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); | |
226 | mutex_unlock(&rt2x00dev->csr_mutex); | 212 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); |
227 | ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); | ||
228 | return; | ||
229 | |||
230 | rf_write: | ||
231 | reg = 0; | ||
232 | rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); | ||
233 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); | ||
234 | 213 | ||
235 | reg = 0; | 214 | reg = 0; |
236 | rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); | 215 | rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); |
237 | rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); | 216 | rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); |
238 | rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); | 217 | rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); |
239 | rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); | 218 | rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); |
240 | 219 | ||
241 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); | 220 | rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); |
242 | rt2x00_rf_write(rt2x00dev, word, value); | 221 | rt2x00_rf_write(rt2x00dev, word, value); |
222 | } | ||
243 | 223 | ||
244 | mutex_unlock(&rt2x00dev->csr_mutex); | 224 | mutex_unlock(&rt2x00dev->csr_mutex); |
245 | } | 225 | } |
@@ -1128,7 +1108,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) | |||
1128 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); | 1108 | struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); |
1129 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; | 1109 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; |
1130 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 1110 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
1131 | int pipe = usb_sndbulkpipe(usb_dev, 1); | 1111 | int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint); |
1132 | int length; | 1112 | int length; |
1133 | u16 reg; | 1113 | u16 reg; |
1134 | 1114 | ||
@@ -1154,7 +1134,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) | |||
1154 | * length of the data to usb_fill_bulk_urb. Pass the skb | 1134 | * length of the data to usb_fill_bulk_urb. Pass the skb |
1155 | * to the driver to determine what the length should be. | 1135 | * to the driver to determine what the length should be. |
1156 | */ | 1136 | */ |
1157 | length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); | 1137 | length = rt2x00dev->ops->lib->get_tx_data_len(entry); |
1158 | 1138 | ||
1159 | usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, | 1139 | usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, |
1160 | entry->skb->data, length, rt2500usb_beacondone, | 1140 | entry->skb->data, length, rt2500usb_beacondone, |
@@ -1176,8 +1156,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) | |||
1176 | usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); | 1156 | usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); |
1177 | } | 1157 | } |
1178 | 1158 | ||
1179 | static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | 1159 | static int rt2500usb_get_tx_data_len(struct queue_entry *entry) |
1180 | struct sk_buff *skb) | ||
1181 | { | 1160 | { |
1182 | int length; | 1161 | int length; |
1183 | 1162 | ||
@@ -1185,8 +1164,8 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | |||
1185 | * The length _must_ be a multiple of 2, | 1164 | * The length _must_ be a multiple of 2, |
1186 | * but it must _not_ be a multiple of the USB packet size. | 1165 | * but it must _not_ be a multiple of the USB packet size. |
1187 | */ | 1166 | */ |
1188 | length = roundup(skb->len, 2); | 1167 | length = roundup(entry->skb->len, 2); |
1189 | length += (2 * !(length % rt2x00dev->usb_maxpacket)); | 1168 | length += (2 * !(length % entry->queue->usb_maxpacket)); |
1190 | 1169 | ||
1191 | return length; | 1170 | return length; |
1192 | } | 1171 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index fee61bee1e7e..780ba7365810 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -555,8 +555,7 @@ struct rt2x00lib_ops { | |||
555 | struct txentry_desc *txdesc); | 555 | struct txentry_desc *txdesc); |
556 | int (*write_tx_data) (struct queue_entry *entry); | 556 | int (*write_tx_data) (struct queue_entry *entry); |
557 | void (*write_beacon) (struct queue_entry *entry); | 557 | void (*write_beacon) (struct queue_entry *entry); |
558 | int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, | 558 | int (*get_tx_data_len) (struct queue_entry *entry); |
559 | struct sk_buff *skb); | ||
560 | void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, | 559 | void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, |
561 | const enum data_queue_qid queue); | 560 | const enum data_queue_qid queue); |
562 | 561 | ||
@@ -799,11 +798,6 @@ struct rt2x00_dev { | |||
799 | short lna_gain; | 798 | short lna_gain; |
800 | 799 | ||
801 | /* | 800 | /* |
802 | * USB Max frame size (for rt2500usb & rt73usb). | ||
803 | */ | ||
804 | u16 usb_maxpacket; | ||
805 | |||
806 | /* | ||
807 | * Current TX power value. | 801 | * Current TX power value. |
808 | */ | 802 | */ |
809 | u16 tx_power; | 803 | u16 tx_power; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index 66c61b1eca5d..68f4e0fc35b9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c | |||
@@ -111,12 +111,6 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, | |||
111 | led->led_dev.name = name; | 111 | led->led_dev.name = name; |
112 | led->led_dev.brightness = LED_OFF; | 112 | led->led_dev.brightness = LED_OFF; |
113 | 113 | ||
114 | /* | ||
115 | * Ensure the LED is off, it might have been enabled | ||
116 | * by the hardware when the device was powered on. | ||
117 | */ | ||
118 | led->led_dev.brightness_set(&led->led_dev, LED_OFF); | ||
119 | |||
120 | retval = led_classdev_register(device, &led->led_dev); | 114 | retval = led_classdev_register(device, &led->led_dev); |
121 | if (retval) { | 115 | if (retval) { |
122 | ERROR(rt2x00dev, "Failed to register led handler.\n"); | 116 | ERROR(rt2x00dev, "Failed to register led handler.\n"); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 48636b0dd895..4c0395729066 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -132,8 +132,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
132 | ERROR(rt2x00dev, | 132 | ERROR(rt2x00dev, |
133 | "Attempt to send packet over invalid queue %d.\n" | 133 | "Attempt to send packet over invalid queue %d.\n" |
134 | "Please file bug report to %s.\n", qid, DRV_PROJECT); | 134 | "Please file bug report to %s.\n", qid, DRV_PROJECT); |
135 | dev_kfree_skb_any(skb); | 135 | goto exit_fail; |
136 | return NETDEV_TX_OK; | ||
137 | } | 136 | } |
138 | 137 | ||
139 | /* | 138 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index e33bd0f150c5..d52b22b82d1f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -32,6 +32,31 @@ | |||
32 | #include "rt2x00pci.h" | 32 | #include "rt2x00pci.h" |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * Register access. | ||
36 | */ | ||
37 | int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
38 | const unsigned int offset, | ||
39 | const struct rt2x00_field32 field, | ||
40 | u32 *reg) | ||
41 | { | ||
42 | unsigned int i; | ||
43 | |||
44 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
45 | rt2x00pci_register_read(rt2x00dev, offset, reg); | ||
46 | if (!rt2x00_get_field32(*reg, field)) | ||
47 | return 1; | ||
48 | udelay(REGISTER_BUSY_DELAY); | ||
49 | } | ||
50 | |||
51 | ERROR(rt2x00dev, "Indirect register access failed: " | ||
52 | "offset=0x%.08x, value=0x%.08x\n", offset, *reg); | ||
53 | *reg = ~0; | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); | ||
58 | |||
59 | /* | ||
35 | * TX data handlers. | 60 | * TX data handlers. |
36 | */ | 61 | */ |
37 | int rt2x00pci_write_tx_data(struct queue_entry *entry) | 62 | int rt2x00pci_write_tx_data(struct queue_entry *entry) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 96a2082a3532..9c0a4d77bc1b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h | |||
@@ -77,6 +77,24 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, | |||
77 | } | 77 | } |
78 | 78 | ||
79 | /** | 79 | /** |
80 | * rt2x00pci_regbusy_read - Read from register with busy check | ||
81 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
82 | * @offset: Register offset | ||
83 | * @field: Field to check if register is busy | ||
84 | * @reg: Pointer to where register contents should be stored | ||
85 | * | ||
86 | * This function will read the given register, and checks if the | ||
87 | * register is busy. If it is, it will sleep for a couple of | ||
88 | * microseconds before reading the register again. If the register | ||
89 | * is not read after a certain timeout, this function will return | ||
90 | * FALSE. | ||
91 | */ | ||
92 | int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
93 | const unsigned int offset, | ||
94 | const struct rt2x00_field32 field, | ||
95 | u32 *reg); | ||
96 | |||
97 | /** | ||
80 | * rt2x00pci_write_tx_data - Initialize data for TX operation | 98 | * rt2x00pci_write_tx_data - Initialize data for TX operation |
81 | * @entry: The entry where the frame is located | 99 | * @entry: The entry where the frame is located |
82 | * | 100 | * |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index d7752dbd2023..b8de9d2750e4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -386,7 +386,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
386 | u8 rate_idx, rate_flags; | 386 | u8 rate_idx, rate_flags; |
387 | 387 | ||
388 | if (unlikely(rt2x00queue_full(queue))) | 388 | if (unlikely(rt2x00queue_full(queue))) |
389 | return -EINVAL; | 389 | return -ENOBUFS; |
390 | 390 | ||
391 | if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { | 391 | if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { |
392 | ERROR(queue->rt2x00dev, | 392 | ERROR(queue->rt2x00dev, |
@@ -415,7 +415,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
415 | tx_info = IEEE80211_SKB_CB(skb); | 415 | tx_info = IEEE80211_SKB_CB(skb); |
416 | rate_idx = tx_info->control.rates[0].idx; | 416 | rate_idx = tx_info->control.rates[0].idx; |
417 | rate_flags = tx_info->control.rates[0].flags; | 417 | rate_flags = tx_info->control.rates[0].flags; |
418 | skbdesc = get_skb_frame_desc(entry->skb); | 418 | skbdesc = get_skb_frame_desc(skb); |
419 | memset(skbdesc, 0, sizeof(*skbdesc)); | 419 | memset(skbdesc, 0, sizeof(*skbdesc)); |
420 | skbdesc->entry = entry; | 420 | skbdesc->entry = entry; |
421 | skbdesc->tx_rate_idx = rate_idx; | 421 | skbdesc->tx_rate_idx = rate_idx; |
@@ -427,20 +427,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
427 | * the frame so we can provide it to the driver seperately. | 427 | * the frame so we can provide it to the driver seperately. |
428 | */ | 428 | */ |
429 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && | 429 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && |
430 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { | 430 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) |
431 | rt2x00crypto_tx_remove_iv(skb, iv_len); | 431 | rt2x00crypto_tx_remove_iv(skb, iv_len); |
432 | } | ||
433 | 432 | ||
434 | /* | 433 | /* |
435 | * It could be possible that the queue was corrupted and this | 434 | * It could be possible that the queue was corrupted and this |
436 | * call failed. Just drop the frame, we cannot rollback and pass | 435 | * call failed. Since we always return NETDEV_TX_OK to mac80211, |
437 | * the frame to mac80211 because the skb->cb has now been tainted. | 436 | * this frame will simply be dropped. |
438 | */ | 437 | */ |
439 | if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { | 438 | if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { |
440 | clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 439 | clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
441 | dev_kfree_skb_any(entry->skb); | ||
442 | entry->skb = NULL; | 440 | entry->skb = NULL; |
443 | return 0; | 441 | return -EIO; |
444 | } | 442 | } |
445 | 443 | ||
446 | if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) | 444 | if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 4d3c7246f9ae..2e99ab53ec65 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -380,6 +380,8 @@ enum queue_index { | |||
380 | * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). | 380 | * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). |
381 | * @data_size: Maximum data size for the frames in this queue. | 381 | * @data_size: Maximum data size for the frames in this queue. |
382 | * @desc_size: Hardware descriptor size for the data in this queue. | 382 | * @desc_size: Hardware descriptor size for the data in this queue. |
383 | * @usb_endpoint: Device endpoint used for communication (USB only) | ||
384 | * @usb_maxpacket: Max packet size for given endpoint (USB only) | ||
383 | */ | 385 | */ |
384 | struct data_queue { | 386 | struct data_queue { |
385 | struct rt2x00_dev *rt2x00dev; | 387 | struct rt2x00_dev *rt2x00dev; |
@@ -401,6 +403,9 @@ struct data_queue { | |||
401 | 403 | ||
402 | unsigned short data_size; | 404 | unsigned short data_size; |
403 | unsigned short desc_size; | 405 | unsigned short desc_size; |
406 | |||
407 | unsigned short usb_endpoint; | ||
408 | unsigned short usb_maxpacket; | ||
404 | }; | 409 | }; |
405 | 410 | ||
406 | /** | 411 | /** |
@@ -444,6 +449,19 @@ struct data_queue_desc { | |||
444 | &(__dev)->tx[(__dev)->ops->tx_queues] | 449 | &(__dev)->tx[(__dev)->ops->tx_queues] |
445 | 450 | ||
446 | /** | 451 | /** |
452 | * queue_next - Return pointer to next queue in list (HELPER MACRO). | ||
453 | * @__queue: Current queue for which we need the next queue | ||
454 | * | ||
455 | * Using the current queue address we take the address directly | ||
456 | * after the queue to take the next queue. Note that this macro | ||
457 | * should be used carefully since it does not protect against | ||
458 | * moving past the end of the list. (See macros &queue_end and | ||
459 | * &tx_queue_end for determining the end of the queue). | ||
460 | */ | ||
461 | #define queue_next(__queue) \ | ||
462 | &(__queue)[1] | ||
463 | |||
464 | /** | ||
447 | * queue_loop - Loop through the queues within a specific range (HELPER MACRO). | 465 | * queue_loop - Loop through the queues within a specific range (HELPER MACRO). |
448 | * @__entry: Pointer where the current queue entry will be stored in. | 466 | * @__entry: Pointer where the current queue entry will be stored in. |
449 | * @__start: Start queue pointer. | 467 | * @__start: Start queue pointer. |
@@ -453,8 +471,8 @@ struct data_queue_desc { | |||
453 | */ | 471 | */ |
454 | #define queue_loop(__entry, __start, __end) \ | 472 | #define queue_loop(__entry, __start, __end) \ |
455 | for ((__entry) = (__start); \ | 473 | for ((__entry) = (__start); \ |
456 | prefetch(&(__entry)[1]), (__entry) != (__end); \ | 474 | prefetch(queue_next(__entry)), (__entry) != (__end);\ |
457 | (__entry) = &(__entry)[1]) | 475 | (__entry) = queue_next(__entry)) |
458 | 476 | ||
459 | /** | 477 | /** |
460 | * queue_for_each - Loop through all queues | 478 | * queue_for_each - Loop through all queues |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index c507b0d9409f..83df312ac56f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -154,6 +154,28 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, | |||
154 | } | 154 | } |
155 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff); | 155 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff); |
156 | 156 | ||
157 | int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
158 | const unsigned int offset, | ||
159 | struct rt2x00_field32 field, | ||
160 | u32 *reg) | ||
161 | { | ||
162 | unsigned int i; | ||
163 | |||
164 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
165 | rt2x00usb_register_read_lock(rt2x00dev, offset, reg); | ||
166 | if (!rt2x00_get_field32(*reg, field)) | ||
167 | return 1; | ||
168 | udelay(REGISTER_BUSY_DELAY); | ||
169 | } | ||
170 | |||
171 | ERROR(rt2x00dev, "Indirect register access failed: " | ||
172 | "offset=0x%.08x, value=0x%.08x\n", offset, *reg); | ||
173 | *reg = ~0; | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); | ||
178 | |||
157 | /* | 179 | /* |
158 | * TX data handlers. | 180 | * TX data handlers. |
159 | */ | 181 | */ |
@@ -212,10 +234,10 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry) | |||
212 | * length of the data to usb_fill_bulk_urb. Pass the skb | 234 | * length of the data to usb_fill_bulk_urb. Pass the skb |
213 | * to the driver to determine what the length should be. | 235 | * to the driver to determine what the length should be. |
214 | */ | 236 | */ |
215 | length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); | 237 | length = rt2x00dev->ops->lib->get_tx_data_len(entry); |
216 | 238 | ||
217 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, | 239 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, |
218 | usb_sndbulkpipe(usb_dev, 1), | 240 | usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint), |
219 | entry->skb->data, length, | 241 | entry->skb->data, length, |
220 | rt2x00usb_interrupt_txdone, entry); | 242 | rt2x00usb_interrupt_txdone, entry); |
221 | 243 | ||
@@ -356,10 +378,11 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
356 | struct usb_device *usb_dev = | 378 | struct usb_device *usb_dev = |
357 | to_usb_device_intf(entry->queue->rt2x00dev->dev); | 379 | to_usb_device_intf(entry->queue->rt2x00dev->dev); |
358 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 380 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
381 | int pipe; | ||
359 | 382 | ||
360 | if (entry->queue->qid == QID_RX) { | 383 | if (entry->queue->qid == QID_RX) { |
361 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, | 384 | pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); |
362 | usb_rcvbulkpipe(usb_dev, 1), | 385 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, |
363 | entry->skb->data, entry->skb->len, | 386 | entry->skb->data, entry->skb->len, |
364 | rt2x00usb_interrupt_rxdone, entry); | 387 | rt2x00usb_interrupt_rxdone, entry); |
365 | 388 | ||
@@ -371,6 +394,76 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
371 | } | 394 | } |
372 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); | 395 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
373 | 396 | ||
397 | static void rt2x00usb_assign_endpoint(struct data_queue *queue, | ||
398 | struct usb_endpoint_descriptor *ep_desc) | ||
399 | { | ||
400 | struct usb_device *usb_dev = to_usb_device_intf(queue->rt2x00dev->dev); | ||
401 | int pipe; | ||
402 | |||
403 | queue->usb_endpoint = usb_endpoint_num(ep_desc); | ||
404 | |||
405 | if (queue->qid == QID_RX) { | ||
406 | pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint); | ||
407 | queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0); | ||
408 | } else { | ||
409 | pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint); | ||
410 | queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1); | ||
411 | } | ||
412 | |||
413 | if (!queue->usb_maxpacket) | ||
414 | queue->usb_maxpacket = 1; | ||
415 | } | ||
416 | |||
417 | static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev) | ||
418 | { | ||
419 | struct usb_interface *intf = to_usb_interface(rt2x00dev->dev); | ||
420 | struct usb_host_interface *intf_desc = intf->cur_altsetting; | ||
421 | struct usb_endpoint_descriptor *ep_desc; | ||
422 | struct data_queue *queue = rt2x00dev->tx; | ||
423 | struct usb_endpoint_descriptor *tx_ep_desc = NULL; | ||
424 | unsigned int i; | ||
425 | |||
426 | /* | ||
427 | * Walk through all available endpoints to search for "bulk in" | ||
428 | * and "bulk out" endpoints. When we find such endpoints collect | ||
429 | * the information we need from the descriptor and assign it | ||
430 | * to the queue. | ||
431 | */ | ||
432 | for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) { | ||
433 | ep_desc = &intf_desc->endpoint[i].desc; | ||
434 | |||
435 | if (usb_endpoint_is_bulk_in(ep_desc)) { | ||
436 | rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc); | ||
437 | } else if (usb_endpoint_is_bulk_out(ep_desc)) { | ||
438 | rt2x00usb_assign_endpoint(queue, ep_desc); | ||
439 | |||
440 | if (queue != queue_end(rt2x00dev)) | ||
441 | queue = queue_next(queue); | ||
442 | tx_ep_desc = ep_desc; | ||
443 | } | ||
444 | } | ||
445 | |||
446 | /* | ||
447 | * At least 1 endpoint for RX and 1 endpoint for TX must be available. | ||
448 | */ | ||
449 | if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) { | ||
450 | ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n"); | ||
451 | return -EPIPE; | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * It might be possible not all queues have a dedicated endpoint. | ||
456 | * Loop through all TX queues and copy the endpoint information | ||
457 | * which we have gathered from already assigned endpoints. | ||
458 | */ | ||
459 | txall_queue_for_each(rt2x00dev, queue) { | ||
460 | if (!queue->usb_endpoint) | ||
461 | rt2x00usb_assign_endpoint(queue, tx_ep_desc); | ||
462 | } | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
374 | static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, | 467 | static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, |
375 | struct data_queue *queue) | 468 | struct data_queue *queue) |
376 | { | 469 | { |
@@ -442,6 +535,13 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) | |||
442 | int status; | 535 | int status; |
443 | 536 | ||
444 | /* | 537 | /* |
538 | * Find endpoints for each queue | ||
539 | */ | ||
540 | status = rt2x00usb_find_endpoints(rt2x00dev); | ||
541 | if (status) | ||
542 | goto exit; | ||
543 | |||
544 | /* | ||
445 | * Allocate DMA | 545 | * Allocate DMA |
446 | */ | 546 | */ |
447 | queue_for_each(rt2x00dev, queue) { | 547 | queue_for_each(rt2x00dev, queue) { |
@@ -532,11 +632,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, | |||
532 | rt2x00dev->ops = ops; | 632 | rt2x00dev->ops = ops; |
533 | rt2x00dev->hw = hw; | 633 | rt2x00dev->hw = hw; |
534 | 634 | ||
535 | rt2x00dev->usb_maxpacket = | ||
536 | usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1); | ||
537 | if (!rt2x00dev->usb_maxpacket) | ||
538 | rt2x00dev->usb_maxpacket = 1; | ||
539 | |||
540 | retval = rt2x00usb_alloc_reg(rt2x00dev); | 635 | retval = rt2x00usb_alloc_reg(rt2x00dev); |
541 | if (retval) | 636 | if (retval) |
542 | goto exit_free_device; | 637 | goto exit_free_device; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 4104f0e8fa48..2bd4ac855f52 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h | |||
@@ -231,6 +231,142 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, | |||
231 | REGISTER_TIMEOUT16(length)); | 231 | REGISTER_TIMEOUT16(length)); |
232 | } | 232 | } |
233 | 233 | ||
234 | /** | ||
235 | * rt2x00usb_regbusy_read - Read 32bit register word | ||
236 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
237 | * @offset: Register offset | ||
238 | * @value: Pointer to where register contents should be stored | ||
239 | * | ||
240 | * This function is a simple wrapper for 32bit register access | ||
241 | * through rt2x00usb_vendor_request_buff(). | ||
242 | */ | ||
243 | static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev, | ||
244 | const unsigned int offset, | ||
245 | u32 *value) | ||
246 | { | ||
247 | __le32 reg; | ||
248 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | ||
249 | USB_VENDOR_REQUEST_IN, offset, | ||
250 | ®, sizeof(reg), REGISTER_TIMEOUT); | ||
251 | *value = le32_to_cpu(reg); | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * rt2x00usb_register_read_lock - Read 32bit register word | ||
256 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
257 | * @offset: Register offset | ||
258 | * @value: Pointer to where register contents should be stored | ||
259 | * | ||
260 | * This function is a simple wrapper for 32bit register access | ||
261 | * through rt2x00usb_vendor_req_buff_lock(). | ||
262 | */ | ||
263 | static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev, | ||
264 | const unsigned int offset, | ||
265 | u32 *value) | ||
266 | { | ||
267 | __le32 reg; | ||
268 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, | ||
269 | USB_VENDOR_REQUEST_IN, offset, | ||
270 | ®, sizeof(reg), REGISTER_TIMEOUT); | ||
271 | *value = le32_to_cpu(reg); | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * rt2x00usb_register_multiread - Read 32bit register words | ||
276 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
277 | * @offset: Register offset | ||
278 | * @value: Pointer to where register contents should be stored | ||
279 | * @length: Length of the data | ||
280 | * | ||
281 | * This function is a simple wrapper for 32bit register access | ||
282 | * through rt2x00usb_vendor_request_buff(). | ||
283 | */ | ||
284 | static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev, | ||
285 | const unsigned int offset, | ||
286 | void *value, const u32 length) | ||
287 | { | ||
288 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | ||
289 | USB_VENDOR_REQUEST_IN, offset, | ||
290 | value, length, | ||
291 | REGISTER_TIMEOUT32(length)); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * rt2x00usb_register_write - Write 32bit register word | ||
296 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
297 | * @offset: Register offset | ||
298 | * @value: Data which should be written | ||
299 | * | ||
300 | * This function is a simple wrapper for 32bit register access | ||
301 | * through rt2x00usb_vendor_request_buff(). | ||
302 | */ | ||
303 | static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev, | ||
304 | const unsigned int offset, | ||
305 | u32 value) | ||
306 | { | ||
307 | __le32 reg = cpu_to_le32(value); | ||
308 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | ||
309 | USB_VENDOR_REQUEST_OUT, offset, | ||
310 | ®, sizeof(reg), REGISTER_TIMEOUT); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * rt2x00usb_register_write_lock - Write 32bit register word | ||
315 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
316 | * @offset: Register offset | ||
317 | * @value: Data which should be written | ||
318 | * | ||
319 | * This function is a simple wrapper for 32bit register access | ||
320 | * through rt2x00usb_vendor_req_buff_lock(). | ||
321 | */ | ||
322 | static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev, | ||
323 | const unsigned int offset, | ||
324 | u32 value) | ||
325 | { | ||
326 | __le32 reg = cpu_to_le32(value); | ||
327 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, | ||
328 | USB_VENDOR_REQUEST_OUT, offset, | ||
329 | ®, sizeof(reg), REGISTER_TIMEOUT); | ||
330 | } | ||
331 | |||
332 | /** | ||
333 | * rt2x00usb_register_multiwrite - Write 32bit register words | ||
334 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
335 | * @offset: Register offset | ||
336 | * @value: Data which should be written | ||
337 | * @length: Length of the data | ||
338 | * | ||
339 | * This function is a simple wrapper for 32bit register access | ||
340 | * through rt2x00usb_vendor_request_buff(). | ||
341 | */ | ||
342 | static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | ||
343 | const unsigned int offset, | ||
344 | void *value, const u32 length) | ||
345 | { | ||
346 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | ||
347 | USB_VENDOR_REQUEST_OUT, offset, | ||
348 | value, length, | ||
349 | REGISTER_TIMEOUT32(length)); | ||
350 | } | ||
351 | |||
352 | /** | ||
353 | * rt2x00usb_regbusy_read - Read from register with busy check | ||
354 | * @rt2x00dev: Device pointer, see &struct rt2x00_dev. | ||
355 | * @offset: Register offset | ||
356 | * @field: Field to check if register is busy | ||
357 | * @reg: Pointer to where register contents should be stored | ||
358 | * | ||
359 | * This function will read the given register, and checks if the | ||
360 | * register is busy. If it is, it will sleep for a couple of | ||
361 | * microseconds before reading the register again. If the register | ||
362 | * is not read after a certain timeout, this function will return | ||
363 | * FALSE. | ||
364 | */ | ||
365 | int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, | ||
366 | const unsigned int offset, | ||
367 | struct rt2x00_field32 field, | ||
368 | u32 *reg); | ||
369 | |||
234 | /* | 370 | /* |
235 | * Radio handlers | 371 | * Radio handlers |
236 | */ | 372 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 89ac34fbadf2..d54443c25fe3 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -55,20 +55,13 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | |||
55 | * the access attempt is considered to have failed, | 55 | * the access attempt is considered to have failed, |
56 | * and we will print an error. | 56 | * and we will print an error. |
57 | */ | 57 | */ |
58 | static u32 rt61pci_bbp_check(struct rt2x00_dev *rt2x00dev) | 58 | #define WAIT_FOR_BBP(__dev, __reg) \ |
59 | { | 59 | rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) |
60 | u32 reg; | 60 | #define WAIT_FOR_RF(__dev, __reg) \ |
61 | unsigned int i; | 61 | rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) |
62 | 62 | #define WAIT_FOR_MCU(__dev, __reg) \ | |
63 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 63 | rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \ |
64 | rt2x00pci_register_read(rt2x00dev, PHY_CSR3, ®); | 64 | H2M_MAILBOX_CSR_OWNER, (__reg)) |
65 | if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | ||
66 | break; | ||
67 | udelay(REGISTER_BUSY_DELAY); | ||
68 | } | ||
69 | |||
70 | return reg; | ||
71 | } | ||
72 | 65 | ||
73 | static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, | 66 | static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, |
74 | const unsigned int word, const u8 value) | 67 | const unsigned int word, const u8 value) |
@@ -78,30 +71,20 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
78 | mutex_lock(&rt2x00dev->csr_mutex); | 71 | mutex_lock(&rt2x00dev->csr_mutex); |
79 | 72 | ||
80 | /* | 73 | /* |
81 | * Wait until the BBP becomes ready. | 74 | * Wait until the BBP becomes available, afterwards we |
82 | */ | 75 | * can safely write the new data into the register. |
83 | reg = rt61pci_bbp_check(rt2x00dev); | ||
84 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | ||
85 | goto exit_fail; | ||
86 | |||
87 | /* | ||
88 | * Write the data into the BBP. | ||
89 | */ | 76 | */ |
90 | reg = 0; | 77 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
91 | rt2x00_set_field32(®, PHY_CSR3_VALUE, value); | 78 | reg = 0; |
92 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); | 79 | rt2x00_set_field32(®, PHY_CSR3_VALUE, value); |
93 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | 80 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); |
94 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); | 81 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); |
95 | 82 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); | |
96 | rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); | ||
97 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
98 | 83 | ||
99 | return; | 84 | rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); |
85 | } | ||
100 | 86 | ||
101 | exit_fail: | ||
102 | mutex_unlock(&rt2x00dev->csr_mutex); | 87 | mutex_unlock(&rt2x00dev->csr_mutex); |
103 | |||
104 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); | ||
105 | } | 88 | } |
106 | 89 | ||
107 | static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, | 90 | static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -112,72 +95,53 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
112 | mutex_lock(&rt2x00dev->csr_mutex); | 95 | mutex_lock(&rt2x00dev->csr_mutex); |
113 | 96 | ||
114 | /* | 97 | /* |
115 | * Wait until the BBP becomes ready. | 98 | * Wait until the BBP becomes available, afterwards we |
99 | * can safely write the read request into the register. | ||
100 | * After the data has been written, we wait until hardware | ||
101 | * returns the correct value, if at any time the register | ||
102 | * doesn't become available in time, reg will be 0xffffffff | ||
103 | * which means we return 0xff to the caller. | ||
116 | */ | 104 | */ |
117 | reg = rt61pci_bbp_check(rt2x00dev); | 105 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
118 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | 106 | reg = 0; |
119 | goto exit_fail; | 107 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); |
108 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | ||
109 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); | ||
120 | 110 | ||
121 | /* | 111 | rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); |
122 | * Write the request into the BBP. | ||
123 | */ | ||
124 | reg = 0; | ||
125 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); | ||
126 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | ||
127 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); | ||
128 | 112 | ||
129 | rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); | 113 | WAIT_FOR_BBP(rt2x00dev, ®); |
130 | 114 | } | |
131 | /* | ||
132 | * Wait until the BBP becomes ready. | ||
133 | */ | ||
134 | reg = rt61pci_bbp_check(rt2x00dev); | ||
135 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | ||
136 | goto exit_fail; | ||
137 | 115 | ||
138 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); | 116 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); |
139 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
140 | |||
141 | return; | ||
142 | 117 | ||
143 | exit_fail: | ||
144 | mutex_unlock(&rt2x00dev->csr_mutex); | 118 | mutex_unlock(&rt2x00dev->csr_mutex); |
145 | |||
146 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); | ||
147 | *value = 0xff; | ||
148 | } | 119 | } |
149 | 120 | ||
150 | static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, | 121 | static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, |
151 | const unsigned int word, const u32 value) | 122 | const unsigned int word, const u32 value) |
152 | { | 123 | { |
153 | u32 reg; | 124 | u32 reg; |
154 | unsigned int i; | ||
155 | 125 | ||
156 | if (!word) | 126 | if (!word) |
157 | return; | 127 | return; |
158 | 128 | ||
159 | mutex_lock(&rt2x00dev->csr_mutex); | 129 | mutex_lock(&rt2x00dev->csr_mutex); |
160 | 130 | ||
161 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 131 | /* |
162 | rt2x00pci_register_read(rt2x00dev, PHY_CSR4, ®); | 132 | * Wait until the RF becomes available, afterwards we |
163 | if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) | 133 | * can safely write the new data into the register. |
164 | goto rf_write; | 134 | */ |
165 | udelay(REGISTER_BUSY_DELAY); | 135 | if (WAIT_FOR_RF(rt2x00dev, ®)) { |
166 | } | 136 | reg = 0; |
167 | 137 | rt2x00_set_field32(®, PHY_CSR4_VALUE, value); | |
168 | mutex_unlock(&rt2x00dev->csr_mutex); | 138 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 21); |
169 | ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); | 139 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); |
170 | return; | 140 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); |
171 | |||
172 | rf_write: | ||
173 | reg = 0; | ||
174 | rt2x00_set_field32(®, PHY_CSR4_VALUE, value); | ||
175 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 21); | ||
176 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); | ||
177 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); | ||
178 | 141 | ||
179 | rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); | 142 | rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); |
180 | rt2x00_rf_write(rt2x00dev, word, value); | 143 | rt2x00_rf_write(rt2x00dev, word, value); |
144 | } | ||
181 | 145 | ||
182 | mutex_unlock(&rt2x00dev->csr_mutex); | 146 | mutex_unlock(&rt2x00dev->csr_mutex); |
183 | } | 147 | } |
@@ -196,32 +160,25 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
196 | 160 | ||
197 | mutex_lock(&rt2x00dev->csr_mutex); | 161 | mutex_lock(&rt2x00dev->csr_mutex); |
198 | 162 | ||
199 | rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CSR, ®); | 163 | /* |
200 | 164 | * Wait until the MCU becomes available, afterwards we | |
201 | if (rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER)) | 165 | * can safely write the new data into the register. |
202 | goto exit_fail; | 166 | */ |
203 | 167 | if (WAIT_FOR_MCU(rt2x00dev, ®)) { | |
204 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); | 168 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); |
205 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); | 169 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); |
206 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); | 170 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); |
207 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); | 171 | rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); |
208 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); | 172 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); |
209 | |||
210 | rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®); | ||
211 | rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); | ||
212 | rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); | ||
213 | rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); | ||
214 | |||
215 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
216 | 173 | ||
217 | return; | 174 | rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®); |
175 | rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); | ||
176 | rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); | ||
177 | rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); | ||
178 | } | ||
218 | 179 | ||
219 | exit_fail: | ||
220 | mutex_unlock(&rt2x00dev->csr_mutex); | 180 | mutex_unlock(&rt2x00dev->csr_mutex); |
221 | 181 | ||
222 | ERROR(rt2x00dev, | ||
223 | "mcu request error. Request 0x%02x failed for token 0x%02x.\n", | ||
224 | command, token); | ||
225 | } | 182 | } |
226 | #endif /* CONFIG_RT2X00_LIB_LEDS */ | 183 | #endif /* CONFIG_RT2X00_LIB_LEDS */ |
227 | 184 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index d1a63e0017da..37a782dc8080 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | |||
46 | /* | 46 | /* |
47 | * Register access. | 47 | * Register access. |
48 | * All access to the CSR registers will go through the methods | 48 | * All access to the CSR registers will go through the methods |
49 | * rt73usb_register_read and rt73usb_register_write. | 49 | * rt2x00usb_register_read and rt2x00usb_register_write. |
50 | * BBP and RF register require indirect register access, | 50 | * BBP and RF register require indirect register access, |
51 | * and use the CSR registers BBPCSR and RFCSR to achieve this. | 51 | * and use the CSR registers BBPCSR and RFCSR to achieve this. |
52 | * These indirect registers work with busy bits, | 52 | * These indirect registers work with busy bits, |
@@ -57,78 +57,10 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | |||
57 | * and we will print an error. | 57 | * and we will print an error. |
58 | * The _lock versions must be used if you already hold the csr_mutex | 58 | * The _lock versions must be used if you already hold the csr_mutex |
59 | */ | 59 | */ |
60 | static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev, | 60 | #define WAIT_FOR_BBP(__dev, __reg) \ |
61 | const unsigned int offset, u32 *value) | 61 | rt2x00usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) |
62 | { | 62 | #define WAIT_FOR_RF(__dev, __reg) \ |
63 | __le32 reg; | 63 | rt2x00usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) |
64 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | ||
65 | USB_VENDOR_REQUEST_IN, offset, | ||
66 | ®, sizeof(u32), REGISTER_TIMEOUT); | ||
67 | *value = le32_to_cpu(reg); | ||
68 | } | ||
69 | |||
70 | static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev, | ||
71 | const unsigned int offset, u32 *value) | ||
72 | { | ||
73 | __le32 reg; | ||
74 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, | ||
75 | USB_VENDOR_REQUEST_IN, offset, | ||
76 | ®, sizeof(u32), REGISTER_TIMEOUT); | ||
77 | *value = le32_to_cpu(reg); | ||
78 | } | ||
79 | |||
80 | static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev, | ||
81 | const unsigned int offset, | ||
82 | void *value, const u32 length) | ||
83 | { | ||
84 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | ||
85 | USB_VENDOR_REQUEST_IN, offset, | ||
86 | value, length, | ||
87 | REGISTER_TIMEOUT32(length)); | ||
88 | } | ||
89 | |||
90 | static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev, | ||
91 | const unsigned int offset, u32 value) | ||
92 | { | ||
93 | __le32 reg = cpu_to_le32(value); | ||
94 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | ||
95 | USB_VENDOR_REQUEST_OUT, offset, | ||
96 | ®, sizeof(u32), REGISTER_TIMEOUT); | ||
97 | } | ||
98 | |||
99 | static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev, | ||
100 | const unsigned int offset, u32 value) | ||
101 | { | ||
102 | __le32 reg = cpu_to_le32(value); | ||
103 | rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, | ||
104 | USB_VENDOR_REQUEST_OUT, offset, | ||
105 | ®, sizeof(u32), REGISTER_TIMEOUT); | ||
106 | } | ||
107 | |||
108 | static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | ||
109 | const unsigned int offset, | ||
110 | void *value, const u32 length) | ||
111 | { | ||
112 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | ||
113 | USB_VENDOR_REQUEST_OUT, offset, | ||
114 | value, length, | ||
115 | REGISTER_TIMEOUT32(length)); | ||
116 | } | ||
117 | |||
118 | static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev) | ||
119 | { | ||
120 | u32 reg; | ||
121 | unsigned int i; | ||
122 | |||
123 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
124 | rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, ®); | ||
125 | if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | ||
126 | break; | ||
127 | udelay(REGISTER_BUSY_DELAY); | ||
128 | } | ||
129 | |||
130 | return reg; | ||
131 | } | ||
132 | 64 | ||
133 | static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, | 65 | static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, |
134 | const unsigned int word, const u8 value) | 66 | const unsigned int word, const u8 value) |
@@ -138,30 +70,20 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, | |||
138 | mutex_lock(&rt2x00dev->csr_mutex); | 70 | mutex_lock(&rt2x00dev->csr_mutex); |
139 | 71 | ||
140 | /* | 72 | /* |
141 | * Wait until the BBP becomes ready. | 73 | * Wait until the BBP becomes available, afterwards we |
74 | * can safely write the new data into the register. | ||
142 | */ | 75 | */ |
143 | reg = rt73usb_bbp_check(rt2x00dev); | 76 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
144 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | 77 | reg = 0; |
145 | goto exit_fail; | 78 | rt2x00_set_field32(®, PHY_CSR3_VALUE, value); |
146 | 79 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); | |
147 | /* | 80 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); |
148 | * Write the data into the BBP. | 81 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); |
149 | */ | 82 | |
150 | reg = 0; | 83 | rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); |
151 | rt2x00_set_field32(®, PHY_CSR3_VALUE, value); | 84 | } |
152 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); | ||
153 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | ||
154 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); | ||
155 | |||
156 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); | ||
157 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
158 | |||
159 | return; | ||
160 | 85 | ||
161 | exit_fail: | ||
162 | mutex_unlock(&rt2x00dev->csr_mutex); | 86 | mutex_unlock(&rt2x00dev->csr_mutex); |
163 | |||
164 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); | ||
165 | } | 87 | } |
166 | 88 | ||
167 | static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, | 89 | static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, |
@@ -172,79 +94,59 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, | |||
172 | mutex_lock(&rt2x00dev->csr_mutex); | 94 | mutex_lock(&rt2x00dev->csr_mutex); |
173 | 95 | ||
174 | /* | 96 | /* |
175 | * Wait until the BBP becomes ready. | 97 | * Wait until the BBP becomes available, afterwards we |
98 | * can safely write the read request into the register. | ||
99 | * After the data has been written, we wait until hardware | ||
100 | * returns the correct value, if at any time the register | ||
101 | * doesn't become available in time, reg will be 0xffffffff | ||
102 | * which means we return 0xff to the caller. | ||
176 | */ | 103 | */ |
177 | reg = rt73usb_bbp_check(rt2x00dev); | 104 | if (WAIT_FOR_BBP(rt2x00dev, ®)) { |
178 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | 105 | reg = 0; |
179 | goto exit_fail; | 106 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); |
107 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | ||
108 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); | ||
180 | 109 | ||
181 | /* | 110 | rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); |
182 | * Write the request into the BBP. | ||
183 | */ | ||
184 | reg = 0; | ||
185 | rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); | ||
186 | rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); | ||
187 | rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); | ||
188 | 111 | ||
189 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); | 112 | WAIT_FOR_BBP(rt2x00dev, ®); |
190 | 113 | } | |
191 | /* | ||
192 | * Wait until the BBP becomes ready. | ||
193 | */ | ||
194 | reg = rt73usb_bbp_check(rt2x00dev); | ||
195 | if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) | ||
196 | goto exit_fail; | ||
197 | 114 | ||
198 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); | 115 | *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); |
199 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
200 | 116 | ||
201 | return; | ||
202 | |||
203 | exit_fail: | ||
204 | mutex_unlock(&rt2x00dev->csr_mutex); | 117 | mutex_unlock(&rt2x00dev->csr_mutex); |
205 | |||
206 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); | ||
207 | *value = 0xff; | ||
208 | } | 118 | } |
209 | 119 | ||
210 | static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, | 120 | static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, |
211 | const unsigned int word, const u32 value) | 121 | const unsigned int word, const u32 value) |
212 | { | 122 | { |
213 | u32 reg; | 123 | u32 reg; |
214 | unsigned int i; | ||
215 | 124 | ||
216 | if (!word) | 125 | if (!word) |
217 | return; | 126 | return; |
218 | 127 | ||
219 | mutex_lock(&rt2x00dev->csr_mutex); | 128 | mutex_lock(&rt2x00dev->csr_mutex); |
220 | 129 | ||
221 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | ||
222 | rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, ®); | ||
223 | if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) | ||
224 | goto rf_write; | ||
225 | udelay(REGISTER_BUSY_DELAY); | ||
226 | } | ||
227 | |||
228 | mutex_unlock(&rt2x00dev->csr_mutex); | ||
229 | ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n"); | ||
230 | return; | ||
231 | |||
232 | rf_write: | ||
233 | reg = 0; | ||
234 | rt2x00_set_field32(®, PHY_CSR4_VALUE, value); | ||
235 | |||
236 | /* | 130 | /* |
237 | * RF5225 and RF2527 contain 21 bits per RF register value, | 131 | * Wait until the RF becomes available, afterwards we |
238 | * all others contain 20 bits. | 132 | * can safely write the new data into the register. |
239 | */ | 133 | */ |
240 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, | 134 | if (WAIT_FOR_RF(rt2x00dev, ®)) { |
241 | 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 135 | reg = 0; |
242 | rt2x00_rf(&rt2x00dev->chip, RF2527))); | 136 | rt2x00_set_field32(®, PHY_CSR4_VALUE, value); |
243 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); | 137 | /* |
244 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); | 138 | * RF5225 and RF2527 contain 21 bits per RF register value, |
245 | 139 | * all others contain 20 bits. | |
246 | rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); | 140 | */ |
247 | rt2x00_rf_write(rt2x00dev, word, value); | 141 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, |
142 | 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || | ||
143 | rt2x00_rf(&rt2x00dev->chip, RF2527))); | ||
144 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); | ||
145 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); | ||
146 | |||
147 | rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); | ||
148 | rt2x00_rf_write(rt2x00dev, word, value); | ||
149 | } | ||
248 | 150 | ||
249 | mutex_unlock(&rt2x00dev->csr_mutex); | 151 | mutex_unlock(&rt2x00dev->csr_mutex); |
250 | } | 152 | } |
@@ -253,8 +155,8 @@ rf_write: | |||
253 | static const struct rt2x00debug rt73usb_rt2x00debug = { | 155 | static const struct rt2x00debug rt73usb_rt2x00debug = { |
254 | .owner = THIS_MODULE, | 156 | .owner = THIS_MODULE, |
255 | .csr = { | 157 | .csr = { |
256 | .read = rt73usb_register_read, | 158 | .read = rt2x00usb_register_read, |
257 | .write = rt73usb_register_write, | 159 | .write = rt2x00usb_register_write, |
258 | .flags = RT2X00DEBUGFS_OFFSET, | 160 | .flags = RT2X00DEBUGFS_OFFSET, |
259 | .word_base = CSR_REG_BASE, | 161 | .word_base = CSR_REG_BASE, |
260 | .word_size = sizeof(u32), | 162 | .word_size = sizeof(u32), |
@@ -333,10 +235,10 @@ static int rt73usb_blink_set(struct led_classdev *led_cdev, | |||
333 | container_of(led_cdev, struct rt2x00_led, led_dev); | 235 | container_of(led_cdev, struct rt2x00_led, led_dev); |
334 | u32 reg; | 236 | u32 reg; |
335 | 237 | ||
336 | rt73usb_register_read(led->rt2x00dev, MAC_CSR14, ®); | 238 | rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14, ®); |
337 | rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on); | 239 | rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on); |
338 | rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); | 240 | rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); |
339 | rt73usb_register_write(led->rt2x00dev, MAC_CSR14, reg); | 241 | rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg); |
340 | 242 | ||
341 | return 0; | 243 | return 0; |
342 | } | 244 | } |
@@ -379,7 +281,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
379 | */ | 281 | */ |
380 | mask = (0xf << crypto->bssidx); | 282 | mask = (0xf << crypto->bssidx); |
381 | 283 | ||
382 | rt73usb_register_read(rt2x00dev, SEC_CSR0, ®); | 284 | rt2x00usb_register_read(rt2x00dev, SEC_CSR0, ®); |
383 | reg &= mask; | 285 | reg &= mask; |
384 | 286 | ||
385 | if (reg && reg == mask) | 287 | if (reg && reg == mask) |
@@ -416,16 +318,16 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
416 | field.bit_offset = (3 * key->hw_key_idx); | 318 | field.bit_offset = (3 * key->hw_key_idx); |
417 | field.bit_mask = 0x7 << field.bit_offset; | 319 | field.bit_mask = 0x7 << field.bit_offset; |
418 | 320 | ||
419 | rt73usb_register_read(rt2x00dev, SEC_CSR1, ®); | 321 | rt2x00usb_register_read(rt2x00dev, SEC_CSR1, ®); |
420 | rt2x00_set_field32(®, field, crypto->cipher); | 322 | rt2x00_set_field32(®, field, crypto->cipher); |
421 | rt73usb_register_write(rt2x00dev, SEC_CSR1, reg); | 323 | rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg); |
422 | } else { | 324 | } else { |
423 | field.bit_offset = (3 * (key->hw_key_idx - 8)); | 325 | field.bit_offset = (3 * (key->hw_key_idx - 8)); |
424 | field.bit_mask = 0x7 << field.bit_offset; | 326 | field.bit_mask = 0x7 << field.bit_offset; |
425 | 327 | ||
426 | rt73usb_register_read(rt2x00dev, SEC_CSR5, ®); | 328 | rt2x00usb_register_read(rt2x00dev, SEC_CSR5, ®); |
427 | rt2x00_set_field32(®, field, crypto->cipher); | 329 | rt2x00_set_field32(®, field, crypto->cipher); |
428 | rt73usb_register_write(rt2x00dev, SEC_CSR5, reg); | 330 | rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg); |
429 | } | 331 | } |
430 | 332 | ||
431 | /* | 333 | /* |
@@ -448,12 +350,12 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, | |||
448 | */ | 350 | */ |
449 | mask = 1 << key->hw_key_idx; | 351 | mask = 1 << key->hw_key_idx; |
450 | 352 | ||
451 | rt73usb_register_read(rt2x00dev, SEC_CSR0, ®); | 353 | rt2x00usb_register_read(rt2x00dev, SEC_CSR0, ®); |
452 | if (crypto->cmd == SET_KEY) | 354 | if (crypto->cmd == SET_KEY) |
453 | reg |= mask; | 355 | reg |= mask; |
454 | else if (crypto->cmd == DISABLE_KEY) | 356 | else if (crypto->cmd == DISABLE_KEY) |
455 | reg &= ~mask; | 357 | reg &= ~mask; |
456 | rt73usb_register_write(rt2x00dev, SEC_CSR0, reg); | 358 | rt2x00usb_register_write(rt2x00dev, SEC_CSR0, reg); |
457 | 359 | ||
458 | return 0; | 360 | return 0; |
459 | } | 361 | } |
@@ -478,10 +380,10 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
478 | * When both registers are full, we drop the key, | 380 | * When both registers are full, we drop the key, |
479 | * otherwise we use the first invalid entry. | 381 | * otherwise we use the first invalid entry. |
480 | */ | 382 | */ |
481 | rt73usb_register_read(rt2x00dev, SEC_CSR2, ®); | 383 | rt2x00usb_register_read(rt2x00dev, SEC_CSR2, ®); |
482 | if (reg && reg == ~0) { | 384 | if (reg && reg == ~0) { |
483 | key->hw_key_idx = 32; | 385 | key->hw_key_idx = 32; |
484 | rt73usb_register_read(rt2x00dev, SEC_CSR3, ®); | 386 | rt2x00usb_register_read(rt2x00dev, SEC_CSR3, ®); |
485 | if (reg && reg == ~0) | 387 | if (reg && reg == ~0) |
486 | return -ENOSPC; | 388 | return -ENOSPC; |
487 | } | 389 | } |
@@ -509,14 +411,14 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
509 | /* | 411 | /* |
510 | * Send the address and cipher type to the hardware register. | 412 | * Send the address and cipher type to the hardware register. |
511 | * This data fits within the CSR cache size, so we can use | 413 | * This data fits within the CSR cache size, so we can use |
512 | * rt73usb_register_multiwrite() directly. | 414 | * rt2x00usb_register_multiwrite() directly. |
513 | */ | 415 | */ |
514 | memset(&addr_entry, 0, sizeof(addr_entry)); | 416 | memset(&addr_entry, 0, sizeof(addr_entry)); |
515 | memcpy(&addr_entry, crypto->address, ETH_ALEN); | 417 | memcpy(&addr_entry, crypto->address, ETH_ALEN); |
516 | addr_entry.cipher = crypto->cipher; | 418 | addr_entry.cipher = crypto->cipher; |
517 | 419 | ||
518 | reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); | 420 | reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); |
519 | rt73usb_register_multiwrite(rt2x00dev, reg, | 421 | rt2x00usb_register_multiwrite(rt2x00dev, reg, |
520 | &addr_entry, sizeof(addr_entry)); | 422 | &addr_entry, sizeof(addr_entry)); |
521 | 423 | ||
522 | /* | 424 | /* |
@@ -524,9 +426,9 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
524 | * without this received frames will not be decrypted | 426 | * without this received frames will not be decrypted |
525 | * by the hardware. | 427 | * by the hardware. |
526 | */ | 428 | */ |
527 | rt73usb_register_read(rt2x00dev, SEC_CSR4, ®); | 429 | rt2x00usb_register_read(rt2x00dev, SEC_CSR4, ®); |
528 | reg |= (1 << crypto->bssidx); | 430 | reg |= (1 << crypto->bssidx); |
529 | rt73usb_register_write(rt2x00dev, SEC_CSR4, reg); | 431 | rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg); |
530 | 432 | ||
531 | /* | 433 | /* |
532 | * The driver does not support the IV/EIV generation | 434 | * The driver does not support the IV/EIV generation |
@@ -549,21 +451,21 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, | |||
549 | if (key->hw_key_idx < 32) { | 451 | if (key->hw_key_idx < 32) { |
550 | mask = 1 << key->hw_key_idx; | 452 | mask = 1 << key->hw_key_idx; |
551 | 453 | ||
552 | rt73usb_register_read(rt2x00dev, SEC_CSR2, ®); | 454 | rt2x00usb_register_read(rt2x00dev, SEC_CSR2, ®); |
553 | if (crypto->cmd == SET_KEY) | 455 | if (crypto->cmd == SET_KEY) |
554 | reg |= mask; | 456 | reg |= mask; |
555 | else if (crypto->cmd == DISABLE_KEY) | 457 | else if (crypto->cmd == DISABLE_KEY) |
556 | reg &= ~mask; | 458 | reg &= ~mask; |
557 | rt73usb_register_write(rt2x00dev, SEC_CSR2, reg); | 459 | rt2x00usb_register_write(rt2x00dev, SEC_CSR2, reg); |
558 | } else { | 460 | } else { |
559 | mask = 1 << (key->hw_key_idx - 32); | 461 | mask = 1 << (key->hw_key_idx - 32); |
560 | 462 | ||
561 | rt73usb_register_read(rt2x00dev, SEC_CSR3, ®); | 463 | rt2x00usb_register_read(rt2x00dev, SEC_CSR3, ®); |
562 | if (crypto->cmd == SET_KEY) | 464 | if (crypto->cmd == SET_KEY) |
563 | reg |= mask; | 465 | reg |= mask; |
564 | else if (crypto->cmd == DISABLE_KEY) | 466 | else if (crypto->cmd == DISABLE_KEY) |
565 | reg &= ~mask; | 467 | reg &= ~mask; |
566 | rt73usb_register_write(rt2x00dev, SEC_CSR3, reg); | 468 | rt2x00usb_register_write(rt2x00dev, SEC_CSR3, reg); |
567 | } | 469 | } |
568 | 470 | ||
569 | return 0; | 471 | return 0; |
@@ -580,7 +482,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, | |||
580 | * and broadcast frames will always be accepted since | 482 | * and broadcast frames will always be accepted since |
581 | * there is no filter for it at this time. | 483 | * there is no filter for it at this time. |
582 | */ | 484 | */ |
583 | rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); | 485 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); |
584 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, | 486 | rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, |
585 | !(filter_flags & FIF_FCSFAIL)); | 487 | !(filter_flags & FIF_FCSFAIL)); |
586 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, | 488 | rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, |
@@ -598,7 +500,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, | |||
598 | rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); | 500 | rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); |
599 | rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, | 501 | rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, |
600 | !(filter_flags & FIF_CONTROL)); | 502 | !(filter_flags & FIF_CONTROL)); |
601 | rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); | 503 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); |
602 | } | 504 | } |
603 | 505 | ||
604 | static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, | 506 | static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, |
@@ -617,16 +519,16 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
617 | * bits which (when set to 0) will invalidate the entire beacon. | 519 | * bits which (when set to 0) will invalidate the entire beacon. |
618 | */ | 520 | */ |
619 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); | 521 | beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); |
620 | rt73usb_register_write(rt2x00dev, beacon_base, 0); | 522 | rt2x00usb_register_write(rt2x00dev, beacon_base, 0); |
621 | 523 | ||
622 | /* | 524 | /* |
623 | * Enable synchronisation. | 525 | * Enable synchronisation. |
624 | */ | 526 | */ |
625 | rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); | 527 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); |
626 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | 528 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); |
627 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); | 529 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); |
628 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | 530 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); |
629 | rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 531 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
630 | } | 532 | } |
631 | 533 | ||
632 | if (flags & CONFIG_UPDATE_MAC) { | 534 | if (flags & CONFIG_UPDATE_MAC) { |
@@ -634,7 +536,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
634 | rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); | 536 | rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); |
635 | conf->mac[1] = cpu_to_le32(reg); | 537 | conf->mac[1] = cpu_to_le32(reg); |
636 | 538 | ||
637 | rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, | 539 | rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR2, |
638 | conf->mac, sizeof(conf->mac)); | 540 | conf->mac, sizeof(conf->mac)); |
639 | } | 541 | } |
640 | 542 | ||
@@ -643,7 +545,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, | |||
643 | rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); | 545 | rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); |
644 | conf->bssid[1] = cpu_to_le32(reg); | 546 | conf->bssid[1] = cpu_to_le32(reg); |
645 | 547 | ||
646 | rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, | 548 | rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR4, |
647 | conf->bssid, sizeof(conf->bssid)); | 549 | conf->bssid, sizeof(conf->bssid)); |
648 | } | 550 | } |
649 | } | 551 | } |
@@ -653,26 +555,26 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, | |||
653 | { | 555 | { |
654 | u32 reg; | 556 | u32 reg; |
655 | 557 | ||
656 | rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); | 558 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); |
657 | rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); | 559 | rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); |
658 | rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); | 560 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); |
659 | 561 | ||
660 | rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); | 562 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); |
661 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, | 563 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, |
662 | !!erp->short_preamble); | 564 | !!erp->short_preamble); |
663 | rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); | 565 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); |
664 | 566 | ||
665 | rt73usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); | 567 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); |
666 | 568 | ||
667 | rt73usb_register_read(rt2x00dev, MAC_CSR9, ®); | 569 | rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); |
668 | rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); | 570 | rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); |
669 | rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); | 571 | rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); |
670 | 572 | ||
671 | rt73usb_register_read(rt2x00dev, MAC_CSR8, ®); | 573 | rt2x00usb_register_read(rt2x00dev, MAC_CSR8, ®); |
672 | rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); | 574 | rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); |
673 | rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); | 575 | rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); |
674 | rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); | 576 | rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); |
675 | rt73usb_register_write(rt2x00dev, MAC_CSR8, reg); | 577 | rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg); |
676 | } | 578 | } |
677 | 579 | ||
678 | static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, | 580 | static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, |
@@ -818,14 +720,14 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
818 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) | 720 | for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) |
819 | rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); | 721 | rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); |
820 | 722 | ||
821 | rt73usb_register_read(rt2x00dev, PHY_CSR0, ®); | 723 | rt2x00usb_register_read(rt2x00dev, PHY_CSR0, ®); |
822 | 724 | ||
823 | rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, | 725 | rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, |
824 | (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)); | 726 | (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)); |
825 | rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, | 727 | rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, |
826 | (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)); | 728 | (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)); |
827 | 729 | ||
828 | rt73usb_register_write(rt2x00dev, PHY_CSR0, reg); | 730 | rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); |
829 | 731 | ||
830 | if (rt2x00_rf(&rt2x00dev->chip, RF5226) || | 732 | if (rt2x00_rf(&rt2x00dev->chip, RF5226) || |
831 | rt2x00_rf(&rt2x00dev->chip, RF5225)) | 733 | rt2x00_rf(&rt2x00dev->chip, RF5225)) |
@@ -915,12 +817,12 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, | |||
915 | { | 817 | { |
916 | u32 reg; | 818 | u32 reg; |
917 | 819 | ||
918 | rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); | 820 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); |
919 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, | 821 | rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, |
920 | libconf->conf->long_frame_max_tx_count); | 822 | libconf->conf->long_frame_max_tx_count); |
921 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, | 823 | rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, |
922 | libconf->conf->short_frame_max_tx_count); | 824 | libconf->conf->short_frame_max_tx_count); |
923 | rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); | 825 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); |
924 | } | 826 | } |
925 | 827 | ||
926 | static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, | 828 | static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, |
@@ -928,18 +830,18 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, | |||
928 | { | 830 | { |
929 | u32 reg; | 831 | u32 reg; |
930 | 832 | ||
931 | rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); | 833 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); |
932 | rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); | 834 | rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); |
933 | rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); | 835 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); |
934 | 836 | ||
935 | rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); | 837 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); |
936 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); | 838 | rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); |
937 | rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); | 839 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); |
938 | 840 | ||
939 | rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); | 841 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); |
940 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, | 842 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, |
941 | libconf->conf->beacon_int * 16); | 843 | libconf->conf->beacon_int * 16); |
942 | rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 844 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
943 | } | 845 | } |
944 | 846 | ||
945 | static void rt73usb_config(struct rt2x00_dev *rt2x00dev, | 847 | static void rt73usb_config(struct rt2x00_dev *rt2x00dev, |
@@ -972,13 +874,13 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev, | |||
972 | /* | 874 | /* |
973 | * Update FCS error count from register. | 875 | * Update FCS error count from register. |
974 | */ | 876 | */ |
975 | rt73usb_register_read(rt2x00dev, STA_CSR0, ®); | 877 | rt2x00usb_register_read(rt2x00dev, STA_CSR0, ®); |
976 | qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); | 878 | qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); |
977 | 879 | ||
978 | /* | 880 | /* |
979 | * Update False CCA count from register. | 881 | * Update False CCA count from register. |
980 | */ | 882 | */ |
981 | rt73usb_register_read(rt2x00dev, STA_CSR1, ®); | 883 | rt2x00usb_register_read(rt2x00dev, STA_CSR1, ®); |
982 | qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); | 884 | qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); |
983 | } | 885 | } |
984 | 886 | ||
@@ -1138,7 +1040,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, | |||
1138 | * Wait for stable hardware. | 1040 | * Wait for stable hardware. |
1139 | */ | 1041 | */ |
1140 | for (i = 0; i < 100; i++) { | 1042 | for (i = 0; i < 100; i++) { |
1141 | rt73usb_register_read(rt2x00dev, MAC_CSR0, ®); | 1043 | rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); |
1142 | if (reg) | 1044 | if (reg) |
1143 | break; | 1045 | break; |
1144 | msleep(1); | 1046 | msleep(1); |
@@ -1180,13 +1082,13 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1180 | { | 1082 | { |
1181 | u32 reg; | 1083 | u32 reg; |
1182 | 1084 | ||
1183 | rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); | 1085 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); |
1184 | rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1); | 1086 | rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1); |
1185 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); | 1087 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); |
1186 | rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0); | 1088 | rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0); |
1187 | rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); | 1089 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); |
1188 | 1090 | ||
1189 | rt73usb_register_read(rt2x00dev, TXRX_CSR1, ®); | 1091 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR1, ®); |
1190 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */ | 1092 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */ |
1191 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1); | 1093 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1); |
1192 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */ | 1094 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */ |
@@ -1195,12 +1097,12 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1195 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1); | 1097 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1); |
1196 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */ | 1098 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */ |
1197 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1); | 1099 | rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1); |
1198 | rt73usb_register_write(rt2x00dev, TXRX_CSR1, reg); | 1100 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR1, reg); |
1199 | 1101 | ||
1200 | /* | 1102 | /* |
1201 | * CCK TXD BBP registers | 1103 | * CCK TXD BBP registers |
1202 | */ | 1104 | */ |
1203 | rt73usb_register_read(rt2x00dev, TXRX_CSR2, ®); | 1105 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR2, ®); |
1204 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13); | 1106 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13); |
1205 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1); | 1107 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1); |
1206 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12); | 1108 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12); |
@@ -1209,77 +1111,77 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1209 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1); | 1111 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1); |
1210 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10); | 1112 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10); |
1211 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1); | 1113 | rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1); |
1212 | rt73usb_register_write(rt2x00dev, TXRX_CSR2, reg); | 1114 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR2, reg); |
1213 | 1115 | ||
1214 | /* | 1116 | /* |
1215 | * OFDM TXD BBP registers | 1117 | * OFDM TXD BBP registers |
1216 | */ | 1118 | */ |
1217 | rt73usb_register_read(rt2x00dev, TXRX_CSR3, ®); | 1119 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR3, ®); |
1218 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7); | 1120 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7); |
1219 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1); | 1121 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1); |
1220 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6); | 1122 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6); |
1221 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1); | 1123 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1); |
1222 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5); | 1124 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5); |
1223 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1); | 1125 | rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1); |
1224 | rt73usb_register_write(rt2x00dev, TXRX_CSR3, reg); | 1126 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg); |
1225 | 1127 | ||
1226 | rt73usb_register_read(rt2x00dev, TXRX_CSR7, ®); | 1128 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR7, ®); |
1227 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59); | 1129 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59); |
1228 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53); | 1130 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53); |
1229 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49); | 1131 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49); |
1230 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46); | 1132 | rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46); |
1231 | rt73usb_register_write(rt2x00dev, TXRX_CSR7, reg); | 1133 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg); |
1232 | 1134 | ||
1233 | rt73usb_register_read(rt2x00dev, TXRX_CSR8, ®); | 1135 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR8, ®); |
1234 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44); | 1136 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44); |
1235 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42); | 1137 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42); |
1236 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42); | 1138 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42); |
1237 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42); | 1139 | rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42); |
1238 | rt73usb_register_write(rt2x00dev, TXRX_CSR8, reg); | 1140 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg); |
1239 | 1141 | ||
1240 | rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); | 1142 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); |
1241 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, 0); | 1143 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, 0); |
1242 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); | 1144 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); |
1243 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0); | 1145 | rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0); |
1244 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | 1146 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); |
1245 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 1147 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); |
1246 | rt2x00_set_field32(®, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0); | 1148 | rt2x00_set_field32(®, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0); |
1247 | rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 1149 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
1248 | 1150 | ||
1249 | rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); | 1151 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); |
1250 | 1152 | ||
1251 | rt73usb_register_read(rt2x00dev, MAC_CSR6, ®); | 1153 | rt2x00usb_register_read(rt2x00dev, MAC_CSR6, ®); |
1252 | rt2x00_set_field32(®, MAC_CSR6_MAX_FRAME_UNIT, 0xfff); | 1154 | rt2x00_set_field32(®, MAC_CSR6_MAX_FRAME_UNIT, 0xfff); |
1253 | rt73usb_register_write(rt2x00dev, MAC_CSR6, reg); | 1155 | rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg); |
1254 | 1156 | ||
1255 | rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718); | 1157 | rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718); |
1256 | 1158 | ||
1257 | if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) | 1159 | if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) |
1258 | return -EBUSY; | 1160 | return -EBUSY; |
1259 | 1161 | ||
1260 | rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00); | 1162 | rt2x00usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00); |
1261 | 1163 | ||
1262 | /* | 1164 | /* |
1263 | * Invalidate all Shared Keys (SEC_CSR0), | 1165 | * Invalidate all Shared Keys (SEC_CSR0), |
1264 | * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) | 1166 | * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) |
1265 | */ | 1167 | */ |
1266 | rt73usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000); | 1168 | rt2x00usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000); |
1267 | rt73usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000); | 1169 | rt2x00usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000); |
1268 | rt73usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); | 1170 | rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); |
1269 | 1171 | ||
1270 | reg = 0x000023b0; | 1172 | reg = 0x000023b0; |
1271 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 1173 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || |
1272 | rt2x00_rf(&rt2x00dev->chip, RF2527)) | 1174 | rt2x00_rf(&rt2x00dev->chip, RF2527)) |
1273 | rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); | 1175 | rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); |
1274 | rt73usb_register_write(rt2x00dev, PHY_CSR1, reg); | 1176 | rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); |
1275 | 1177 | ||
1276 | rt73usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06); | 1178 | rt2x00usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06); |
1277 | rt73usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606); | 1179 | rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606); |
1278 | rt73usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408); | 1180 | rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408); |
1279 | 1181 | ||
1280 | rt73usb_register_read(rt2x00dev, MAC_CSR9, ®); | 1182 | rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); |
1281 | rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); | 1183 | rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); |
1282 | rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); | 1184 | rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); |
1283 | 1185 | ||
1284 | /* | 1186 | /* |
1285 | * Clear all beacons | 1187 | * Clear all beacons |
@@ -1287,36 +1189,36 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1287 | * the first byte since that byte contains the VALID and OWNER | 1189 | * the first byte since that byte contains the VALID and OWNER |
1288 | * bits which (when set to 0) will invalidate the entire beacon. | 1190 | * bits which (when set to 0) will invalidate the entire beacon. |
1289 | */ | 1191 | */ |
1290 | rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); | 1192 | rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); |
1291 | rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); | 1193 | rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); |
1292 | rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); | 1194 | rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); |
1293 | rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); | 1195 | rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); |
1294 | 1196 | ||
1295 | /* | 1197 | /* |
1296 | * We must clear the error counters. | 1198 | * We must clear the error counters. |
1297 | * These registers are cleared on read, | 1199 | * These registers are cleared on read, |
1298 | * so we may pass a useless variable to store the value. | 1200 | * so we may pass a useless variable to store the value. |
1299 | */ | 1201 | */ |
1300 | rt73usb_register_read(rt2x00dev, STA_CSR0, ®); | 1202 | rt2x00usb_register_read(rt2x00dev, STA_CSR0, ®); |
1301 | rt73usb_register_read(rt2x00dev, STA_CSR1, ®); | 1203 | rt2x00usb_register_read(rt2x00dev, STA_CSR1, ®); |
1302 | rt73usb_register_read(rt2x00dev, STA_CSR2, ®); | 1204 | rt2x00usb_register_read(rt2x00dev, STA_CSR2, ®); |
1303 | 1205 | ||
1304 | /* | 1206 | /* |
1305 | * Reset MAC and BBP registers. | 1207 | * Reset MAC and BBP registers. |
1306 | */ | 1208 | */ |
1307 | rt73usb_register_read(rt2x00dev, MAC_CSR1, ®); | 1209 | rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®); |
1308 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); | 1210 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); |
1309 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); | 1211 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); |
1310 | rt73usb_register_write(rt2x00dev, MAC_CSR1, reg); | 1212 | rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg); |
1311 | 1213 | ||
1312 | rt73usb_register_read(rt2x00dev, MAC_CSR1, ®); | 1214 | rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®); |
1313 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); | 1215 | rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); |
1314 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); | 1216 | rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); |
1315 | rt73usb_register_write(rt2x00dev, MAC_CSR1, reg); | 1217 | rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg); |
1316 | 1218 | ||
1317 | rt73usb_register_read(rt2x00dev, MAC_CSR1, ®); | 1219 | rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®); |
1318 | rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); | 1220 | rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); |
1319 | rt73usb_register_write(rt2x00dev, MAC_CSR1, reg); | 1221 | rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg); |
1320 | 1222 | ||
1321 | return 0; | 1223 | return 0; |
1322 | } | 1224 | } |
@@ -1394,11 +1296,11 @@ static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, | |||
1394 | { | 1296 | { |
1395 | u32 reg; | 1297 | u32 reg; |
1396 | 1298 | ||
1397 | rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); | 1299 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); |
1398 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, | 1300 | rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, |
1399 | (state == STATE_RADIO_RX_OFF) || | 1301 | (state == STATE_RADIO_RX_OFF) || |
1400 | (state == STATE_RADIO_RX_OFF_LINK)); | 1302 | (state == STATE_RADIO_RX_OFF_LINK)); |
1401 | rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); | 1303 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); |
1402 | } | 1304 | } |
1403 | 1305 | ||
1404 | static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) | 1306 | static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) |
@@ -1415,12 +1317,12 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) | |||
1415 | 1317 | ||
1416 | static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev) | 1318 | static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev) |
1417 | { | 1319 | { |
1418 | rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818); | 1320 | rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818); |
1419 | 1321 | ||
1420 | /* | 1322 | /* |
1421 | * Disable synchronisation. | 1323 | * Disable synchronisation. |
1422 | */ | 1324 | */ |
1423 | rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); | 1325 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, 0); |
1424 | 1326 | ||
1425 | rt2x00usb_disable_radio(rt2x00dev); | 1327 | rt2x00usb_disable_radio(rt2x00dev); |
1426 | } | 1328 | } |
@@ -1433,10 +1335,10 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) | |||
1433 | 1335 | ||
1434 | put_to_sleep = (state != STATE_AWAKE); | 1336 | put_to_sleep = (state != STATE_AWAKE); |
1435 | 1337 | ||
1436 | rt73usb_register_read(rt2x00dev, MAC_CSR12, ®); | 1338 | rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®); |
1437 | rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep); | 1339 | rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep); |
1438 | rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep); | 1340 | rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep); |
1439 | rt73usb_register_write(rt2x00dev, MAC_CSR12, reg); | 1341 | rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg); |
1440 | 1342 | ||
1441 | /* | 1343 | /* |
1442 | * Device is not guaranteed to be in the requested state yet. | 1344 | * Device is not guaranteed to be in the requested state yet. |
@@ -1444,7 +1346,7 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) | |||
1444 | * device has entered the correct state. | 1346 | * device has entered the correct state. |
1445 | */ | 1347 | */ |
1446 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 1348 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
1447 | rt73usb_register_read(rt2x00dev, MAC_CSR12, ®); | 1349 | rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®); |
1448 | state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); | 1350 | state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); |
1449 | if (state == !put_to_sleep) | 1351 | if (state == !put_to_sleep) |
1450 | return 0; | 1352 | return 0; |
@@ -1584,11 +1486,11 @@ static void rt73usb_write_beacon(struct queue_entry *entry) | |||
1584 | * Disable beaconing while we are reloading the beacon data, | 1486 | * Disable beaconing while we are reloading the beacon data, |
1585 | * otherwise we might be sending out invalid data. | 1487 | * otherwise we might be sending out invalid data. |
1586 | */ | 1488 | */ |
1587 | rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); | 1489 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); |
1588 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); | 1490 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); |
1589 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); | 1491 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); |
1590 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); | 1492 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); |
1591 | rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 1493 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
1592 | 1494 | ||
1593 | /* | 1495 | /* |
1594 | * Write entire beacon with descriptor to register. | 1496 | * Write entire beacon with descriptor to register. |
@@ -1606,8 +1508,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry) | |||
1606 | entry->skb = NULL; | 1508 | entry->skb = NULL; |
1607 | } | 1509 | } |
1608 | 1510 | ||
1609 | static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | 1511 | static int rt73usb_get_tx_data_len(struct queue_entry *entry) |
1610 | struct sk_buff *skb) | ||
1611 | { | 1512 | { |
1612 | int length; | 1513 | int length; |
1613 | 1514 | ||
@@ -1615,8 +1516,8 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, | |||
1615 | * The length _must_ be a multiple of 4, | 1516 | * The length _must_ be a multiple of 4, |
1616 | * but it must _not_ be a multiple of the USB packet size. | 1517 | * but it must _not_ be a multiple of the USB packet size. |
1617 | */ | 1518 | */ |
1618 | length = roundup(skb->len, 4); | 1519 | length = roundup(entry->skb->len, 4); |
1619 | length += (4 * !(length % rt2x00dev->usb_maxpacket)); | 1520 | length += (4 * !(length % entry->queue->usb_maxpacket)); |
1620 | 1521 | ||
1621 | return length; | 1522 | return length; |
1622 | } | 1523 | } |
@@ -1635,14 +1536,14 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, | |||
1635 | * For Wi-Fi faily generated beacons between participating stations. | 1536 | * For Wi-Fi faily generated beacons between participating stations. |
1636 | * Set TBTT phase adaptive adjustment step to 8us (default 16us) | 1537 | * Set TBTT phase adaptive adjustment step to 8us (default 16us) |
1637 | */ | 1538 | */ |
1638 | rt73usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); | 1539 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); |
1639 | 1540 | ||
1640 | rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); | 1541 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); |
1641 | if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { | 1542 | if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { |
1642 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); | 1543 | rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); |
1643 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); | 1544 | rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); |
1644 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); | 1545 | rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); |
1645 | rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); | 1546 | rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); |
1646 | } | 1547 | } |
1647 | } | 1548 | } |
1648 | 1549 | ||
@@ -1881,7 +1782,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1881 | * Identify RF chipset. | 1782 | * Identify RF chipset. |
1882 | */ | 1783 | */ |
1883 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); | 1784 | value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); |
1884 | rt73usb_register_read(rt2x00dev, MAC_CSR0, ®); | 1785 | rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); |
1885 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); | 1786 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); |
1886 | 1787 | ||
1887 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) { | 1788 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) { |
@@ -2235,33 +2136,33 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, | |||
2235 | field.bit_offset = queue_idx * 16; | 2136 | field.bit_offset = queue_idx * 16; |
2236 | field.bit_mask = 0xffff << field.bit_offset; | 2137 | field.bit_mask = 0xffff << field.bit_offset; |
2237 | 2138 | ||
2238 | rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®); | 2139 | rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR0, ®); |
2239 | rt2x00_set_field32(®, field, queue->txop); | 2140 | rt2x00_set_field32(®, field, queue->txop); |
2240 | rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg); | 2141 | rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg); |
2241 | } else if (queue_idx < 4) { | 2142 | } else if (queue_idx < 4) { |
2242 | field.bit_offset = (queue_idx - 2) * 16; | 2143 | field.bit_offset = (queue_idx - 2) * 16; |
2243 | field.bit_mask = 0xffff << field.bit_offset; | 2144 | field.bit_mask = 0xffff << field.bit_offset; |
2244 | 2145 | ||
2245 | rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®); | 2146 | rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR1, ®); |
2246 | rt2x00_set_field32(®, field, queue->txop); | 2147 | rt2x00_set_field32(®, field, queue->txop); |
2247 | rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg); | 2148 | rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg); |
2248 | } | 2149 | } |
2249 | 2150 | ||
2250 | /* Update WMM registers */ | 2151 | /* Update WMM registers */ |
2251 | field.bit_offset = queue_idx * 4; | 2152 | field.bit_offset = queue_idx * 4; |
2252 | field.bit_mask = 0xf << field.bit_offset; | 2153 | field.bit_mask = 0xf << field.bit_offset; |
2253 | 2154 | ||
2254 | rt73usb_register_read(rt2x00dev, AIFSN_CSR, ®); | 2155 | rt2x00usb_register_read(rt2x00dev, AIFSN_CSR, ®); |
2255 | rt2x00_set_field32(®, field, queue->aifs); | 2156 | rt2x00_set_field32(®, field, queue->aifs); |
2256 | rt73usb_register_write(rt2x00dev, AIFSN_CSR, reg); | 2157 | rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg); |
2257 | 2158 | ||
2258 | rt73usb_register_read(rt2x00dev, CWMIN_CSR, ®); | 2159 | rt2x00usb_register_read(rt2x00dev, CWMIN_CSR, ®); |
2259 | rt2x00_set_field32(®, field, queue->cw_min); | 2160 | rt2x00_set_field32(®, field, queue->cw_min); |
2260 | rt73usb_register_write(rt2x00dev, CWMIN_CSR, reg); | 2161 | rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg); |
2261 | 2162 | ||
2262 | rt73usb_register_read(rt2x00dev, CWMAX_CSR, ®); | 2163 | rt2x00usb_register_read(rt2x00dev, CWMAX_CSR, ®); |
2263 | rt2x00_set_field32(®, field, queue->cw_max); | 2164 | rt2x00_set_field32(®, field, queue->cw_max); |
2264 | rt73usb_register_write(rt2x00dev, CWMAX_CSR, reg); | 2165 | rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg); |
2265 | 2166 | ||
2266 | return 0; | 2167 | return 0; |
2267 | } | 2168 | } |
@@ -2279,9 +2180,9 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) | |||
2279 | u64 tsf; | 2180 | u64 tsf; |
2280 | u32 reg; | 2181 | u32 reg; |
2281 | 2182 | ||
2282 | rt73usb_register_read(rt2x00dev, TXRX_CSR13, ®); | 2183 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, ®); |
2283 | tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; | 2184 | tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; |
2284 | rt73usb_register_read(rt2x00dev, TXRX_CSR12, ®); | 2185 | rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, ®); |
2285 | tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER); | 2186 | tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER); |
2286 | 2187 | ||
2287 | return tsf; | 2188 | return tsf; |
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index 33725d0978b3..c385407a9941 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h | |||
@@ -111,6 +111,13 @@ struct rtl8187_priv { | |||
111 | u8 signal; | 111 | u8 signal; |
112 | u8 quality; | 112 | u8 quality; |
113 | u8 noise; | 113 | u8 noise; |
114 | u8 slot_time; | ||
115 | u8 aifsn[4]; | ||
116 | struct { | ||
117 | __le64 buf; | ||
118 | struct urb *urb; | ||
119 | struct sk_buff_head queue; | ||
120 | } b_tx_status; | ||
114 | }; | 121 | }; |
115 | 122 | ||
116 | void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); | 123 | void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 4a9f76f46f77..69ea5222f163 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -176,8 +176,27 @@ static void rtl8187_tx_cb(struct urb *urb) | |||
176 | skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : | 176 | skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : |
177 | sizeof(struct rtl8187_tx_hdr)); | 177 | sizeof(struct rtl8187_tx_hdr)); |
178 | ieee80211_tx_info_clear_status(info); | 178 | ieee80211_tx_info_clear_status(info); |
179 | info->flags |= IEEE80211_TX_STAT_ACK; | 179 | |
180 | ieee80211_tx_status_irqsafe(hw, skb); | 180 | if (!urb->status && |
181 | !(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
182 | priv->is_rtl8187b) { | ||
183 | skb_queue_tail(&priv->b_tx_status.queue, skb); | ||
184 | |||
185 | /* queue is "full", discard last items */ | ||
186 | while (skb_queue_len(&priv->b_tx_status.queue) > 5) { | ||
187 | struct sk_buff *old_skb; | ||
188 | |||
189 | dev_dbg(&priv->udev->dev, | ||
190 | "transmit status queue full\n"); | ||
191 | |||
192 | old_skb = skb_dequeue(&priv->b_tx_status.queue); | ||
193 | ieee80211_tx_status_irqsafe(hw, old_skb); | ||
194 | } | ||
195 | } else { | ||
196 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !urb->status) | ||
197 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
198 | ieee80211_tx_status_irqsafe(hw, skb); | ||
199 | } | ||
181 | } | 200 | } |
182 | 201 | ||
183 | static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | 202 | static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) |
@@ -219,7 +238,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
219 | hdr->flags = cpu_to_le32(flags); | 238 | hdr->flags = cpu_to_le32(flags); |
220 | hdr->len = 0; | 239 | hdr->len = 0; |
221 | hdr->rts_duration = rts_dur; | 240 | hdr->rts_duration = rts_dur; |
222 | hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); | 241 | hdr->retry = cpu_to_le32(info->control.rates[0].count << 8); |
223 | buf = hdr; | 242 | buf = hdr; |
224 | 243 | ||
225 | ep = 2; | 244 | ep = 2; |
@@ -237,7 +256,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
237 | memset(hdr, 0, sizeof(*hdr)); | 256 | memset(hdr, 0, sizeof(*hdr)); |
238 | hdr->flags = cpu_to_le32(flags); | 257 | hdr->flags = cpu_to_le32(flags); |
239 | hdr->rts_duration = rts_dur; | 258 | hdr->rts_duration = rts_dur; |
240 | hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); | 259 | hdr->retry = cpu_to_le32(info->control.rates[0].count << 8); |
241 | hdr->tx_duration = | 260 | hdr->tx_duration = |
242 | ieee80211_generic_frame_duration(dev, priv->vif, | 261 | ieee80211_generic_frame_duration(dev, priv->vif, |
243 | skb->len, txrate); | 262 | skb->len, txrate); |
@@ -403,6 +422,109 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) | |||
403 | return 0; | 422 | return 0; |
404 | } | 423 | } |
405 | 424 | ||
425 | static void rtl8187b_status_cb(struct urb *urb) | ||
426 | { | ||
427 | struct ieee80211_hw *hw = (struct ieee80211_hw *)urb->context; | ||
428 | struct rtl8187_priv *priv = hw->priv; | ||
429 | u64 val; | ||
430 | unsigned int cmd_type; | ||
431 | |||
432 | if (unlikely(urb->status)) { | ||
433 | usb_free_urb(urb); | ||
434 | return; | ||
435 | } | ||
436 | |||
437 | /* | ||
438 | * Read from status buffer: | ||
439 | * | ||
440 | * bits [30:31] = cmd type: | ||
441 | * - 0 indicates tx beacon interrupt | ||
442 | * - 1 indicates tx close descriptor | ||
443 | * | ||
444 | * In the case of tx beacon interrupt: | ||
445 | * [0:9] = Last Beacon CW | ||
446 | * [10:29] = reserved | ||
447 | * [30:31] = 00b | ||
448 | * [32:63] = Last Beacon TSF | ||
449 | * | ||
450 | * If it's tx close descriptor: | ||
451 | * [0:7] = Packet Retry Count | ||
452 | * [8:14] = RTS Retry Count | ||
453 | * [15] = TOK | ||
454 | * [16:27] = Sequence No | ||
455 | * [28] = LS | ||
456 | * [29] = FS | ||
457 | * [30:31] = 01b | ||
458 | * [32:47] = unused (reserved?) | ||
459 | * [48:63] = MAC Used Time | ||
460 | */ | ||
461 | val = le64_to_cpu(priv->b_tx_status.buf); | ||
462 | |||
463 | cmd_type = (val >> 30) & 0x3; | ||
464 | if (cmd_type == 1) { | ||
465 | unsigned int pkt_rc, seq_no; | ||
466 | bool tok; | ||
467 | struct sk_buff *skb; | ||
468 | struct ieee80211_hdr *ieee80211hdr; | ||
469 | unsigned long flags; | ||
470 | |||
471 | pkt_rc = val & 0xFF; | ||
472 | tok = val & (1 << 15); | ||
473 | seq_no = (val >> 16) & 0xFFF; | ||
474 | |||
475 | spin_lock_irqsave(&priv->b_tx_status.queue.lock, flags); | ||
476 | skb_queue_reverse_walk(&priv->b_tx_status.queue, skb) { | ||
477 | ieee80211hdr = (struct ieee80211_hdr *)skb->data; | ||
478 | |||
479 | /* | ||
480 | * While testing, it was discovered that the seq_no | ||
481 | * doesn't actually contains the sequence number. | ||
482 | * Instead of returning just the 12 bits of sequence | ||
483 | * number, hardware is returning entire sequence control | ||
484 | * (fragment number plus sequence number) in a 12 bit | ||
485 | * only field overflowing after some time. As a | ||
486 | * workaround, just consider the lower bits, and expect | ||
487 | * it's unlikely we wrongly ack some sent data | ||
488 | */ | ||
489 | if ((le16_to_cpu(ieee80211hdr->seq_ctrl) | ||
490 | & 0xFFF) == seq_no) | ||
491 | break; | ||
492 | } | ||
493 | if (skb != (struct sk_buff *) &priv->b_tx_status.queue) { | ||
494 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
495 | |||
496 | __skb_unlink(skb, &priv->b_tx_status.queue); | ||
497 | if (tok) | ||
498 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
499 | info->status.rates[0].count = pkt_rc + 1; | ||
500 | |||
501 | ieee80211_tx_status_irqsafe(hw, skb); | ||
502 | } | ||
503 | spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags); | ||
504 | } | ||
505 | |||
506 | usb_submit_urb(urb, GFP_ATOMIC); | ||
507 | } | ||
508 | |||
509 | static int rtl8187b_init_status_urb(struct ieee80211_hw *dev) | ||
510 | { | ||
511 | struct rtl8187_priv *priv = dev->priv; | ||
512 | struct urb *entry; | ||
513 | |||
514 | entry = usb_alloc_urb(0, GFP_KERNEL); | ||
515 | if (!entry) | ||
516 | return -ENOMEM; | ||
517 | priv->b_tx_status.urb = entry; | ||
518 | |||
519 | usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9), | ||
520 | &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf), | ||
521 | rtl8187b_status_cb, dev); | ||
522 | |||
523 | usb_submit_urb(entry, GFP_KERNEL); | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
406 | static int rtl8187_cmd_reset(struct ieee80211_hw *dev) | 528 | static int rtl8187_cmd_reset(struct ieee80211_hw *dev) |
407 | { | 529 | { |
408 | struct rtl8187_priv *priv = dev->priv; | 530 | struct rtl8187_priv *priv = dev->priv; |
@@ -712,6 +834,13 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev) | |||
712 | 834 | ||
713 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1); | 835 | rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1); |
714 | 836 | ||
837 | priv->slot_time = 0x9; | ||
838 | priv->aifsn[0] = 2; /* AIFSN[AC_VO] */ | ||
839 | priv->aifsn[1] = 2; /* AIFSN[AC_VI] */ | ||
840 | priv->aifsn[2] = 7; /* AIFSN[AC_BK] */ | ||
841 | priv->aifsn[3] = 3; /* AIFSN[AC_BE] */ | ||
842 | rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); | ||
843 | |||
715 | return 0; | 844 | return 0; |
716 | } | 845 | } |
717 | 846 | ||
@@ -748,6 +877,7 @@ static int rtl8187_start(struct ieee80211_hw *dev) | |||
748 | (7 << 0 /* long retry limit */) | | 877 | (7 << 0 /* long retry limit */) | |
749 | (7 << 21 /* MAX TX DMA */)); | 878 | (7 << 21 /* MAX TX DMA */)); |
750 | rtl8187_init_urbs(dev); | 879 | rtl8187_init_urbs(dev); |
880 | rtl8187b_init_status_urb(dev); | ||
751 | mutex_unlock(&priv->conf_mutex); | 881 | mutex_unlock(&priv->conf_mutex); |
752 | return 0; | 882 | return 0; |
753 | } | 883 | } |
@@ -824,6 +954,9 @@ static void rtl8187_stop(struct ieee80211_hw *dev) | |||
824 | usb_kill_urb(info->urb); | 954 | usb_kill_urb(info->urb); |
825 | kfree_skb(skb); | 955 | kfree_skb(skb); |
826 | } | 956 | } |
957 | while ((skb = skb_dequeue(&priv->b_tx_status.queue))) | ||
958 | dev_kfree_skb_any(skb); | ||
959 | usb_kill_urb(priv->b_tx_status.urb); | ||
827 | mutex_unlock(&priv->conf_mutex); | 960 | mutex_unlock(&priv->conf_mutex); |
828 | } | 961 | } |
829 | 962 | ||
@@ -919,24 +1052,38 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, | |||
919 | return 0; | 1052 | return 0; |
920 | } | 1053 | } |
921 | 1054 | ||
1055 | /* | ||
1056 | * With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for | ||
1057 | * example. Thus we have to use raw values for AC_*_PARAM register addresses. | ||
1058 | */ | ||
1059 | static __le32 *rtl8187b_ac_addr[4] = { | ||
1060 | (__le32 *) 0xFFF0, /* AC_VO */ | ||
1061 | (__le32 *) 0xFFF4, /* AC_VI */ | ||
1062 | (__le32 *) 0xFFFC, /* AC_BK */ | ||
1063 | (__le32 *) 0xFFF8, /* AC_BE */ | ||
1064 | }; | ||
1065 | |||
1066 | #define SIFS_TIME 0xa | ||
1067 | |||
922 | static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot, | 1068 | static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot, |
923 | bool use_short_preamble) | 1069 | bool use_short_preamble) |
924 | { | 1070 | { |
925 | if (priv->is_rtl8187b) { | 1071 | if (priv->is_rtl8187b) { |
926 | u8 difs, eifs, slot_time; | 1072 | u8 difs, eifs; |
927 | u16 ack_timeout; | 1073 | u16 ack_timeout; |
1074 | int queue; | ||
928 | 1075 | ||
929 | if (use_short_slot) { | 1076 | if (use_short_slot) { |
930 | slot_time = 0x9; | 1077 | priv->slot_time = 0x9; |
931 | difs = 0x1c; | 1078 | difs = 0x1c; |
932 | eifs = 0x53; | 1079 | eifs = 0x53; |
933 | } else { | 1080 | } else { |
934 | slot_time = 0x14; | 1081 | priv->slot_time = 0x14; |
935 | difs = 0x32; | 1082 | difs = 0x32; |
936 | eifs = 0x5b; | 1083 | eifs = 0x5b; |
937 | } | 1084 | } |
938 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0xa); | 1085 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); |
939 | rtl818x_iowrite8(priv, &priv->map->SLOT, slot_time); | 1086 | rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time); |
940 | rtl818x_iowrite8(priv, &priv->map->DIFS, difs); | 1087 | rtl818x_iowrite8(priv, &priv->map->DIFS, difs); |
941 | 1088 | ||
942 | /* | 1089 | /* |
@@ -957,18 +1104,21 @@ static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot, | |||
957 | ack_timeout += 144; | 1104 | ack_timeout += 144; |
958 | rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, | 1105 | rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, |
959 | DIV_ROUND_UP(ack_timeout, 4)); | 1106 | DIV_ROUND_UP(ack_timeout, 4)); |
1107 | |||
1108 | for (queue = 0; queue < 4; queue++) | ||
1109 | rtl818x_iowrite8(priv, (u8 *) rtl8187b_ac_addr[queue], | ||
1110 | priv->aifsn[queue] * priv->slot_time + | ||
1111 | SIFS_TIME); | ||
960 | } else { | 1112 | } else { |
961 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); | 1113 | rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); |
962 | if (use_short_slot) { | 1114 | if (use_short_slot) { |
963 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); | 1115 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); |
964 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); | 1116 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); |
965 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); | 1117 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); |
966 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); | ||
967 | } else { | 1118 | } else { |
968 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); | 1119 | rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); |
969 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); | 1120 | rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); |
970 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); | 1121 | rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); |
971 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); | ||
972 | } | 1122 | } |
973 | } | 1123 | } |
974 | } | 1124 | } |
@@ -1017,6 +1167,42 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev, | |||
1017 | rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); | 1167 | rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); |
1018 | } | 1168 | } |
1019 | 1169 | ||
1170 | static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue, | ||
1171 | const struct ieee80211_tx_queue_params *params) | ||
1172 | { | ||
1173 | struct rtl8187_priv *priv = dev->priv; | ||
1174 | u8 cw_min, cw_max; | ||
1175 | |||
1176 | if (queue > 3) | ||
1177 | return -EINVAL; | ||
1178 | |||
1179 | cw_min = fls(params->cw_min); | ||
1180 | cw_max = fls(params->cw_max); | ||
1181 | |||
1182 | if (priv->is_rtl8187b) { | ||
1183 | priv->aifsn[queue] = params->aifs; | ||
1184 | |||
1185 | /* | ||
1186 | * This is the structure of AC_*_PARAM registers in 8187B: | ||
1187 | * - TXOP limit field, bit offset = 16 | ||
1188 | * - ECWmax, bit offset = 12 | ||
1189 | * - ECWmin, bit offset = 8 | ||
1190 | * - AIFS, bit offset = 0 | ||
1191 | */ | ||
1192 | rtl818x_iowrite32(priv, rtl8187b_ac_addr[queue], | ||
1193 | (params->txop << 16) | (cw_max << 12) | | ||
1194 | (cw_min << 8) | (params->aifs * | ||
1195 | priv->slot_time + SIFS_TIME)); | ||
1196 | } else { | ||
1197 | if (queue != 0) | ||
1198 | return -EINVAL; | ||
1199 | |||
1200 | rtl818x_iowrite8(priv, &priv->map->CW_VAL, | ||
1201 | cw_min | (cw_max << 4)); | ||
1202 | } | ||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1020 | static const struct ieee80211_ops rtl8187_ops = { | 1206 | static const struct ieee80211_ops rtl8187_ops = { |
1021 | .tx = rtl8187_tx, | 1207 | .tx = rtl8187_tx, |
1022 | .start = rtl8187_start, | 1208 | .start = rtl8187_start, |
@@ -1027,6 +1213,7 @@ static const struct ieee80211_ops rtl8187_ops = { | |||
1027 | .config_interface = rtl8187_config_interface, | 1213 | .config_interface = rtl8187_config_interface, |
1028 | .bss_info_changed = rtl8187_bss_info_changed, | 1214 | .bss_info_changed = rtl8187_bss_info_changed, |
1029 | .configure_filter = rtl8187_configure_filter, | 1215 | .configure_filter = rtl8187_configure_filter, |
1216 | .conf_tx = rtl8187_conf_tx | ||
1030 | }; | 1217 | }; |
1031 | 1218 | ||
1032 | static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 1219 | static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
@@ -1222,9 +1409,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1222 | } | 1409 | } |
1223 | 1410 | ||
1224 | if (priv->is_rtl8187b) { | 1411 | if (priv->is_rtl8187b) { |
1225 | printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " | 1412 | printk(KERN_WARNING "rtl8187: 8187B chip detected.\n"); |
1226 | "is EXPERIMENTAL, and could damage your\n" | ||
1227 | " hardware, use at your own risk\n"); | ||
1228 | dev->flags |= IEEE80211_HW_SIGNAL_DBM; | 1413 | dev->flags |= IEEE80211_HW_SIGNAL_DBM; |
1229 | } else { | 1414 | } else { |
1230 | dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC; | 1415 | dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC; |
@@ -1256,6 +1441,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1256 | goto err_free_dev; | 1441 | goto err_free_dev; |
1257 | } | 1442 | } |
1258 | mutex_init(&priv->conf_mutex); | 1443 | mutex_init(&priv->conf_mutex); |
1444 | skb_queue_head_init(&priv->b_tx_status.queue); | ||
1259 | 1445 | ||
1260 | printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n", | 1446 | printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n", |
1261 | wiphy_name(dev->wiphy), dev->wiphy->perm_addr, | 1447 | wiphy_name(dev->wiphy), dev->wiphy->perm_addr, |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c index 69030be62b36..4e75e8e7fa90 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c | |||
@@ -878,12 +878,6 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev) | |||
878 | for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++) | 878 | for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++) |
879 | rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]); | 879 | rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]); |
880 | 880 | ||
881 | rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28); | ||
882 | rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28); | ||
883 | rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28); | ||
884 | rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28); | ||
885 | rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); | ||
886 | |||
887 | rtl8225_write_phy_ofdm(dev, 0x97, 0x46); | 881 | rtl8225_write_phy_ofdm(dev, 0x97, 0x46); |
888 | rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); | 882 | rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); |
889 | rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); | 883 | rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 56b0eb25d927..a6ec928186ad 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1042,6 +1042,68 @@ enum ieee80211_spectrum_mgmt_actioncode { | |||
1042 | WLAN_ACTION_SPCT_CHL_SWITCH = 4, | 1042 | WLAN_ACTION_SPCT_CHL_SWITCH = 4, |
1043 | }; | 1043 | }; |
1044 | 1044 | ||
1045 | /* | ||
1046 | * IEEE 802.11-2007 7.3.2.9 Country information element | ||
1047 | * | ||
1048 | * Minimum length is 8 octets, ie len must be evenly | ||
1049 | * divisible by 2 | ||
1050 | */ | ||
1051 | |||
1052 | /* Although the spec says 8 I'm seeing 6 in practice */ | ||
1053 | #define IEEE80211_COUNTRY_IE_MIN_LEN 6 | ||
1054 | |||
1055 | /* | ||
1056 | * For regulatory extension stuff see IEEE 802.11-2007 | ||
1057 | * Annex I (page 1141) and Annex J (page 1147). Also | ||
1058 | * review 7.3.2.9. | ||
1059 | * | ||
1060 | * When dot11RegulatoryClassesRequired is true and the | ||
1061 | * first_channel/reg_extension_id is >= 201 then the IE | ||
1062 | * compromises of the 'ext' struct represented below: | ||
1063 | * | ||
1064 | * - Regulatory extension ID - when generating IE this just needs | ||
1065 | * to be monotonically increasing for each triplet passed in | ||
1066 | * the IE | ||
1067 | * - Regulatory class - index into set of rules | ||
1068 | * - Coverage class - index into air propagation time (Table 7-27), | ||
1069 | * in microseconds, you can compute the air propagation time from | ||
1070 | * the index by multiplying by 3, so index 10 yields a propagation | ||
1071 | * of 10 us. Valid values are 0-31, values 32-255 are not defined | ||
1072 | * yet. A value of 0 inicates air propagation of <= 1 us. | ||
1073 | * | ||
1074 | * See also Table I.2 for Emission limit sets and table | ||
1075 | * I.3 for Behavior limit sets. Table J.1 indicates how to map | ||
1076 | * a reg_class to an emission limit set and behavior limit set. | ||
1077 | */ | ||
1078 | #define IEEE80211_COUNTRY_EXTENSION_ID 201 | ||
1079 | |||
1080 | /* | ||
1081 | * Channels numbers in the IE must be monotonically increasing | ||
1082 | * if dot11RegulatoryClassesRequired is not true. | ||
1083 | * | ||
1084 | * If dot11RegulatoryClassesRequired is true consecutive | ||
1085 | * subband triplets following a regulatory triplet shall | ||
1086 | * have monotonically increasing first_channel number fields. | ||
1087 | * | ||
1088 | * Channel numbers shall not overlap. | ||
1089 | * | ||
1090 | * Note that max_power is signed. | ||
1091 | */ | ||
1092 | struct ieee80211_country_ie_triplet { | ||
1093 | union { | ||
1094 | struct { | ||
1095 | u8 first_channel; | ||
1096 | u8 num_channels; | ||
1097 | s8 max_power; | ||
1098 | } __attribute__ ((packed)) chans; | ||
1099 | struct { | ||
1100 | u8 reg_extension_id; | ||
1101 | u8 reg_class; | ||
1102 | u8 coverage_class; | ||
1103 | } __attribute__ ((packed)) ext; | ||
1104 | }; | ||
1105 | } __attribute__ ((packed)); | ||
1106 | |||
1045 | /* BACK action code */ | 1107 | /* BACK action code */ |
1046 | enum ieee80211_back_actioncode { | 1108 | enum ieee80211_back_actioncode { |
1047 | WLAN_ACTION_ADDBA_REQ = 0, | 1109 | WLAN_ACTION_ADDBA_REQ = 0, |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 79827345351d..e08c8bcfb78d 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -508,6 +508,8 @@ enum nl80211_band_attr { | |||
508 | * on this channel in current regulatory domain. | 508 | * on this channel in current regulatory domain. |
509 | * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory | 509 | * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory |
510 | * on this channel in current regulatory domain. | 510 | * on this channel in current regulatory domain. |
511 | * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm | ||
512 | * (100 * dBm). | ||
511 | */ | 513 | */ |
512 | enum nl80211_frequency_attr { | 514 | enum nl80211_frequency_attr { |
513 | __NL80211_FREQUENCY_ATTR_INVALID, | 515 | __NL80211_FREQUENCY_ATTR_INVALID, |
@@ -516,12 +518,15 @@ enum nl80211_frequency_attr { | |||
516 | NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, | 518 | NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, |
517 | NL80211_FREQUENCY_ATTR_NO_IBSS, | 519 | NL80211_FREQUENCY_ATTR_NO_IBSS, |
518 | NL80211_FREQUENCY_ATTR_RADAR, | 520 | NL80211_FREQUENCY_ATTR_RADAR, |
521 | NL80211_FREQUENCY_ATTR_MAX_TX_POWER, | ||
519 | 522 | ||
520 | /* keep last */ | 523 | /* keep last */ |
521 | __NL80211_FREQUENCY_ATTR_AFTER_LAST, | 524 | __NL80211_FREQUENCY_ATTR_AFTER_LAST, |
522 | NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 | 525 | NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 |
523 | }; | 526 | }; |
524 | 527 | ||
528 | #define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER | ||
529 | |||
525 | /** | 530 | /** |
526 | * enum nl80211_bitrate_attr - bitrate attributes | 531 | * enum nl80211_bitrate_attr - bitrate attributes |
527 | * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps | 532 | * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps |
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index 4cd64b0d9825..f376a93927f7 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h | |||
@@ -108,6 +108,7 @@ struct rfkill { | |||
108 | 108 | ||
109 | struct device dev; | 109 | struct device dev; |
110 | struct list_head node; | 110 | struct list_head node; |
111 | enum rfkill_state state_for_resume; | ||
111 | }; | 112 | }; |
112 | #define to_rfkill(d) container_of(d, struct rfkill, dev) | 113 | #define to_rfkill(d) container_of(d, struct rfkill, dev) |
113 | 114 | ||
diff --git a/include/net/wireless.h b/include/net/wireless.h index 412351560b76..21c5d966142d 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h | |||
@@ -181,6 +181,11 @@ struct ieee80211_supported_band { | |||
181 | * struct wiphy - wireless hardware description | 181 | * struct wiphy - wireless hardware description |
182 | * @idx: the wiphy index assigned to this item | 182 | * @idx: the wiphy index assigned to this item |
183 | * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name> | 183 | * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name> |
184 | * @fw_handles_regulatory: tells us the firmware for this device | ||
185 | * has its own regulatory solution and cannot identify the | ||
186 | * ISO / IEC 3166 alpha2 it belongs to. When this is enabled | ||
187 | * we will disregard the first regulatory hint (when the | ||
188 | * initiator is %REGDOM_SET_BY_CORE). | ||
184 | * @reg_notifier: the driver's regulatory notification callback | 189 | * @reg_notifier: the driver's regulatory notification callback |
185 | */ | 190 | */ |
186 | struct wiphy { | 191 | struct wiphy { |
@@ -192,6 +197,8 @@ struct wiphy { | |||
192 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ | 197 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ |
193 | u16 interface_modes; | 198 | u16 interface_modes; |
194 | 199 | ||
200 | bool fw_handles_regulatory; | ||
201 | |||
195 | /* If multiple wiphys are registered and you're handed e.g. | 202 | /* If multiple wiphys are registered and you're handed e.g. |
196 | * a regular netdev with assigned ieee80211_ptr, you won't | 203 | * a regular netdev with assigned ieee80211_ptr, you won't |
197 | * know whether it points to a wiphy your driver has registered | 204 | * know whether it points to a wiphy your driver has registered |
@@ -373,4 +380,19 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband, | |||
373 | * for a regulatory domain structure for the respective country. | 380 | * for a regulatory domain structure for the respective country. |
374 | */ | 381 | */ |
375 | extern void regulatory_hint(struct wiphy *wiphy, const char *alpha2); | 382 | extern void regulatory_hint(struct wiphy *wiphy, const char *alpha2); |
383 | |||
384 | /** | ||
385 | * regulatory_hint_11d - hints a country IE as a regulatory domain | ||
386 | * @wiphy: the wireless device giving the hint (used only for reporting | ||
387 | * conflicts) | ||
388 | * @country_ie: pointer to the country IE | ||
389 | * @country_ie_len: length of the country IE | ||
390 | * | ||
391 | * We will intersect the rd with the what CRDA tells us should apply | ||
392 | * for the alpha2 this country IE belongs to, this prevents APs from | ||
393 | * sending us incorrect or outdated information against a country. | ||
394 | */ | ||
395 | extern void regulatory_hint_11d(struct wiphy *wiphy, | ||
396 | u8 *country_ie, | ||
397 | u8 country_ie_len); | ||
376 | #endif /* __NET_WIRELESS_H */ | 398 | #endif /* __NET_WIRELESS_H */ |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 7f710a27e91c..60c16162474c 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -16,20 +16,20 @@ menu "Rate control algorithm selection" | |||
16 | 16 | ||
17 | config MAC80211_RC_PID | 17 | config MAC80211_RC_PID |
18 | bool "PID controller based rate control algorithm" if EMBEDDED | 18 | bool "PID controller based rate control algorithm" if EMBEDDED |
19 | default y | ||
20 | ---help--- | 19 | ---help--- |
21 | This option enables a TX rate control algorithm for | 20 | This option enables a TX rate control algorithm for |
22 | mac80211 that uses a PID controller to select the TX | 21 | mac80211 that uses a PID controller to select the TX |
23 | rate. | 22 | rate. |
24 | 23 | ||
25 | config MAC80211_RC_MINSTREL | 24 | config MAC80211_RC_MINSTREL |
26 | bool "Minstrel" | 25 | bool "Minstrel" if EMBEDDED |
26 | default y | ||
27 | ---help--- | 27 | ---help--- |
28 | This option enables the 'minstrel' TX rate control algorithm | 28 | This option enables the 'minstrel' TX rate control algorithm |
29 | 29 | ||
30 | choice | 30 | choice |
31 | prompt "Default rate control algorithm" | 31 | prompt "Default rate control algorithm" |
32 | default MAC80211_RC_DEFAULT_PID | 32 | default MAC80211_RC_DEFAULT_MINSTREL |
33 | ---help--- | 33 | ---help--- |
34 | This option selects the default rate control algorithm | 34 | This option selects the default rate control algorithm |
35 | mac80211 will use. Note that this default can still be | 35 | mac80211 will use. Note that this default can still be |
@@ -55,8 +55,8 @@ endchoice | |||
55 | 55 | ||
56 | config MAC80211_RC_DEFAULT | 56 | config MAC80211_RC_DEFAULT |
57 | string | 57 | string |
58 | default "pid" if MAC80211_RC_DEFAULT_PID | ||
59 | default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL | 58 | default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL |
59 | default "pid" if MAC80211_RC_DEFAULT_PID | ||
60 | default "" | 60 | default "" |
61 | 61 | ||
62 | endmenu | 62 | endmenu |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 3e231d756776..a1eed7032c9b 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -36,7 +36,7 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | |||
36 | 36 | ||
37 | ht_cap->ht_supported = true; | 37 | ht_cap->ht_supported = true; |
38 | 38 | ||
39 | ht_cap->cap = ht_cap->cap & sband->ht_cap.cap; | 39 | ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) & sband->ht_cap.cap; |
40 | ht_cap->cap &= ~IEEE80211_HT_CAP_SM_PS; | 40 | ht_cap->cap &= ~IEEE80211_HT_CAP_SM_PS; |
41 | ht_cap->cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS; | 41 | ht_cap->cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS; |
42 | 42 | ||
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d631dc96c323..cec9b6d3e1ce 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -722,7 +722,6 @@ EXPORT_SYMBOL(ieee80211_alloc_hw); | |||
722 | int ieee80211_register_hw(struct ieee80211_hw *hw) | 722 | int ieee80211_register_hw(struct ieee80211_hw *hw) |
723 | { | 723 | { |
724 | struct ieee80211_local *local = hw_to_local(hw); | 724 | struct ieee80211_local *local = hw_to_local(hw); |
725 | const char *name; | ||
726 | int result; | 725 | int result; |
727 | enum ieee80211_band band; | 726 | enum ieee80211_band band; |
728 | struct net_device *mdev; | 727 | struct net_device *mdev; |
@@ -787,8 +786,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
787 | mdev->header_ops = &ieee80211_header_ops; | 786 | mdev->header_ops = &ieee80211_header_ops; |
788 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; | 787 | mdev->set_multicast_list = ieee80211_master_set_multicast_list; |
789 | 788 | ||
790 | name = wiphy_dev(local->hw.wiphy)->driver->name; | 789 | local->hw.workqueue = |
791 | local->hw.workqueue = create_freezeable_workqueue(name); | 790 | create_freezeable_workqueue(wiphy_name(local->hw.wiphy)); |
792 | if (!local->hw.workqueue) { | 791 | if (!local->hw.workqueue) { |
793 | result = -ENOMEM; | 792 | result = -ENOMEM; |
794 | goto fail_workqueue; | 793 | goto fail_workqueue; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d81a4d2cd3aa..7600ac9b87fe 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -802,6 +802,10 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
802 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); | 802 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); |
803 | } | 803 | } |
804 | 804 | ||
805 | /* | ||
806 | * The disassoc 'reason' argument can be either our own reason | ||
807 | * if self disconnected or a reason code from the AP. | ||
808 | */ | ||
805 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | 809 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
806 | struct ieee80211_if_sta *ifsta, bool deauth, | 810 | struct ieee80211_if_sta *ifsta, bool deauth, |
807 | bool self_disconnected, u16 reason) | 811 | bool self_disconnected, u16 reason) |
@@ -848,7 +852,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
848 | 852 | ||
849 | ieee80211_sta_send_apinfo(sdata, ifsta); | 853 | ieee80211_sta_send_apinfo(sdata, ifsta); |
850 | 854 | ||
851 | if (self_disconnected) | 855 | if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) |
852 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 856 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
853 | 857 | ||
854 | sta_info_unlink(&sta); | 858 | sta_info_unlink(&sta); |
@@ -1163,7 +1167,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1163 | IEEE80211_RETRY_AUTH_INTERVAL); | 1167 | IEEE80211_RETRY_AUTH_INTERVAL); |
1164 | } | 1168 | } |
1165 | 1169 | ||
1166 | ieee80211_set_disassoc(sdata, ifsta, false, false, 0); | 1170 | ieee80211_set_disassoc(sdata, ifsta, false, false, reason_code); |
1167 | } | 1171 | } |
1168 | 1172 | ||
1169 | 1173 | ||
@@ -1736,6 +1740,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1736 | ap_ht_cap_flags); | 1740 | ap_ht_cap_flags); |
1737 | } | 1741 | } |
1738 | 1742 | ||
1743 | if (elems.country_elem) { | ||
1744 | /* Note we are only reviewing this on beacons | ||
1745 | * for the BSSID we are associated to */ | ||
1746 | regulatory_hint_11d(local->hw.wiphy, | ||
1747 | elems.country_elem, elems.country_elem_len); | ||
1748 | } | ||
1749 | |||
1739 | ieee80211_bss_info_change_notify(sdata, changed); | 1750 | ieee80211_bss_info_change_notify(sdata, changed); |
1740 | } | 1751 | } |
1741 | 1752 | ||
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 96ceb7e86c5c..b16801cde06f 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -256,7 +256,7 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba | |||
256 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) { | 256 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) { |
257 | spinfo->tx_num_failed += 2; | 257 | spinfo->tx_num_failed += 2; |
258 | spinfo->tx_num_xmit++; | 258 | spinfo->tx_num_xmit++; |
259 | } else if (info->status.rates[0].count) { | 259 | } else if (info->status.rates[0].count > 1) { |
260 | spinfo->tx_num_failed++; | 260 | spinfo->tx_num_failed++; |
261 | spinfo->tx_num_xmit++; | 261 | spinfo->tx_num_xmit++; |
262 | } | 262 | } |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 7bbb98e846a3..7043ddc75498 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/scatterlist.h> | 19 | #include <linux/scatterlist.h> |
20 | #include <asm/unaligned.h> | ||
20 | 21 | ||
21 | #include <net/mac80211.h> | 22 | #include <net/mac80211.h> |
22 | #include "ieee80211_i.h" | 23 | #include "ieee80211_i.h" |
@@ -125,10 +126,10 @@ void ieee80211_wep_encrypt_data(struct crypto_blkcipher *tfm, u8 *rc4key, | |||
125 | { | 126 | { |
126 | struct blkcipher_desc desc = { .tfm = tfm }; | 127 | struct blkcipher_desc desc = { .tfm = tfm }; |
127 | struct scatterlist sg; | 128 | struct scatterlist sg; |
128 | __le32 *icv; | 129 | __le32 icv; |
129 | 130 | ||
130 | icv = (__le32 *)(data + data_len); | 131 | icv = cpu_to_le32(~crc32_le(~0, data, data_len)); |
131 | *icv = cpu_to_le32(~crc32_le(~0, data, data_len)); | 132 | put_unaligned(icv, (__le32 *)(data + data_len)); |
132 | 133 | ||
133 | crypto_blkcipher_setkey(tfm, rc4key, klen); | 134 | crypto_blkcipher_setkey(tfm, rc4key, klen); |
134 | sg_init_one(&sg, data, data_len + WEP_ICV_LEN); | 135 | sg_init_one(&sg, data, data_len + WEP_ICV_LEN); |
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index ec26eae8004d..051d2c9ea66b 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
@@ -565,16 +565,22 @@ static void rfkill_release(struct device *dev) | |||
565 | #ifdef CONFIG_PM | 565 | #ifdef CONFIG_PM |
566 | static int rfkill_suspend(struct device *dev, pm_message_t state) | 566 | static int rfkill_suspend(struct device *dev, pm_message_t state) |
567 | { | 567 | { |
568 | struct rfkill *rfkill = to_rfkill(dev); | ||
569 | |||
568 | /* mark class device as suspended */ | 570 | /* mark class device as suspended */ |
569 | if (dev->power.power_state.event != state.event) | 571 | if (dev->power.power_state.event != state.event) |
570 | dev->power.power_state = state; | 572 | dev->power.power_state = state; |
571 | 573 | ||
574 | /* store state for the resume handler */ | ||
575 | rfkill->state_for_resume = rfkill->state; | ||
576 | |||
572 | return 0; | 577 | return 0; |
573 | } | 578 | } |
574 | 579 | ||
575 | static int rfkill_resume(struct device *dev) | 580 | static int rfkill_resume(struct device *dev) |
576 | { | 581 | { |
577 | struct rfkill *rfkill = to_rfkill(dev); | 582 | struct rfkill *rfkill = to_rfkill(dev); |
583 | enum rfkill_state newstate; | ||
578 | 584 | ||
579 | if (dev->power.power_state.event != PM_EVENT_ON) { | 585 | if (dev->power.power_state.event != PM_EVENT_ON) { |
580 | mutex_lock(&rfkill->mutex); | 586 | mutex_lock(&rfkill->mutex); |
@@ -582,6 +588,15 @@ static int rfkill_resume(struct device *dev) | |||
582 | dev->power.power_state.event = PM_EVENT_ON; | 588 | dev->power.power_state.event = PM_EVENT_ON; |
583 | 589 | ||
584 | /* | 590 | /* |
591 | * rfkill->state could have been modified before we got | ||
592 | * called, and won't be updated by rfkill_toggle_radio() | ||
593 | * in force mode. Sync it FIRST. | ||
594 | */ | ||
595 | if (rfkill->get_state && | ||
596 | !rfkill->get_state(rfkill->data, &newstate)) | ||
597 | rfkill->state = newstate; | ||
598 | |||
599 | /* | ||
585 | * If we are under EPO, kick transmitter offline, | 600 | * If we are under EPO, kick transmitter offline, |
586 | * otherwise restore to pre-suspend state. | 601 | * otherwise restore to pre-suspend state. |
587 | * | 602 | * |
@@ -590,7 +605,7 @@ static int rfkill_resume(struct device *dev) | |||
590 | rfkill_toggle_radio(rfkill, | 605 | rfkill_toggle_radio(rfkill, |
591 | rfkill_epo_lock_active ? | 606 | rfkill_epo_lock_active ? |
592 | RFKILL_STATE_SOFT_BLOCKED : | 607 | RFKILL_STATE_SOFT_BLOCKED : |
593 | rfkill->state, | 608 | rfkill->state_for_resume, |
594 | 1); | 609 | 1); |
595 | 610 | ||
596 | mutex_unlock(&rfkill->mutex); | 611 | mutex_unlock(&rfkill->mutex); |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index f7c64dbe86cc..e28e2b8fa436 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -1,6 +1,15 @@ | |||
1 | config CFG80211 | 1 | config CFG80211 |
2 | tristate "Improved wireless configuration API" | 2 | tristate "Improved wireless configuration API" |
3 | 3 | ||
4 | config CFG80211_REG_DEBUG | ||
5 | bool "cfg80211 regulatory debugging" | ||
6 | depends on CFG80211 | ||
7 | default n | ||
8 | ---help--- | ||
9 | You can enable this if you want to debug regulatory changes. | ||
10 | |||
11 | If unsure, say N. | ||
12 | |||
4 | config NL80211 | 13 | config NL80211 |
5 | bool "nl80211 new netlink interface support" | 14 | bool "nl80211 new netlink interface support" |
6 | depends on CFG80211 | 15 | depends on CFG80211 |
@@ -40,6 +49,8 @@ config WIRELESS_OLD_REGULATORY | |||
40 | ieee80211_regdom module parameter. This is being phased out and you | 49 | ieee80211_regdom module parameter. This is being phased out and you |
41 | should stop using them ASAP. | 50 | should stop using them ASAP. |
42 | 51 | ||
52 | Note: You will need CRDA if you want 802.11d support | ||
53 | |||
43 | Say Y unless you have installed a new userspace application. | 54 | Say Y unless you have installed a new userspace application. |
44 | Also say Y if have one currently depending on the ieee80211_regdom | 55 | Also say Y if have one currently depending on the ieee80211_regdom |
45 | module parameter and cannot port it to use the new userspace | 56 | module parameter and cannot port it to use the new userspace |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 39e3d10fccde..b96fc0c3f1c4 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include "nl80211.h" | 19 | #include "nl80211.h" |
20 | #include "core.h" | 20 | #include "core.h" |
21 | #include "sysfs.h" | 21 | #include "sysfs.h" |
22 | #include "reg.h" | ||
23 | 22 | ||
24 | /* name for sysfs, %d is appended */ | 23 | /* name for sysfs, %d is appended */ |
25 | #define PHY_NAME "phy" | 24 | #define PHY_NAME "phy" |
@@ -348,6 +347,10 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
348 | /* unlock again before freeing */ | 347 | /* unlock again before freeing */ |
349 | mutex_unlock(&drv->mtx); | 348 | mutex_unlock(&drv->mtx); |
350 | 349 | ||
350 | /* If this device got a regulatory hint tell core its | ||
351 | * free to listen now to a new shiny device regulatory hint */ | ||
352 | reg_device_remove(wiphy); | ||
353 | |||
351 | list_del(&drv->list); | 354 | list_del(&drv->list); |
352 | device_del(&drv->wiphy.dev); | 355 | device_del(&drv->wiphy.dev); |
353 | debugfs_remove(drv->wiphy.debugfsdir); | 356 | debugfs_remove(drv->wiphy.debugfsdir); |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 771cc5cc7658..f7fb9f413028 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <net/genetlink.h> | 11 | #include <net/genetlink.h> |
12 | #include <net/wireless.h> | 12 | #include <net/wireless.h> |
13 | #include <net/cfg80211.h> | 13 | #include <net/cfg80211.h> |
14 | #include "reg.h" | ||
14 | 15 | ||
15 | struct cfg80211_registered_device { | 16 | struct cfg80211_registered_device { |
16 | struct cfg80211_ops *ops; | 17 | struct cfg80211_ops *ops; |
@@ -21,6 +22,18 @@ struct cfg80211_registered_device { | |||
21 | * any call is in progress */ | 22 | * any call is in progress */ |
22 | struct mutex mtx; | 23 | struct mutex mtx; |
23 | 24 | ||
25 | /* ISO / IEC 3166 alpha2 for which this device is receiving | ||
26 | * country IEs on, this can help disregard country IEs from APs | ||
27 | * on the same alpha2 quickly. The alpha2 may differ from | ||
28 | * cfg80211_regdomain's alpha2 when an intersection has occurred. | ||
29 | * If the AP is reconfigured this can also be used to tell us if | ||
30 | * the country on the country IE changed. */ | ||
31 | char country_ie_alpha2[2]; | ||
32 | |||
33 | /* If a Country IE has been received this tells us the environment | ||
34 | * which its telling us its in. This defaults to ENVIRON_ANY */ | ||
35 | enum environment_cap env; | ||
36 | |||
24 | /* wiphy index, internal only */ | 37 | /* wiphy index, internal only */ |
25 | int idx; | 38 | int idx; |
26 | 39 | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e3e1494e769a..c9141e3df9ba 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -198,6 +198,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
198 | if (chan->flags & IEEE80211_CHAN_RADAR) | 198 | if (chan->flags & IEEE80211_CHAN_RADAR) |
199 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); | 199 | NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR); |
200 | 200 | ||
201 | NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER, | ||
202 | DBM_TO_MBM(chan->max_power)); | ||
203 | |||
201 | nla_nest_end(msg, nl_freq); | 204 | nla_nest_end(msg, nl_freq); |
202 | } | 205 | } |
203 | 206 | ||
@@ -1760,7 +1763,7 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
1760 | return -EINVAL; | 1763 | return -EINVAL; |
1761 | #endif | 1764 | #endif |
1762 | mutex_lock(&cfg80211_drv_mutex); | 1765 | mutex_lock(&cfg80211_drv_mutex); |
1763 | r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data); | 1766 | r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY); |
1764 | mutex_unlock(&cfg80211_drv_mutex); | 1767 | mutex_unlock(&cfg80211_drv_mutex); |
1765 | return r; | 1768 | return r; |
1766 | } | 1769 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4c7e39d466c4..0990059f7e48 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -60,12 +60,18 @@ | |||
60 | * @intersect: indicates whether the wireless core should intersect | 60 | * @intersect: indicates whether the wireless core should intersect |
61 | * the requested regulatory domain with the presently set regulatory | 61 | * the requested regulatory domain with the presently set regulatory |
62 | * domain. | 62 | * domain. |
63 | * @country_ie_checksum: checksum of the last processed and accepted | ||
64 | * country IE | ||
65 | * @country_ie_env: lets us know if the AP is telling us we are outdoor, | ||
66 | * indoor, or if it doesn't matter | ||
63 | */ | 67 | */ |
64 | struct regulatory_request { | 68 | struct regulatory_request { |
65 | struct wiphy *wiphy; | 69 | struct wiphy *wiphy; |
66 | enum reg_set_by initiator; | 70 | enum reg_set_by initiator; |
67 | char alpha2[2]; | 71 | char alpha2[2]; |
68 | bool intersect; | 72 | bool intersect; |
73 | u32 country_ie_checksum; | ||
74 | enum environment_cap country_ie_env; | ||
69 | }; | 75 | }; |
70 | 76 | ||
71 | /* Receipt of information from last regulatory request */ | 77 | /* Receipt of information from last regulatory request */ |
@@ -85,6 +91,11 @@ static u32 supported_bandwidths[] = { | |||
85 | * information to give us an alpha2 */ | 91 | * information to give us an alpha2 */ |
86 | static const struct ieee80211_regdomain *cfg80211_regdomain; | 92 | static const struct ieee80211_regdomain *cfg80211_regdomain; |
87 | 93 | ||
94 | /* We use this as a place for the rd structure built from the | ||
95 | * last parsed country IE to rest until CRDA gets back to us with | ||
96 | * what it thinks should apply for the same country */ | ||
97 | static const struct ieee80211_regdomain *country_ie_regdomain; | ||
98 | |||
88 | /* We keep a static world regulatory domain in case of the absence of CRDA */ | 99 | /* We keep a static world regulatory domain in case of the absence of CRDA */ |
89 | static const struct ieee80211_regdomain world_regdom = { | 100 | static const struct ieee80211_regdomain world_regdom = { |
90 | .n_reg_rules = 1, | 101 | .n_reg_rules = 1, |
@@ -264,6 +275,18 @@ static bool is_unknown_alpha2(const char *alpha2) | |||
264 | return false; | 275 | return false; |
265 | } | 276 | } |
266 | 277 | ||
278 | static bool is_intersected_alpha2(const char *alpha2) | ||
279 | { | ||
280 | if (!alpha2) | ||
281 | return false; | ||
282 | /* Special case where regulatory domain is the | ||
283 | * result of an intersection between two regulatory domain | ||
284 | * structures */ | ||
285 | if (alpha2[0] == '9' && alpha2[1] == '8') | ||
286 | return true; | ||
287 | return false; | ||
288 | } | ||
289 | |||
267 | static bool is_an_alpha2(const char *alpha2) | 290 | static bool is_an_alpha2(const char *alpha2) |
268 | { | 291 | { |
269 | if (!alpha2) | 292 | if (!alpha2) |
@@ -292,6 +315,25 @@ static bool regdom_changed(const char *alpha2) | |||
292 | return true; | 315 | return true; |
293 | } | 316 | } |
294 | 317 | ||
318 | /** | ||
319 | * country_ie_integrity_changes - tells us if the country IE has changed | ||
320 | * @checksum: checksum of country IE of fields we are interested in | ||
321 | * | ||
322 | * If the country IE has not changed you can ignore it safely. This is | ||
323 | * useful to determine if two devices are seeing two different country IEs | ||
324 | * even on the same alpha2. Note that this will return false if no IE has | ||
325 | * been set on the wireless core yet. | ||
326 | */ | ||
327 | static bool country_ie_integrity_changes(u32 checksum) | ||
328 | { | ||
329 | /* If no IE has been set then the checksum doesn't change */ | ||
330 | if (unlikely(!last_request->country_ie_checksum)) | ||
331 | return false; | ||
332 | if (unlikely(last_request->country_ie_checksum != checksum)) | ||
333 | return true; | ||
334 | return false; | ||
335 | } | ||
336 | |||
295 | /* This lets us keep regulatory code which is updated on a regulatory | 337 | /* This lets us keep regulatory code which is updated on a regulatory |
296 | * basis in userspace. */ | 338 | * basis in userspace. */ |
297 | static int call_crda(const char *alpha2) | 339 | static int call_crda(const char *alpha2) |
@@ -330,7 +372,7 @@ static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) | |||
330 | const struct ieee80211_freq_range *freq_range = &rule->freq_range; | 372 | const struct ieee80211_freq_range *freq_range = &rule->freq_range; |
331 | u32 freq_diff; | 373 | u32 freq_diff; |
332 | 374 | ||
333 | if (freq_range->start_freq_khz == 0 || freq_range->end_freq_khz == 0) | 375 | if (freq_range->start_freq_khz <= 0 || freq_range->end_freq_khz <= 0) |
334 | return false; | 376 | return false; |
335 | 377 | ||
336 | if (freq_range->start_freq_khz > freq_range->end_freq_khz) | 378 | if (freq_range->start_freq_khz > freq_range->end_freq_khz) |
@@ -352,6 +394,9 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd) | |||
352 | if (!rd->n_reg_rules) | 394 | if (!rd->n_reg_rules) |
353 | return false; | 395 | return false; |
354 | 396 | ||
397 | if (WARN_ON(rd->n_reg_rules > NL80211_MAX_SUPP_REG_RULES)) | ||
398 | return false; | ||
399 | |||
355 | for (i = 0; i < rd->n_reg_rules; i++) { | 400 | for (i = 0; i < rd->n_reg_rules; i++) { |
356 | reg_rule = &rd->reg_rules[i]; | 401 | reg_rule = &rd->reg_rules[i]; |
357 | if (!is_valid_reg_rule(reg_rule)) | 402 | if (!is_valid_reg_rule(reg_rule)) |
@@ -376,6 +421,174 @@ static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range, | |||
376 | return 0; | 421 | return 0; |
377 | } | 422 | } |
378 | 423 | ||
424 | /* Converts a country IE to a regulatory domain. A regulatory domain | ||
425 | * structure has a lot of information which the IE doesn't yet have, | ||
426 | * so for the other values we use upper max values as we will intersect | ||
427 | * with our userspace regulatory agent to get lower bounds. */ | ||
428 | static struct ieee80211_regdomain *country_ie_2_rd( | ||
429 | u8 *country_ie, | ||
430 | u8 country_ie_len, | ||
431 | u32 *checksum) | ||
432 | { | ||
433 | struct ieee80211_regdomain *rd = NULL; | ||
434 | unsigned int i = 0; | ||
435 | char alpha2[2]; | ||
436 | u32 flags = 0; | ||
437 | u32 num_rules = 0, size_of_regd = 0; | ||
438 | u8 *triplets_start = NULL; | ||
439 | u8 len_at_triplet = 0; | ||
440 | /* the last channel we have registered in a subband (triplet) */ | ||
441 | int last_sub_max_channel = 0; | ||
442 | |||
443 | *checksum = 0xDEADBEEF; | ||
444 | |||
445 | /* Country IE requirements */ | ||
446 | BUG_ON(country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN || | ||
447 | country_ie_len & 0x01); | ||
448 | |||
449 | alpha2[0] = country_ie[0]; | ||
450 | alpha2[1] = country_ie[1]; | ||
451 | |||
452 | /* | ||
453 | * Third octet can be: | ||
454 | * 'I' - Indoor | ||
455 | * 'O' - Outdoor | ||
456 | * | ||
457 | * anything else we assume is no restrictions | ||
458 | */ | ||
459 | if (country_ie[2] == 'I') | ||
460 | flags = NL80211_RRF_NO_OUTDOOR; | ||
461 | else if (country_ie[2] == 'O') | ||
462 | flags = NL80211_RRF_NO_INDOOR; | ||
463 | |||
464 | country_ie += 3; | ||
465 | country_ie_len -= 3; | ||
466 | |||
467 | triplets_start = country_ie; | ||
468 | len_at_triplet = country_ie_len; | ||
469 | |||
470 | *checksum ^= ((flags ^ alpha2[0] ^ alpha2[1]) << 8); | ||
471 | |||
472 | /* We need to build a reg rule for each triplet, but first we must | ||
473 | * calculate the number of reg rules we will need. We will need one | ||
474 | * for each channel subband */ | ||
475 | while (country_ie_len >= 3) { | ||
476 | struct ieee80211_country_ie_triplet *triplet = | ||
477 | (struct ieee80211_country_ie_triplet *) country_ie; | ||
478 | int cur_sub_max_channel = 0, cur_channel = 0; | ||
479 | |||
480 | if (triplet->ext.reg_extension_id >= | ||
481 | IEEE80211_COUNTRY_EXTENSION_ID) { | ||
482 | country_ie += 3; | ||
483 | country_ie_len -= 3; | ||
484 | continue; | ||
485 | } | ||
486 | |||
487 | cur_channel = triplet->chans.first_channel; | ||
488 | cur_sub_max_channel = ieee80211_channel_to_frequency( | ||
489 | cur_channel + triplet->chans.num_channels); | ||
490 | |||
491 | /* Basic sanity check */ | ||
492 | if (cur_sub_max_channel < cur_channel) | ||
493 | return NULL; | ||
494 | |||
495 | /* Do not allow overlapping channels. Also channels | ||
496 | * passed in each subband must be monotonically | ||
497 | * increasing */ | ||
498 | if (last_sub_max_channel) { | ||
499 | if (cur_channel <= last_sub_max_channel) | ||
500 | return NULL; | ||
501 | if (cur_sub_max_channel <= last_sub_max_channel) | ||
502 | return NULL; | ||
503 | } | ||
504 | |||
505 | /* When dot11RegulatoryClassesRequired is supported | ||
506 | * we can throw ext triplets as part of this soup, | ||
507 | * for now we don't care when those change as we | ||
508 | * don't support them */ | ||
509 | *checksum ^= ((cur_channel ^ cur_sub_max_channel) << 8) | | ||
510 | ((cur_sub_max_channel ^ cur_sub_max_channel) << 16) | | ||
511 | ((triplet->chans.max_power ^ cur_sub_max_channel) << 24); | ||
512 | |||
513 | last_sub_max_channel = cur_sub_max_channel; | ||
514 | |||
515 | country_ie += 3; | ||
516 | country_ie_len -= 3; | ||
517 | num_rules++; | ||
518 | |||
519 | /* Note: this is not a IEEE requirement but | ||
520 | * simply a memory requirement */ | ||
521 | if (num_rules > NL80211_MAX_SUPP_REG_RULES) | ||
522 | return NULL; | ||
523 | } | ||
524 | |||
525 | country_ie = triplets_start; | ||
526 | country_ie_len = len_at_triplet; | ||
527 | |||
528 | size_of_regd = sizeof(struct ieee80211_regdomain) + | ||
529 | (num_rules * sizeof(struct ieee80211_reg_rule)); | ||
530 | |||
531 | rd = kzalloc(size_of_regd, GFP_KERNEL); | ||
532 | if (!rd) | ||
533 | return NULL; | ||
534 | |||
535 | rd->n_reg_rules = num_rules; | ||
536 | rd->alpha2[0] = alpha2[0]; | ||
537 | rd->alpha2[1] = alpha2[1]; | ||
538 | |||
539 | /* This time around we fill in the rd */ | ||
540 | while (country_ie_len >= 3) { | ||
541 | struct ieee80211_country_ie_triplet *triplet = | ||
542 | (struct ieee80211_country_ie_triplet *) country_ie; | ||
543 | struct ieee80211_reg_rule *reg_rule = NULL; | ||
544 | struct ieee80211_freq_range *freq_range = NULL; | ||
545 | struct ieee80211_power_rule *power_rule = NULL; | ||
546 | |||
547 | /* Must parse if dot11RegulatoryClassesRequired is true, | ||
548 | * we don't support this yet */ | ||
549 | if (triplet->ext.reg_extension_id >= | ||
550 | IEEE80211_COUNTRY_EXTENSION_ID) { | ||
551 | country_ie += 3; | ||
552 | country_ie_len -= 3; | ||
553 | continue; | ||
554 | } | ||
555 | |||
556 | reg_rule = &rd->reg_rules[i]; | ||
557 | freq_range = ®_rule->freq_range; | ||
558 | power_rule = ®_rule->power_rule; | ||
559 | |||
560 | reg_rule->flags = flags; | ||
561 | |||
562 | /* The +10 is since the regulatory domain expects | ||
563 | * the actual band edge, not the center of freq for | ||
564 | * its start and end freqs, assuming 20 MHz bandwidth on | ||
565 | * the channels passed */ | ||
566 | freq_range->start_freq_khz = | ||
567 | MHZ_TO_KHZ(ieee80211_channel_to_frequency( | ||
568 | triplet->chans.first_channel) - 10); | ||
569 | freq_range->end_freq_khz = | ||
570 | MHZ_TO_KHZ(ieee80211_channel_to_frequency( | ||
571 | triplet->chans.first_channel + | ||
572 | triplet->chans.num_channels) + 10); | ||
573 | |||
574 | /* Large arbitrary values, we intersect later */ | ||
575 | /* Increment this if we ever support >= 40 MHz channels | ||
576 | * in IEEE 802.11 */ | ||
577 | freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40); | ||
578 | power_rule->max_antenna_gain = DBI_TO_MBI(100); | ||
579 | power_rule->max_eirp = DBM_TO_MBM(100); | ||
580 | |||
581 | country_ie += 3; | ||
582 | country_ie_len -= 3; | ||
583 | i++; | ||
584 | |||
585 | BUG_ON(i > NL80211_MAX_SUPP_REG_RULES); | ||
586 | } | ||
587 | |||
588 | return rd; | ||
589 | } | ||
590 | |||
591 | |||
379 | /* Helper for regdom_intersect(), this does the real | 592 | /* Helper for regdom_intersect(), this does the real |
380 | * mathematical intersection fun */ | 593 | * mathematical intersection fun */ |
381 | static int reg_rules_intersect( | 594 | static int reg_rules_intersect( |
@@ -603,12 +816,23 @@ static void handle_band(struct ieee80211_supported_band *sband) | |||
603 | handle_channel(&sband->channels[i]); | 816 | handle_channel(&sband->channels[i]); |
604 | } | 817 | } |
605 | 818 | ||
819 | static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) | ||
820 | { | ||
821 | if (!last_request) | ||
822 | return true; | ||
823 | if (setby == REGDOM_SET_BY_CORE && | ||
824 | wiphy->fw_handles_regulatory) | ||
825 | return true; | ||
826 | return false; | ||
827 | } | ||
828 | |||
606 | static void update_all_wiphy_regulatory(enum reg_set_by setby) | 829 | static void update_all_wiphy_regulatory(enum reg_set_by setby) |
607 | { | 830 | { |
608 | struct cfg80211_registered_device *drv; | 831 | struct cfg80211_registered_device *drv; |
609 | 832 | ||
610 | list_for_each_entry(drv, &cfg80211_drv_list, list) | 833 | list_for_each_entry(drv, &cfg80211_drv_list, list) |
611 | wiphy_update_regulatory(&drv->wiphy, setby); | 834 | if (!ignore_reg_update(&drv->wiphy, setby)) |
835 | wiphy_update_regulatory(&drv->wiphy, setby); | ||
612 | } | 836 | } |
613 | 837 | ||
614 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) | 838 | void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) |
@@ -660,16 +884,14 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
660 | return -EOPNOTSUPP; | 884 | return -EOPNOTSUPP; |
661 | return -EALREADY; | 885 | return -EALREADY; |
662 | } | 886 | } |
663 | /* Two consecutive Country IE hints on the same wiphy */ | 887 | /* Two consecutive Country IE hints on the same wiphy. |
664 | if (!alpha2_equal(cfg80211_regdomain->alpha2, alpha2)) | 888 | * This should be picked up early by the driver/stack */ |
889 | if (WARN_ON(!alpha2_equal(cfg80211_regdomain->alpha2, | ||
890 | alpha2))) | ||
665 | return 0; | 891 | return 0; |
666 | return -EALREADY; | 892 | return -EALREADY; |
667 | } | 893 | } |
668 | /* | 894 | return REG_INTERSECT; |
669 | * Ignore Country IE hints for now, need to think about | ||
670 | * what we need to do to support multi-domain operation. | ||
671 | */ | ||
672 | return -EOPNOTSUPP; | ||
673 | case REGDOM_SET_BY_DRIVER: | 895 | case REGDOM_SET_BY_DRIVER: |
674 | if (last_request->initiator == REGDOM_SET_BY_DRIVER) | 896 | if (last_request->initiator == REGDOM_SET_BY_DRIVER) |
675 | return -EALREADY; | 897 | return -EALREADY; |
@@ -677,6 +899,11 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
677 | case REGDOM_SET_BY_USER: | 899 | case REGDOM_SET_BY_USER: |
678 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) | 900 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) |
679 | return REG_INTERSECT; | 901 | return REG_INTERSECT; |
902 | /* If the user knows better the user should set the regdom | ||
903 | * to their country before the IE is picked up */ | ||
904 | if (last_request->initiator == REGDOM_SET_BY_USER && | ||
905 | last_request->intersect) | ||
906 | return -EOPNOTSUPP; | ||
680 | return 0; | 907 | return 0; |
681 | } | 908 | } |
682 | 909 | ||
@@ -685,7 +912,9 @@ static int ignore_request(struct wiphy *wiphy, enum reg_set_by set_by, | |||
685 | 912 | ||
686 | /* Caller must hold &cfg80211_drv_mutex */ | 913 | /* Caller must hold &cfg80211_drv_mutex */ |
687 | int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | 914 | int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, |
688 | const char *alpha2) | 915 | const char *alpha2, |
916 | u32 country_ie_checksum, | ||
917 | enum environment_cap env) | ||
689 | { | 918 | { |
690 | struct regulatory_request *request; | 919 | struct regulatory_request *request; |
691 | bool intersect = false; | 920 | bool intersect = false; |
@@ -698,36 +927,32 @@ int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | |||
698 | else if (r) | 927 | else if (r) |
699 | return r; | 928 | return r; |
700 | 929 | ||
701 | switch (set_by) { | 930 | request = kzalloc(sizeof(struct regulatory_request), |
702 | case REGDOM_SET_BY_CORE: | 931 | GFP_KERNEL); |
703 | case REGDOM_SET_BY_COUNTRY_IE: | 932 | if (!request) |
704 | case REGDOM_SET_BY_DRIVER: | 933 | return -ENOMEM; |
705 | case REGDOM_SET_BY_USER: | ||
706 | request = kzalloc(sizeof(struct regulatory_request), | ||
707 | GFP_KERNEL); | ||
708 | if (!request) | ||
709 | return -ENOMEM; | ||
710 | |||
711 | request->alpha2[0] = alpha2[0]; | ||
712 | request->alpha2[1] = alpha2[1]; | ||
713 | request->initiator = set_by; | ||
714 | request->wiphy = wiphy; | ||
715 | request->intersect = intersect; | ||
716 | |||
717 | kfree(last_request); | ||
718 | last_request = request; | ||
719 | r = call_crda(alpha2); | ||
720 | #ifndef CONFIG_WIRELESS_OLD_REGULATORY | ||
721 | if (r) | ||
722 | printk(KERN_ERR "cfg80211: Failed calling CRDA\n"); | ||
723 | #endif | ||
724 | break; | ||
725 | default: | ||
726 | r = -ENOTSUPP; | ||
727 | break; | ||
728 | } | ||
729 | 934 | ||
730 | return r; | 935 | request->alpha2[0] = alpha2[0]; |
936 | request->alpha2[1] = alpha2[1]; | ||
937 | request->initiator = set_by; | ||
938 | request->wiphy = wiphy; | ||
939 | request->intersect = intersect; | ||
940 | request->country_ie_checksum = country_ie_checksum; | ||
941 | request->country_ie_env = env; | ||
942 | |||
943 | kfree(last_request); | ||
944 | last_request = request; | ||
945 | /* | ||
946 | * Note: When CONFIG_WIRELESS_OLD_REGULATORY is enabled | ||
947 | * AND if CRDA is NOT present nothing will happen, if someone | ||
948 | * wants to bother with 11d with OLD_REG you can add a timer. | ||
949 | * If after x amount of time nothing happens you can call: | ||
950 | * | ||
951 | * return set_regdom(country_ie_regdomain); | ||
952 | * | ||
953 | * to intersect with the static rd | ||
954 | */ | ||
955 | return call_crda(alpha2); | ||
731 | } | 956 | } |
732 | 957 | ||
733 | void regulatory_hint(struct wiphy *wiphy, const char *alpha2) | 958 | void regulatory_hint(struct wiphy *wiphy, const char *alpha2) |
@@ -735,11 +960,120 @@ void regulatory_hint(struct wiphy *wiphy, const char *alpha2) | |||
735 | BUG_ON(!alpha2); | 960 | BUG_ON(!alpha2); |
736 | 961 | ||
737 | mutex_lock(&cfg80211_drv_mutex); | 962 | mutex_lock(&cfg80211_drv_mutex); |
738 | __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2); | 963 | __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, 0, ENVIRON_ANY); |
739 | mutex_unlock(&cfg80211_drv_mutex); | 964 | mutex_unlock(&cfg80211_drv_mutex); |
740 | } | 965 | } |
741 | EXPORT_SYMBOL(regulatory_hint); | 966 | EXPORT_SYMBOL(regulatory_hint); |
742 | 967 | ||
968 | static bool reg_same_country_ie_hint(struct wiphy *wiphy, | ||
969 | u32 country_ie_checksum) | ||
970 | { | ||
971 | if (!last_request->wiphy) | ||
972 | return false; | ||
973 | if (likely(last_request->wiphy != wiphy)) | ||
974 | return !country_ie_integrity_changes(country_ie_checksum); | ||
975 | /* We should not have let these through at this point, they | ||
976 | * should have been picked up earlier by the first alpha2 check | ||
977 | * on the device */ | ||
978 | if (WARN_ON(!country_ie_integrity_changes(country_ie_checksum))) | ||
979 | return true; | ||
980 | return false; | ||
981 | } | ||
982 | |||
983 | void regulatory_hint_11d(struct wiphy *wiphy, | ||
984 | u8 *country_ie, | ||
985 | u8 country_ie_len) | ||
986 | { | ||
987 | struct ieee80211_regdomain *rd = NULL; | ||
988 | char alpha2[2]; | ||
989 | u32 checksum = 0; | ||
990 | enum environment_cap env = ENVIRON_ANY; | ||
991 | |||
992 | mutex_lock(&cfg80211_drv_mutex); | ||
993 | |||
994 | /* IE len must be evenly divisible by 2 */ | ||
995 | if (country_ie_len & 0x01) | ||
996 | goto out; | ||
997 | |||
998 | if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) | ||
999 | goto out; | ||
1000 | |||
1001 | /* Pending country IE processing, this can happen after we | ||
1002 | * call CRDA and wait for a response if a beacon was received before | ||
1003 | * we were able to process the last regulatory_hint_11d() call */ | ||
1004 | if (country_ie_regdomain) | ||
1005 | goto out; | ||
1006 | |||
1007 | alpha2[0] = country_ie[0]; | ||
1008 | alpha2[1] = country_ie[1]; | ||
1009 | |||
1010 | if (country_ie[2] == 'I') | ||
1011 | env = ENVIRON_INDOOR; | ||
1012 | else if (country_ie[2] == 'O') | ||
1013 | env = ENVIRON_OUTDOOR; | ||
1014 | |||
1015 | /* We will run this for *every* beacon processed for the BSSID, so | ||
1016 | * we optimize an early check to exit out early if we don't have to | ||
1017 | * do anything */ | ||
1018 | if (likely(last_request->wiphy)) { | ||
1019 | struct cfg80211_registered_device *drv_last_ie; | ||
1020 | |||
1021 | drv_last_ie = wiphy_to_dev(last_request->wiphy); | ||
1022 | |||
1023 | /* Lets keep this simple -- we trust the first AP | ||
1024 | * after we intersect with CRDA */ | ||
1025 | if (likely(last_request->wiphy == wiphy)) { | ||
1026 | /* Ignore IEs coming in on this wiphy with | ||
1027 | * the same alpha2 and environment cap */ | ||
1028 | if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2, | ||
1029 | alpha2) && | ||
1030 | env == drv_last_ie->env)) { | ||
1031 | goto out; | ||
1032 | } | ||
1033 | /* the wiphy moved on to another BSSID or the AP | ||
1034 | * was reconfigured. XXX: We need to deal with the | ||
1035 | * case where the user suspends and goes to goes | ||
1036 | * to another country, and then gets IEs from an | ||
1037 | * AP with different settings */ | ||
1038 | goto out; | ||
1039 | } else { | ||
1040 | /* Ignore IEs coming in on two separate wiphys with | ||
1041 | * the same alpha2 and environment cap */ | ||
1042 | if (likely(alpha2_equal(drv_last_ie->country_ie_alpha2, | ||
1043 | alpha2) && | ||
1044 | env == drv_last_ie->env)) { | ||
1045 | goto out; | ||
1046 | } | ||
1047 | /* We could potentially intersect though */ | ||
1048 | goto out; | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | rd = country_ie_2_rd(country_ie, country_ie_len, &checksum); | ||
1053 | if (!rd) | ||
1054 | goto out; | ||
1055 | |||
1056 | /* This will not happen right now but we leave it here for the | ||
1057 | * the future when we want to add suspend/resume support and having | ||
1058 | * the user move to another country after doing so, or having the user | ||
1059 | * move to another AP. Right now we just trust the first AP. This is why | ||
1060 | * this is marked as likley(). If we hit this before we add this support | ||
1061 | * we want to be informed of it as it would indicate a mistake in the | ||
1062 | * current design */ | ||
1063 | if (likely(WARN_ON(reg_same_country_ie_hint(wiphy, checksum)))) | ||
1064 | goto out; | ||
1065 | |||
1066 | /* We keep this around for when CRDA comes back with a response so | ||
1067 | * we can intersect with that */ | ||
1068 | country_ie_regdomain = rd; | ||
1069 | |||
1070 | __regulatory_hint(wiphy, REGDOM_SET_BY_COUNTRY_IE, | ||
1071 | country_ie_regdomain->alpha2, checksum, env); | ||
1072 | |||
1073 | out: | ||
1074 | mutex_unlock(&cfg80211_drv_mutex); | ||
1075 | } | ||
1076 | EXPORT_SYMBOL(regulatory_hint_11d); | ||
743 | 1077 | ||
744 | static void print_rd_rules(const struct ieee80211_regdomain *rd) | 1078 | static void print_rd_rules(const struct ieee80211_regdomain *rd) |
745 | { | 1079 | { |
@@ -779,7 +1113,25 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
779 | static void print_regdomain(const struct ieee80211_regdomain *rd) | 1113 | static void print_regdomain(const struct ieee80211_regdomain *rd) |
780 | { | 1114 | { |
781 | 1115 | ||
782 | if (is_world_regdom(rd->alpha2)) | 1116 | if (is_intersected_alpha2(rd->alpha2)) { |
1117 | struct wiphy *wiphy = NULL; | ||
1118 | struct cfg80211_registered_device *drv; | ||
1119 | |||
1120 | if (last_request->initiator == REGDOM_SET_BY_COUNTRY_IE) { | ||
1121 | if (last_request->wiphy) { | ||
1122 | wiphy = last_request->wiphy; | ||
1123 | drv = wiphy_to_dev(wiphy); | ||
1124 | printk(KERN_INFO "cfg80211: Current regulatory " | ||
1125 | "domain updated by AP to: %c%c\n", | ||
1126 | drv->country_ie_alpha2[0], | ||
1127 | drv->country_ie_alpha2[1]); | ||
1128 | } else | ||
1129 | printk(KERN_INFO "cfg80211: Current regulatory " | ||
1130 | "domain intersected: \n"); | ||
1131 | } else | ||
1132 | printk(KERN_INFO "cfg80211: Current regulatory " | ||
1133 | "intersected: \n"); | ||
1134 | } else if (is_world_regdom(rd->alpha2)) | ||
783 | printk(KERN_INFO "cfg80211: World regulatory " | 1135 | printk(KERN_INFO "cfg80211: World regulatory " |
784 | "domain updated:\n"); | 1136 | "domain updated:\n"); |
785 | else { | 1137 | else { |
@@ -802,10 +1154,39 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd) | |||
802 | print_rd_rules(rd); | 1154 | print_rd_rules(rd); |
803 | } | 1155 | } |
804 | 1156 | ||
1157 | #ifdef CONFIG_CFG80211_REG_DEBUG | ||
1158 | static void reg_country_ie_process_debug( | ||
1159 | const struct ieee80211_regdomain *rd, | ||
1160 | const struct ieee80211_regdomain *country_ie_regdomain, | ||
1161 | const struct ieee80211_regdomain *intersected_rd) | ||
1162 | { | ||
1163 | printk(KERN_DEBUG "cfg80211: Received country IE:\n"); | ||
1164 | print_regdomain_info(country_ie_regdomain); | ||
1165 | printk(KERN_DEBUG "cfg80211: CRDA thinks this should applied:\n"); | ||
1166 | print_regdomain_info(rd); | ||
1167 | if (intersected_rd) { | ||
1168 | printk(KERN_DEBUG "cfg80211: We intersect both of these " | ||
1169 | "and get:\n"); | ||
1170 | print_regdomain_info(rd); | ||
1171 | return; | ||
1172 | } | ||
1173 | printk(KERN_DEBUG "cfg80211: Intersection between both failed\n"); | ||
1174 | } | ||
1175 | #else | ||
1176 | static inline void reg_country_ie_process_debug( | ||
1177 | const struct ieee80211_regdomain *rd, | ||
1178 | const struct ieee80211_regdomain *country_ie_regdomain, | ||
1179 | const struct ieee80211_regdomain *intersected_rd) | ||
1180 | { | ||
1181 | } | ||
1182 | #endif | ||
1183 | |||
805 | /* Takes ownership of rd only if it doesn't fail */ | 1184 | /* Takes ownership of rd only if it doesn't fail */ |
806 | static int __set_regdom(const struct ieee80211_regdomain *rd) | 1185 | static int __set_regdom(const struct ieee80211_regdomain *rd) |
807 | { | 1186 | { |
808 | const struct ieee80211_regdomain *intersected_rd = NULL; | 1187 | const struct ieee80211_regdomain *intersected_rd = NULL; |
1188 | struct cfg80211_registered_device *drv = NULL; | ||
1189 | struct wiphy *wiphy = NULL; | ||
809 | /* Some basic sanity checks first */ | 1190 | /* Some basic sanity checks first */ |
810 | 1191 | ||
811 | if (is_world_regdom(rd->alpha2)) { | 1192 | if (is_world_regdom(rd->alpha2)) { |
@@ -822,10 +1203,18 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
822 | if (!last_request) | 1203 | if (!last_request) |
823 | return -EINVAL; | 1204 | return -EINVAL; |
824 | 1205 | ||
825 | /* allow overriding the static definitions if CRDA is present */ | 1206 | /* Lets only bother proceeding on the same alpha2 if the current |
826 | if (!is_old_static_regdom(cfg80211_regdomain) && | 1207 | * rd is non static (it means CRDA was present and was used last) |
827 | !regdom_changed(rd->alpha2)) | 1208 | * and the pending request came in from a country IE */ |
828 | return -EINVAL; | 1209 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { |
1210 | /* If someone else asked us to change the rd lets only bother | ||
1211 | * checking if the alpha2 changes if CRDA was already called */ | ||
1212 | if (!is_old_static_regdom(cfg80211_regdomain) && | ||
1213 | !regdom_changed(rd->alpha2)) | ||
1214 | return -EINVAL; | ||
1215 | } | ||
1216 | |||
1217 | wiphy = last_request->wiphy; | ||
829 | 1218 | ||
830 | /* Now lets set the regulatory domain, update all driver channels | 1219 | /* Now lets set the regulatory domain, update all driver channels |
831 | * and finally inform them of what we have done, in case they want | 1220 | * and finally inform them of what we have done, in case they want |
@@ -835,36 +1224,78 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
835 | if (WARN_ON(!reg_is_valid_request(rd->alpha2))) | 1224 | if (WARN_ON(!reg_is_valid_request(rd->alpha2))) |
836 | return -EINVAL; | 1225 | return -EINVAL; |
837 | 1226 | ||
838 | reset_regdomains(); | 1227 | if (!is_valid_rd(rd)) { |
1228 | printk(KERN_ERR "cfg80211: Invalid " | ||
1229 | "regulatory domain detected:\n"); | ||
1230 | print_regdomain_info(rd); | ||
1231 | return -EINVAL; | ||
1232 | } | ||
839 | 1233 | ||
840 | /* Country IE parsing coming soon */ | 1234 | if (!last_request->intersect) { |
841 | switch (last_request->initiator) { | 1235 | reset_regdomains(); |
842 | case REGDOM_SET_BY_CORE: | 1236 | cfg80211_regdomain = rd; |
843 | case REGDOM_SET_BY_DRIVER: | 1237 | return 0; |
844 | case REGDOM_SET_BY_USER: | ||
845 | if (!is_valid_rd(rd)) { | ||
846 | printk(KERN_ERR "cfg80211: Invalid " | ||
847 | "regulatory domain detected:\n"); | ||
848 | print_regdomain_info(rd); | ||
849 | return -EINVAL; | ||
850 | } | ||
851 | break; | ||
852 | case REGDOM_SET_BY_COUNTRY_IE: /* Not yet */ | ||
853 | WARN_ON(1); | ||
854 | default: | ||
855 | return -EOPNOTSUPP; | ||
856 | } | 1238 | } |
857 | 1239 | ||
858 | if (unlikely(last_request->intersect)) { | 1240 | /* Intersection requires a bit more work */ |
1241 | |||
1242 | if (last_request->initiator != REGDOM_SET_BY_COUNTRY_IE) { | ||
1243 | |||
859 | intersected_rd = regdom_intersect(rd, cfg80211_regdomain); | 1244 | intersected_rd = regdom_intersect(rd, cfg80211_regdomain); |
860 | if (!intersected_rd) | 1245 | if (!intersected_rd) |
861 | return -EINVAL; | 1246 | return -EINVAL; |
1247 | |||
1248 | /* We can trash what CRDA provided now */ | ||
862 | kfree(rd); | 1249 | kfree(rd); |
863 | rd = intersected_rd; | 1250 | rd = NULL; |
1251 | |||
1252 | reset_regdomains(); | ||
1253 | cfg80211_regdomain = intersected_rd; | ||
1254 | |||
1255 | return 0; | ||
864 | } | 1256 | } |
865 | 1257 | ||
866 | /* Tada! */ | 1258 | /* |
867 | cfg80211_regdomain = rd; | 1259 | * Country IE requests are handled a bit differently, we intersect |
1260 | * the country IE rd with what CRDA believes that country should have | ||
1261 | */ | ||
1262 | |||
1263 | BUG_ON(!country_ie_regdomain); | ||
1264 | |||
1265 | if (rd != country_ie_regdomain) { | ||
1266 | /* Intersect what CRDA returned and our what we | ||
1267 | * had built from the Country IE received */ | ||
1268 | |||
1269 | intersected_rd = regdom_intersect(rd, country_ie_regdomain); | ||
1270 | |||
1271 | reg_country_ie_process_debug(rd, country_ie_regdomain, | ||
1272 | intersected_rd); | ||
1273 | |||
1274 | kfree(country_ie_regdomain); | ||
1275 | country_ie_regdomain = NULL; | ||
1276 | } else { | ||
1277 | /* This would happen when CRDA was not present and | ||
1278 | * OLD_REGULATORY was enabled. We intersect our Country | ||
1279 | * IE rd and what was set on cfg80211 originally */ | ||
1280 | intersected_rd = regdom_intersect(rd, cfg80211_regdomain); | ||
1281 | } | ||
1282 | |||
1283 | if (!intersected_rd) | ||
1284 | return -EINVAL; | ||
1285 | |||
1286 | drv = wiphy_to_dev(wiphy); | ||
1287 | |||
1288 | drv->country_ie_alpha2[0] = rd->alpha2[0]; | ||
1289 | drv->country_ie_alpha2[1] = rd->alpha2[1]; | ||
1290 | drv->env = last_request->country_ie_env; | ||
1291 | |||
1292 | BUG_ON(intersected_rd == rd); | ||
1293 | |||
1294 | kfree(rd); | ||
1295 | rd = NULL; | ||
1296 | |||
1297 | reset_regdomains(); | ||
1298 | cfg80211_regdomain = intersected_rd; | ||
868 | 1299 | ||
869 | return 0; | 1300 | return 0; |
870 | } | 1301 | } |
@@ -885,16 +1316,28 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
885 | } | 1316 | } |
886 | 1317 | ||
887 | /* This would make this whole thing pointless */ | 1318 | /* This would make this whole thing pointless */ |
888 | BUG_ON(rd != cfg80211_regdomain); | 1319 | if (!last_request->intersect) |
1320 | BUG_ON(rd != cfg80211_regdomain); | ||
889 | 1321 | ||
890 | /* update all wiphys now with the new established regulatory domain */ | 1322 | /* update all wiphys now with the new established regulatory domain */ |
891 | update_all_wiphy_regulatory(last_request->initiator); | 1323 | update_all_wiphy_regulatory(last_request->initiator); |
892 | 1324 | ||
893 | print_regdomain(rd); | 1325 | print_regdomain(cfg80211_regdomain); |
894 | 1326 | ||
895 | return r; | 1327 | return r; |
896 | } | 1328 | } |
897 | 1329 | ||
1330 | /* Caller must hold cfg80211_drv_mutex */ | ||
1331 | void reg_device_remove(struct wiphy *wiphy) | ||
1332 | { | ||
1333 | if (!last_request->wiphy) | ||
1334 | return; | ||
1335 | if (last_request->wiphy != wiphy) | ||
1336 | return; | ||
1337 | last_request->wiphy = NULL; | ||
1338 | last_request->country_ie_env = ENVIRON_ANY; | ||
1339 | } | ||
1340 | |||
898 | int regulatory_init(void) | 1341 | int regulatory_init(void) |
899 | { | 1342 | { |
900 | int err; | 1343 | int err; |
@@ -914,11 +1357,11 @@ int regulatory_init(void) | |||
914 | * that is not a valid ISO / IEC 3166 alpha2 */ | 1357 | * that is not a valid ISO / IEC 3166 alpha2 */ |
915 | if (ieee80211_regdom[0] != 'E' || ieee80211_regdom[1] != 'U') | 1358 | if (ieee80211_regdom[0] != 'E' || ieee80211_regdom[1] != 'U') |
916 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, | 1359 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, |
917 | ieee80211_regdom); | 1360 | ieee80211_regdom, 0, ENVIRON_ANY); |
918 | #else | 1361 | #else |
919 | cfg80211_regdomain = cfg80211_world_regdom; | 1362 | cfg80211_regdomain = cfg80211_world_regdom; |
920 | 1363 | ||
921 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00"); | 1364 | err = __regulatory_hint(NULL, REGDOM_SET_BY_CORE, "00", 0, ENVIRON_ANY); |
922 | if (err) | 1365 | if (err) |
923 | printk(KERN_ERR "cfg80211: calling CRDA failed - " | 1366 | printk(KERN_ERR "cfg80211: calling CRDA failed - " |
924 | "unable to update world regulatory domain, " | 1367 | "unable to update world regulatory domain, " |
@@ -934,6 +1377,9 @@ void regulatory_exit(void) | |||
934 | 1377 | ||
935 | reset_regdomains(); | 1378 | reset_regdomains(); |
936 | 1379 | ||
1380 | kfree(country_ie_regdomain); | ||
1381 | country_ie_regdomain = NULL; | ||
1382 | |||
937 | kfree(last_request); | 1383 | kfree(last_request); |
938 | 1384 | ||
939 | platform_device_unregister(reg_pdev); | 1385 | platform_device_unregister(reg_pdev); |
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index c9b6b6358bbe..a76ea3ff7cd6 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
@@ -4,28 +4,41 @@ | |||
4 | bool is_world_regdom(const char *alpha2); | 4 | bool is_world_regdom(const char *alpha2); |
5 | bool reg_is_valid_request(const char *alpha2); | 5 | bool reg_is_valid_request(const char *alpha2); |
6 | 6 | ||
7 | void reg_device_remove(struct wiphy *wiphy); | ||
8 | |||
7 | int regulatory_init(void); | 9 | int regulatory_init(void); |
8 | void regulatory_exit(void); | 10 | void regulatory_exit(void); |
9 | 11 | ||
10 | int set_regdom(const struct ieee80211_regdomain *rd); | 12 | int set_regdom(const struct ieee80211_regdomain *rd); |
11 | 13 | ||
14 | enum environment_cap { | ||
15 | ENVIRON_ANY, | ||
16 | ENVIRON_INDOOR, | ||
17 | ENVIRON_OUTDOOR, | ||
18 | }; | ||
19 | |||
20 | |||
12 | /** | 21 | /** |
13 | * __regulatory_hint - hint to the wireless core a regulatory domain | 22 | * __regulatory_hint - hint to the wireless core a regulatory domain |
14 | * @wiphy: if the hint comes from country information from an AP, this | 23 | * @wiphy: if the hint comes from country information from an AP, this |
15 | * is required to be set to the wiphy that received the information | 24 | * is required to be set to the wiphy that received the information |
16 | * @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain | 25 | * @alpha2: the ISO/IEC 3166 alpha2 being claimed the regulatory domain |
17 | * should be in. | 26 | * should be in. |
27 | * @country_ie_checksum: checksum of processed country IE, set this to 0 | ||
28 | * if the hint did not come from a country IE | ||
29 | * @country_ie_env: the environment the IE told us we are in, %ENVIRON_* | ||
18 | * | 30 | * |
19 | * The Wireless subsystem can use this function to hint to the wireless core | 31 | * The Wireless subsystem can use this function to hint to the wireless core |
20 | * what it believes should be the current regulatory domain by | 32 | * what it believes should be the current regulatory domain by giving it an |
21 | * giving it an ISO/IEC 3166 alpha2 country code it knows its regulatory | 33 | * ISO/IEC 3166 alpha2 country code it knows its regulatory domain should be |
22 | * domain should be in. | 34 | * in. |
23 | * | 35 | * |
24 | * Returns zero if all went fine, %-EALREADY if a regulatory domain had | 36 | * Returns zero if all went fine, %-EALREADY if a regulatory domain had |
25 | * already been set or other standard error codes. | 37 | * already been set or other standard error codes. |
26 | * | 38 | * |
27 | */ | 39 | */ |
28 | extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, | 40 | extern int __regulatory_hint(struct wiphy *wiphy, enum reg_set_by set_by, |
29 | const char *alpha2); | 41 | const char *alpha2, u32 country_ie_checksum, |
42 | enum environment_cap country_ie_env); | ||
30 | 43 | ||
31 | #endif /* __NET_WIRELESS_REG_H */ | 44 | #endif /* __NET_WIRELESS_REG_H */ |