diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/wireless/ath/ath5k | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/wireless/ath/ath5k')
29 files changed, 6387 insertions, 5058 deletions
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig index eb83b7b4d0e3..e18a9aa7b6ca 100644 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ b/drivers/net/wireless/ath/ath5k/Kconfig | |||
@@ -1,9 +1,12 @@ | |||
1 | config ATH5K | 1 | config ATH5K |
2 | tristate "Atheros 5xxx wireless cards support" | 2 | tristate "Atheros 5xxx wireless cards support" |
3 | depends on PCI && MAC80211 | 3 | depends on (PCI || ATHEROS_AR231X) && MAC80211 |
4 | select MAC80211_LEDS | 4 | select MAC80211_LEDS |
5 | select LEDS_CLASS | 5 | select LEDS_CLASS |
6 | select NEW_LEDS | 6 | select NEW_LEDS |
7 | select AVERAGE | ||
8 | select ATH5K_AHB if (ATHEROS_AR231X && !PCI) | ||
9 | select ATH5K_PCI if (!ATHEROS_AR231X && PCI) | ||
7 | ---help--- | 10 | ---help--- |
8 | This module adds support for wireless adapters based on | 11 | This module adds support for wireless adapters based on |
9 | Atheros 5xxx chipset. | 12 | Atheros 5xxx chipset. |
@@ -37,3 +40,27 @@ config ATH5K_DEBUG | |||
37 | 40 | ||
38 | modprobe ath5k debug=0x00000400 | 41 | modprobe ath5k debug=0x00000400 |
39 | 42 | ||
43 | config ATH5K_TRACER | ||
44 | bool "Atheros 5xxx tracer" | ||
45 | depends on ATH5K | ||
46 | depends on EVENT_TRACING | ||
47 | ---help--- | ||
48 | Say Y here to enable tracepoints for the ath5k driver | ||
49 | using the kernel tracing infrastructure. Select this | ||
50 | option if you are interested in debugging the driver. | ||
51 | |||
52 | If unsure, say N. | ||
53 | |||
54 | config ATH5K_AHB | ||
55 | bool "Atheros 5xxx AHB bus support" | ||
56 | depends on (ATHEROS_AR231X && !PCI) | ||
57 | ---help--- | ||
58 | This adds support for WiSoC type chipsets of the 5xxx Atheros | ||
59 | family. | ||
60 | |||
61 | config ATH5K_PCI | ||
62 | bool "Atheros 5xxx PCI bus support" | ||
63 | depends on (!ATHEROS_AR231X && PCI) | ||
64 | ---help--- | ||
65 | This adds support for PCI type chipsets of the 5xxx Atheros | ||
66 | family. | ||
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile index 2242a140e4fe..f60b3899afc4 100644 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ b/drivers/net/wireless/ath/ath5k/Makefile | |||
@@ -14,5 +14,8 @@ ath5k-y += led.o | |||
14 | ath5k-y += rfkill.o | 14 | ath5k-y += rfkill.o |
15 | ath5k-y += ani.o | 15 | ath5k-y += ani.o |
16 | ath5k-y += sysfs.o | 16 | ath5k-y += sysfs.o |
17 | ath5k-y += mac80211-ops.o | ||
17 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o | 18 | ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o |
19 | ath5k-$(CONFIG_ATH5K_AHB) += ahb.o | ||
20 | ath5k-$(CONFIG_ATH5K_PCI) += pci.o | ||
18 | obj-$(CONFIG_ATH5K) += ath5k.o | 21 | obj-$(CONFIG_ATH5K) += ath5k.o |
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c new file mode 100644 index 000000000000..ea9982781559 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/ahb.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> | ||
4 | * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> | ||
5 | * | ||
6 | * Permission to use, copy, modify, and/or distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | #include <linux/nl80211.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/etherdevice.h> | ||
22 | #include <ar231x_platform.h> | ||
23 | #include "ath5k.h" | ||
24 | #include "debug.h" | ||
25 | #include "base.h" | ||
26 | #include "reg.h" | ||
27 | #include "debug.h" | ||
28 | |||
29 | /* return bus cachesize in 4B word units */ | ||
30 | static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz) | ||
31 | { | ||
32 | *csz = L1_CACHE_BYTES >> 2; | ||
33 | } | ||
34 | |||
35 | static bool | ||
36 | ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | ||
37 | { | ||
38 | struct ath5k_softc *sc = common->priv; | ||
39 | struct platform_device *pdev = to_platform_device(sc->dev); | ||
40 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | ||
41 | u16 *eeprom, *eeprom_end; | ||
42 | |||
43 | |||
44 | |||
45 | bcfg = pdev->dev.platform_data; | ||
46 | eeprom = (u16 *) bcfg->radio; | ||
47 | eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ; | ||
48 | |||
49 | eeprom += off; | ||
50 | if (eeprom > eeprom_end) | ||
51 | return false; | ||
52 | |||
53 | *data = *eeprom; | ||
54 | return true; | ||
55 | } | ||
56 | |||
57 | int ath5k_hw_read_srev(struct ath5k_hw *ah) | ||
58 | { | ||
59 | struct ath5k_softc *sc = ah->ah_sc; | ||
60 | struct platform_device *pdev = to_platform_device(sc->dev); | ||
61 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | ||
62 | ah->ah_mac_srev = bcfg->devid; | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
67 | { | ||
68 | struct ath5k_softc *sc = ah->ah_sc; | ||
69 | struct platform_device *pdev = to_platform_device(sc->dev); | ||
70 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | ||
71 | u8 *cfg_mac; | ||
72 | |||
73 | if (to_platform_device(sc->dev)->id == 0) | ||
74 | cfg_mac = bcfg->config->wlan0_mac; | ||
75 | else | ||
76 | cfg_mac = bcfg->config->wlan1_mac; | ||
77 | |||
78 | memcpy(mac, cfg_mac, ETH_ALEN); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static const struct ath_bus_ops ath_ahb_bus_ops = { | ||
83 | .ath_bus_type = ATH_AHB, | ||
84 | .read_cachesize = ath5k_ahb_read_cachesize, | ||
85 | .eeprom_read = ath5k_ahb_eeprom_read, | ||
86 | .eeprom_read_mac = ath5k_ahb_eeprom_read_mac, | ||
87 | }; | ||
88 | |||
89 | /*Initialization*/ | ||
90 | static int ath_ahb_probe(struct platform_device *pdev) | ||
91 | { | ||
92 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | ||
93 | struct ath5k_softc *sc; | ||
94 | struct ieee80211_hw *hw; | ||
95 | struct resource *res; | ||
96 | void __iomem *mem; | ||
97 | int irq; | ||
98 | int ret = 0; | ||
99 | u32 reg; | ||
100 | |||
101 | if (!pdev->dev.platform_data) { | ||
102 | dev_err(&pdev->dev, "no platform data specified\n"); | ||
103 | ret = -EINVAL; | ||
104 | goto err_out; | ||
105 | } | ||
106 | |||
107 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
108 | if (res == NULL) { | ||
109 | dev_err(&pdev->dev, "no memory resource found\n"); | ||
110 | ret = -ENXIO; | ||
111 | goto err_out; | ||
112 | } | ||
113 | |||
114 | mem = ioremap_nocache(res->start, resource_size(res)); | ||
115 | if (mem == NULL) { | ||
116 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
117 | ret = -ENOMEM; | ||
118 | goto err_out; | ||
119 | } | ||
120 | |||
121 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
122 | if (res == NULL) { | ||
123 | dev_err(&pdev->dev, "no IRQ resource found\n"); | ||
124 | ret = -ENXIO; | ||
125 | goto err_out; | ||
126 | } | ||
127 | |||
128 | irq = res->start; | ||
129 | |||
130 | hw = ieee80211_alloc_hw(sizeof(struct ath5k_softc), &ath5k_hw_ops); | ||
131 | if (hw == NULL) { | ||
132 | dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); | ||
133 | ret = -ENOMEM; | ||
134 | goto err_out; | ||
135 | } | ||
136 | |||
137 | sc = hw->priv; | ||
138 | sc->hw = hw; | ||
139 | sc->dev = &pdev->dev; | ||
140 | sc->iobase = mem; | ||
141 | sc->irq = irq; | ||
142 | sc->devid = bcfg->devid; | ||
143 | |||
144 | if (bcfg->devid >= AR5K_SREV_AR2315_R6) { | ||
145 | /* Enable WMAC AHB arbitration */ | ||
146 | reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); | ||
147 | reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN; | ||
148 | __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); | ||
149 | |||
150 | /* Enable global WMAC swapping */ | ||
151 | reg = __raw_readl((void __iomem *) AR5K_AR2315_BYTESWAP); | ||
152 | reg |= AR5K_AR2315_BYTESWAP_WMAC; | ||
153 | __raw_writel(reg, (void __iomem *) AR5K_AR2315_BYTESWAP); | ||
154 | } else { | ||
155 | /* Enable WMAC DMA access (assuming 5312 or 231x*/ | ||
156 | /* TODO: check other platforms */ | ||
157 | reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); | ||
158 | if (to_platform_device(sc->dev)->id == 0) | ||
159 | reg |= AR5K_AR5312_ENABLE_WLAN0; | ||
160 | else | ||
161 | reg |= AR5K_AR5312_ENABLE_WLAN1; | ||
162 | __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); | ||
163 | |||
164 | /* | ||
165 | * On a dual-band AR5312, the multiband radio is only | ||
166 | * used as pass-through. Disable 2 GHz support in the | ||
167 | * driver for it | ||
168 | */ | ||
169 | if (to_platform_device(sc->dev)->id == 0 && | ||
170 | (bcfg->config->flags & (BD_WLAN0|BD_WLAN1)) == | ||
171 | (BD_WLAN1|BD_WLAN0)) | ||
172 | __set_bit(ATH_STAT_2G_DISABLED, sc->status); | ||
173 | } | ||
174 | |||
175 | ret = ath5k_init_softc(sc, &ath_ahb_bus_ops); | ||
176 | if (ret != 0) { | ||
177 | dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); | ||
178 | ret = -ENODEV; | ||
179 | goto err_free_hw; | ||
180 | } | ||
181 | |||
182 | platform_set_drvdata(pdev, hw); | ||
183 | |||
184 | return 0; | ||
185 | |||
186 | err_free_hw: | ||
187 | ieee80211_free_hw(hw); | ||
188 | platform_set_drvdata(pdev, NULL); | ||
189 | err_out: | ||
190 | return ret; | ||
191 | } | ||
192 | |||
193 | static int ath_ahb_remove(struct platform_device *pdev) | ||
194 | { | ||
195 | struct ar231x_board_config *bcfg = pdev->dev.platform_data; | ||
196 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | ||
197 | struct ath5k_softc *sc; | ||
198 | u32 reg; | ||
199 | |||
200 | if (!hw) | ||
201 | return 0; | ||
202 | |||
203 | sc = hw->priv; | ||
204 | |||
205 | if (bcfg->devid >= AR5K_SREV_AR2315_R6) { | ||
206 | /* Disable WMAC AHB arbitration */ | ||
207 | reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); | ||
208 | reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN; | ||
209 | __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); | ||
210 | } else { | ||
211 | /*Stop DMA access */ | ||
212 | reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); | ||
213 | if (to_platform_device(sc->dev)->id == 0) | ||
214 | reg &= ~AR5K_AR5312_ENABLE_WLAN0; | ||
215 | else | ||
216 | reg &= ~AR5K_AR5312_ENABLE_WLAN1; | ||
217 | __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); | ||
218 | } | ||
219 | |||
220 | ath5k_deinit_softc(sc); | ||
221 | platform_set_drvdata(pdev, NULL); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static struct platform_driver ath_ahb_driver = { | ||
227 | .probe = ath_ahb_probe, | ||
228 | .remove = ath_ahb_remove, | ||
229 | .driver = { | ||
230 | .name = "ar231x-wmac", | ||
231 | .owner = THIS_MODULE, | ||
232 | }, | ||
233 | }; | ||
234 | |||
235 | static int __init | ||
236 | ath5k_ahb_init(void) | ||
237 | { | ||
238 | return platform_driver_register(&ath_ahb_driver); | ||
239 | } | ||
240 | |||
241 | static void __exit | ||
242 | ath5k_ahb_exit(void) | ||
243 | { | ||
244 | platform_driver_unregister(&ath_ahb_driver); | ||
245 | } | ||
246 | |||
247 | module_init(ath5k_ahb_init); | ||
248 | module_exit(ath5k_ahb_exit); | ||
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index 26dbe65fedb0..f915f404302d 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -58,20 +58,20 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) | |||
58 | { | 58 | { |
59 | /* TODO: | 59 | /* TODO: |
60 | * ANI documents suggest the following five levels to use, but the HAL | 60 | * ANI documents suggest the following five levels to use, but the HAL |
61 | * and ath9k use only use the last two levels, making this | 61 | * and ath9k use only the last two levels, making this |
62 | * essentially an on/off option. There *may* be a reason for this (???), | 62 | * essentially an on/off option. There *may* be a reason for this (???), |
63 | * so i stick with the HAL version for now... | 63 | * so i stick with the HAL version for now... |
64 | */ | 64 | */ |
65 | #if 0 | 65 | #if 0 |
66 | const s8 hi[] = { -18, -18, -16, -14, -12 }; | 66 | static const s8 lo[] = { -52, -56, -60, -64, -70 }; |
67 | const s8 lo[] = { -52, -56, -60, -64, -70 }; | 67 | static const s8 hi[] = { -18, -18, -16, -14, -12 }; |
68 | const s8 sz[] = { -34, -41, -48, -55, -62 }; | 68 | static const s8 sz[] = { -34, -41, -48, -55, -62 }; |
69 | const s8 fr[] = { -70, -72, -75, -78, -80 }; | 69 | static const s8 fr[] = { -70, -72, -75, -78, -80 }; |
70 | #else | 70 | #else |
71 | const s8 sz[] = { -55, -62 }; | 71 | static const s8 lo[] = { -64, -70 }; |
72 | const s8 lo[] = { -64, -70 }; | 72 | static const s8 hi[] = { -14, -12 }; |
73 | const s8 hi[] = { -14, -12 }; | 73 | static const s8 sz[] = { -55, -62 }; |
74 | const s8 fr[] = { -78, -80 }; | 74 | static const s8 fr[] = { -78, -80 }; |
75 | #endif | 75 | #endif |
76 | if (level < 0 || level >= ARRAY_SIZE(sz)) { | 76 | if (level < 0 || level >= ARRAY_SIZE(sz)) { |
77 | ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range", | 77 | ATH5K_ERR(ah->ah_sc, "noise immuniy level %d out of range", |
@@ -102,7 +102,7 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) | |||
102 | void | 102 | void |
103 | ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) | 103 | ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) |
104 | { | 104 | { |
105 | const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; | 105 | static const int val[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; |
106 | 106 | ||
107 | if (level < 0 || level >= ARRAY_SIZE(val) || | 107 | if (level < 0 || level >= ARRAY_SIZE(val) || |
108 | level > ah->ah_sc->ani_state.max_spur_level) { | 108 | level > ah->ah_sc->ani_state.max_spur_level) { |
@@ -127,7 +127,7 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) | |||
127 | void | 127 | void |
128 | ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) | 128 | ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) |
129 | { | 129 | { |
130 | const int val[] = { 0, 4, 8 }; | 130 | static const int val[] = { 0, 4, 8 }; |
131 | 131 | ||
132 | if (level < 0 || level >= ARRAY_SIZE(val)) { | 132 | if (level < 0 || level >= ARRAY_SIZE(val)) { |
133 | ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level); | 133 | ATH5K_ERR(ah->ah_sc, "firstep level %d out of range", level); |
@@ -151,12 +151,12 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level) | |||
151 | void | 151 | void |
152 | ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) | 152 | ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) |
153 | { | 153 | { |
154 | const int m1l[] = { 127, 50 }; | 154 | static const int m1l[] = { 127, 50 }; |
155 | const int m2l[] = { 127, 40 }; | 155 | static const int m2l[] = { 127, 40 }; |
156 | const int m1[] = { 127, 0x4d }; | 156 | static const int m1[] = { 127, 0x4d }; |
157 | const int m2[] = { 127, 0x40 }; | 157 | static const int m2[] = { 127, 0x40 }; |
158 | const int m2cnt[] = { 31, 16 }; | 158 | static const int m2cnt[] = { 31, 16 }; |
159 | const int m2lcnt[] = { 63, 48 }; | 159 | static const int m2lcnt[] = { 63, 48 }; |
160 | 160 | ||
161 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, | 161 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_WEAK_OFDM_LOW_THR, |
162 | AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]); | 162 | AR5K_PHY_WEAK_OFDM_LOW_THR_M1, m1l[on]); |
@@ -192,7 +192,7 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on) | |||
192 | void | 192 | void |
193 | ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) | 193 | ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on) |
194 | { | 194 | { |
195 | const int val[] = { 8, 6 }; | 195 | static const int val[] = { 8, 6 }; |
196 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR, | 196 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_CCK_CROSSCORR, |
197 | AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]); | 197 | AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR, val[on]); |
198 | ah->ah_sc->ani_state.cck_weak_sig = on; | 198 | ah->ah_sc->ani_state.cck_weak_sig = on; |
@@ -216,7 +216,7 @@ static void | |||
216 | ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, | 216 | ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, |
217 | bool ofdm_trigger) | 217 | bool ofdm_trigger) |
218 | { | 218 | { |
219 | int rssi = ah->ah_beacon_rssi_avg.avg; | 219 | int rssi = ewma_read(&ah->ah_beacon_rssi_avg); |
220 | 220 | ||
221 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)", | 221 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "raise immunity (%s)", |
222 | ofdm_trigger ? "ODFM" : "CCK"); | 222 | ofdm_trigger ? "ODFM" : "CCK"); |
@@ -301,7 +301,7 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as, | |||
301 | static void | 301 | static void |
302 | ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) | 302 | ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) |
303 | { | 303 | { |
304 | int rssi = ah->ah_beacon_rssi_avg.avg; | 304 | int rssi = ewma_read(&ah->ah_beacon_rssi_avg); |
305 | 305 | ||
306 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity"); | 306 | ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_ANI, "lower immunity"); |
307 | 307 | ||
@@ -355,41 +355,28 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) | |||
355 | 355 | ||
356 | 356 | ||
357 | /** | 357 | /** |
358 | * ath5k_hw_ani_get_listen_time() - Calculate time spent listening | 358 | * ath5k_hw_ani_get_listen_time() - Update counters and return listening time |
359 | * | 359 | * |
360 | * Return an approximation of the time spent "listening" in milliseconds (ms) | 360 | * Return an approximation of the time spent "listening" in milliseconds (ms) |
361 | * since the last call of this function by deducting the cycles spent | 361 | * since the last call of this function. |
362 | * transmitting and receiving from the total cycle count. | 362 | * Save a snapshot of the counter values for debugging/statistics. |
363 | * Save profile count values for debugging/statistics and because we might want | ||
364 | * to use them later. | ||
365 | * | ||
366 | * We assume no one else clears these registers! | ||
367 | */ | 363 | */ |
368 | static int | 364 | static int |
369 | ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as) | 365 | ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as) |
370 | { | 366 | { |
367 | struct ath_common *common = ath5k_hw_common(ah); | ||
371 | int listen; | 368 | int listen; |
372 | 369 | ||
373 | /* freeze */ | 370 | spin_lock_bh(&common->cc_lock); |
374 | ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC); | 371 | |
375 | /* read */ | 372 | ath_hw_cycle_counters_update(common); |
376 | as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE); | 373 | memcpy(&as->last_cc, &common->cc_ani, sizeof(as->last_cc)); |
377 | as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR); | 374 | |
378 | as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX); | 375 | /* clears common->cc_ani */ |
379 | as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX); | 376 | listen = ath_hw_get_listen_time(common); |
380 | /* clear */ | 377 | |
381 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); | 378 | spin_unlock_bh(&common->cc_lock); |
382 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); | 379 | |
383 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); | ||
384 | ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); | ||
385 | /* un-freeze */ | ||
386 | ath5k_hw_reg_write(ah, 0, AR5K_MIBC); | ||
387 | |||
388 | /* TODO: where does 44000 come from? (11g clock rate?) */ | ||
389 | listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000; | ||
390 | |||
391 | if (as->pfc_cycles == 0 || listen < 0) | ||
392 | return 0; | ||
393 | return listen; | 380 | return listen; |
394 | } | 381 | } |
395 | 382 | ||
@@ -552,9 +539,9 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah) | |||
552 | if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) | 539 | if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) |
553 | return; | 540 | return; |
554 | 541 | ||
555 | /* if one of the errors triggered, we can get a superfluous second | 542 | /* If one of the errors triggered, we can get a superfluous second |
556 | * interrupt, even though we have already reset the register. the | 543 | * interrupt, even though we have already reset the register. The |
557 | * function detects that so we can return early */ | 544 | * function detects that so we can return early. */ |
558 | if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) | 545 | if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) |
559 | return; | 546 | return; |
560 | 547 | ||
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h index 55cf26d8522c..034015397093 100644 --- a/drivers/net/wireless/ath/ath5k/ani.h +++ b/drivers/net/wireless/ath/ath5k/ani.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #define ATH5K_ANI_RSSI_THR_HIGH 40 | 27 | #define ATH5K_ANI_RSSI_THR_HIGH 40 |
28 | #define ATH5K_ANI_RSSI_THR_LOW 7 | 28 | #define ATH5K_ANI_RSSI_THR_LOW 7 |
29 | 29 | ||
30 | /* maximum availabe levels */ | 30 | /* maximum available levels */ |
31 | #define ATH5K_ANI_MAX_FIRSTEP_LVL 2 | 31 | #define ATH5K_ANI_MAX_FIRSTEP_LVL 2 |
32 | #define ATH5K_ANI_MAX_NOISE_IMM_LVL 1 | 32 | #define ATH5K_ANI_MAX_NOISE_IMM_LVL 1 |
33 | 33 | ||
@@ -75,10 +75,7 @@ struct ath5k_ani_state { | |||
75 | unsigned int cck_errors; | 75 | unsigned int cck_errors; |
76 | 76 | ||
77 | /* debug/statistics only: numbers from last ANI calibration */ | 77 | /* debug/statistics only: numbers from last ANI calibration */ |
78 | unsigned int pfc_tx; | 78 | struct ath_cycle_counters last_cc; |
79 | unsigned int pfc_rx; | ||
80 | unsigned int pfc_busy; | ||
81 | unsigned int pfc_cycles; | ||
82 | unsigned int last_listen; | 79 | unsigned int last_listen; |
83 | unsigned int last_ofdm_errors; | 80 | unsigned int last_ofdm_errors; |
84 | unsigned int last_cck_errors; | 81 | unsigned int last_cck_errors; |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ea6362a8988d..bb50700436fe 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -25,6 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/average.h> | ||
28 | #include <net/mac80211.h> | 29 | #include <net/mac80211.h> |
29 | 30 | ||
30 | /* RX/TX descriptor hw structs | 31 | /* RX/TX descriptor hw structs |
@@ -153,19 +154,6 @@ | |||
153 | udelay(1); \ | 154 | udelay(1); \ |
154 | } while (0) | 155 | } while (0) |
155 | 156 | ||
156 | /* Register dumps are done per operation mode */ | ||
157 | #define AR5K_INI_RFGAIN_5GHZ 0 | ||
158 | #define AR5K_INI_RFGAIN_2GHZ 1 | ||
159 | |||
160 | /* TODO: Clean this up */ | ||
161 | #define AR5K_INI_VAL_11A 0 | ||
162 | #define AR5K_INI_VAL_11A_TURBO 1 | ||
163 | #define AR5K_INI_VAL_11B 2 | ||
164 | #define AR5K_INI_VAL_11G 3 | ||
165 | #define AR5K_INI_VAL_11G_TURBO 4 | ||
166 | #define AR5K_INI_VAL_XR 0 | ||
167 | #define AR5K_INI_VAL_MAX 5 | ||
168 | |||
169 | /* | 157 | /* |
170 | * Some tuneable values (these should be changeable by the user) | 158 | * Some tuneable values (these should be changeable by the user) |
171 | * TODO: Make use of them and add more options OR use debug/configfs | 159 | * TODO: Make use of them and add more options OR use debug/configfs |
@@ -175,7 +163,7 @@ | |||
175 | #define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 | 163 | #define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 |
176 | #define AR5K_TUNE_RADAR_ALERT false | 164 | #define AR5K_TUNE_RADAR_ALERT false |
177 | #define AR5K_TUNE_MIN_TX_FIFO_THRES 1 | 165 | #define AR5K_TUNE_MIN_TX_FIFO_THRES 1 |
178 | #define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1) | 166 | #define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_FRAME_LEN / 64) + 1) |
179 | #define AR5K_TUNE_REGISTER_TIMEOUT 20000 | 167 | #define AR5K_TUNE_REGISTER_TIMEOUT 20000 |
180 | /* Register for RSSI threshold has a mask of 0xff, so 255 seems to | 168 | /* Register for RSSI threshold has a mask of 0xff, so 255 seems to |
181 | * be the max value. */ | 169 | * be the max value. */ |
@@ -206,6 +194,8 @@ | |||
206 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ | 194 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_ANI 1000 /* 1 sec */ |
207 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */ | 195 | #define ATH5K_TUNE_CALIBRATION_INTERVAL_NF 60000 /* 60 sec */ |
208 | 196 | ||
197 | #define ATH5K_TX_COMPLETE_POLL_INT 3000 /* 3 sec */ | ||
198 | |||
209 | #define AR5K_INIT_CARR_SENSE_EN 1 | 199 | #define AR5K_INIT_CARR_SENSE_EN 1 |
210 | 200 | ||
211 | /*Swap RX/TX Descriptor for big endian archs*/ | 201 | /*Swap RX/TX Descriptor for big endian archs*/ |
@@ -219,45 +209,61 @@ | |||
219 | 209 | ||
220 | /* Initial values */ | 210 | /* Initial values */ |
221 | #define AR5K_INIT_CYCRSSI_THR1 2 | 211 | #define AR5K_INIT_CYCRSSI_THR1 2 |
222 | #define AR5K_INIT_TX_LATENCY 502 | ||
223 | #define AR5K_INIT_USEC 39 | ||
224 | #define AR5K_INIT_USEC_TURBO 79 | ||
225 | #define AR5K_INIT_USEC_32 31 | ||
226 | #define AR5K_INIT_SLOT_TIME 396 | ||
227 | #define AR5K_INIT_SLOT_TIME_TURBO 480 | ||
228 | #define AR5K_INIT_ACK_CTS_TIMEOUT 1024 | ||
229 | #define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 | ||
230 | #define AR5K_INIT_PROG_IFS 920 | ||
231 | #define AR5K_INIT_PROG_IFS_TURBO 960 | ||
232 | #define AR5K_INIT_EIFS 3440 | ||
233 | #define AR5K_INIT_EIFS_TURBO 6880 | ||
234 | #define AR5K_INIT_SIFS 560 | ||
235 | #define AR5K_INIT_SIFS_TURBO 480 | ||
236 | #define AR5K_INIT_SH_RETRY 10 | ||
237 | #define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY | ||
238 | #define AR5K_INIT_SSH_RETRY 32 | ||
239 | #define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY | ||
240 | #define AR5K_INIT_TX_RETRY 10 | ||
241 | |||
242 | #define AR5K_INIT_TRANSMIT_LATENCY ( \ | ||
243 | (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ | ||
244 | (AR5K_INIT_USEC) \ | ||
245 | ) | ||
246 | #define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \ | ||
247 | (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ | ||
248 | (AR5K_INIT_USEC_TURBO) \ | ||
249 | ) | ||
250 | #define AR5K_INIT_PROTO_TIME_CNTRL ( \ | ||
251 | (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \ | ||
252 | (AR5K_INIT_PROG_IFS) \ | ||
253 | ) | ||
254 | #define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \ | ||
255 | (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \ | ||
256 | (AR5K_INIT_PROG_IFS_TURBO) \ | ||
257 | ) | ||
258 | 212 | ||
259 | /* token to use for aifs, cwmin, cwmax in MadWiFi */ | 213 | /* Tx retry limit defaults from standard */ |
260 | #define AR5K_TXQ_USEDEFAULT ((u32) -1) | 214 | #define AR5K_INIT_RETRY_SHORT 7 |
215 | #define AR5K_INIT_RETRY_LONG 4 | ||
216 | |||
217 | /* Slot time */ | ||
218 | #define AR5K_INIT_SLOT_TIME_TURBO 6 | ||
219 | #define AR5K_INIT_SLOT_TIME_DEFAULT 9 | ||
220 | #define AR5K_INIT_SLOT_TIME_HALF_RATE 13 | ||
221 | #define AR5K_INIT_SLOT_TIME_QUARTER_RATE 21 | ||
222 | #define AR5K_INIT_SLOT_TIME_B 20 | ||
223 | #define AR5K_SLOT_TIME_MAX 0xffff | ||
224 | |||
225 | /* SIFS */ | ||
226 | #define AR5K_INIT_SIFS_TURBO 6 | ||
227 | #define AR5K_INIT_SIFS_DEFAULT_BG 10 | ||
228 | #define AR5K_INIT_SIFS_DEFAULT_A 16 | ||
229 | #define AR5K_INIT_SIFS_HALF_RATE 32 | ||
230 | #define AR5K_INIT_SIFS_QUARTER_RATE 64 | ||
231 | |||
232 | /* Used to calculate tx time for non 5/10/40MHz | ||
233 | * operation */ | ||
234 | /* It's preamble time + signal time (16 + 4) */ | ||
235 | #define AR5K_INIT_OFDM_PREAMPLE_TIME 20 | ||
236 | /* Preamble time for 40MHz (turbo) operation (min ?) */ | ||
237 | #define AR5K_INIT_OFDM_PREAMBLE_TIME_MIN 14 | ||
238 | #define AR5K_INIT_OFDM_SYMBOL_TIME 4 | ||
239 | #define AR5K_INIT_OFDM_PLCP_BITS 22 | ||
240 | |||
241 | /* Rx latency for 5 and 10MHz operation (max ?) */ | ||
242 | #define AR5K_INIT_RX_LAT_MAX 63 | ||
243 | /* Tx latencies from initvals (5212 only but no problem | ||
244 | * because we only tweak them on 5212) */ | ||
245 | #define AR5K_INIT_TX_LAT_A 54 | ||
246 | #define AR5K_INIT_TX_LAT_BG 384 | ||
247 | /* Tx latency for 40MHz (turbo) operation (min ?) */ | ||
248 | #define AR5K_INIT_TX_LAT_MIN 32 | ||
249 | /* Default Tx/Rx latencies (same for 5211)*/ | ||
250 | #define AR5K_INIT_TX_LATENCY_5210 54 | ||
251 | #define AR5K_INIT_RX_LATENCY_5210 29 | ||
252 | |||
253 | /* Tx frame to Tx data start delay */ | ||
254 | #define AR5K_INIT_TXF2TXD_START_DEFAULT 14 | ||
255 | #define AR5K_INIT_TXF2TXD_START_DELAY_10MHZ 12 | ||
256 | #define AR5K_INIT_TXF2TXD_START_DELAY_5MHZ 13 | ||
257 | |||
258 | /* We need to increase PHY switch and agc settling time | ||
259 | * on turbo mode */ | ||
260 | #define AR5K_SWITCH_SETTLING 5760 | ||
261 | #define AR5K_SWITCH_SETTLING_TURBO 7168 | ||
262 | |||
263 | #define AR5K_AGC_SETTLING 28 | ||
264 | /* 38 on 5210 but shouldn't matter */ | ||
265 | #define AR5K_AGC_SETTLING_TURBO 37 | ||
266 | |||
261 | 267 | ||
262 | /* GENERIC CHIPSET DEFINITIONS */ | 268 | /* GENERIC CHIPSET DEFINITIONS */ |
263 | 269 | ||
@@ -303,12 +309,19 @@ struct ath5k_srev_name { | |||
303 | #define AR5K_SREV_AR5311B 0x30 /* Spirit */ | 309 | #define AR5K_SREV_AR5311B 0x30 /* Spirit */ |
304 | #define AR5K_SREV_AR5211 0x40 /* Oahu */ | 310 | #define AR5K_SREV_AR5211 0x40 /* Oahu */ |
305 | #define AR5K_SREV_AR5212 0x50 /* Venice */ | 311 | #define AR5K_SREV_AR5212 0x50 /* Venice */ |
312 | #define AR5K_SREV_AR5312_R2 0x52 /* AP31 */ | ||
306 | #define AR5K_SREV_AR5212_V4 0x54 /* ??? */ | 313 | #define AR5K_SREV_AR5212_V4 0x54 /* ??? */ |
307 | #define AR5K_SREV_AR5213 0x55 /* ??? */ | 314 | #define AR5K_SREV_AR5213 0x55 /* ??? */ |
315 | #define AR5K_SREV_AR5312_R7 0x57 /* AP30 */ | ||
316 | #define AR5K_SREV_AR2313_R8 0x58 /* AP43 */ | ||
308 | #define AR5K_SREV_AR5213A 0x59 /* Hainan */ | 317 | #define AR5K_SREV_AR5213A 0x59 /* Hainan */ |
309 | #define AR5K_SREV_AR2413 0x78 /* Griffin lite */ | 318 | #define AR5K_SREV_AR2413 0x78 /* Griffin lite */ |
310 | #define AR5K_SREV_AR2414 0x70 /* Griffin */ | 319 | #define AR5K_SREV_AR2414 0x70 /* Griffin */ |
320 | #define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */ | ||
321 | #define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */ | ||
311 | #define AR5K_SREV_AR5424 0x90 /* Condor */ | 322 | #define AR5K_SREV_AR5424 0x90 /* Condor */ |
323 | #define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */ | ||
324 | #define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */ | ||
312 | #define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ | 325 | #define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ |
313 | #define AR5K_SREV_AR5414 0xa0 /* Eagle */ | 326 | #define AR5K_SREV_AR5414 0xa0 /* Eagle */ |
314 | #define AR5K_SREV_AR2415 0xb0 /* Talon */ | 327 | #define AR5K_SREV_AR2415 0xb0 /* Talon */ |
@@ -343,15 +356,12 @@ struct ath5k_srev_name { | |||
343 | #define AR5K_SREV_PHY_5413 0x61 | 356 | #define AR5K_SREV_PHY_5413 0x61 |
344 | #define AR5K_SREV_PHY_2425 0x70 | 357 | #define AR5K_SREV_PHY_2425 0x70 |
345 | 358 | ||
346 | /* IEEE defs */ | ||
347 | #define IEEE80211_MAX_LEN 2500 | ||
348 | |||
349 | /* TODO add support to mac80211 for vendor-specific rates and modes */ | 359 | /* TODO add support to mac80211 for vendor-specific rates and modes */ |
350 | 360 | ||
351 | /* | 361 | /* |
352 | * Some of this information is based on Documentation from: | 362 | * Some of this information is based on Documentation from: |
353 | * | 363 | * |
354 | * http://madwifi.org/wiki/ChipsetFeatures/SuperAG | 364 | * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG |
355 | * | 365 | * |
356 | * Modulation for Atheros' eXtended Range - range enhancing extension that is | 366 | * Modulation for Atheros' eXtended Range - range enhancing extension that is |
357 | * supposed to double the distance an Atheros client device can keep a | 367 | * supposed to double the distance an Atheros client device can keep a |
@@ -407,12 +417,10 @@ struct ath5k_srev_name { | |||
407 | 417 | ||
408 | enum ath5k_driver_mode { | 418 | enum ath5k_driver_mode { |
409 | AR5K_MODE_11A = 0, | 419 | AR5K_MODE_11A = 0, |
410 | AR5K_MODE_11A_TURBO = 1, | 420 | AR5K_MODE_11B = 1, |
411 | AR5K_MODE_11B = 2, | 421 | AR5K_MODE_11G = 2, |
412 | AR5K_MODE_11G = 3, | ||
413 | AR5K_MODE_11G_TURBO = 4, | ||
414 | AR5K_MODE_XR = 0, | 422 | AR5K_MODE_XR = 0, |
415 | AR5K_MODE_MAX = 5 | 423 | AR5K_MODE_MAX = 3 |
416 | }; | 424 | }; |
417 | 425 | ||
418 | enum ath5k_ant_mode { | 426 | enum ath5k_ant_mode { |
@@ -426,6 +434,12 @@ enum ath5k_ant_mode { | |||
426 | AR5K_ANTMODE_MAX, | 434 | AR5K_ANTMODE_MAX, |
427 | }; | 435 | }; |
428 | 436 | ||
437 | enum ath5k_bw_mode { | ||
438 | AR5K_BWMODE_DEFAULT = 0, /* 20MHz, default operation */ | ||
439 | AR5K_BWMODE_5MHZ = 1, /* Quarter rate */ | ||
440 | AR5K_BWMODE_10MHZ = 2, /* Half rate */ | ||
441 | AR5K_BWMODE_40MHZ = 3 /* Turbo */ | ||
442 | }; | ||
429 | 443 | ||
430 | /****************\ | 444 | /****************\ |
431 | TX DEFINITIONS | 445 | TX DEFINITIONS |
@@ -438,12 +452,10 @@ struct ath5k_tx_status { | |||
438 | u16 ts_seqnum; | 452 | u16 ts_seqnum; |
439 | u16 ts_tstamp; | 453 | u16 ts_tstamp; |
440 | u8 ts_status; | 454 | u8 ts_status; |
441 | u8 ts_rate[4]; | ||
442 | u8 ts_retry[4]; | ||
443 | u8 ts_final_idx; | 455 | u8 ts_final_idx; |
456 | u8 ts_final_retry; | ||
444 | s8 ts_rssi; | 457 | s8 ts_rssi; |
445 | u8 ts_shortretry; | 458 | u8 ts_shortretry; |
446 | u8 ts_longretry; | ||
447 | u8 ts_virtcol; | 459 | u8 ts_virtcol; |
448 | u8 ts_antenna; | 460 | u8 ts_antenna; |
449 | }; | 461 | }; |
@@ -498,7 +510,7 @@ enum ath5k_tx_queue_id { | |||
498 | AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, | 510 | AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, |
499 | AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, | 511 | AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, |
500 | AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/ | 512 | AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/ |
501 | AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/ | 513 | AR5K_TX_QUEUE_ID_DATA_MAX = 3, /*IEEE80211_TX_QUEUE_DATA3*/ |
502 | AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/ | 514 | AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/ |
503 | AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/ | 515 | AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/ |
504 | AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/ | 516 | AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/ |
@@ -531,9 +543,9 @@ struct ath5k_txq_info { | |||
531 | enum ath5k_tx_queue tqi_type; | 543 | enum ath5k_tx_queue tqi_type; |
532 | enum ath5k_tx_queue_subtype tqi_subtype; | 544 | enum ath5k_tx_queue_subtype tqi_subtype; |
533 | u16 tqi_flags; /* Tx queue flags (see above) */ | 545 | u16 tqi_flags; /* Tx queue flags (see above) */ |
534 | u32 tqi_aifs; /* Arbitrated Interframe Space */ | 546 | u8 tqi_aifs; /* Arbitrated Interframe Space */ |
535 | s32 tqi_cw_min; /* Minimum Contention Window */ | 547 | u16 tqi_cw_min; /* Minimum Contention Window */ |
536 | s32 tqi_cw_max; /* Maximum Contention Window */ | 548 | u16 tqi_cw_max; /* Maximum Contention Window */ |
537 | u32 tqi_cbr_period; /* Constant bit rate period */ | 549 | u32 tqi_cbr_period; /* Constant bit rate period */ |
538 | u32 tqi_cbr_overflow_limit; | 550 | u32 tqi_cbr_overflow_limit; |
539 | u32 tqi_burst_time; | 551 | u32 tqi_burst_time; |
@@ -658,7 +670,6 @@ struct ath5k_gain { | |||
658 | 670 | ||
659 | /* channel_flags */ | 671 | /* channel_flags */ |
660 | #define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */ | 672 | #define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */ |
661 | #define CHANNEL_TURBO 0x0010 /* Turbo Channel */ | ||
662 | #define CHANNEL_CCK 0x0020 /* CCK channel */ | 673 | #define CHANNEL_CCK 0x0020 /* CCK channel */ |
663 | #define CHANNEL_OFDM 0x0040 /* OFDM channel */ | 674 | #define CHANNEL_OFDM 0x0040 /* OFDM channel */ |
664 | #define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */ | 675 | #define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */ |
@@ -670,16 +681,10 @@ struct ath5k_gain { | |||
670 | #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) | 681 | #define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) |
671 | #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) | 682 | #define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) |
672 | #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) | 683 | #define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) |
673 | #define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO) | ||
674 | #define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO) | ||
675 | #define CHANNEL_108A CHANNEL_T | ||
676 | #define CHANNEL_108G CHANNEL_TG | ||
677 | #define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) | 684 | #define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) |
678 | 685 | ||
679 | #define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \ | 686 | #define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ) |
680 | CHANNEL_TURBO) | ||
681 | 687 | ||
682 | #define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO) | ||
683 | #define CHANNEL_MODES CHANNEL_ALL | 688 | #define CHANNEL_MODES CHANNEL_ALL |
684 | 689 | ||
685 | /* | 690 | /* |
@@ -867,6 +872,19 @@ enum ath5k_int { | |||
867 | AR5K_INT_QTRIG = 0x40000000, /* Non common */ | 872 | AR5K_INT_QTRIG = 0x40000000, /* Non common */ |
868 | AR5K_INT_GLOBAL = 0x80000000, | 873 | AR5K_INT_GLOBAL = 0x80000000, |
869 | 874 | ||
875 | AR5K_INT_TX_ALL = AR5K_INT_TXOK | ||
876 | | AR5K_INT_TXDESC | ||
877 | | AR5K_INT_TXERR | ||
878 | | AR5K_INT_TXEOL | ||
879 | | AR5K_INT_TXURN, | ||
880 | |||
881 | AR5K_INT_RX_ALL = AR5K_INT_RXOK | ||
882 | | AR5K_INT_RXDESC | ||
883 | | AR5K_INT_RXERR | ||
884 | | AR5K_INT_RXNOFRM | ||
885 | | AR5K_INT_RXEOL | ||
886 | | AR5K_INT_RXORN, | ||
887 | |||
870 | AR5K_INT_COMMON = AR5K_INT_RXOK | 888 | AR5K_INT_COMMON = AR5K_INT_RXOK |
871 | | AR5K_INT_RXDESC | 889 | | AR5K_INT_RXDESC |
872 | | AR5K_INT_RXERR | 890 | | AR5K_INT_RXERR |
@@ -1028,17 +1046,15 @@ struct ath5k_hw { | |||
1028 | enum ath5k_int ah_imr; | 1046 | enum ath5k_int ah_imr; |
1029 | 1047 | ||
1030 | struct ieee80211_channel *ah_current_channel; | 1048 | struct ieee80211_channel *ah_current_channel; |
1031 | bool ah_turbo; | ||
1032 | bool ah_calibration; | 1049 | bool ah_calibration; |
1033 | bool ah_single_chip; | 1050 | bool ah_single_chip; |
1034 | bool ah_aes_support; | ||
1035 | bool ah_combined_mic; | ||
1036 | 1051 | ||
1037 | enum ath5k_version ah_version; | 1052 | enum ath5k_version ah_version; |
1038 | enum ath5k_radio ah_radio; | 1053 | enum ath5k_radio ah_radio; |
1039 | u32 ah_phy; | 1054 | u32 ah_phy; |
1040 | u32 ah_mac_srev; | 1055 | u32 ah_mac_srev; |
1041 | u16 ah_mac_version; | 1056 | u16 ah_mac_version; |
1057 | u16 ah_mac_revision; | ||
1042 | u16 ah_phy_revision; | 1058 | u16 ah_phy_revision; |
1043 | u16 ah_radio_5ghz_revision; | 1059 | u16 ah_radio_5ghz_revision; |
1044 | u16 ah_radio_2ghz_revision; | 1060 | u16 ah_radio_2ghz_revision; |
@@ -1046,19 +1062,19 @@ struct ath5k_hw { | |||
1046 | #define ah_modes ah_capabilities.cap_mode | 1062 | #define ah_modes ah_capabilities.cap_mode |
1047 | #define ah_ee_version ah_capabilities.cap_eeprom.ee_version | 1063 | #define ah_ee_version ah_capabilities.cap_eeprom.ee_version |
1048 | 1064 | ||
1049 | u32 ah_atim_window; | 1065 | u8 ah_retry_long; |
1050 | u32 ah_aifs; | 1066 | u8 ah_retry_short; |
1051 | u32 ah_cw_min; | 1067 | |
1052 | u32 ah_cw_max; | ||
1053 | u32 ah_limit_tx_retries; | ||
1054 | u8 ah_coverage_class; | 1068 | u8 ah_coverage_class; |
1069 | bool ah_ack_bitrate_high; | ||
1070 | u8 ah_bwmode; | ||
1071 | bool ah_short_slot; | ||
1055 | 1072 | ||
1056 | /* Antenna Control */ | 1073 | /* Antenna Control */ |
1057 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 1074 | u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
1058 | u8 ah_ant_mode; | 1075 | u8 ah_ant_mode; |
1059 | u8 ah_tx_ant; | 1076 | u8 ah_tx_ant; |
1060 | u8 ah_def_ant; | 1077 | u8 ah_def_ant; |
1061 | bool ah_software_retry; | ||
1062 | 1078 | ||
1063 | struct ath5k_capabilities ah_capabilities; | 1079 | struct ath5k_capabilities ah_capabilities; |
1064 | 1080 | ||
@@ -1094,12 +1110,14 @@ struct ath5k_hw { | |||
1094 | /* Values in 0.25dB units */ | 1110 | /* Values in 0.25dB units */ |
1095 | s16 txp_min_pwr; | 1111 | s16 txp_min_pwr; |
1096 | s16 txp_max_pwr; | 1112 | s16 txp_max_pwr; |
1113 | s16 txp_cur_pwr; | ||
1097 | /* Values in 0.5dB units */ | 1114 | /* Values in 0.5dB units */ |
1098 | s16 txp_offset; | 1115 | s16 txp_offset; |
1099 | s16 txp_ofdm; | 1116 | s16 txp_ofdm; |
1100 | s16 txp_cck_ofdm_gainf_delta; | 1117 | s16 txp_cck_ofdm_gainf_delta; |
1101 | /* Value in dB units */ | 1118 | /* Value in dB units */ |
1102 | s16 txp_cck_ofdm_pwr_delta; | 1119 | s16 txp_cck_ofdm_pwr_delta; |
1120 | bool txp_setup; | ||
1103 | } ah_txpower; | 1121 | } ah_txpower; |
1104 | 1122 | ||
1105 | struct { | 1123 | struct { |
@@ -1111,7 +1129,7 @@ struct ath5k_hw { | |||
1111 | struct ath5k_nfcal_hist ah_nfcal_hist; | 1129 | struct ath5k_nfcal_hist ah_nfcal_hist; |
1112 | 1130 | ||
1113 | /* average beacon RSSI in our BSS (used by ANI) */ | 1131 | /* average beacon RSSI in our BSS (used by ANI) */ |
1114 | struct ath5k_avg_val ah_beacon_rssi_avg; | 1132 | struct ewma ah_beacon_rssi_avg; |
1115 | 1133 | ||
1116 | /* noise floor from last periodic calibration */ | 1134 | /* noise floor from last periodic calibration */ |
1117 | s32 ah_noise_floor; | 1135 | s32 ah_noise_floor; |
@@ -1137,39 +1155,80 @@ struct ath5k_hw { | |||
1137 | struct ath5k_rx_status *); | 1155 | struct ath5k_rx_status *); |
1138 | }; | 1156 | }; |
1139 | 1157 | ||
1158 | struct ath_bus_ops { | ||
1159 | enum ath_bus_type ath_bus_type; | ||
1160 | void (*read_cachesize)(struct ath_common *common, int *csz); | ||
1161 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); | ||
1162 | int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac); | ||
1163 | }; | ||
1164 | |||
1140 | /* | 1165 | /* |
1141 | * Prototypes | 1166 | * Prototypes |
1142 | */ | 1167 | */ |
1168 | extern const struct ieee80211_ops ath5k_hw_ops; | ||
1143 | 1169 | ||
1144 | /* Attach/Detach Functions */ | 1170 | /* Initialization and detach functions */ |
1145 | int ath5k_hw_attach(struct ath5k_softc *sc); | 1171 | int ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops); |
1146 | void ath5k_hw_detach(struct ath5k_hw *ah); | 1172 | void ath5k_deinit_softc(struct ath5k_softc *sc); |
1173 | int ath5k_hw_init(struct ath5k_softc *sc); | ||
1174 | void ath5k_hw_deinit(struct ath5k_hw *ah); | ||
1147 | 1175 | ||
1148 | int ath5k_sysfs_register(struct ath5k_softc *sc); | 1176 | int ath5k_sysfs_register(struct ath5k_softc *sc); |
1149 | void ath5k_sysfs_unregister(struct ath5k_softc *sc); | 1177 | void ath5k_sysfs_unregister(struct ath5k_softc *sc); |
1150 | 1178 | ||
1179 | /* base.c */ | ||
1180 | struct ath5k_buf; | ||
1181 | struct ath5k_txq; | ||
1182 | |||
1183 | void set_beacon_filter(struct ieee80211_hw *hw, bool enable); | ||
1184 | bool ath_any_vif_assoc(struct ath5k_softc *sc); | ||
1185 | void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
1186 | struct ath5k_txq *txq); | ||
1187 | int ath5k_init_hw(struct ath5k_softc *sc); | ||
1188 | int ath5k_stop_hw(struct ath5k_softc *sc); | ||
1189 | void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif); | ||
1190 | void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, | ||
1191 | struct ieee80211_vif *vif); | ||
1192 | int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan); | ||
1193 | void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | ||
1194 | int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); | ||
1195 | void ath5k_beacon_config(struct ath5k_softc *sc); | ||
1196 | void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf); | ||
1197 | void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf); | ||
1198 | |||
1199 | /*Chip id helper functions */ | ||
1200 | const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val); | ||
1201 | int ath5k_hw_read_srev(struct ath5k_hw *ah); | ||
1202 | |||
1151 | /* LED functions */ | 1203 | /* LED functions */ |
1152 | int ath5k_init_leds(struct ath5k_softc *sc); | 1204 | int ath5k_init_leds(struct ath5k_softc *sc); |
1153 | void ath5k_led_enable(struct ath5k_softc *sc); | 1205 | void ath5k_led_enable(struct ath5k_softc *sc); |
1154 | void ath5k_led_off(struct ath5k_softc *sc); | 1206 | void ath5k_led_off(struct ath5k_softc *sc); |
1155 | void ath5k_unregister_leds(struct ath5k_softc *sc); | 1207 | void ath5k_unregister_leds(struct ath5k_softc *sc); |
1156 | 1208 | ||
1209 | |||
1157 | /* Reset Functions */ | 1210 | /* Reset Functions */ |
1158 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); | 1211 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); |
1159 | int ath5k_hw_on_hold(struct ath5k_hw *ah); | 1212 | int ath5k_hw_on_hold(struct ath5k_hw *ah); |
1160 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 1213 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
1161 | struct ieee80211_channel *channel, bool change_channel); | 1214 | struct ieee80211_channel *channel, bool fast, bool skip_pcu); |
1162 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | 1215 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, |
1163 | bool is_set); | 1216 | bool is_set); |
1164 | /* Power management functions */ | 1217 | /* Power management functions */ |
1165 | 1218 | ||
1219 | |||
1220 | /* Clock rate related functions */ | ||
1221 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | ||
1222 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | ||
1223 | void ath5k_hw_set_clockrate(struct ath5k_hw *ah); | ||
1224 | |||
1225 | |||
1166 | /* DMA Related Functions */ | 1226 | /* DMA Related Functions */ |
1167 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); | 1227 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); |
1168 | int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); | ||
1169 | u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); | 1228 | u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); |
1170 | void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); | 1229 | int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); |
1171 | int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); | 1230 | int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); |
1172 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); | 1231 | int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue); |
1173 | u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); | 1232 | u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); |
1174 | int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, | 1233 | int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, |
1175 | u32 phys_addr); | 1234 | u32 phys_addr); |
@@ -1179,42 +1238,42 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); | |||
1179 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); | 1238 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); |
1180 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); | 1239 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); |
1181 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); | 1240 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); |
1241 | /* Init/Stop functions */ | ||
1242 | void ath5k_hw_dma_init(struct ath5k_hw *ah); | ||
1243 | int ath5k_hw_dma_stop(struct ath5k_hw *ah); | ||
1182 | 1244 | ||
1183 | /* EEPROM access functions */ | 1245 | /* EEPROM access functions */ |
1184 | int ath5k_eeprom_init(struct ath5k_hw *ah); | 1246 | int ath5k_eeprom_init(struct ath5k_hw *ah); |
1185 | void ath5k_eeprom_detach(struct ath5k_hw *ah); | 1247 | void ath5k_eeprom_detach(struct ath5k_hw *ah); |
1186 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); | 1248 | |
1187 | 1249 | ||
1188 | /* Protocol Control Unit Functions */ | 1250 | /* Protocol Control Unit Functions */ |
1251 | /* Helpers */ | ||
1252 | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, | ||
1253 | int len, struct ieee80211_rate *rate, bool shortpre); | ||
1254 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); | ||
1255 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); | ||
1189 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); | 1256 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); |
1190 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); | 1257 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); |
1191 | /* BSSID Functions */ | 1258 | /* RX filter control*/ |
1192 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1259 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1193 | void ath5k_hw_set_associd(struct ath5k_hw *ah); | 1260 | void ath5k_hw_set_bssid(struct ath5k_hw *ah); |
1194 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | 1261 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
1195 | /* Receive start/stop functions */ | ||
1196 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | ||
1197 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | ||
1198 | /* RX Filter functions */ | ||
1199 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); | 1262 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); |
1200 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); | 1263 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); |
1201 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); | 1264 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); |
1265 | /* Receive (DRU) start/stop functions */ | ||
1266 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | ||
1267 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | ||
1202 | /* Beacon control functions */ | 1268 | /* Beacon control functions */ |
1203 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); | 1269 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); |
1204 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); | 1270 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); |
1205 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah); | 1271 | void ath5k_hw_reset_tsf(struct ath5k_hw *ah); |
1206 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); | 1272 | void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); |
1207 | /* ACK bit rate */ | 1273 | bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); |
1208 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); | 1274 | /* Init function */ |
1209 | /* Clock rate related functions */ | 1275 | void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
1210 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | 1276 | u8 mode); |
1211 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | ||
1212 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); | ||
1213 | /* Key table (WEP) functions */ | ||
1214 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); | ||
1215 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | ||
1216 | const struct ieee80211_key_conf *key, const u8 *mac); | ||
1217 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); | ||
1218 | 1277 | ||
1219 | /* Queue Control Unit, DFS Control Unit Functions */ | 1278 | /* Queue Control Unit, DFS Control Unit Functions */ |
1220 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | 1279 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, |
@@ -1224,10 +1283,14 @@ int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | |||
1224 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, | 1283 | int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, |
1225 | enum ath5k_tx_queue queue_type, | 1284 | enum ath5k_tx_queue queue_type, |
1226 | struct ath5k_txq_info *queue_info); | 1285 | struct ath5k_txq_info *queue_info); |
1286 | void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, | ||
1287 | unsigned int queue); | ||
1227 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); | 1288 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); |
1228 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1289 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1229 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1290 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1230 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); | 1291 | int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time); |
1292 | /* Init function */ | ||
1293 | int ath5k_hw_init_queues(struct ath5k_hw *ah); | ||
1231 | 1294 | ||
1232 | /* Hardware Descriptor Functions */ | 1295 | /* Hardware Descriptor Functions */ |
1233 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); | 1296 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); |
@@ -1237,6 +1300,7 @@ int ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
1237 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | 1300 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, |
1238 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3); | 1301 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3); |
1239 | 1302 | ||
1303 | |||
1240 | /* GPIO Functions */ | 1304 | /* GPIO Functions */ |
1241 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); | 1305 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); |
1242 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); | 1306 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); |
@@ -1246,11 +1310,13 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); | |||
1246 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, | 1310 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, |
1247 | u32 interrupt_level); | 1311 | u32 interrupt_level); |
1248 | 1312 | ||
1249 | /* rfkill Functions */ | 1313 | |
1314 | /* RFkill Functions */ | ||
1250 | void ath5k_rfkill_hw_start(struct ath5k_hw *ah); | 1315 | void ath5k_rfkill_hw_start(struct ath5k_hw *ah); |
1251 | void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); | 1316 | void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); |
1252 | 1317 | ||
1253 | /* Misc functions */ | 1318 | |
1319 | /* Misc functions TODO: Cleanup */ | ||
1254 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah); | 1320 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah); |
1255 | int ath5k_hw_get_capability(struct ath5k_hw *ah, | 1321 | int ath5k_hw_get_capability(struct ath5k_hw *ah, |
1256 | enum ath5k_capability_type cap_type, u32 capability, | 1322 | enum ath5k_capability_type cap_type, u32 capability, |
@@ -1258,19 +1324,20 @@ int ath5k_hw_get_capability(struct ath5k_hw *ah, | |||
1258 | int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); | 1324 | int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); |
1259 | int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); | 1325 | int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); |
1260 | 1326 | ||
1327 | |||
1261 | /* Initial register settings functions */ | 1328 | /* Initial register settings functions */ |
1262 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); | 1329 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); |
1263 | 1330 | ||
1264 | /* Initialize RF */ | 1331 | |
1265 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, | 1332 | /* PHY functions */ |
1266 | struct ieee80211_channel *channel, | 1333 | /* Misc PHY functions */ |
1267 | unsigned int mode); | 1334 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); |
1268 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); | 1335 | int ath5k_hw_phy_disable(struct ath5k_hw *ah); |
1336 | /* Gain_F optimization */ | ||
1269 | enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); | 1337 | enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); |
1270 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); | 1338 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); |
1271 | /* PHY/RF channel functions */ | 1339 | /* PHY/RF channel functions */ |
1272 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); | 1340 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); |
1273 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | ||
1274 | /* PHY calibration */ | 1341 | /* PHY calibration */ |
1275 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); | 1342 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); |
1276 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | 1343 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, |
@@ -1279,18 +1346,14 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah); | |||
1279 | /* Spur mitigation */ | 1346 | /* Spur mitigation */ |
1280 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1347 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, |
1281 | struct ieee80211_channel *channel); | 1348 | struct ieee80211_channel *channel); |
1282 | void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | ||
1283 | struct ieee80211_channel *channel); | ||
1284 | /* Misc PHY functions */ | ||
1285 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); | ||
1286 | int ath5k_hw_phy_disable(struct ath5k_hw *ah); | ||
1287 | /* Antenna control */ | 1349 | /* Antenna control */ |
1288 | void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); | 1350 | void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); |
1289 | void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode); | 1351 | void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode); |
1290 | /* TX power setup */ | 1352 | /* TX power setup */ |
1291 | int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | ||
1292 | u8 ee_mode, u8 txpower); | ||
1293 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | 1353 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); |
1354 | /* Init function */ | ||
1355 | int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | ||
1356 | u8 mode, bool fast); | ||
1294 | 1357 | ||
1295 | /* | 1358 | /* |
1296 | * Functions used internaly | 1359 | * Functions used internaly |
@@ -1306,6 +1369,32 @@ static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) | |||
1306 | return &(ath5k_hw_common(ah)->regulatory); | 1369 | return &(ath5k_hw_common(ah)->regulatory); |
1307 | } | 1370 | } |
1308 | 1371 | ||
1372 | #ifdef CONFIG_ATHEROS_AR231X | ||
1373 | #define AR5K_AR2315_PCI_BASE ((void __iomem *)0xb0100000) | ||
1374 | |||
1375 | static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg) | ||
1376 | { | ||
1377 | /* On AR2315 and AR2317 the PCI clock domain registers | ||
1378 | * are outside of the WMAC register space */ | ||
1379 | if (unlikely((reg >= 0x4000) && (reg < 0x5000) && | ||
1380 | (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6))) | ||
1381 | return AR5K_AR2315_PCI_BASE + reg; | ||
1382 | |||
1383 | return ah->ah_iobase + reg; | ||
1384 | } | ||
1385 | |||
1386 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) | ||
1387 | { | ||
1388 | return __raw_readl(ath5k_ahb_reg(ah, reg)); | ||
1389 | } | ||
1390 | |||
1391 | static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) | ||
1392 | { | ||
1393 | __raw_writel(val, ath5k_ahb_reg(ah, reg)); | ||
1394 | } | ||
1395 | |||
1396 | #else | ||
1397 | |||
1309 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) | 1398 | static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) |
1310 | { | 1399 | { |
1311 | return ioread32(ah->ah_iobase + reg); | 1400 | return ioread32(ah->ah_iobase + reg); |
@@ -1316,6 +1405,24 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) | |||
1316 | iowrite32(val, ah->ah_iobase + reg); | 1405 | iowrite32(val, ah->ah_iobase + reg); |
1317 | } | 1406 | } |
1318 | 1407 | ||
1408 | #endif | ||
1409 | |||
1410 | static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah) | ||
1411 | { | ||
1412 | return ath5k_hw_common(ah)->bus_ops->ath_bus_type; | ||
1413 | } | ||
1414 | |||
1415 | static inline void ath5k_read_cachesize(struct ath_common *common, int *csz) | ||
1416 | { | ||
1417 | common->bus_ops->read_cachesize(common, csz); | ||
1418 | } | ||
1419 | |||
1420 | static inline bool ath5k_hw_nvram_read(struct ath5k_hw *ah, u32 off, u16 *data) | ||
1421 | { | ||
1422 | struct ath_common *common = ath5k_hw_common(ah); | ||
1423 | return common->bus_ops->eeprom_read(common, off, data); | ||
1424 | } | ||
1425 | |||
1319 | static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | 1426 | static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) |
1320 | { | 1427 | { |
1321 | u32 retval = 0, bit, i; | 1428 | u32 retval = 0, bit, i; |
@@ -1328,27 +1435,4 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | |||
1328 | return retval; | 1435 | return retval; |
1329 | } | 1436 | } |
1330 | 1437 | ||
1331 | #define AVG_SAMPLES 8 | ||
1332 | #define AVG_FACTOR 1000 | ||
1333 | |||
1334 | /** | ||
1335 | * ath5k_moving_average - Exponentially weighted moving average | ||
1336 | * @avg: average structure | ||
1337 | * @val: current value | ||
1338 | * | ||
1339 | * This implementation make use of a struct ath5k_avg_val to prevent rounding | ||
1340 | * errors. | ||
1341 | */ | ||
1342 | static inline struct ath5k_avg_val | ||
1343 | ath5k_moving_average(const struct ath5k_avg_val avg, const int val) | ||
1344 | { | ||
1345 | struct ath5k_avg_val new; | ||
1346 | new.avg_weight = avg.avg_weight ? | ||
1347 | (((avg.avg_weight * ((AVG_SAMPLES) - 1)) + | ||
1348 | (val * (AVG_FACTOR))) / (AVG_SAMPLES)) : | ||
1349 | (val * (AVG_FACTOR)); | ||
1350 | new.avg = new.avg_weight / (AVG_FACTOR); | ||
1351 | return new; | ||
1352 | } | ||
1353 | |||
1354 | #endif | 1438 | #endif |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index b32e28caeee2..1588401de3c4 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -93,16 +93,16 @@ static int ath5k_hw_post(struct ath5k_hw *ah) | |||
93 | } | 93 | } |
94 | 94 | ||
95 | /** | 95 | /** |
96 | * ath5k_hw_attach - Check if hw is supported and init the needed structs | 96 | * ath5k_hw_init - Check if hw is supported and init the needed structs |
97 | * | 97 | * |
98 | * @sc: The &struct ath5k_softc we got from the driver's attach function | 98 | * @sc: The &struct ath5k_softc we got from the driver's init_softc function |
99 | * | 99 | * |
100 | * Check if the device is supported, perform a POST and initialize the needed | 100 | * Check if the device is supported, perform a POST and initialize the needed |
101 | * structs. Returns -ENOMEM if we don't have memory for the needed structs, | 101 | * structs. Returns -ENOMEM if we don't have memory for the needed structs, |
102 | * -ENODEV if the device is not supported or prints an error msg if something | 102 | * -ENODEV if the device is not supported or prints an error msg if something |
103 | * else went wrong. | 103 | * else went wrong. |
104 | */ | 104 | */ |
105 | int ath5k_hw_attach(struct ath5k_softc *sc) | 105 | int ath5k_hw_init(struct ath5k_softc *sc) |
106 | { | 106 | { |
107 | struct ath5k_hw *ah = sc->ah; | 107 | struct ath5k_hw *ah = sc->ah; |
108 | struct ath_common *common = ath5k_hw_common(ah); | 108 | struct ath_common *common = ath5k_hw_common(ah); |
@@ -115,14 +115,11 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
115 | * HW information | 115 | * HW information |
116 | */ | 116 | */ |
117 | ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; | 117 | ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; |
118 | ah->ah_turbo = false; | 118 | ah->ah_bwmode = AR5K_BWMODE_DEFAULT; |
119 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | 119 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; |
120 | ah->ah_imr = 0; | 120 | ah->ah_imr = 0; |
121 | ah->ah_atim_window = 0; | 121 | ah->ah_retry_short = AR5K_INIT_RETRY_SHORT; |
122 | ah->ah_aifs = AR5K_TUNE_AIFS; | 122 | ah->ah_retry_long = AR5K_INIT_RETRY_LONG; |
123 | ah->ah_cw_min = AR5K_TUNE_CWMIN; | ||
124 | ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; | ||
125 | ah->ah_software_retry = false; | ||
126 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; | 123 | ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; |
127 | ah->ah_noise_floor = -95; /* until first NF calibration is run */ | 124 | ah->ah_noise_floor = -95; /* until first NF calibration is run */ |
128 | sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; | 125 | sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO; |
@@ -131,7 +128,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
131 | /* | 128 | /* |
132 | * Find the mac version | 129 | * Find the mac version |
133 | */ | 130 | */ |
134 | srev = ath5k_hw_reg_read(ah, AR5K_SREV); | 131 | ath5k_hw_read_srev(ah); |
132 | srev = ah->ah_mac_srev; | ||
135 | if (srev < AR5K_SREV_AR5311) | 133 | if (srev < AR5K_SREV_AR5311) |
136 | ah->ah_version = AR5K_AR5210; | 134 | ah->ah_version = AR5K_AR5210; |
137 | else if (srev < AR5K_SREV_AR5212) | 135 | else if (srev < AR5K_SREV_AR5212) |
@@ -139,26 +137,28 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
139 | else | 137 | else |
140 | ah->ah_version = AR5K_AR5212; | 138 | ah->ah_version = AR5K_AR5212; |
141 | 139 | ||
142 | /*Fill the ath5k_hw struct with the needed functions*/ | 140 | /* Get the MAC revision */ |
141 | ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); | ||
142 | ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); | ||
143 | |||
144 | /* Fill the ath5k_hw struct with the needed functions */ | ||
143 | ret = ath5k_hw_init_desc_functions(ah); | 145 | ret = ath5k_hw_init_desc_functions(ah); |
144 | if (ret) | 146 | if (ret) |
145 | goto err_free; | 147 | goto err; |
146 | 148 | ||
147 | /* Bring device out of sleep and reset it's units */ | 149 | /* Bring device out of sleep and reset its units */ |
148 | ret = ath5k_hw_nic_wakeup(ah, 0, true); | 150 | ret = ath5k_hw_nic_wakeup(ah, 0, true); |
149 | if (ret) | 151 | if (ret) |
150 | goto err_free; | 152 | goto err; |
151 | 153 | ||
152 | /* Get MAC, PHY and RADIO revisions */ | 154 | /* Get PHY and RADIO revisions */ |
153 | ah->ah_mac_srev = srev; | ||
154 | ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); | ||
155 | ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & | 155 | ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & |
156 | 0xffffffff; | 156 | 0xffffffff; |
157 | ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, | 157 | ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, |
158 | CHANNEL_5GHZ); | 158 | CHANNEL_5GHZ); |
159 | ah->ah_phy = AR5K_PHY(0); | 159 | ah->ah_phy = AR5K_PHY(0); |
160 | 160 | ||
161 | /* Try to identify radio chip based on it's srev */ | 161 | /* Try to identify radio chip based on its srev */ |
162 | switch (ah->ah_radio_5ghz_revision & 0xf0) { | 162 | switch (ah->ah_radio_5ghz_revision & 0xf0) { |
163 | case AR5K_SREV_RAD_5111: | 163 | case AR5K_SREV_RAD_5111: |
164 | ah->ah_radio = AR5K_RF5111; | 164 | ah->ah_radio = AR5K_RF5111; |
@@ -220,7 +220,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
220 | ah->ah_radio = AR5K_RF5112; | 220 | ah->ah_radio = AR5K_RF5112; |
221 | ah->ah_single_chip = false; | 221 | ah->ah_single_chip = false; |
222 | ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B; | 222 | ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B; |
223 | } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) { | 223 | } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4) || |
224 | ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) { | ||
224 | ah->ah_radio = AR5K_RF2316; | 225 | ah->ah_radio = AR5K_RF2316; |
225 | ah->ah_single_chip = true; | 226 | ah->ah_single_chip = true; |
226 | ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316; | 227 | ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316; |
@@ -237,7 +238,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
237 | } else { | 238 | } else { |
238 | ATH5K_ERR(sc, "Couldn't identify radio revision.\n"); | 239 | ATH5K_ERR(sc, "Couldn't identify radio revision.\n"); |
239 | ret = -ENODEV; | 240 | ret = -ENODEV; |
240 | goto err_free; | 241 | goto err; |
241 | } | 242 | } |
242 | } | 243 | } |
243 | 244 | ||
@@ -247,7 +248,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
247 | (srev < AR5K_SREV_AR2425)) { | 248 | (srev < AR5K_SREV_AR2425)) { |
248 | ATH5K_ERR(sc, "Device not yet supported.\n"); | 249 | ATH5K_ERR(sc, "Device not yet supported.\n"); |
249 | ret = -ENODEV; | 250 | ret = -ENODEV; |
250 | goto err_free; | 251 | goto err; |
251 | } | 252 | } |
252 | 253 | ||
253 | /* | 254 | /* |
@@ -255,7 +256,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
255 | */ | 256 | */ |
256 | ret = ath5k_hw_post(ah); | 257 | ret = ath5k_hw_post(ah); |
257 | if (ret) | 258 | if (ret) |
258 | goto err_free; | 259 | goto err; |
259 | 260 | ||
260 | /* Enable pci core retry fix on Hainan (5213A) and later chips */ | 261 | /* Enable pci core retry fix on Hainan (5213A) and later chips */ |
261 | if (srev >= AR5K_SREV_AR5213A) | 262 | if (srev >= AR5K_SREV_AR5213A) |
@@ -268,7 +269,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
268 | ret = ath5k_eeprom_init(ah); | 269 | ret = ath5k_eeprom_init(ah); |
269 | if (ret) { | 270 | if (ret) { |
270 | ATH5K_ERR(sc, "unable to init EEPROM\n"); | 271 | ATH5K_ERR(sc, "unable to init EEPROM\n"); |
271 | goto err_free; | 272 | goto err; |
272 | } | 273 | } |
273 | 274 | ||
274 | ee = &ah->ah_capabilities.cap_eeprom; | 275 | ee = &ah->ah_capabilities.cap_eeprom; |
@@ -276,7 +277,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
276 | /* | 277 | /* |
277 | * Write PCI-E power save settings | 278 | * Write PCI-E power save settings |
278 | */ | 279 | */ |
279 | if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { | 280 | if ((ah->ah_version == AR5K_AR5212) && pdev && (pci_is_pcie(pdev))) { |
280 | ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); | 281 | ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); |
281 | ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); | 282 | ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); |
282 | 283 | ||
@@ -308,18 +309,26 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
308 | /* Get misc capabilities */ | 309 | /* Get misc capabilities */ |
309 | ret = ath5k_hw_set_capabilities(ah); | 310 | ret = ath5k_hw_set_capabilities(ah); |
310 | if (ret) { | 311 | if (ret) { |
311 | ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", | 312 | ATH5K_ERR(sc, "unable to get device capabilities\n"); |
312 | sc->pdev->device); | 313 | goto err; |
313 | goto err_free; | 314 | } |
315 | |||
316 | if (test_bit(ATH_STAT_2G_DISABLED, sc->status)) { | ||
317 | __clear_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); | ||
318 | __clear_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); | ||
314 | } | 319 | } |
315 | 320 | ||
316 | /* Crypto settings */ | 321 | /* Crypto settings */ |
317 | ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && | 322 | common->keymax = (sc->ah->ah_version == AR5K_AR5210 ? |
318 | (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && | 323 | AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211); |
319 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); | 324 | |
325 | if (srev >= AR5K_SREV_AR5212_V4 && | ||
326 | (ee->ee_version < AR5K_EEPROM_VERSION_5_0 || | ||
327 | !AR5K_EEPROM_AES_DIS(ee->ee_misc5))) | ||
328 | common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; | ||
320 | 329 | ||
321 | if (srev >= AR5K_SREV_AR2414) { | 330 | if (srev >= AR5K_SREV_AR2414) { |
322 | ah->ah_combined_mic = true; | 331 | common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; |
323 | AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, | 332 | AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, |
324 | AR5K_MISC_MODE_COMBINED_MIC); | 333 | AR5K_MISC_MODE_COMBINED_MIC); |
325 | } | 334 | } |
@@ -329,7 +338,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
329 | 338 | ||
330 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 339 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
331 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); | 340 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); |
332 | ath5k_hw_set_associd(ah); | 341 | ath5k_hw_set_bssid(ah); |
333 | ath5k_hw_set_opmode(ah, sc->opmode); | 342 | ath5k_hw_set_opmode(ah, sc->opmode); |
334 | 343 | ||
335 | ath5k_hw_rfgain_opt_init(ah); | 344 | ath5k_hw_rfgain_opt_init(ah); |
@@ -340,17 +349,16 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
340 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); | 349 | ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); |
341 | 350 | ||
342 | return 0; | 351 | return 0; |
343 | err_free: | 352 | err: |
344 | kfree(ah); | ||
345 | return ret; | 353 | return ret; |
346 | } | 354 | } |
347 | 355 | ||
348 | /** | 356 | /** |
349 | * ath5k_hw_detach - Free the ath5k_hw struct | 357 | * ath5k_hw_deinit - Free the ath5k_hw struct |
350 | * | 358 | * |
351 | * @ah: The &struct ath5k_hw | 359 | * @ah: The &struct ath5k_hw |
352 | */ | 360 | */ |
353 | void ath5k_hw_detach(struct ath5k_hw *ah) | 361 | void ath5k_hw_deinit(struct ath5k_hw *ah) |
354 | { | 362 | { |
355 | __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); | 363 | __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); |
356 | 364 | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index d77ce9906b6c..b6c5d3715b96 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -47,11 +47,10 @@ | |||
47 | #include <linux/io.h> | 47 | #include <linux/io.h> |
48 | #include <linux/netdevice.h> | 48 | #include <linux/netdevice.h> |
49 | #include <linux/cache.h> | 49 | #include <linux/cache.h> |
50 | #include <linux/pci.h> | ||
51 | #include <linux/pci-aspm.h> | ||
52 | #include <linux/ethtool.h> | 50 | #include <linux/ethtool.h> |
53 | #include <linux/uaccess.h> | 51 | #include <linux/uaccess.h> |
54 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
53 | #include <linux/etherdevice.h> | ||
55 | 54 | ||
56 | #include <net/ieee80211_radiotap.h> | 55 | #include <net/ieee80211_radiotap.h> |
57 | 56 | ||
@@ -62,18 +61,21 @@ | |||
62 | #include "debug.h" | 61 | #include "debug.h" |
63 | #include "ani.h" | 62 | #include "ani.h" |
64 | 63 | ||
65 | static int modparam_nohwcrypt; | 64 | #define CREATE_TRACE_POINTS |
66 | module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); | 65 | #include "trace.h" |
66 | |||
67 | int ath5k_modparam_nohwcrypt; | ||
68 | module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO); | ||
67 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 69 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
68 | 70 | ||
69 | static int modparam_all_channels; | 71 | static int modparam_all_channels; |
70 | module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); | 72 | module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); |
71 | MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); | 73 | MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); |
72 | 74 | ||
75 | static int modparam_fastchanswitch; | ||
76 | module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO); | ||
77 | MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios."); | ||
73 | 78 | ||
74 | /******************\ | ||
75 | * Internal defines * | ||
76 | \******************/ | ||
77 | 79 | ||
78 | /* Module info */ | 80 | /* Module info */ |
79 | MODULE_AUTHOR("Jiri Slaby"); | 81 | MODULE_AUTHOR("Jiri Slaby"); |
@@ -81,35 +83,24 @@ MODULE_AUTHOR("Nick Kossifidis"); | |||
81 | MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); | 83 | MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); |
82 | MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); | 84 | MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); |
83 | MODULE_LICENSE("Dual BSD/GPL"); | 85 | MODULE_LICENSE("Dual BSD/GPL"); |
84 | MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); | 86 | |
85 | 87 | static int ath5k_init(struct ieee80211_hw *hw); | |
86 | 88 | static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, | |
87 | /* Known PCI ids */ | 89 | bool skip_pcu); |
88 | static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { | 90 | int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif); |
89 | { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ | 91 | void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); |
90 | { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ | ||
91 | { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ | ||
92 | { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ | ||
93 | { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ | ||
94 | { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ | ||
95 | { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ | ||
96 | { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ | ||
97 | { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ | ||
98 | { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ | ||
99 | { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ | ||
100 | { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ | ||
101 | { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ | ||
102 | { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ | ||
103 | { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ | ||
104 | { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ | ||
105 | { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ | ||
106 | { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ | ||
107 | { 0 } | ||
108 | }; | ||
109 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); | ||
110 | 92 | ||
111 | /* Known SREVs */ | 93 | /* Known SREVs */ |
112 | static const struct ath5k_srev_name srev_names[] = { | 94 | static const struct ath5k_srev_name srev_names[] = { |
95 | #ifdef CONFIG_ATHEROS_AR231X | ||
96 | { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 }, | ||
97 | { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 }, | ||
98 | { "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 }, | ||
99 | { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R6 }, | ||
100 | { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R7 }, | ||
101 | { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R1 }, | ||
102 | { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R2 }, | ||
103 | #else | ||
113 | { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, | 104 | { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, |
114 | { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, | 105 | { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, |
115 | { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, | 106 | { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, |
@@ -128,6 +119,7 @@ static const struct ath5k_srev_name srev_names[] = { | |||
128 | { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, | 119 | { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, |
129 | { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, | 120 | { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, |
130 | { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, | 121 | { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, |
122 | #endif | ||
131 | { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, | 123 | { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, |
132 | { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, | 124 | { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, |
133 | { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, | 125 | { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, |
@@ -141,10 +133,12 @@ static const struct ath5k_srev_name srev_names[] = { | |||
141 | { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, | 133 | { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, |
142 | { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, | 134 | { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, |
143 | { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, | 135 | { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, |
144 | { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, | ||
145 | { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, | ||
146 | { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, | 136 | { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, |
147 | { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, | 137 | { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, |
138 | #ifdef CONFIG_ATHEROS_AR231X | ||
139 | { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, | ||
140 | { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, | ||
141 | #endif | ||
148 | { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, | 142 | { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, |
149 | }; | 143 | }; |
150 | 144 | ||
@@ -190,190 +184,6 @@ static const struct ieee80211_rate ath5k_rates[] = { | |||
190 | /* XR missing */ | 184 | /* XR missing */ |
191 | }; | 185 | }; |
192 | 186 | ||
193 | /* | ||
194 | * Prototypes - PCI stack related functions | ||
195 | */ | ||
196 | static int __devinit ath5k_pci_probe(struct pci_dev *pdev, | ||
197 | const struct pci_device_id *id); | ||
198 | static void __devexit ath5k_pci_remove(struct pci_dev *pdev); | ||
199 | #ifdef CONFIG_PM_SLEEP | ||
200 | static int ath5k_pci_suspend(struct device *dev); | ||
201 | static int ath5k_pci_resume(struct device *dev); | ||
202 | |||
203 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | ||
204 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | ||
205 | #else | ||
206 | #define ATH5K_PM_OPS NULL | ||
207 | #endif /* CONFIG_PM_SLEEP */ | ||
208 | |||
209 | static struct pci_driver ath5k_pci_driver = { | ||
210 | .name = KBUILD_MODNAME, | ||
211 | .id_table = ath5k_pci_id_table, | ||
212 | .probe = ath5k_pci_probe, | ||
213 | .remove = __devexit_p(ath5k_pci_remove), | ||
214 | .driver.pm = ATH5K_PM_OPS, | ||
215 | }; | ||
216 | |||
217 | |||
218 | |||
219 | /* | ||
220 | * Prototypes - MAC 802.11 stack related functions | ||
221 | */ | ||
222 | static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
223 | static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
224 | struct ath5k_txq *txq); | ||
225 | static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); | ||
226 | static int ath5k_start(struct ieee80211_hw *hw); | ||
227 | static void ath5k_stop(struct ieee80211_hw *hw); | ||
228 | static int ath5k_add_interface(struct ieee80211_hw *hw, | ||
229 | struct ieee80211_vif *vif); | ||
230 | static void ath5k_remove_interface(struct ieee80211_hw *hw, | ||
231 | struct ieee80211_vif *vif); | ||
232 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); | ||
233 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | ||
234 | struct netdev_hw_addr_list *mc_list); | ||
235 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | ||
236 | unsigned int changed_flags, | ||
237 | unsigned int *new_flags, | ||
238 | u64 multicast); | ||
239 | static int ath5k_set_key(struct ieee80211_hw *hw, | ||
240 | enum set_key_cmd cmd, | ||
241 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | ||
242 | struct ieee80211_key_conf *key); | ||
243 | static int ath5k_get_stats(struct ieee80211_hw *hw, | ||
244 | struct ieee80211_low_level_stats *stats); | ||
245 | static int ath5k_get_survey(struct ieee80211_hw *hw, | ||
246 | int idx, struct survey_info *survey); | ||
247 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | ||
248 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); | ||
249 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | ||
250 | static int ath5k_beacon_update(struct ieee80211_hw *hw, | ||
251 | struct ieee80211_vif *vif); | ||
252 | static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | ||
253 | struct ieee80211_vif *vif, | ||
254 | struct ieee80211_bss_conf *bss_conf, | ||
255 | u32 changes); | ||
256 | static void ath5k_sw_scan_start(struct ieee80211_hw *hw); | ||
257 | static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); | ||
258 | static void ath5k_set_coverage_class(struct ieee80211_hw *hw, | ||
259 | u8 coverage_class); | ||
260 | |||
261 | static const struct ieee80211_ops ath5k_hw_ops = { | ||
262 | .tx = ath5k_tx, | ||
263 | .start = ath5k_start, | ||
264 | .stop = ath5k_stop, | ||
265 | .add_interface = ath5k_add_interface, | ||
266 | .remove_interface = ath5k_remove_interface, | ||
267 | .config = ath5k_config, | ||
268 | .prepare_multicast = ath5k_prepare_multicast, | ||
269 | .configure_filter = ath5k_configure_filter, | ||
270 | .set_key = ath5k_set_key, | ||
271 | .get_stats = ath5k_get_stats, | ||
272 | .get_survey = ath5k_get_survey, | ||
273 | .conf_tx = NULL, | ||
274 | .get_tsf = ath5k_get_tsf, | ||
275 | .set_tsf = ath5k_set_tsf, | ||
276 | .reset_tsf = ath5k_reset_tsf, | ||
277 | .bss_info_changed = ath5k_bss_info_changed, | ||
278 | .sw_scan_start = ath5k_sw_scan_start, | ||
279 | .sw_scan_complete = ath5k_sw_scan_complete, | ||
280 | .set_coverage_class = ath5k_set_coverage_class, | ||
281 | }; | ||
282 | |||
283 | /* | ||
284 | * Prototypes - Internal functions | ||
285 | */ | ||
286 | /* Attach detach */ | ||
287 | static int ath5k_attach(struct pci_dev *pdev, | ||
288 | struct ieee80211_hw *hw); | ||
289 | static void ath5k_detach(struct pci_dev *pdev, | ||
290 | struct ieee80211_hw *hw); | ||
291 | /* Channel/mode setup */ | ||
292 | static inline short ath5k_ieee2mhz(short chan); | ||
293 | static unsigned int ath5k_copy_channels(struct ath5k_hw *ah, | ||
294 | struct ieee80211_channel *channels, | ||
295 | unsigned int mode, | ||
296 | unsigned int max); | ||
297 | static int ath5k_setup_bands(struct ieee80211_hw *hw); | ||
298 | static int ath5k_chan_set(struct ath5k_softc *sc, | ||
299 | struct ieee80211_channel *chan); | ||
300 | static void ath5k_setcurmode(struct ath5k_softc *sc, | ||
301 | unsigned int mode); | ||
302 | static void ath5k_mode_setup(struct ath5k_softc *sc); | ||
303 | |||
304 | /* Descriptor setup */ | ||
305 | static int ath5k_desc_alloc(struct ath5k_softc *sc, | ||
306 | struct pci_dev *pdev); | ||
307 | static void ath5k_desc_free(struct ath5k_softc *sc, | ||
308 | struct pci_dev *pdev); | ||
309 | /* Buffers setup */ | ||
310 | static int ath5k_rxbuf_setup(struct ath5k_softc *sc, | ||
311 | struct ath5k_buf *bf); | ||
312 | static int ath5k_txbuf_setup(struct ath5k_softc *sc, | ||
313 | struct ath5k_buf *bf, | ||
314 | struct ath5k_txq *txq, int padsize); | ||
315 | |||
316 | static inline void ath5k_txbuf_free_skb(struct ath5k_softc *sc, | ||
317 | struct ath5k_buf *bf) | ||
318 | { | ||
319 | BUG_ON(!bf); | ||
320 | if (!bf->skb) | ||
321 | return; | ||
322 | pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, | ||
323 | PCI_DMA_TODEVICE); | ||
324 | dev_kfree_skb_any(bf->skb); | ||
325 | bf->skb = NULL; | ||
326 | bf->skbaddr = 0; | ||
327 | bf->desc->ds_data = 0; | ||
328 | } | ||
329 | |||
330 | static inline void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, | ||
331 | struct ath5k_buf *bf) | ||
332 | { | ||
333 | struct ath5k_hw *ah = sc->ah; | ||
334 | struct ath_common *common = ath5k_hw_common(ah); | ||
335 | |||
336 | BUG_ON(!bf); | ||
337 | if (!bf->skb) | ||
338 | return; | ||
339 | pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize, | ||
340 | PCI_DMA_FROMDEVICE); | ||
341 | dev_kfree_skb_any(bf->skb); | ||
342 | bf->skb = NULL; | ||
343 | bf->skbaddr = 0; | ||
344 | bf->desc->ds_data = 0; | ||
345 | } | ||
346 | |||
347 | |||
348 | /* Queues setup */ | ||
349 | static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc, | ||
350 | int qtype, int subtype); | ||
351 | static int ath5k_beaconq_setup(struct ath5k_hw *ah); | ||
352 | static int ath5k_beaconq_config(struct ath5k_softc *sc); | ||
353 | static void ath5k_txq_drainq(struct ath5k_softc *sc, | ||
354 | struct ath5k_txq *txq); | ||
355 | static void ath5k_txq_cleanup(struct ath5k_softc *sc); | ||
356 | static void ath5k_txq_release(struct ath5k_softc *sc); | ||
357 | /* Rx handling */ | ||
358 | static int ath5k_rx_start(struct ath5k_softc *sc); | ||
359 | static void ath5k_rx_stop(struct ath5k_softc *sc); | ||
360 | static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, | ||
361 | struct sk_buff *skb, | ||
362 | struct ath5k_rx_status *rs); | ||
363 | static void ath5k_tasklet_rx(unsigned long data); | ||
364 | /* Tx handling */ | ||
365 | static void ath5k_tx_processq(struct ath5k_softc *sc, | ||
366 | struct ath5k_txq *txq); | ||
367 | static void ath5k_tasklet_tx(unsigned long data); | ||
368 | /* Beacon handling */ | ||
369 | static int ath5k_beacon_setup(struct ath5k_softc *sc, | ||
370 | struct ath5k_buf *bf); | ||
371 | static void ath5k_beacon_send(struct ath5k_softc *sc); | ||
372 | static void ath5k_beacon_config(struct ath5k_softc *sc); | ||
373 | static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); | ||
374 | static void ath5k_tasklet_beacon(unsigned long data); | ||
375 | static void ath5k_tasklet_ani(unsigned long data); | ||
376 | |||
377 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | 187 | static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) |
378 | { | 188 | { |
379 | u64 tsf = ath5k_hw_get_tsf64(ah); | 189 | u64 tsf = ath5k_hw_get_tsf64(ah); |
@@ -384,51 +194,7 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | |||
384 | return (tsf & ~0x7fff) | rstamp; | 194 | return (tsf & ~0x7fff) | rstamp; |
385 | } | 195 | } |
386 | 196 | ||
387 | /* Interrupt handling */ | 197 | const char * |
388 | static int ath5k_init(struct ath5k_softc *sc); | ||
389 | static int ath5k_stop_locked(struct ath5k_softc *sc); | ||
390 | static int ath5k_stop_hw(struct ath5k_softc *sc); | ||
391 | static irqreturn_t ath5k_intr(int irq, void *dev_id); | ||
392 | static void ath5k_reset_work(struct work_struct *work); | ||
393 | |||
394 | static void ath5k_tasklet_calibrate(unsigned long data); | ||
395 | |||
396 | /* | ||
397 | * Module init/exit functions | ||
398 | */ | ||
399 | static int __init | ||
400 | init_ath5k_pci(void) | ||
401 | { | ||
402 | int ret; | ||
403 | |||
404 | ath5k_debug_init(); | ||
405 | |||
406 | ret = pci_register_driver(&ath5k_pci_driver); | ||
407 | if (ret) { | ||
408 | printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); | ||
409 | return ret; | ||
410 | } | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static void __exit | ||
416 | exit_ath5k_pci(void) | ||
417 | { | ||
418 | pci_unregister_driver(&ath5k_pci_driver); | ||
419 | |||
420 | ath5k_debug_finish(); | ||
421 | } | ||
422 | |||
423 | module_init(init_ath5k_pci); | ||
424 | module_exit(exit_ath5k_pci); | ||
425 | |||
426 | |||
427 | /********************\ | ||
428 | * PCI Initialization * | ||
429 | \********************/ | ||
430 | |||
431 | static const char * | ||
432 | ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) | 198 | ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) |
433 | { | 199 | { |
434 | const char *name = "xxxxx"; | 200 | const char *name = "xxxxx"; |
@@ -466,299 +232,6 @@ static const struct ath_ops ath5k_common_ops = { | |||
466 | .write = ath5k_iowrite32, | 232 | .write = ath5k_iowrite32, |
467 | }; | 233 | }; |
468 | 234 | ||
469 | static int __devinit | ||
470 | ath5k_pci_probe(struct pci_dev *pdev, | ||
471 | const struct pci_device_id *id) | ||
472 | { | ||
473 | void __iomem *mem; | ||
474 | struct ath5k_softc *sc; | ||
475 | struct ath_common *common; | ||
476 | struct ieee80211_hw *hw; | ||
477 | int ret; | ||
478 | u8 csz; | ||
479 | |||
480 | /* | ||
481 | * L0s needs to be disabled on all ath5k cards. | ||
482 | * | ||
483 | * For distributions shipping with CONFIG_PCIEASPM (this will be enabled | ||
484 | * by default in the future in 2.6.36) this will also mean both L1 and | ||
485 | * L0s will be disabled when a pre 1.1 PCIe device is detected. We do | ||
486 | * know L1 works correctly even for all ath5k pre 1.1 PCIe devices | ||
487 | * though but cannot currently undue the effect of a blacklist, for | ||
488 | * details you can read pcie_aspm_sanity_check() and see how it adjusts | ||
489 | * the device link capability. | ||
490 | * | ||
491 | * It may be possible in the future to implement some PCI API to allow | ||
492 | * drivers to override blacklists for pre 1.1 PCIe but for now it is | ||
493 | * best to accept that both L0s and L1 will be disabled completely for | ||
494 | * distributions shipping with CONFIG_PCIEASPM rather than having this | ||
495 | * issue present. Motivation for adding this new API will be to help | ||
496 | * with power consumption for some of these devices. | ||
497 | */ | ||
498 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); | ||
499 | |||
500 | ret = pci_enable_device(pdev); | ||
501 | if (ret) { | ||
502 | dev_err(&pdev->dev, "can't enable device\n"); | ||
503 | goto err; | ||
504 | } | ||
505 | |||
506 | /* XXX 32-bit addressing only */ | ||
507 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
508 | if (ret) { | ||
509 | dev_err(&pdev->dev, "32-bit DMA not available\n"); | ||
510 | goto err_dis; | ||
511 | } | ||
512 | |||
513 | /* | ||
514 | * Cache line size is used to size and align various | ||
515 | * structures used to communicate with the hardware. | ||
516 | */ | ||
517 | pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); | ||
518 | if (csz == 0) { | ||
519 | /* | ||
520 | * Linux 2.4.18 (at least) writes the cache line size | ||
521 | * register as a 16-bit wide register which is wrong. | ||
522 | * We must have this setup properly for rx buffer | ||
523 | * DMA to work so force a reasonable value here if it | ||
524 | * comes up zero. | ||
525 | */ | ||
526 | csz = L1_CACHE_BYTES >> 2; | ||
527 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | ||
528 | } | ||
529 | /* | ||
530 | * The default setting of latency timer yields poor results, | ||
531 | * set it to the value used by other systems. It may be worth | ||
532 | * tweaking this setting more. | ||
533 | */ | ||
534 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); | ||
535 | |||
536 | /* Enable bus mastering */ | ||
537 | pci_set_master(pdev); | ||
538 | |||
539 | /* | ||
540 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
541 | * PCI Tx retries from interfering with C3 CPU state. | ||
542 | */ | ||
543 | pci_write_config_byte(pdev, 0x41, 0); | ||
544 | |||
545 | ret = pci_request_region(pdev, 0, "ath5k"); | ||
546 | if (ret) { | ||
547 | dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); | ||
548 | goto err_dis; | ||
549 | } | ||
550 | |||
551 | mem = pci_iomap(pdev, 0, 0); | ||
552 | if (!mem) { | ||
553 | dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; | ||
554 | ret = -EIO; | ||
555 | goto err_reg; | ||
556 | } | ||
557 | |||
558 | /* | ||
559 | * Allocate hw (mac80211 main struct) | ||
560 | * and hw->priv (driver private data) | ||
561 | */ | ||
562 | hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); | ||
563 | if (hw == NULL) { | ||
564 | dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); | ||
565 | ret = -ENOMEM; | ||
566 | goto err_map; | ||
567 | } | ||
568 | |||
569 | dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); | ||
570 | |||
571 | /* Initialize driver private data */ | ||
572 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
573 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | ||
574 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
575 | IEEE80211_HW_SIGNAL_DBM; | ||
576 | |||
577 | hw->wiphy->interface_modes = | ||
578 | BIT(NL80211_IFTYPE_AP) | | ||
579 | BIT(NL80211_IFTYPE_STATION) | | ||
580 | BIT(NL80211_IFTYPE_ADHOC) | | ||
581 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
582 | |||
583 | hw->extra_tx_headroom = 2; | ||
584 | hw->channel_change_time = 5000; | ||
585 | sc = hw->priv; | ||
586 | sc->hw = hw; | ||
587 | sc->pdev = pdev; | ||
588 | |||
589 | ath5k_debug_init_device(sc); | ||
590 | |||
591 | /* | ||
592 | * Mark the device as detached to avoid processing | ||
593 | * interrupts until setup is complete. | ||
594 | */ | ||
595 | __set_bit(ATH_STAT_INVALID, sc->status); | ||
596 | |||
597 | sc->iobase = mem; /* So we can unmap it on detach */ | ||
598 | sc->opmode = NL80211_IFTYPE_STATION; | ||
599 | sc->bintval = 1000; | ||
600 | mutex_init(&sc->lock); | ||
601 | spin_lock_init(&sc->rxbuflock); | ||
602 | spin_lock_init(&sc->txbuflock); | ||
603 | spin_lock_init(&sc->block); | ||
604 | |||
605 | /* Set private data */ | ||
606 | pci_set_drvdata(pdev, sc); | ||
607 | |||
608 | /* Setup interrupt handler */ | ||
609 | ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); | ||
610 | if (ret) { | ||
611 | ATH5K_ERR(sc, "request_irq failed\n"); | ||
612 | goto err_free; | ||
613 | } | ||
614 | |||
615 | /*If we passed the test malloc a ath5k_hw struct*/ | ||
616 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | ||
617 | if (!sc->ah) { | ||
618 | ret = -ENOMEM; | ||
619 | ATH5K_ERR(sc, "out of memory\n"); | ||
620 | goto err_irq; | ||
621 | } | ||
622 | |||
623 | sc->ah->ah_sc = sc; | ||
624 | sc->ah->ah_iobase = sc->iobase; | ||
625 | common = ath5k_hw_common(sc->ah); | ||
626 | common->ops = &ath5k_common_ops; | ||
627 | common->ah = sc->ah; | ||
628 | common->hw = hw; | ||
629 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
630 | |||
631 | /* Initialize device */ | ||
632 | ret = ath5k_hw_attach(sc); | ||
633 | if (ret) { | ||
634 | goto err_free_ah; | ||
635 | } | ||
636 | |||
637 | /* set up multi-rate retry capabilities */ | ||
638 | if (sc->ah->ah_version == AR5K_AR5212) { | ||
639 | hw->max_rates = 4; | ||
640 | hw->max_rate_tries = 11; | ||
641 | } | ||
642 | |||
643 | /* Finish private driver data initialization */ | ||
644 | ret = ath5k_attach(pdev, hw); | ||
645 | if (ret) | ||
646 | goto err_ah; | ||
647 | |||
648 | ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", | ||
649 | ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), | ||
650 | sc->ah->ah_mac_srev, | ||
651 | sc->ah->ah_phy_revision); | ||
652 | |||
653 | if (!sc->ah->ah_single_chip) { | ||
654 | /* Single chip radio (!RF5111) */ | ||
655 | if (sc->ah->ah_radio_5ghz_revision && | ||
656 | !sc->ah->ah_radio_2ghz_revision) { | ||
657 | /* No 5GHz support -> report 2GHz radio */ | ||
658 | if (!test_bit(AR5K_MODE_11A, | ||
659 | sc->ah->ah_capabilities.cap_mode)) { | ||
660 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
661 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
662 | sc->ah->ah_radio_5ghz_revision), | ||
663 | sc->ah->ah_radio_5ghz_revision); | ||
664 | /* No 2GHz support (5110 and some | ||
665 | * 5Ghz only cards) -> report 5Ghz radio */ | ||
666 | } else if (!test_bit(AR5K_MODE_11B, | ||
667 | sc->ah->ah_capabilities.cap_mode)) { | ||
668 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
669 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
670 | sc->ah->ah_radio_5ghz_revision), | ||
671 | sc->ah->ah_radio_5ghz_revision); | ||
672 | /* Multiband radio */ | ||
673 | } else { | ||
674 | ATH5K_INFO(sc, "RF%s multiband radio found" | ||
675 | " (0x%x)\n", | ||
676 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
677 | sc->ah->ah_radio_5ghz_revision), | ||
678 | sc->ah->ah_radio_5ghz_revision); | ||
679 | } | ||
680 | } | ||
681 | /* Multi chip radio (RF5111 - RF2111) -> | ||
682 | * report both 2GHz/5GHz radios */ | ||
683 | else if (sc->ah->ah_radio_5ghz_revision && | ||
684 | sc->ah->ah_radio_2ghz_revision){ | ||
685 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
686 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
687 | sc->ah->ah_radio_5ghz_revision), | ||
688 | sc->ah->ah_radio_5ghz_revision); | ||
689 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
690 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
691 | sc->ah->ah_radio_2ghz_revision), | ||
692 | sc->ah->ah_radio_2ghz_revision); | ||
693 | } | ||
694 | } | ||
695 | |||
696 | |||
697 | /* ready to process interrupts */ | ||
698 | __clear_bit(ATH_STAT_INVALID, sc->status); | ||
699 | |||
700 | return 0; | ||
701 | err_ah: | ||
702 | ath5k_hw_detach(sc->ah); | ||
703 | err_irq: | ||
704 | free_irq(pdev->irq, sc); | ||
705 | err_free_ah: | ||
706 | kfree(sc->ah); | ||
707 | err_free: | ||
708 | ieee80211_free_hw(hw); | ||
709 | err_map: | ||
710 | pci_iounmap(pdev, mem); | ||
711 | err_reg: | ||
712 | pci_release_region(pdev, 0); | ||
713 | err_dis: | ||
714 | pci_disable_device(pdev); | ||
715 | err: | ||
716 | return ret; | ||
717 | } | ||
718 | |||
719 | static void __devexit | ||
720 | ath5k_pci_remove(struct pci_dev *pdev) | ||
721 | { | ||
722 | struct ath5k_softc *sc = pci_get_drvdata(pdev); | ||
723 | |||
724 | ath5k_debug_finish_device(sc); | ||
725 | ath5k_detach(pdev, sc->hw); | ||
726 | ath5k_hw_detach(sc->ah); | ||
727 | kfree(sc->ah); | ||
728 | free_irq(pdev->irq, sc); | ||
729 | pci_iounmap(pdev, sc->iobase); | ||
730 | pci_release_region(pdev, 0); | ||
731 | pci_disable_device(pdev); | ||
732 | ieee80211_free_hw(sc->hw); | ||
733 | } | ||
734 | |||
735 | #ifdef CONFIG_PM_SLEEP | ||
736 | static int ath5k_pci_suspend(struct device *dev) | ||
737 | { | ||
738 | struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev)); | ||
739 | |||
740 | ath5k_led_off(sc); | ||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | static int ath5k_pci_resume(struct device *dev) | ||
745 | { | ||
746 | struct pci_dev *pdev = to_pci_dev(dev); | ||
747 | struct ath5k_softc *sc = pci_get_drvdata(pdev); | ||
748 | |||
749 | /* | ||
750 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
751 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
752 | * PCI Tx retries from interfering with C3 CPU state | ||
753 | */ | ||
754 | pci_write_config_byte(pdev, 0x41, 0); | ||
755 | |||
756 | ath5k_led_enable(sc); | ||
757 | return 0; | ||
758 | } | ||
759 | #endif /* CONFIG_PM_SLEEP */ | ||
760 | |||
761 | |||
762 | /***********************\ | 235 | /***********************\ |
763 | * Driver Initialization * | 236 | * Driver Initialization * |
764 | \***********************/ | 237 | \***********************/ |
@@ -772,260 +245,83 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re | |||
772 | return ath_reg_notifier_apply(wiphy, request, regulatory); | 245 | return ath_reg_notifier_apply(wiphy, request, regulatory); |
773 | } | 246 | } |
774 | 247 | ||
775 | static int | ||
776 | ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | ||
777 | { | ||
778 | struct ath5k_softc *sc = hw->priv; | ||
779 | struct ath5k_hw *ah = sc->ah; | ||
780 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); | ||
781 | u8 mac[ETH_ALEN] = {}; | ||
782 | int ret; | ||
783 | |||
784 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); | ||
785 | |||
786 | /* | ||
787 | * Check if the MAC has multi-rate retry support. | ||
788 | * We do this by trying to setup a fake extended | ||
789 | * descriptor. MAC's that don't have support will | ||
790 | * return false w/o doing anything. MAC's that do | ||
791 | * support it will return true w/o doing anything. | ||
792 | */ | ||
793 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | ||
794 | |||
795 | if (ret < 0) | ||
796 | goto err; | ||
797 | if (ret > 0) | ||
798 | __set_bit(ATH_STAT_MRRETRY, sc->status); | ||
799 | |||
800 | /* | ||
801 | * Collect the channel list. The 802.11 layer | ||
802 | * is resposible for filtering this list based | ||
803 | * on settings like the phy mode and regulatory | ||
804 | * domain restrictions. | ||
805 | */ | ||
806 | ret = ath5k_setup_bands(hw); | ||
807 | if (ret) { | ||
808 | ATH5K_ERR(sc, "can't get channels\n"); | ||
809 | goto err; | ||
810 | } | ||
811 | |||
812 | /* NB: setup here so ath5k_rate_update is happy */ | ||
813 | if (test_bit(AR5K_MODE_11A, ah->ah_modes)) | ||
814 | ath5k_setcurmode(sc, AR5K_MODE_11A); | ||
815 | else | ||
816 | ath5k_setcurmode(sc, AR5K_MODE_11B); | ||
817 | |||
818 | /* | ||
819 | * Allocate tx+rx descriptors and populate the lists. | ||
820 | */ | ||
821 | ret = ath5k_desc_alloc(sc, pdev); | ||
822 | if (ret) { | ||
823 | ATH5K_ERR(sc, "can't allocate descriptors\n"); | ||
824 | goto err; | ||
825 | } | ||
826 | |||
827 | /* | ||
828 | * Allocate hardware transmit queues: one queue for | ||
829 | * beacon frames and one data queue for each QoS | ||
830 | * priority. Note that hw functions handle reseting | ||
831 | * these queues at the needed time. | ||
832 | */ | ||
833 | ret = ath5k_beaconq_setup(ah); | ||
834 | if (ret < 0) { | ||
835 | ATH5K_ERR(sc, "can't setup a beacon xmit queue\n"); | ||
836 | goto err_desc; | ||
837 | } | ||
838 | sc->bhalq = ret; | ||
839 | sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0); | ||
840 | if (IS_ERR(sc->cabq)) { | ||
841 | ATH5K_ERR(sc, "can't setup cab queue\n"); | ||
842 | ret = PTR_ERR(sc->cabq); | ||
843 | goto err_bhal; | ||
844 | } | ||
845 | |||
846 | sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); | ||
847 | if (IS_ERR(sc->txq)) { | ||
848 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
849 | ret = PTR_ERR(sc->txq); | ||
850 | goto err_queues; | ||
851 | } | ||
852 | |||
853 | tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); | ||
854 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); | ||
855 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); | ||
856 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); | ||
857 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); | ||
858 | |||
859 | INIT_WORK(&sc->reset_work, ath5k_reset_work); | ||
860 | |||
861 | ret = ath5k_eeprom_read_mac(ah, mac); | ||
862 | if (ret) { | ||
863 | ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", | ||
864 | sc->pdev->device); | ||
865 | goto err_queues; | ||
866 | } | ||
867 | |||
868 | SET_IEEE80211_PERM_ADDR(hw, mac); | ||
869 | /* All MAC address bits matter for ACKs */ | ||
870 | memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
871 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | ||
872 | |||
873 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; | ||
874 | ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); | ||
875 | if (ret) { | ||
876 | ATH5K_ERR(sc, "can't initialize regulatory system\n"); | ||
877 | goto err_queues; | ||
878 | } | ||
879 | |||
880 | ret = ieee80211_register_hw(hw); | ||
881 | if (ret) { | ||
882 | ATH5K_ERR(sc, "can't register ieee80211 hw\n"); | ||
883 | goto err_queues; | ||
884 | } | ||
885 | |||
886 | if (!ath_is_world_regd(regulatory)) | ||
887 | regulatory_hint(hw->wiphy, regulatory->alpha2); | ||
888 | |||
889 | ath5k_init_leds(sc); | ||
890 | |||
891 | ath5k_sysfs_register(sc); | ||
892 | |||
893 | return 0; | ||
894 | err_queues: | ||
895 | ath5k_txq_release(sc); | ||
896 | err_bhal: | ||
897 | ath5k_hw_release_tx_queue(ah, sc->bhalq); | ||
898 | err_desc: | ||
899 | ath5k_desc_free(sc, pdev); | ||
900 | err: | ||
901 | return ret; | ||
902 | } | ||
903 | |||
904 | static void | ||
905 | ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) | ||
906 | { | ||
907 | struct ath5k_softc *sc = hw->priv; | ||
908 | |||
909 | /* | ||
910 | * NB: the order of these is important: | ||
911 | * o call the 802.11 layer before detaching ath5k_hw to | ||
912 | * insure callbacks into the driver to delete global | ||
913 | * key cache entries can be handled | ||
914 | * o reclaim the tx queue data structures after calling | ||
915 | * the 802.11 layer as we'll get called back to reclaim | ||
916 | * node state and potentially want to use them | ||
917 | * o to cleanup the tx queues the hal is called, so detach | ||
918 | * it last | ||
919 | * XXX: ??? detach ath5k_hw ??? | ||
920 | * Other than that, it's straightforward... | ||
921 | */ | ||
922 | ieee80211_unregister_hw(hw); | ||
923 | ath5k_desc_free(sc, pdev); | ||
924 | ath5k_txq_release(sc); | ||
925 | ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); | ||
926 | ath5k_unregister_leds(sc); | ||
927 | |||
928 | ath5k_sysfs_unregister(sc); | ||
929 | /* | ||
930 | * NB: can't reclaim these until after ieee80211_ifdetach | ||
931 | * returns because we'll get called back to reclaim node | ||
932 | * state and potentially want to use them. | ||
933 | */ | ||
934 | } | ||
935 | |||
936 | |||
937 | |||
938 | |||
939 | /********************\ | 248 | /********************\ |
940 | * Channel/mode setup * | 249 | * Channel/mode setup * |
941 | \********************/ | 250 | \********************/ |
942 | 251 | ||
943 | /* | 252 | /* |
944 | * Convert IEEE channel number to MHz frequency. | ||
945 | */ | ||
946 | static inline short | ||
947 | ath5k_ieee2mhz(short chan) | ||
948 | { | ||
949 | if (chan <= 14 || chan >= 27) | ||
950 | return ieee80211chan2mhz(chan); | ||
951 | else | ||
952 | return 2212 + chan * 20; | ||
953 | } | ||
954 | |||
955 | /* | ||
956 | * Returns true for the channel numbers used without all_channels modparam. | 253 | * Returns true for the channel numbers used without all_channels modparam. |
957 | */ | 254 | */ |
958 | static bool ath5k_is_standard_channel(short chan) | 255 | static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band) |
959 | { | 256 | { |
960 | return ((chan <= 14) || | 257 | if (band == IEEE80211_BAND_2GHZ && chan <= 14) |
961 | /* UNII 1,2 */ | 258 | return true; |
962 | ((chan & 3) == 0 && chan >= 36 && chan <= 64) || | 259 | |
260 | return /* UNII 1,2 */ | ||
261 | (((chan & 3) == 0 && chan >= 36 && chan <= 64) || | ||
963 | /* midband */ | 262 | /* midband */ |
964 | ((chan & 3) == 0 && chan >= 100 && chan <= 140) || | 263 | ((chan & 3) == 0 && chan >= 100 && chan <= 140) || |
965 | /* UNII-3 */ | 264 | /* UNII-3 */ |
966 | ((chan & 3) == 1 && chan >= 149 && chan <= 165)); | 265 | ((chan & 3) == 1 && chan >= 149 && chan <= 165) || |
266 | /* 802.11j 5.030-5.080 GHz (20MHz) */ | ||
267 | (chan == 8 || chan == 12 || chan == 16) || | ||
268 | /* 802.11j 4.9GHz (20MHz) */ | ||
269 | (chan == 184 || chan == 188 || chan == 192 || chan == 196)); | ||
967 | } | 270 | } |
968 | 271 | ||
969 | static unsigned int | 272 | static unsigned int |
970 | ath5k_copy_channels(struct ath5k_hw *ah, | 273 | ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, |
971 | struct ieee80211_channel *channels, | 274 | unsigned int mode, unsigned int max) |
972 | unsigned int mode, | ||
973 | unsigned int max) | ||
974 | { | 275 | { |
975 | unsigned int i, count, size, chfreq, freq, ch; | 276 | unsigned int count, size, chfreq, freq, ch; |
976 | 277 | enum ieee80211_band band; | |
977 | if (!test_bit(mode, ah->ah_modes)) | ||
978 | return 0; | ||
979 | 278 | ||
980 | switch (mode) { | 279 | switch (mode) { |
981 | case AR5K_MODE_11A: | 280 | case AR5K_MODE_11A: |
982 | case AR5K_MODE_11A_TURBO: | ||
983 | /* 1..220, but 2GHz frequencies are filtered by check_channel */ | 281 | /* 1..220, but 2GHz frequencies are filtered by check_channel */ |
984 | size = 220 ; | 282 | size = 220; |
985 | chfreq = CHANNEL_5GHZ; | 283 | chfreq = CHANNEL_5GHZ; |
284 | band = IEEE80211_BAND_5GHZ; | ||
986 | break; | 285 | break; |
987 | case AR5K_MODE_11B: | 286 | case AR5K_MODE_11B: |
988 | case AR5K_MODE_11G: | 287 | case AR5K_MODE_11G: |
989 | case AR5K_MODE_11G_TURBO: | ||
990 | size = 26; | 288 | size = 26; |
991 | chfreq = CHANNEL_2GHZ; | 289 | chfreq = CHANNEL_2GHZ; |
290 | band = IEEE80211_BAND_2GHZ; | ||
992 | break; | 291 | break; |
993 | default: | 292 | default: |
994 | ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n"); | 293 | ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n"); |
995 | return 0; | 294 | return 0; |
996 | } | 295 | } |
997 | 296 | ||
998 | for (i = 0, count = 0; i < size && max > 0; i++) { | 297 | count = 0; |
999 | ch = i + 1 ; | 298 | for (ch = 1; ch <= size && count < max; ch++) { |
1000 | freq = ath5k_ieee2mhz(ch); | 299 | freq = ieee80211_channel_to_frequency(ch, band); |
300 | |||
301 | if (freq == 0) /* mapping failed - not a standard channel */ | ||
302 | continue; | ||
1001 | 303 | ||
1002 | /* Check if channel is supported by the chipset */ | 304 | /* Check if channel is supported by the chipset */ |
1003 | if (!ath5k_channel_ok(ah, freq, chfreq)) | 305 | if (!ath5k_channel_ok(ah, freq, chfreq)) |
1004 | continue; | 306 | continue; |
1005 | 307 | ||
1006 | if (!modparam_all_channels && !ath5k_is_standard_channel(ch)) | 308 | if (!modparam_all_channels && |
309 | !ath5k_is_standard_channel(ch, band)) | ||
1007 | continue; | 310 | continue; |
1008 | 311 | ||
1009 | /* Write channel info and increment counter */ | 312 | /* Write channel info and increment counter */ |
1010 | channels[count].center_freq = freq; | 313 | channels[count].center_freq = freq; |
1011 | channels[count].band = (chfreq == CHANNEL_2GHZ) ? | 314 | channels[count].band = band; |
1012 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | ||
1013 | switch (mode) { | 315 | switch (mode) { |
1014 | case AR5K_MODE_11A: | 316 | case AR5K_MODE_11A: |
1015 | case AR5K_MODE_11G: | 317 | case AR5K_MODE_11G: |
1016 | channels[count].hw_value = chfreq | CHANNEL_OFDM; | 318 | channels[count].hw_value = chfreq | CHANNEL_OFDM; |
1017 | break; | 319 | break; |
1018 | case AR5K_MODE_11A_TURBO: | ||
1019 | case AR5K_MODE_11G_TURBO: | ||
1020 | channels[count].hw_value = chfreq | | ||
1021 | CHANNEL_OFDM | CHANNEL_TURBO; | ||
1022 | break; | ||
1023 | case AR5K_MODE_11B: | 320 | case AR5K_MODE_11B: |
1024 | channels[count].hw_value = CHANNEL_B; | 321 | channels[count].hw_value = CHANNEL_B; |
1025 | } | 322 | } |
1026 | 323 | ||
1027 | count++; | 324 | count++; |
1028 | max--; | ||
1029 | } | 325 | } |
1030 | 326 | ||
1031 | return count; | 327 | return count; |
@@ -1070,7 +366,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
1070 | sband->n_bitrates = 12; | 366 | sband->n_bitrates = 12; |
1071 | 367 | ||
1072 | sband->channels = sc->channels; | 368 | sband->channels = sc->channels; |
1073 | sband->n_channels = ath5k_copy_channels(ah, sband->channels, | 369 | sband->n_channels = ath5k_setup_channels(ah, sband->channels, |
1074 | AR5K_MODE_11G, max_c); | 370 | AR5K_MODE_11G, max_c); |
1075 | 371 | ||
1076 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; | 372 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; |
@@ -1096,7 +392,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
1096 | } | 392 | } |
1097 | 393 | ||
1098 | sband->channels = sc->channels; | 394 | sband->channels = sc->channels; |
1099 | sband->n_channels = ath5k_copy_channels(ah, sband->channels, | 395 | sband->n_channels = ath5k_setup_channels(ah, sband->channels, |
1100 | AR5K_MODE_11B, max_c); | 396 | AR5K_MODE_11B, max_c); |
1101 | 397 | ||
1102 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; | 398 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; |
@@ -1116,7 +412,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
1116 | sband->n_bitrates = 8; | 412 | sband->n_bitrates = 8; |
1117 | 413 | ||
1118 | sband->channels = &sc->channels[count_c]; | 414 | sband->channels = &sc->channels[count_c]; |
1119 | sband->n_channels = ath5k_copy_channels(ah, sband->channels, | 415 | sband->n_channels = ath5k_setup_channels(ah, sband->channels, |
1120 | AR5K_MODE_11A, max_c); | 416 | AR5K_MODE_11A, max_c); |
1121 | 417 | ||
1122 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; | 418 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; |
@@ -1135,7 +431,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw) | |||
1135 | * | 431 | * |
1136 | * Called with sc->lock. | 432 | * Called with sc->lock. |
1137 | */ | 433 | */ |
1138 | static int | 434 | int |
1139 | ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | 435 | ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) |
1140 | { | 436 | { |
1141 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | 437 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
@@ -1148,38 +444,102 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) | |||
1148 | * hardware at the new frequency, and then re-enable | 444 | * hardware at the new frequency, and then re-enable |
1149 | * the relevant bits of the h/w. | 445 | * the relevant bits of the h/w. |
1150 | */ | 446 | */ |
1151 | return ath5k_reset(sc, chan); | 447 | return ath5k_reset(sc, chan, true); |
1152 | } | 448 | } |
1153 | 449 | ||
1154 | static void | 450 | void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
1155 | ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) | ||
1156 | { | 451 | { |
1157 | sc->curmode = mode; | 452 | struct ath5k_vif_iter_data *iter_data = data; |
453 | int i; | ||
454 | struct ath5k_vif *avf = (void *)vif->drv_priv; | ||
1158 | 455 | ||
1159 | if (mode == AR5K_MODE_11A) { | 456 | if (iter_data->hw_macaddr) |
1160 | sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ]; | 457 | for (i = 0; i < ETH_ALEN; i++) |
1161 | } else { | 458 | iter_data->mask[i] &= |
1162 | sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ]; | 459 | ~(iter_data->hw_macaddr[i] ^ mac[i]); |
460 | |||
461 | if (!iter_data->found_active) { | ||
462 | iter_data->found_active = true; | ||
463 | memcpy(iter_data->active_mac, mac, ETH_ALEN); | ||
464 | } | ||
465 | |||
466 | if (iter_data->need_set_hw_addr && iter_data->hw_macaddr) | ||
467 | if (compare_ether_addr(iter_data->hw_macaddr, mac) == 0) | ||
468 | iter_data->need_set_hw_addr = false; | ||
469 | |||
470 | if (!iter_data->any_assoc) { | ||
471 | if (avf->assoc) | ||
472 | iter_data->any_assoc = true; | ||
473 | } | ||
474 | |||
475 | /* Calculate combined mode - when APs are active, operate in AP mode. | ||
476 | * Otherwise use the mode of the new interface. This can currently | ||
477 | * only deal with combinations of APs and STAs. Only one ad-hoc | ||
478 | * interfaces is allowed. | ||
479 | */ | ||
480 | if (avf->opmode == NL80211_IFTYPE_AP) | ||
481 | iter_data->opmode = NL80211_IFTYPE_AP; | ||
482 | else { | ||
483 | if (avf->opmode == NL80211_IFTYPE_STATION) | ||
484 | iter_data->n_stas++; | ||
485 | if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED) | ||
486 | iter_data->opmode = avf->opmode; | ||
1163 | } | 487 | } |
1164 | } | 488 | } |
1165 | 489 | ||
1166 | static void | 490 | void |
1167 | ath5k_mode_setup(struct ath5k_softc *sc) | 491 | ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, |
492 | struct ieee80211_vif *vif) | ||
1168 | { | 493 | { |
1169 | struct ath5k_hw *ah = sc->ah; | 494 | struct ath_common *common = ath5k_hw_common(sc->ah); |
495 | struct ath5k_vif_iter_data iter_data; | ||
1170 | u32 rfilt; | 496 | u32 rfilt; |
1171 | 497 | ||
1172 | /* configure rx filter */ | 498 | /* |
1173 | rfilt = sc->filter_flags; | 499 | * Use the hardware MAC address as reference, the hardware uses it |
1174 | ath5k_hw_set_rx_filter(ah, rfilt); | 500 | * together with the BSSID mask when matching addresses. |
1175 | 501 | */ | |
1176 | if (ath5k_hw_hasbssidmask(ah)) | 502 | iter_data.hw_macaddr = common->macaddr; |
1177 | ath5k_hw_set_bssid_mask(ah, sc->bssidmask); | 503 | memset(&iter_data.mask, 0xff, ETH_ALEN); |
1178 | 504 | iter_data.found_active = false; | |
1179 | /* configure operational mode */ | 505 | iter_data.need_set_hw_addr = true; |
1180 | ath5k_hw_set_opmode(ah, sc->opmode); | 506 | iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED; |
507 | iter_data.n_stas = 0; | ||
508 | |||
509 | if (vif) | ||
510 | ath5k_vif_iter(&iter_data, vif->addr, vif); | ||
511 | |||
512 | /* Get list of all active MAC addresses */ | ||
513 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter, | ||
514 | &iter_data); | ||
515 | memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN); | ||
516 | |||
517 | sc->opmode = iter_data.opmode; | ||
518 | if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED) | ||
519 | /* Nothing active, default to station mode */ | ||
520 | sc->opmode = NL80211_IFTYPE_STATION; | ||
521 | |||
522 | ath5k_hw_set_opmode(sc->ah, sc->opmode); | ||
523 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", | ||
524 | sc->opmode, ath_opmode_to_string(sc->opmode)); | ||
525 | |||
526 | if (iter_data.need_set_hw_addr && iter_data.found_active) | ||
527 | ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac); | ||
528 | |||
529 | if (ath5k_hw_hasbssidmask(sc->ah)) | ||
530 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | ||
531 | |||
532 | /* Set up RX Filter */ | ||
533 | if (iter_data.n_stas > 1) { | ||
534 | /* If you have multiple STA interfaces connected to | ||
535 | * different APs, ARPs are not received (most of the time?) | ||
536 | * Enabling PROMISC appears to fix that probem. | ||
537 | */ | ||
538 | sc->filter_flags |= AR5K_RX_FILTER_PROM; | ||
539 | } | ||
1181 | 540 | ||
1182 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode); | 541 | rfilt = sc->filter_flags; |
542 | ath5k_hw_set_rx_filter(sc->ah, rfilt); | ||
1183 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); | 543 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); |
1184 | } | 544 | } |
1185 | 545 | ||
@@ -1193,7 +553,7 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) | |||
1193 | "hw_rix out of bounds: %x\n", hw_rix)) | 553 | "hw_rix out of bounds: %x\n", hw_rix)) |
1194 | return 0; | 554 | return 0; |
1195 | 555 | ||
1196 | rix = sc->rate_idx[sc->curband->band][hw_rix]; | 556 | rix = sc->rate_idx[sc->curchan->band][hw_rix]; |
1197 | if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix)) | 557 | if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix)) |
1198 | rix = 0; | 558 | rix = 0; |
1199 | 559 | ||
@@ -1224,10 +584,11 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) | |||
1224 | return NULL; | 584 | return NULL; |
1225 | } | 585 | } |
1226 | 586 | ||
1227 | *skb_addr = pci_map_single(sc->pdev, | 587 | *skb_addr = dma_map_single(sc->dev, |
1228 | skb->data, common->rx_bufsize, | 588 | skb->data, common->rx_bufsize, |
1229 | PCI_DMA_FROMDEVICE); | 589 | DMA_FROM_DEVICE); |
1230 | if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { | 590 | |
591 | if (unlikely(dma_mapping_error(sc->dev, *skb_addr))) { | ||
1231 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); | 592 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); |
1232 | dev_kfree_skb(skb); | 593 | dev_kfree_skb(skb); |
1233 | return NULL; | 594 | return NULL; |
@@ -1323,8 +684,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1323 | flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; | 684 | flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; |
1324 | 685 | ||
1325 | /* XXX endianness */ | 686 | /* XXX endianness */ |
1326 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | 687 | bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, |
1327 | PCI_DMA_TODEVICE); | 688 | DMA_TO_DEVICE); |
1328 | 689 | ||
1329 | rate = ieee80211_get_tx_rate(sc->hw, info); | 690 | rate = ieee80211_get_tx_rate(sc->hw, info); |
1330 | if (!rate) { | 691 | if (!rate) { |
@@ -1352,13 +713,13 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1352 | flags |= AR5K_TXDESC_RTSENA; | 713 | flags |= AR5K_TXDESC_RTSENA; |
1353 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; | 714 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; |
1354 | duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, | 715 | duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, |
1355 | sc->vif, pktlen, info)); | 716 | info->control.vif, pktlen, info)); |
1356 | } | 717 | } |
1357 | if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 718 | if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
1358 | flags |= AR5K_TXDESC_CTSENA; | 719 | flags |= AR5K_TXDESC_CTSENA; |
1359 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; | 720 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; |
1360 | duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, | 721 | duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, |
1361 | sc->vif, pktlen, info)); | 722 | info->control.vif, pktlen, info)); |
1362 | } | 723 | } |
1363 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 724 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1364 | ieee80211_get_hdrlen_from_skb(skb), padsize, | 725 | ieee80211_get_hdrlen_from_skb(skb), padsize, |
@@ -1391,6 +752,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1391 | 752 | ||
1392 | spin_lock_bh(&txq->lock); | 753 | spin_lock_bh(&txq->lock); |
1393 | list_add_tail(&bf->list, &txq->q); | 754 | list_add_tail(&bf->list, &txq->q); |
755 | txq->txq_len++; | ||
1394 | if (txq->link == NULL) /* is this first packet? */ | 756 | if (txq->link == NULL) /* is this first packet? */ |
1395 | ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); | 757 | ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); |
1396 | else /* no, so only link it */ | 758 | else /* no, so only link it */ |
@@ -1403,7 +765,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, | |||
1403 | 765 | ||
1404 | return 0; | 766 | return 0; |
1405 | err_unmap: | 767 | err_unmap: |
1406 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); | 768 | dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); |
1407 | return ret; | 769 | return ret; |
1408 | } | 770 | } |
1409 | 771 | ||
@@ -1412,7 +774,7 @@ err_unmap: | |||
1412 | \*******************/ | 774 | \*******************/ |
1413 | 775 | ||
1414 | static int | 776 | static int |
1415 | ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) | 777 | ath5k_desc_alloc(struct ath5k_softc *sc) |
1416 | { | 778 | { |
1417 | struct ath5k_desc *ds; | 779 | struct ath5k_desc *ds; |
1418 | struct ath5k_buf *bf; | 780 | struct ath5k_buf *bf; |
@@ -1423,7 +785,9 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) | |||
1423 | /* allocate descriptors */ | 785 | /* allocate descriptors */ |
1424 | sc->desc_len = sizeof(struct ath5k_desc) * | 786 | sc->desc_len = sizeof(struct ath5k_desc) * |
1425 | (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); | 787 | (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); |
1426 | sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr); | 788 | |
789 | sc->desc = dma_alloc_coherent(sc->dev, sc->desc_len, | ||
790 | &sc->desc_daddr, GFP_KERNEL); | ||
1427 | if (sc->desc == NULL) { | 791 | if (sc->desc == NULL) { |
1428 | ATH5K_ERR(sc, "can't allocate descriptors\n"); | 792 | ATH5K_ERR(sc, "can't allocate descriptors\n"); |
1429 | ret = -ENOMEM; | 793 | ret = -ENOMEM; |
@@ -1459,44 +823,75 @@ ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) | |||
1459 | list_add_tail(&bf->list, &sc->txbuf); | 823 | list_add_tail(&bf->list, &sc->txbuf); |
1460 | } | 824 | } |
1461 | 825 | ||
1462 | /* beacon buffer */ | 826 | /* beacon buffers */ |
1463 | bf->desc = ds; | 827 | INIT_LIST_HEAD(&sc->bcbuf); |
1464 | bf->daddr = da; | 828 | for (i = 0; i < ATH_BCBUF; i++, bf++, ds++, da += sizeof(*ds)) { |
1465 | sc->bbuf = bf; | 829 | bf->desc = ds; |
830 | bf->daddr = da; | ||
831 | list_add_tail(&bf->list, &sc->bcbuf); | ||
832 | } | ||
1466 | 833 | ||
1467 | return 0; | 834 | return 0; |
1468 | err_free: | 835 | err_free: |
1469 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); | 836 | dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); |
1470 | err: | 837 | err: |
1471 | sc->desc = NULL; | 838 | sc->desc = NULL; |
1472 | return ret; | 839 | return ret; |
1473 | } | 840 | } |
1474 | 841 | ||
842 | void | ||
843 | ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) | ||
844 | { | ||
845 | BUG_ON(!bf); | ||
846 | if (!bf->skb) | ||
847 | return; | ||
848 | dma_unmap_single(sc->dev, bf->skbaddr, bf->skb->len, | ||
849 | DMA_TO_DEVICE); | ||
850 | dev_kfree_skb_any(bf->skb); | ||
851 | bf->skb = NULL; | ||
852 | bf->skbaddr = 0; | ||
853 | bf->desc->ds_data = 0; | ||
854 | } | ||
855 | |||
856 | void | ||
857 | ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf) | ||
858 | { | ||
859 | struct ath5k_hw *ah = sc->ah; | ||
860 | struct ath_common *common = ath5k_hw_common(ah); | ||
861 | |||
862 | BUG_ON(!bf); | ||
863 | if (!bf->skb) | ||
864 | return; | ||
865 | dma_unmap_single(sc->dev, bf->skbaddr, common->rx_bufsize, | ||
866 | DMA_FROM_DEVICE); | ||
867 | dev_kfree_skb_any(bf->skb); | ||
868 | bf->skb = NULL; | ||
869 | bf->skbaddr = 0; | ||
870 | bf->desc->ds_data = 0; | ||
871 | } | ||
872 | |||
1475 | static void | 873 | static void |
1476 | ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) | 874 | ath5k_desc_free(struct ath5k_softc *sc) |
1477 | { | 875 | { |
1478 | struct ath5k_buf *bf; | 876 | struct ath5k_buf *bf; |
1479 | 877 | ||
1480 | ath5k_txbuf_free_skb(sc, sc->bbuf); | ||
1481 | list_for_each_entry(bf, &sc->txbuf, list) | 878 | list_for_each_entry(bf, &sc->txbuf, list) |
1482 | ath5k_txbuf_free_skb(sc, bf); | 879 | ath5k_txbuf_free_skb(sc, bf); |
1483 | list_for_each_entry(bf, &sc->rxbuf, list) | 880 | list_for_each_entry(bf, &sc->rxbuf, list) |
1484 | ath5k_rxbuf_free_skb(sc, bf); | 881 | ath5k_rxbuf_free_skb(sc, bf); |
882 | list_for_each_entry(bf, &sc->bcbuf, list) | ||
883 | ath5k_txbuf_free_skb(sc, bf); | ||
1485 | 884 | ||
1486 | /* Free memory associated with all descriptors */ | 885 | /* Free memory associated with all descriptors */ |
1487 | pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); | 886 | dma_free_coherent(sc->dev, sc->desc_len, sc->desc, sc->desc_daddr); |
1488 | sc->desc = NULL; | 887 | sc->desc = NULL; |
1489 | sc->desc_daddr = 0; | 888 | sc->desc_daddr = 0; |
1490 | 889 | ||
1491 | kfree(sc->bufptr); | 890 | kfree(sc->bufptr); |
1492 | sc->bufptr = NULL; | 891 | sc->bufptr = NULL; |
1493 | sc->bbuf = NULL; | ||
1494 | } | 892 | } |
1495 | 893 | ||
1496 | 894 | ||
1497 | |||
1498 | |||
1499 | |||
1500 | /**************\ | 895 | /**************\ |
1501 | * Queues setup * | 896 | * Queues setup * |
1502 | \**************/ | 897 | \**************/ |
@@ -1509,16 +904,18 @@ ath5k_txq_setup(struct ath5k_softc *sc, | |||
1509 | struct ath5k_txq *txq; | 904 | struct ath5k_txq *txq; |
1510 | struct ath5k_txq_info qi = { | 905 | struct ath5k_txq_info qi = { |
1511 | .tqi_subtype = subtype, | 906 | .tqi_subtype = subtype, |
1512 | .tqi_aifs = AR5K_TXQ_USEDEFAULT, | 907 | /* XXX: default values not correct for B and XR channels, |
1513 | .tqi_cw_min = AR5K_TXQ_USEDEFAULT, | 908 | * but who cares? */ |
1514 | .tqi_cw_max = AR5K_TXQ_USEDEFAULT | 909 | .tqi_aifs = AR5K_TUNE_AIFS, |
910 | .tqi_cw_min = AR5K_TUNE_CWMIN, | ||
911 | .tqi_cw_max = AR5K_TUNE_CWMAX | ||
1515 | }; | 912 | }; |
1516 | int qnum; | 913 | int qnum; |
1517 | 914 | ||
1518 | /* | 915 | /* |
1519 | * Enable interrupts only for EOL and DESC conditions. | 916 | * Enable interrupts only for EOL and DESC conditions. |
1520 | * We mark tx descriptors to receive a DESC interrupt | 917 | * We mark tx descriptors to receive a DESC interrupt |
1521 | * when a tx queue gets deep; otherwise waiting for the | 918 | * when a tx queue gets deep; otherwise we wait for the |
1522 | * EOL to reap descriptors. Note that this is done to | 919 | * EOL to reap descriptors. Note that this is done to |
1523 | * reduce interrupt load and this only defers reaping | 920 | * reduce interrupt load and this only defers reaping |
1524 | * descriptors, never transmitting frames. Aside from | 921 | * descriptors, never transmitting frames. Aside from |
@@ -1550,6 +947,10 @@ ath5k_txq_setup(struct ath5k_softc *sc, | |||
1550 | INIT_LIST_HEAD(&txq->q); | 947 | INIT_LIST_HEAD(&txq->q); |
1551 | spin_lock_init(&txq->lock); | 948 | spin_lock_init(&txq->lock); |
1552 | txq->setup = true; | 949 | txq->setup = true; |
950 | txq->txq_len = 0; | ||
951 | txq->txq_max = ATH5K_TXQ_LEN_MAX; | ||
952 | txq->txq_poll_mark = false; | ||
953 | txq->txq_stuck = 0; | ||
1553 | } | 954 | } |
1554 | return &sc->txqs[qnum]; | 955 | return &sc->txqs[qnum]; |
1555 | } | 956 | } |
@@ -1558,9 +959,11 @@ static int | |||
1558 | ath5k_beaconq_setup(struct ath5k_hw *ah) | 959 | ath5k_beaconq_setup(struct ath5k_hw *ah) |
1559 | { | 960 | { |
1560 | struct ath5k_txq_info qi = { | 961 | struct ath5k_txq_info qi = { |
1561 | .tqi_aifs = AR5K_TXQ_USEDEFAULT, | 962 | /* XXX: default values not correct for B and XR channels, |
1562 | .tqi_cw_min = AR5K_TXQ_USEDEFAULT, | 963 | * but who cares? */ |
1563 | .tqi_cw_max = AR5K_TXQ_USEDEFAULT, | 964 | .tqi_aifs = AR5K_TUNE_AIFS, |
965 | .tqi_cw_min = AR5K_TUNE_CWMIN, | ||
966 | .tqi_cw_max = AR5K_TUNE_CWMAX, | ||
1564 | /* NB: for dynamic turbo, don't enable any other interrupts */ | 967 | /* NB: for dynamic turbo, don't enable any other interrupts */ |
1565 | .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE | 968 | .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE |
1566 | }; | 969 | }; |
@@ -1594,7 +997,7 @@ ath5k_beaconq_config(struct ath5k_softc *sc) | |||
1594 | */ | 997 | */ |
1595 | qi.tqi_aifs = 0; | 998 | qi.tqi_aifs = 0; |
1596 | qi.tqi_cw_min = 0; | 999 | qi.tqi_cw_min = 0; |
1597 | qi.tqi_cw_max = 2 * ah->ah_cw_min; | 1000 | qi.tqi_cw_max = 2 * AR5K_TUNE_CWMIN; |
1598 | } | 1001 | } |
1599 | 1002 | ||
1600 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | 1003 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, |
@@ -1626,60 +1029,44 @@ err: | |||
1626 | return ret; | 1029 | return ret; |
1627 | } | 1030 | } |
1628 | 1031 | ||
1032 | /** | ||
1033 | * ath5k_drain_tx_buffs - Empty tx buffers | ||
1034 | * | ||
1035 | * @sc The &struct ath5k_softc | ||
1036 | * | ||
1037 | * Empty tx buffers from all queues in preparation | ||
1038 | * of a reset or during shutdown. | ||
1039 | * | ||
1040 | * NB: this assumes output has been stopped and | ||
1041 | * we do not need to block ath5k_tx_tasklet | ||
1042 | */ | ||
1629 | static void | 1043 | static void |
1630 | ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) | 1044 | ath5k_drain_tx_buffs(struct ath5k_softc *sc) |
1631 | { | 1045 | { |
1046 | struct ath5k_txq *txq; | ||
1632 | struct ath5k_buf *bf, *bf0; | 1047 | struct ath5k_buf *bf, *bf0; |
1048 | int i; | ||
1633 | 1049 | ||
1634 | /* | 1050 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { |
1635 | * NB: this assumes output has been stopped and | 1051 | if (sc->txqs[i].setup) { |
1636 | * we do not need to block ath5k_tx_tasklet | 1052 | txq = &sc->txqs[i]; |
1637 | */ | 1053 | spin_lock_bh(&txq->lock); |
1638 | spin_lock_bh(&txq->lock); | 1054 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { |
1639 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | 1055 | ath5k_debug_printtxbuf(sc, bf); |
1640 | ath5k_debug_printtxbuf(sc, bf); | ||
1641 | |||
1642 | ath5k_txbuf_free_skb(sc, bf); | ||
1643 | |||
1644 | spin_lock_bh(&sc->txbuflock); | ||
1645 | list_move_tail(&bf->list, &sc->txbuf); | ||
1646 | sc->txbuf_len++; | ||
1647 | spin_unlock_bh(&sc->txbuflock); | ||
1648 | } | ||
1649 | txq->link = NULL; | ||
1650 | spin_unlock_bh(&txq->lock); | ||
1651 | } | ||
1652 | 1056 | ||
1653 | /* | 1057 | ath5k_txbuf_free_skb(sc, bf); |
1654 | * Drain the transmit queues and reclaim resources. | ||
1655 | */ | ||
1656 | static void | ||
1657 | ath5k_txq_cleanup(struct ath5k_softc *sc) | ||
1658 | { | ||
1659 | struct ath5k_hw *ah = sc->ah; | ||
1660 | unsigned int i; | ||
1661 | 1058 | ||
1662 | /* XXX return value */ | 1059 | spin_lock_bh(&sc->txbuflock); |
1663 | if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) { | 1060 | list_move_tail(&bf->list, &sc->txbuf); |
1664 | /* don't touch the hardware if marked invalid */ | 1061 | sc->txbuf_len++; |
1665 | ath5k_hw_stop_tx_dma(ah, sc->bhalq); | 1062 | txq->txq_len--; |
1666 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", | 1063 | spin_unlock_bh(&sc->txbuflock); |
1667 | ath5k_hw_get_txdp(ah, sc->bhalq)); | ||
1668 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) | ||
1669 | if (sc->txqs[i].setup) { | ||
1670 | ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); | ||
1671 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " | ||
1672 | "link %p\n", | ||
1673 | sc->txqs[i].qnum, | ||
1674 | ath5k_hw_get_txdp(ah, | ||
1675 | sc->txqs[i].qnum), | ||
1676 | sc->txqs[i].link); | ||
1677 | } | 1064 | } |
1065 | txq->link = NULL; | ||
1066 | txq->txq_poll_mark = false; | ||
1067 | spin_unlock_bh(&txq->lock); | ||
1068 | } | ||
1678 | } | 1069 | } |
1679 | |||
1680 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) | ||
1681 | if (sc->txqs[i].setup) | ||
1682 | ath5k_txq_drainq(sc, &sc->txqs[i]); | ||
1683 | } | 1070 | } |
1684 | 1071 | ||
1685 | static void | 1072 | static void |
@@ -1696,8 +1083,6 @@ ath5k_txq_release(struct ath5k_softc *sc) | |||
1696 | } | 1083 | } |
1697 | 1084 | ||
1698 | 1085 | ||
1699 | |||
1700 | |||
1701 | /*************\ | 1086 | /*************\ |
1702 | * RX Handling * | 1087 | * RX Handling * |
1703 | \*************/ | 1088 | \*************/ |
@@ -1713,7 +1098,7 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1713 | struct ath5k_buf *bf; | 1098 | struct ath5k_buf *bf; |
1714 | int ret; | 1099 | int ret; |
1715 | 1100 | ||
1716 | common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz); | 1101 | common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz); |
1717 | 1102 | ||
1718 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", | 1103 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", |
1719 | common->cachelsz, common->rx_bufsize); | 1104 | common->cachelsz, common->rx_bufsize); |
@@ -1732,7 +1117,7 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1732 | spin_unlock_bh(&sc->rxbuflock); | 1117 | spin_unlock_bh(&sc->rxbuflock); |
1733 | 1118 | ||
1734 | ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ | 1119 | ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ |
1735 | ath5k_mode_setup(sc); /* set filters, etc. */ | 1120 | ath5k_update_bssid_mask_and_opmode(sc, NULL); /* set filters, etc. */ |
1736 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ | 1121 | ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ |
1737 | 1122 | ||
1738 | return 0; | 1123 | return 0; |
@@ -1741,16 +1126,19 @@ err: | |||
1741 | } | 1126 | } |
1742 | 1127 | ||
1743 | /* | 1128 | /* |
1744 | * Disable the receive h/w in preparation for a reset. | 1129 | * Disable the receive logic on PCU (DRU) |
1130 | * In preparation for a shutdown. | ||
1131 | * | ||
1132 | * Note: Doesn't stop rx DMA, ath5k_hw_dma_stop | ||
1133 | * does. | ||
1745 | */ | 1134 | */ |
1746 | static void | 1135 | static void |
1747 | ath5k_rx_stop(struct ath5k_softc *sc) | 1136 | ath5k_rx_stop(struct ath5k_softc *sc) |
1748 | { | 1137 | { |
1749 | struct ath5k_hw *ah = sc->ah; | 1138 | struct ath5k_hw *ah = sc->ah; |
1750 | 1139 | ||
1751 | ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ | ||
1752 | ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ | 1140 | ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ |
1753 | ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ | 1141 | ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ |
1754 | 1142 | ||
1755 | ath5k_debug_printrxbuffs(sc, ah); | 1143 | ath5k_debug_printrxbuffs(sc, ah); |
1756 | } | 1144 | } |
@@ -1840,6 +1228,15 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1840 | */ | 1228 | */ |
1841 | if (hw_tu >= sc->nexttbtt) | 1229 | if (hw_tu >= sc->nexttbtt) |
1842 | ath5k_beacon_update_timers(sc, bc_tstamp); | 1230 | ath5k_beacon_update_timers(sc, bc_tstamp); |
1231 | |||
1232 | /* Check if the beacon timers are still correct, because a TSF | ||
1233 | * update might have created a window between them - for a | ||
1234 | * longer description see the comment of this function: */ | ||
1235 | if (!ath5k_hw_check_beacon_timers(sc->ah, sc->bintval)) { | ||
1236 | ath5k_beacon_update_timers(sc, bc_tstamp); | ||
1237 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, | ||
1238 | "fixed beacon timers after beacon receive\n"); | ||
1239 | } | ||
1843 | } | 1240 | } |
1844 | } | 1241 | } |
1845 | 1242 | ||
@@ -1855,15 +1252,14 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) | |||
1855 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) | 1252 | memcmp(mgmt->bssid, common->curbssid, ETH_ALEN) != 0) |
1856 | return; | 1253 | return; |
1857 | 1254 | ||
1858 | ah->ah_beacon_rssi_avg = ath5k_moving_average(ah->ah_beacon_rssi_avg, | 1255 | ewma_add(&ah->ah_beacon_rssi_avg, rssi); |
1859 | rssi); | ||
1860 | 1256 | ||
1861 | /* in IBSS mode we should keep RSSI statistics per neighbour */ | 1257 | /* in IBSS mode we should keep RSSI statistics per neighbour */ |
1862 | /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ | 1258 | /* le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS */ |
1863 | } | 1259 | } |
1864 | 1260 | ||
1865 | /* | 1261 | /* |
1866 | * Compute padding position. skb must contains an IEEE 802.11 frame | 1262 | * Compute padding position. skb must contain an IEEE 802.11 frame |
1867 | */ | 1263 | */ |
1868 | static int ath5k_common_padpos(struct sk_buff *skb) | 1264 | static int ath5k_common_padpos(struct sk_buff *skb) |
1869 | { | 1265 | { |
@@ -1882,10 +1278,9 @@ static int ath5k_common_padpos(struct sk_buff *skb) | |||
1882 | } | 1278 | } |
1883 | 1279 | ||
1884 | /* | 1280 | /* |
1885 | * This function expects a 802.11 frame and returns the number of | 1281 | * This function expects an 802.11 frame and returns the number of |
1886 | * bytes added, or -1 if we don't have enought header room. | 1282 | * bytes added, or -1 if we don't have enough header room. |
1887 | */ | 1283 | */ |
1888 | |||
1889 | static int ath5k_add_padding(struct sk_buff *skb) | 1284 | static int ath5k_add_padding(struct sk_buff *skb) |
1890 | { | 1285 | { |
1891 | int padpos = ath5k_common_padpos(skb); | 1286 | int padpos = ath5k_common_padpos(skb); |
@@ -1905,10 +1300,18 @@ static int ath5k_add_padding(struct sk_buff *skb) | |||
1905 | } | 1300 | } |
1906 | 1301 | ||
1907 | /* | 1302 | /* |
1908 | * This function expects a 802.11 frame and returns the number of | 1303 | * The MAC header is padded to have 32-bit boundary if the |
1909 | * bytes removed | 1304 | * packet payload is non-zero. The general calculation for |
1305 | * padsize would take into account odd header lengths: | ||
1306 | * padsize = 4 - (hdrlen & 3); however, since only | ||
1307 | * even-length headers are used, padding can only be 0 or 2 | ||
1308 | * bytes and we can optimize this a bit. We must not try to | ||
1309 | * remove padding from short control frames that do not have a | ||
1310 | * payload. | ||
1311 | * | ||
1312 | * This function expects an 802.11 frame and returns the number of | ||
1313 | * bytes removed. | ||
1910 | */ | 1314 | */ |
1911 | |||
1912 | static int ath5k_remove_padding(struct sk_buff *skb) | 1315 | static int ath5k_remove_padding(struct sk_buff *skb) |
1913 | { | 1316 | { |
1914 | int padpos = ath5k_common_padpos(skb); | 1317 | int padpos = ath5k_common_padpos(skb); |
@@ -1929,14 +1332,6 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1929 | { | 1332 | { |
1930 | struct ieee80211_rx_status *rxs; | 1333 | struct ieee80211_rx_status *rxs; |
1931 | 1334 | ||
1932 | /* The MAC header is padded to have 32-bit boundary if the | ||
1933 | * packet payload is non-zero. The general calculation for | ||
1934 | * padsize would take into account odd header lengths: | ||
1935 | * padsize = (4 - hdrlen % 4) % 4; However, since only | ||
1936 | * even-length headers are used, padding can only be 0 or 2 | ||
1937 | * bytes and we can optimize this a bit. In addition, we must | ||
1938 | * not try to remove padding from short control frames that do | ||
1939 | * not have payload. */ | ||
1940 | ath5k_remove_padding(skb); | 1335 | ath5k_remove_padding(skb); |
1941 | 1336 | ||
1942 | rxs = IEEE80211_SKB_RXCB(skb); | 1337 | rxs = IEEE80211_SKB_RXCB(skb); |
@@ -1966,10 +1361,10 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1966 | * right now, so it's not too bad... | 1361 | * right now, so it's not too bad... |
1967 | */ | 1362 | */ |
1968 | rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp); | 1363 | rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp); |
1969 | rxs->flag |= RX_FLAG_TSFT; | 1364 | rxs->flag |= RX_FLAG_MACTIME_MPDU; |
1970 | 1365 | ||
1971 | rxs->freq = sc->curchan->center_freq; | 1366 | rxs->freq = sc->curchan->center_freq; |
1972 | rxs->band = sc->curband->band; | 1367 | rxs->band = sc->curchan->band; |
1973 | 1368 | ||
1974 | rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi; | 1369 | rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi; |
1975 | 1370 | ||
@@ -1984,10 +1379,10 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1984 | rxs->flag |= ath5k_rx_decrypted(sc, skb, rs); | 1379 | rxs->flag |= ath5k_rx_decrypted(sc, skb, rs); |
1985 | 1380 | ||
1986 | if (rxs->rate_idx >= 0 && rs->rs_rate == | 1381 | if (rxs->rate_idx >= 0 && rs->rs_rate == |
1987 | sc->curband->bitrates[rxs->rate_idx].hw_value_short) | 1382 | sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short) |
1988 | rxs->flag |= RX_FLAG_SHORTPRE; | 1383 | rxs->flag |= RX_FLAG_SHORTPRE; |
1989 | 1384 | ||
1990 | ath5k_debug_dump_skb(sc, skb, "RX ", 0); | 1385 | trace_ath5k_rx(sc, skb); |
1991 | 1386 | ||
1992 | ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi); | 1387 | ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi); |
1993 | 1388 | ||
@@ -2007,6 +1402,7 @@ static bool | |||
2007 | ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) | 1402 | ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) |
2008 | { | 1403 | { |
2009 | sc->stats.rx_all_count++; | 1404 | sc->stats.rx_all_count++; |
1405 | sc->stats.rx_bytes_count += rs->rs_datalen; | ||
2010 | 1406 | ||
2011 | if (unlikely(rs->rs_status)) { | 1407 | if (unlikely(rs->rs_status)) { |
2012 | if (rs->rs_status & AR5K_RXERR_CRC) | 1408 | if (rs->rs_status & AR5K_RXERR_CRC) |
@@ -2040,9 +1436,8 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) | |||
2040 | return true; | 1436 | return true; |
2041 | } | 1437 | } |
2042 | 1438 | ||
2043 | /* let crypto-error packets fall through in MNTR */ | 1439 | /* reject any frames with non-crypto errors */ |
2044 | if ((rs->rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | 1440 | if (rs->rs_status & ~(AR5K_RXERR_DECRYPT)) |
2045 | sc->opmode != NL80211_IFTYPE_MONITOR) | ||
2046 | return false; | 1441 | return false; |
2047 | } | 1442 | } |
2048 | 1443 | ||
@@ -2054,6 +1449,21 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) | |||
2054 | } | 1449 | } |
2055 | 1450 | ||
2056 | static void | 1451 | static void |
1452 | ath5k_set_current_imask(struct ath5k_softc *sc) | ||
1453 | { | ||
1454 | enum ath5k_int imask = sc->imask; | ||
1455 | unsigned long flags; | ||
1456 | |||
1457 | spin_lock_irqsave(&sc->irqlock, flags); | ||
1458 | if (sc->rx_pending) | ||
1459 | imask &= ~AR5K_INT_RX_ALL; | ||
1460 | if (sc->tx_pending) | ||
1461 | imask &= ~AR5K_INT_TX_ALL; | ||
1462 | ath5k_hw_set_imr(sc->ah, imask); | ||
1463 | spin_unlock_irqrestore(&sc->irqlock, flags); | ||
1464 | } | ||
1465 | |||
1466 | static void | ||
2057 | ath5k_tasklet_rx(unsigned long data) | 1467 | ath5k_tasklet_rx(unsigned long data) |
2058 | { | 1468 | { |
2059 | struct ath5k_rx_status rs = {}; | 1469 | struct ath5k_rx_status rs = {}; |
@@ -2100,9 +1510,9 @@ ath5k_tasklet_rx(unsigned long data) | |||
2100 | if (!next_skb) | 1510 | if (!next_skb) |
2101 | goto next; | 1511 | goto next; |
2102 | 1512 | ||
2103 | pci_unmap_single(sc->pdev, bf->skbaddr, | 1513 | dma_unmap_single(sc->dev, bf->skbaddr, |
2104 | common->rx_bufsize, | 1514 | common->rx_bufsize, |
2105 | PCI_DMA_FROMDEVICE); | 1515 | DMA_FROM_DEVICE); |
2106 | 1516 | ||
2107 | skb_put(skb, rs.rs_datalen); | 1517 | skb_put(skb, rs.rs_datalen); |
2108 | 1518 | ||
@@ -2116,6 +1526,8 @@ next: | |||
2116 | } while (ath5k_rxbuf_setup(sc, bf) == 0); | 1526 | } while (ath5k_rxbuf_setup(sc, bf) == 0); |
2117 | unlock: | 1527 | unlock: |
2118 | spin_unlock(&sc->rxbuflock); | 1528 | spin_unlock(&sc->rxbuflock); |
1529 | sc->rx_pending = false; | ||
1530 | ath5k_set_current_imask(sc); | ||
2119 | } | 1531 | } |
2120 | 1532 | ||
2121 | 1533 | ||
@@ -2123,6 +1535,122 @@ unlock: | |||
2123 | * TX Handling * | 1535 | * TX Handling * |
2124 | \*************/ | 1536 | \*************/ |
2125 | 1537 | ||
1538 | void | ||
1539 | ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
1540 | struct ath5k_txq *txq) | ||
1541 | { | ||
1542 | struct ath5k_softc *sc = hw->priv; | ||
1543 | struct ath5k_buf *bf; | ||
1544 | unsigned long flags; | ||
1545 | int padsize; | ||
1546 | |||
1547 | trace_ath5k_tx(sc, skb, txq); | ||
1548 | |||
1549 | /* | ||
1550 | * The hardware expects the header padded to 4 byte boundaries. | ||
1551 | * If this is not the case, we add the padding after the header. | ||
1552 | */ | ||
1553 | padsize = ath5k_add_padding(skb); | ||
1554 | if (padsize < 0) { | ||
1555 | ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" | ||
1556 | " headroom to pad"); | ||
1557 | goto drop_packet; | ||
1558 | } | ||
1559 | |||
1560 | if (txq->txq_len >= txq->txq_max) | ||
1561 | ieee80211_stop_queue(hw, txq->qnum); | ||
1562 | |||
1563 | spin_lock_irqsave(&sc->txbuflock, flags); | ||
1564 | if (list_empty(&sc->txbuf)) { | ||
1565 | ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); | ||
1566 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
1567 | ieee80211_stop_queues(hw); | ||
1568 | goto drop_packet; | ||
1569 | } | ||
1570 | bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); | ||
1571 | list_del(&bf->list); | ||
1572 | sc->txbuf_len--; | ||
1573 | if (list_empty(&sc->txbuf)) | ||
1574 | ieee80211_stop_queues(hw); | ||
1575 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
1576 | |||
1577 | bf->skb = skb; | ||
1578 | |||
1579 | if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { | ||
1580 | bf->skb = NULL; | ||
1581 | spin_lock_irqsave(&sc->txbuflock, flags); | ||
1582 | list_add_tail(&bf->list, &sc->txbuf); | ||
1583 | sc->txbuf_len++; | ||
1584 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
1585 | goto drop_packet; | ||
1586 | } | ||
1587 | return; | ||
1588 | |||
1589 | drop_packet: | ||
1590 | dev_kfree_skb_any(skb); | ||
1591 | } | ||
1592 | |||
1593 | static void | ||
1594 | ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb, | ||
1595 | struct ath5k_txq *txq, struct ath5k_tx_status *ts) | ||
1596 | { | ||
1597 | struct ieee80211_tx_info *info; | ||
1598 | u8 tries[3]; | ||
1599 | int i; | ||
1600 | |||
1601 | sc->stats.tx_all_count++; | ||
1602 | sc->stats.tx_bytes_count += skb->len; | ||
1603 | info = IEEE80211_SKB_CB(skb); | ||
1604 | |||
1605 | tries[0] = info->status.rates[0].count; | ||
1606 | tries[1] = info->status.rates[1].count; | ||
1607 | tries[2] = info->status.rates[2].count; | ||
1608 | |||
1609 | ieee80211_tx_info_clear_status(info); | ||
1610 | |||
1611 | for (i = 0; i < ts->ts_final_idx; i++) { | ||
1612 | struct ieee80211_tx_rate *r = | ||
1613 | &info->status.rates[i]; | ||
1614 | |||
1615 | r->count = tries[i]; | ||
1616 | } | ||
1617 | |||
1618 | info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry; | ||
1619 | info->status.rates[ts->ts_final_idx + 1].idx = -1; | ||
1620 | |||
1621 | if (unlikely(ts->ts_status)) { | ||
1622 | sc->stats.ack_fail++; | ||
1623 | if (ts->ts_status & AR5K_TXERR_FILT) { | ||
1624 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
1625 | sc->stats.txerr_filt++; | ||
1626 | } | ||
1627 | if (ts->ts_status & AR5K_TXERR_XRETRY) | ||
1628 | sc->stats.txerr_retry++; | ||
1629 | if (ts->ts_status & AR5K_TXERR_FIFO) | ||
1630 | sc->stats.txerr_fifo++; | ||
1631 | } else { | ||
1632 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
1633 | info->status.ack_signal = ts->ts_rssi; | ||
1634 | |||
1635 | /* count the successful attempt as well */ | ||
1636 | info->status.rates[ts->ts_final_idx].count++; | ||
1637 | } | ||
1638 | |||
1639 | /* | ||
1640 | * Remove MAC header padding before giving the frame | ||
1641 | * back to mac80211. | ||
1642 | */ | ||
1643 | ath5k_remove_padding(skb); | ||
1644 | |||
1645 | if (ts->ts_antenna > 0 && ts->ts_antenna < 5) | ||
1646 | sc->stats.antenna_tx[ts->ts_antenna]++; | ||
1647 | else | ||
1648 | sc->stats.antenna_tx[0]++; /* invalid */ | ||
1649 | |||
1650 | trace_ath5k_tx_complete(sc, skb, txq, ts); | ||
1651 | ieee80211_tx_status(sc->hw, skb); | ||
1652 | } | ||
1653 | |||
2126 | static void | 1654 | static void |
2127 | ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | 1655 | ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) |
2128 | { | 1656 | { |
@@ -2130,96 +1658,52 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
2130 | struct ath5k_buf *bf, *bf0; | 1658 | struct ath5k_buf *bf, *bf0; |
2131 | struct ath5k_desc *ds; | 1659 | struct ath5k_desc *ds; |
2132 | struct sk_buff *skb; | 1660 | struct sk_buff *skb; |
2133 | struct ieee80211_tx_info *info; | 1661 | int ret; |
2134 | int i, ret; | ||
2135 | 1662 | ||
2136 | spin_lock(&txq->lock); | 1663 | spin_lock(&txq->lock); |
2137 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | 1664 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { |
2138 | ds = bf->desc; | ||
2139 | |||
2140 | /* | ||
2141 | * It's possible that the hardware can say the buffer is | ||
2142 | * completed when it hasn't yet loaded the ds_link from | ||
2143 | * host memory and moved on. If there are more TX | ||
2144 | * descriptors in the queue, wait for TXDP to change | ||
2145 | * before processing this one. | ||
2146 | */ | ||
2147 | if (ath5k_hw_get_txdp(sc->ah, txq->qnum) == bf->daddr && | ||
2148 | !list_is_last(&bf->list, &txq->q)) | ||
2149 | break; | ||
2150 | |||
2151 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); | ||
2152 | if (unlikely(ret == -EINPROGRESS)) | ||
2153 | break; | ||
2154 | else if (unlikely(ret)) { | ||
2155 | ATH5K_ERR(sc, "error %d while processing queue %u\n", | ||
2156 | ret, txq->qnum); | ||
2157 | break; | ||
2158 | } | ||
2159 | |||
2160 | sc->stats.tx_all_count++; | ||
2161 | skb = bf->skb; | ||
2162 | info = IEEE80211_SKB_CB(skb); | ||
2163 | bf->skb = NULL; | ||
2164 | 1665 | ||
2165 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, | 1666 | txq->txq_poll_mark = false; |
2166 | PCI_DMA_TODEVICE); | ||
2167 | 1667 | ||
2168 | ieee80211_tx_info_clear_status(info); | 1668 | /* skb might already have been processed last time. */ |
2169 | for (i = 0; i < 4; i++) { | 1669 | if (bf->skb != NULL) { |
2170 | struct ieee80211_tx_rate *r = | 1670 | ds = bf->desc; |
2171 | &info->status.rates[i]; | ||
2172 | 1671 | ||
2173 | if (ts.ts_rate[i]) { | 1672 | ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); |
2174 | r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); | 1673 | if (unlikely(ret == -EINPROGRESS)) |
2175 | r->count = ts.ts_retry[i]; | 1674 | break; |
2176 | } else { | 1675 | else if (unlikely(ret)) { |
2177 | r->idx = -1; | 1676 | ATH5K_ERR(sc, |
2178 | r->count = 0; | 1677 | "error %d while processing " |
1678 | "queue %u\n", ret, txq->qnum); | ||
1679 | break; | ||
2179 | } | 1680 | } |
2180 | } | ||
2181 | 1681 | ||
2182 | /* count the successful attempt as well */ | 1682 | skb = bf->skb; |
2183 | info->status.rates[ts.ts_final_idx].count++; | 1683 | bf->skb = NULL; |
2184 | 1684 | ||
2185 | if (unlikely(ts.ts_status)) { | 1685 | dma_unmap_single(sc->dev, bf->skbaddr, skb->len, |
2186 | sc->stats.ack_fail++; | 1686 | DMA_TO_DEVICE); |
2187 | if (ts.ts_status & AR5K_TXERR_FILT) { | 1687 | ath5k_tx_frame_completed(sc, skb, txq, &ts); |
2188 | info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
2189 | sc->stats.txerr_filt++; | ||
2190 | } | ||
2191 | if (ts.ts_status & AR5K_TXERR_XRETRY) | ||
2192 | sc->stats.txerr_retry++; | ||
2193 | if (ts.ts_status & AR5K_TXERR_FIFO) | ||
2194 | sc->stats.txerr_fifo++; | ||
2195 | } else { | ||
2196 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
2197 | info->status.ack_signal = ts.ts_rssi; | ||
2198 | } | 1688 | } |
2199 | 1689 | ||
2200 | /* | 1690 | /* |
2201 | * Remove MAC header padding before giving the frame | 1691 | * It's possible that the hardware can say the buffer is |
2202 | * back to mac80211. | 1692 | * completed when it hasn't yet loaded the ds_link from |
1693 | * host memory and moved on. | ||
1694 | * Always keep the last descriptor to avoid HW races... | ||
2203 | */ | 1695 | */ |
2204 | ath5k_remove_padding(skb); | 1696 | if (ath5k_hw_get_txdp(sc->ah, txq->qnum) != bf->daddr) { |
2205 | 1697 | spin_lock(&sc->txbuflock); | |
2206 | if (ts.ts_antenna > 0 && ts.ts_antenna < 5) | 1698 | list_move_tail(&bf->list, &sc->txbuf); |
2207 | sc->stats.antenna_tx[ts.ts_antenna]++; | 1699 | sc->txbuf_len++; |
2208 | else | 1700 | txq->txq_len--; |
2209 | sc->stats.antenna_tx[0]++; /* invalid */ | 1701 | spin_unlock(&sc->txbuflock); |
2210 | 1702 | } | |
2211 | ieee80211_tx_status(sc->hw, skb); | ||
2212 | |||
2213 | spin_lock(&sc->txbuflock); | ||
2214 | list_move_tail(&bf->list, &sc->txbuf); | ||
2215 | sc->txbuf_len++; | ||
2216 | spin_unlock(&sc->txbuflock); | ||
2217 | } | 1703 | } |
2218 | if (likely(list_empty(&txq->q))) | ||
2219 | txq->link = NULL; | ||
2220 | spin_unlock(&txq->lock); | 1704 | spin_unlock(&txq->lock); |
2221 | if (sc->txbuf_len > ATH_TXBUF / 5) | 1705 | if (txq->txq_len < ATH5K_TXQ_LEN_LOW && txq->qnum < 4) |
2222 | ieee80211_wake_queues(sc->hw); | 1706 | ieee80211_wake_queue(sc->hw, txq->qnum); |
2223 | } | 1707 | } |
2224 | 1708 | ||
2225 | static void | 1709 | static void |
@@ -2231,6 +1715,9 @@ ath5k_tasklet_tx(unsigned long data) | |||
2231 | for (i=0; i < AR5K_NUM_TX_QUEUES; i++) | 1715 | for (i=0; i < AR5K_NUM_TX_QUEUES; i++) |
2232 | if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) | 1716 | if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) |
2233 | ath5k_tx_processq(sc, &sc->txqs[i]); | 1717 | ath5k_tx_processq(sc, &sc->txqs[i]); |
1718 | |||
1719 | sc->tx_pending = false; | ||
1720 | ath5k_set_current_imask(sc); | ||
2234 | } | 1721 | } |
2235 | 1722 | ||
2236 | 1723 | ||
@@ -2253,12 +1740,13 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2253 | u32 flags; | 1740 | u32 flags; |
2254 | const int padsize = 0; | 1741 | const int padsize = 0; |
2255 | 1742 | ||
2256 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | 1743 | bf->skbaddr = dma_map_single(sc->dev, skb->data, skb->len, |
2257 | PCI_DMA_TODEVICE); | 1744 | DMA_TO_DEVICE); |
2258 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " | 1745 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " |
2259 | "skbaddr %llx\n", skb, skb->data, skb->len, | 1746 | "skbaddr %llx\n", skb, skb->data, skb->len, |
2260 | (unsigned long long)bf->skbaddr); | 1747 | (unsigned long long)bf->skbaddr); |
2261 | if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) { | 1748 | |
1749 | if (dma_mapping_error(sc->dev, bf->skbaddr)) { | ||
2262 | ATH5K_ERR(sc, "beacon DMA mapping failed\n"); | 1750 | ATH5K_ERR(sc, "beacon DMA mapping failed\n"); |
2263 | return -EIO; | 1751 | return -EIO; |
2264 | } | 1752 | } |
@@ -2285,10 +1773,11 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2285 | * default antenna which is supposed to be an omni. | 1773 | * default antenna which is supposed to be an omni. |
2286 | * | 1774 | * |
2287 | * Note2: On sectored scenarios it's possible to have | 1775 | * Note2: On sectored scenarios it's possible to have |
2288 | * multiple antennas (1omni -the default- and 14 sectors) | 1776 | * multiple antennas (1 omni -- the default -- and 14 |
2289 | * so if we choose to actually support this mode we need | 1777 | * sectors), so if we choose to actually support this |
2290 | * to allow user to set how many antennas we have and tweak | 1778 | * mode, we need to allow the user to set how many antennas |
2291 | * the code below to send beacons on all of them. | 1779 | * we have and tweak the code below to send beacons |
1780 | * on all of them. | ||
2292 | */ | 1781 | */ |
2293 | if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) | 1782 | if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) |
2294 | antenna = sc->bsent & 4 ? 2 : 1; | 1783 | antenna = sc->bsent & 4 ? 2 : 1; |
@@ -2309,7 +1798,43 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2309 | 1798 | ||
2310 | return 0; | 1799 | return 0; |
2311 | err_unmap: | 1800 | err_unmap: |
2312 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); | 1801 | dma_unmap_single(sc->dev, bf->skbaddr, skb->len, DMA_TO_DEVICE); |
1802 | return ret; | ||
1803 | } | ||
1804 | |||
1805 | /* | ||
1806 | * Updates the beacon that is sent by ath5k_beacon_send. For adhoc, | ||
1807 | * this is called only once at config_bss time, for AP we do it every | ||
1808 | * SWBA interrupt so that the TIM will reflect buffered frames. | ||
1809 | * | ||
1810 | * Called with the beacon lock. | ||
1811 | */ | ||
1812 | int | ||
1813 | ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
1814 | { | ||
1815 | int ret; | ||
1816 | struct ath5k_softc *sc = hw->priv; | ||
1817 | struct ath5k_vif *avf = (void *)vif->drv_priv; | ||
1818 | struct sk_buff *skb; | ||
1819 | |||
1820 | if (WARN_ON(!vif)) { | ||
1821 | ret = -EINVAL; | ||
1822 | goto out; | ||
1823 | } | ||
1824 | |||
1825 | skb = ieee80211_beacon_get(hw, vif); | ||
1826 | |||
1827 | if (!skb) { | ||
1828 | ret = -ENOMEM; | ||
1829 | goto out; | ||
1830 | } | ||
1831 | |||
1832 | ath5k_txbuf_free_skb(sc, avf->bbuf); | ||
1833 | avf->bbuf->skb = skb; | ||
1834 | ret = ath5k_beacon_setup(sc, avf->bbuf); | ||
1835 | if (ret) | ||
1836 | avf->bbuf->skb = NULL; | ||
1837 | out: | ||
2313 | return ret; | 1838 | return ret; |
2314 | } | 1839 | } |
2315 | 1840 | ||
@@ -2324,20 +1849,17 @@ err_unmap: | |||
2324 | static void | 1849 | static void |
2325 | ath5k_beacon_send(struct ath5k_softc *sc) | 1850 | ath5k_beacon_send(struct ath5k_softc *sc) |
2326 | { | 1851 | { |
2327 | struct ath5k_buf *bf = sc->bbuf; | ||
2328 | struct ath5k_hw *ah = sc->ah; | 1852 | struct ath5k_hw *ah = sc->ah; |
1853 | struct ieee80211_vif *vif; | ||
1854 | struct ath5k_vif *avf; | ||
1855 | struct ath5k_buf *bf; | ||
2329 | struct sk_buff *skb; | 1856 | struct sk_buff *skb; |
2330 | 1857 | ||
2331 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); | 1858 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); |
2332 | 1859 | ||
2333 | if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || | ||
2334 | sc->opmode == NL80211_IFTYPE_MONITOR)) { | ||
2335 | ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); | ||
2336 | return; | ||
2337 | } | ||
2338 | /* | 1860 | /* |
2339 | * Check if the previous beacon has gone out. If | 1861 | * Check if the previous beacon has gone out. If |
2340 | * not don't don't try to post another, skip this | 1862 | * not, don't don't try to post another: skip this |
2341 | * period and wait for the next. Missed beacons | 1863 | * period and wait for the next. Missed beacons |
2342 | * indicate a problem and should not occur. If we | 1864 | * indicate a problem and should not occur. If we |
2343 | * miss too many consecutive beacons reset the device. | 1865 | * miss too many consecutive beacons reset the device. |
@@ -2363,35 +1885,60 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2363 | sc->bmisscount = 0; | 1885 | sc->bmisscount = 0; |
2364 | } | 1886 | } |
2365 | 1887 | ||
1888 | if ((sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) || | ||
1889 | sc->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
1890 | u64 tsf = ath5k_hw_get_tsf64(ah); | ||
1891 | u32 tsftu = TSF_TO_TU(tsf); | ||
1892 | int slot = ((tsftu % sc->bintval) * ATH_BCBUF) / sc->bintval; | ||
1893 | vif = sc->bslot[(slot + 1) % ATH_BCBUF]; | ||
1894 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, | ||
1895 | "tsf %llx tsftu %x intval %u slot %u vif %p\n", | ||
1896 | (unsigned long long)tsf, tsftu, sc->bintval, slot, vif); | ||
1897 | } else /* only one interface */ | ||
1898 | vif = sc->bslot[0]; | ||
1899 | |||
1900 | if (!vif) | ||
1901 | return; | ||
1902 | |||
1903 | avf = (void *)vif->drv_priv; | ||
1904 | bf = avf->bbuf; | ||
1905 | if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || | ||
1906 | sc->opmode == NL80211_IFTYPE_MONITOR)) { | ||
1907 | ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); | ||
1908 | return; | ||
1909 | } | ||
1910 | |||
2366 | /* | 1911 | /* |
2367 | * Stop any current dma and put the new frame on the queue. | 1912 | * Stop any current dma and put the new frame on the queue. |
2368 | * This should never fail since we check above that no frames | 1913 | * This should never fail since we check above that no frames |
2369 | * are still pending on the queue. | 1914 | * are still pending on the queue. |
2370 | */ | 1915 | */ |
2371 | if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { | 1916 | if (unlikely(ath5k_hw_stop_beacon_queue(ah, sc->bhalq))) { |
2372 | ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); | 1917 | ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); |
2373 | /* NB: hw still stops DMA, so proceed */ | 1918 | /* NB: hw still stops DMA, so proceed */ |
2374 | } | 1919 | } |
2375 | 1920 | ||
2376 | /* refresh the beacon for AP mode */ | 1921 | /* refresh the beacon for AP or MESH mode */ |
2377 | if (sc->opmode == NL80211_IFTYPE_AP) | 1922 | if (sc->opmode == NL80211_IFTYPE_AP || |
2378 | ath5k_beacon_update(sc->hw, sc->vif); | 1923 | sc->opmode == NL80211_IFTYPE_MESH_POINT) |
1924 | ath5k_beacon_update(sc->hw, vif); | ||
1925 | |||
1926 | trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]); | ||
2379 | 1927 | ||
2380 | ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); | 1928 | ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); |
2381 | ath5k_hw_start_tx_dma(ah, sc->bhalq); | 1929 | ath5k_hw_start_tx_dma(ah, sc->bhalq); |
2382 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", | 1930 | ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", |
2383 | sc->bhalq, (unsigned long long)bf->daddr, bf->desc); | 1931 | sc->bhalq, (unsigned long long)bf->daddr, bf->desc); |
2384 | 1932 | ||
2385 | skb = ieee80211_get_buffered_bc(sc->hw, sc->vif); | 1933 | skb = ieee80211_get_buffered_bc(sc->hw, vif); |
2386 | while (skb) { | 1934 | while (skb) { |
2387 | ath5k_tx_queue(sc->hw, skb, sc->cabq); | 1935 | ath5k_tx_queue(sc->hw, skb, sc->cabq); |
2388 | skb = ieee80211_get_buffered_bc(sc->hw, sc->vif); | 1936 | skb = ieee80211_get_buffered_bc(sc->hw, vif); |
2389 | } | 1937 | } |
2390 | 1938 | ||
2391 | sc->bsent++; | 1939 | sc->bsent++; |
2392 | } | 1940 | } |
2393 | 1941 | ||
2394 | |||
2395 | /** | 1942 | /** |
2396 | * ath5k_beacon_update_timers - update beacon timers | 1943 | * ath5k_beacon_update_timers - update beacon timers |
2397 | * | 1944 | * |
@@ -2408,7 +1955,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2408 | * when we otherwise know we have to update the timers, but we keep it in this | 1955 | * when we otherwise know we have to update the timers, but we keep it in this |
2409 | * function to have it all together in one place. | 1956 | * function to have it all together in one place. |
2410 | */ | 1957 | */ |
2411 | static void | 1958 | void |
2412 | ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | 1959 | ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) |
2413 | { | 1960 | { |
2414 | struct ath5k_hw *ah = sc->ah; | 1961 | struct ath5k_hw *ah = sc->ah; |
@@ -2416,6 +1963,12 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | |||
2416 | u64 hw_tsf; | 1963 | u64 hw_tsf; |
2417 | 1964 | ||
2418 | intval = sc->bintval & AR5K_BEACON_PERIOD; | 1965 | intval = sc->bintval & AR5K_BEACON_PERIOD; |
1966 | if (sc->opmode == NL80211_IFTYPE_AP && sc->num_ap_vifs > 1) { | ||
1967 | intval /= ATH_BCBUF; /* staggered multi-bss beacons */ | ||
1968 | if (intval < 15) | ||
1969 | ATH5K_WARN(sc, "intval %u is too low, min 15\n", | ||
1970 | intval); | ||
1971 | } | ||
2419 | if (WARN_ON(!intval)) | 1972 | if (WARN_ON(!intval)) |
2420 | return; | 1973 | return; |
2421 | 1974 | ||
@@ -2426,8 +1979,11 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | |||
2426 | hw_tsf = ath5k_hw_get_tsf64(ah); | 1979 | hw_tsf = ath5k_hw_get_tsf64(ah); |
2427 | hw_tu = TSF_TO_TU(hw_tsf); | 1980 | hw_tu = TSF_TO_TU(hw_tsf); |
2428 | 1981 | ||
2429 | #define FUDGE 3 | 1982 | #define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3 |
2430 | /* we use FUDGE to make sure the next TBTT is ahead of the current TU */ | 1983 | /* We use FUDGE to make sure the next TBTT is ahead of the current TU. |
1984 | * Since we later subtract AR5K_TUNE_SW_BEACON_RESP (10) in the timer | ||
1985 | * configuration we need to make sure it is bigger than that. */ | ||
1986 | |||
2431 | if (bc_tsf == -1) { | 1987 | if (bc_tsf == -1) { |
2432 | /* | 1988 | /* |
2433 | * no beacons received, called internally. | 1989 | * no beacons received, called internally. |
@@ -2443,7 +1999,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | |||
2443 | intval |= AR5K_BEACON_RESET_TSF; | 1999 | intval |= AR5K_BEACON_RESET_TSF; |
2444 | } else if (bc_tsf > hw_tsf) { | 2000 | } else if (bc_tsf > hw_tsf) { |
2445 | /* | 2001 | /* |
2446 | * beacon received, SW merge happend but HW TSF not yet updated. | 2002 | * beacon received, SW merge happened but HW TSF not yet updated. |
2447 | * not possible to reconfigure timers yet, but next time we | 2003 | * not possible to reconfigure timers yet, but next time we |
2448 | * receive a beacon with the same BSSID, the hardware will | 2004 | * receive a beacon with the same BSSID, the hardware will |
2449 | * automatically update the TSF and then we need to reconfigure | 2005 | * automatically update the TSF and then we need to reconfigure |
@@ -2493,7 +2049,6 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | |||
2493 | intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : ""); | 2049 | intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : ""); |
2494 | } | 2050 | } |
2495 | 2051 | ||
2496 | |||
2497 | /** | 2052 | /** |
2498 | * ath5k_beacon_config - Configure the beacon queues and interrupts | 2053 | * ath5k_beacon_config - Configure the beacon queues and interrupts |
2499 | * | 2054 | * |
@@ -2502,7 +2057,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) | |||
2502 | * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA | 2057 | * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA |
2503 | * interrupts to detect TSF updates only. | 2058 | * interrupts to detect TSF updates only. |
2504 | */ | 2059 | */ |
2505 | static void | 2060 | void |
2506 | ath5k_beacon_config(struct ath5k_softc *sc) | 2061 | ath5k_beacon_config(struct ath5k_softc *sc) |
2507 | { | 2062 | { |
2508 | struct ath5k_hw *ah = sc->ah; | 2063 | struct ath5k_hw *ah = sc->ah; |
@@ -2530,7 +2085,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2530 | } else | 2085 | } else |
2531 | ath5k_beacon_update_timers(sc, -1); | 2086 | ath5k_beacon_update_timers(sc, -1); |
2532 | } else { | 2087 | } else { |
2533 | ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq); | 2088 | ath5k_hw_stop_beacon_queue(sc->ah, sc->bhalq); |
2534 | } | 2089 | } |
2535 | 2090 | ||
2536 | ath5k_hw_set_imr(ah, sc->imask); | 2091 | ath5k_hw_set_imr(ah, sc->imask); |
@@ -2572,155 +2127,6 @@ static void ath5k_tasklet_beacon(unsigned long data) | |||
2572 | * Interrupt handling * | 2127 | * Interrupt handling * |
2573 | \********************/ | 2128 | \********************/ |
2574 | 2129 | ||
2575 | static int | ||
2576 | ath5k_init(struct ath5k_softc *sc) | ||
2577 | { | ||
2578 | struct ath5k_hw *ah = sc->ah; | ||
2579 | int ret, i; | ||
2580 | |||
2581 | mutex_lock(&sc->lock); | ||
2582 | |||
2583 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); | ||
2584 | |||
2585 | /* | ||
2586 | * Stop anything previously setup. This is safe | ||
2587 | * no matter this is the first time through or not. | ||
2588 | */ | ||
2589 | ath5k_stop_locked(sc); | ||
2590 | |||
2591 | /* | ||
2592 | * The basic interface to setting the hardware in a good | ||
2593 | * state is ``reset''. On return the hardware is known to | ||
2594 | * be powered up and with interrupts disabled. This must | ||
2595 | * be followed by initialization of the appropriate bits | ||
2596 | * and then setup of the interrupt mask. | ||
2597 | */ | ||
2598 | sc->curchan = sc->hw->conf.channel; | ||
2599 | sc->curband = &sc->sbands[sc->curchan->band]; | ||
2600 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | ||
2601 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | ||
2602 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; | ||
2603 | |||
2604 | ret = ath5k_reset(sc, NULL); | ||
2605 | if (ret) | ||
2606 | goto done; | ||
2607 | |||
2608 | ath5k_rfkill_hw_start(ah); | ||
2609 | |||
2610 | /* | ||
2611 | * Reset the key cache since some parts do not reset the | ||
2612 | * contents on initial power up or resume from suspend. | ||
2613 | */ | ||
2614 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) | ||
2615 | ath5k_hw_reset_key(ah, i); | ||
2616 | |||
2617 | ath5k_hw_set_ack_bitrate_high(ah, true); | ||
2618 | ret = 0; | ||
2619 | done: | ||
2620 | mmiowb(); | ||
2621 | mutex_unlock(&sc->lock); | ||
2622 | return ret; | ||
2623 | } | ||
2624 | |||
2625 | static int | ||
2626 | ath5k_stop_locked(struct ath5k_softc *sc) | ||
2627 | { | ||
2628 | struct ath5k_hw *ah = sc->ah; | ||
2629 | |||
2630 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n", | ||
2631 | test_bit(ATH_STAT_INVALID, sc->status)); | ||
2632 | |||
2633 | /* | ||
2634 | * Shutdown the hardware and driver: | ||
2635 | * stop output from above | ||
2636 | * disable interrupts | ||
2637 | * turn off timers | ||
2638 | * turn off the radio | ||
2639 | * clear transmit machinery | ||
2640 | * clear receive machinery | ||
2641 | * drain and release tx queues | ||
2642 | * reclaim beacon resources | ||
2643 | * power down hardware | ||
2644 | * | ||
2645 | * Note that some of this work is not possible if the | ||
2646 | * hardware is gone (invalid). | ||
2647 | */ | ||
2648 | ieee80211_stop_queues(sc->hw); | ||
2649 | |||
2650 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2651 | ath5k_led_off(sc); | ||
2652 | ath5k_hw_set_imr(ah, 0); | ||
2653 | synchronize_irq(sc->pdev->irq); | ||
2654 | } | ||
2655 | ath5k_txq_cleanup(sc); | ||
2656 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2657 | ath5k_rx_stop(sc); | ||
2658 | ath5k_hw_phy_disable(ah); | ||
2659 | } | ||
2660 | |||
2661 | return 0; | ||
2662 | } | ||
2663 | |||
2664 | static void stop_tasklets(struct ath5k_softc *sc) | ||
2665 | { | ||
2666 | tasklet_kill(&sc->rxtq); | ||
2667 | tasklet_kill(&sc->txtq); | ||
2668 | tasklet_kill(&sc->calib); | ||
2669 | tasklet_kill(&sc->beacontq); | ||
2670 | tasklet_kill(&sc->ani_tasklet); | ||
2671 | } | ||
2672 | |||
2673 | /* | ||
2674 | * Stop the device, grabbing the top-level lock to protect | ||
2675 | * against concurrent entry through ath5k_init (which can happen | ||
2676 | * if another thread does a system call and the thread doing the | ||
2677 | * stop is preempted). | ||
2678 | */ | ||
2679 | static int | ||
2680 | ath5k_stop_hw(struct ath5k_softc *sc) | ||
2681 | { | ||
2682 | int ret; | ||
2683 | |||
2684 | mutex_lock(&sc->lock); | ||
2685 | ret = ath5k_stop_locked(sc); | ||
2686 | if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2687 | /* | ||
2688 | * Don't set the card in full sleep mode! | ||
2689 | * | ||
2690 | * a) When the device is in this state it must be carefully | ||
2691 | * woken up or references to registers in the PCI clock | ||
2692 | * domain may freeze the bus (and system). This varies | ||
2693 | * by chip and is mostly an issue with newer parts | ||
2694 | * (madwifi sources mentioned srev >= 0x78) that go to | ||
2695 | * sleep more quickly. | ||
2696 | * | ||
2697 | * b) On older chips full sleep results a weird behaviour | ||
2698 | * during wakeup. I tested various cards with srev < 0x78 | ||
2699 | * and they don't wake up after module reload, a second | ||
2700 | * module reload is needed to bring the card up again. | ||
2701 | * | ||
2702 | * Until we figure out what's going on don't enable | ||
2703 | * full chip reset on any chip (this is what Legacy HAL | ||
2704 | * and Sam's HAL do anyway). Instead Perform a full reset | ||
2705 | * on the device (same as initial state after attach) and | ||
2706 | * leave it idle (keep MAC/BB on warm reset) */ | ||
2707 | ret = ath5k_hw_on_hold(sc->ah); | ||
2708 | |||
2709 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, | ||
2710 | "putting device to sleep\n"); | ||
2711 | } | ||
2712 | ath5k_txbuf_free_skb(sc, sc->bbuf); | ||
2713 | |||
2714 | mmiowb(); | ||
2715 | mutex_unlock(&sc->lock); | ||
2716 | |||
2717 | stop_tasklets(sc); | ||
2718 | |||
2719 | ath5k_rfkill_hw_stop(sc->ah); | ||
2720 | |||
2721 | return ret; | ||
2722 | } | ||
2723 | |||
2724 | static void | 2130 | static void |
2725 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) | 2131 | ath5k_intr_calibration_poll(struct ath5k_hw *ah) |
2726 | { | 2132 | { |
@@ -2741,7 +2147,21 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah) | |||
2741 | * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ | 2147 | * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ |
2742 | } | 2148 | } |
2743 | 2149 | ||
2744 | static irqreturn_t | 2150 | static void |
2151 | ath5k_schedule_rx(struct ath5k_softc *sc) | ||
2152 | { | ||
2153 | sc->rx_pending = true; | ||
2154 | tasklet_schedule(&sc->rxtq); | ||
2155 | } | ||
2156 | |||
2157 | static void | ||
2158 | ath5k_schedule_tx(struct ath5k_softc *sc) | ||
2159 | { | ||
2160 | sc->tx_pending = true; | ||
2161 | tasklet_schedule(&sc->txtq); | ||
2162 | } | ||
2163 | |||
2164 | irqreturn_t | ||
2745 | ath5k_intr(int irq, void *dev_id) | 2165 | ath5k_intr(int irq, void *dev_id) |
2746 | { | 2166 | { |
2747 | struct ath5k_softc *sc = dev_id; | 2167 | struct ath5k_softc *sc = dev_id; |
@@ -2750,7 +2170,8 @@ ath5k_intr(int irq, void *dev_id) | |||
2750 | unsigned int counter = 1000; | 2170 | unsigned int counter = 1000; |
2751 | 2171 | ||
2752 | if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || | 2172 | if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || |
2753 | !ath5k_hw_is_intr_pending(ah))) | 2173 | ((ath5k_get_bus_type(ah) != ATH_AHB) && |
2174 | !ath5k_hw_is_intr_pending(ah)))) | ||
2754 | return IRQ_NONE; | 2175 | return IRQ_NONE; |
2755 | 2176 | ||
2756 | do { | 2177 | do { |
@@ -2782,7 +2203,7 @@ ath5k_intr(int irq, void *dev_id) | |||
2782 | ieee80211_queue_work(sc->hw, &sc->reset_work); | 2203 | ieee80211_queue_work(sc->hw, &sc->reset_work); |
2783 | } | 2204 | } |
2784 | else | 2205 | else |
2785 | tasklet_schedule(&sc->rxtq); | 2206 | ath5k_schedule_rx(sc); |
2786 | } else { | 2207 | } else { |
2787 | if (status & AR5K_INT_SWBA) { | 2208 | if (status & AR5K_INT_SWBA) { |
2788 | tasklet_hi_schedule(&sc->beacontq); | 2209 | tasklet_hi_schedule(&sc->beacontq); |
@@ -2800,10 +2221,10 @@ ath5k_intr(int irq, void *dev_id) | |||
2800 | ath5k_hw_update_tx_triglevel(ah, true); | 2221 | ath5k_hw_update_tx_triglevel(ah, true); |
2801 | } | 2222 | } |
2802 | if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) | 2223 | if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) |
2803 | tasklet_schedule(&sc->rxtq); | 2224 | ath5k_schedule_rx(sc); |
2804 | if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC | 2225 | if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC |
2805 | | AR5K_INT_TXERR | AR5K_INT_TXEOL)) | 2226 | | AR5K_INT_TXERR | AR5K_INT_TXEOL)) |
2806 | tasklet_schedule(&sc->txtq); | 2227 | ath5k_schedule_tx(sc); |
2807 | if (status & AR5K_INT_BMISS) { | 2228 | if (status & AR5K_INT_BMISS) { |
2808 | /* TODO */ | 2229 | /* TODO */ |
2809 | } | 2230 | } |
@@ -2816,8 +2237,15 @@ ath5k_intr(int irq, void *dev_id) | |||
2816 | tasklet_schedule(&sc->rf_kill.toggleq); | 2237 | tasklet_schedule(&sc->rf_kill.toggleq); |
2817 | 2238 | ||
2818 | } | 2239 | } |
2240 | |||
2241 | if (ath5k_get_bus_type(ah) == ATH_AHB) | ||
2242 | break; | ||
2243 | |||
2819 | } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); | 2244 | } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); |
2820 | 2245 | ||
2246 | if (sc->rx_pending || sc->tx_pending) | ||
2247 | ath5k_set_current_imask(sc); | ||
2248 | |||
2821 | if (unlikely(!counter)) | 2249 | if (unlikely(!counter)) |
2822 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); | 2250 | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); |
2823 | 2251 | ||
@@ -2857,14 +2285,13 @@ ath5k_tasklet_calibrate(unsigned long data) | |||
2857 | sc->curchan->center_freq)); | 2285 | sc->curchan->center_freq)); |
2858 | 2286 | ||
2859 | /* Noise floor calibration interrupts rx/tx path while I/Q calibration | 2287 | /* Noise floor calibration interrupts rx/tx path while I/Q calibration |
2860 | * doesn't. We stop the queues so that calibration doesn't interfere | 2288 | * doesn't. |
2861 | * with TX and don't run it as often */ | 2289 | * TODO: We should stop TX here, so that it doesn't interfere. |
2290 | * Note that stopping the queues is not enough to stop TX! */ | ||
2862 | if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) { | 2291 | if (time_is_before_eq_jiffies(ah->ah_cal_next_nf)) { |
2863 | ah->ah_cal_next_nf = jiffies + | 2292 | ah->ah_cal_next_nf = jiffies + |
2864 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF); | 2293 | msecs_to_jiffies(ATH5K_TUNE_CALIBRATION_INTERVAL_NF); |
2865 | ieee80211_stop_queues(sc->hw); | ||
2866 | ath5k_hw_update_noise_floor(ah); | 2294 | ath5k_hw_update_noise_floor(ah); |
2867 | ieee80211_wake_queues(sc->hw); | ||
2868 | } | 2295 | } |
2869 | 2296 | ||
2870 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; | 2297 | ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL; |
@@ -2883,570 +2310,676 @@ ath5k_tasklet_ani(unsigned long data) | |||
2883 | } | 2310 | } |
2884 | 2311 | ||
2885 | 2312 | ||
2886 | /********************\ | 2313 | static void |
2887 | * Mac80211 functions * | 2314 | ath5k_tx_complete_poll_work(struct work_struct *work) |
2888 | \********************/ | ||
2889 | |||
2890 | static int | ||
2891 | ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
2892 | { | ||
2893 | struct ath5k_softc *sc = hw->priv; | ||
2894 | |||
2895 | return ath5k_tx_queue(hw, skb, sc->txq); | ||
2896 | } | ||
2897 | |||
2898 | static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
2899 | struct ath5k_txq *txq) | ||
2900 | { | 2315 | { |
2901 | struct ath5k_softc *sc = hw->priv; | 2316 | struct ath5k_softc *sc = container_of(work, struct ath5k_softc, |
2902 | struct ath5k_buf *bf; | 2317 | tx_complete_work.work); |
2903 | unsigned long flags; | 2318 | struct ath5k_txq *txq; |
2904 | int padsize; | 2319 | int i; |
2905 | 2320 | bool needreset = false; | |
2906 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | ||
2907 | 2321 | ||
2908 | if (sc->opmode == NL80211_IFTYPE_MONITOR) | 2322 | mutex_lock(&sc->lock); |
2909 | ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); | ||
2910 | 2323 | ||
2911 | /* | 2324 | for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) { |
2912 | * the hardware expects the header padded to 4 byte boundaries | 2325 | if (sc->txqs[i].setup) { |
2913 | * if this is not the case we add the padding after the header | 2326 | txq = &sc->txqs[i]; |
2914 | */ | 2327 | spin_lock_bh(&txq->lock); |
2915 | padsize = ath5k_add_padding(skb); | 2328 | if (txq->txq_len > 1) { |
2916 | if (padsize < 0) { | 2329 | if (txq->txq_poll_mark) { |
2917 | ATH5K_ERR(sc, "tx hdrlen not %%4: not enough" | 2330 | ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, |
2918 | " headroom to pad"); | 2331 | "TX queue stuck %d\n", |
2919 | goto drop_packet; | 2332 | txq->qnum); |
2333 | needreset = true; | ||
2334 | txq->txq_stuck++; | ||
2335 | spin_unlock_bh(&txq->lock); | ||
2336 | break; | ||
2337 | } else { | ||
2338 | txq->txq_poll_mark = true; | ||
2339 | } | ||
2340 | } | ||
2341 | spin_unlock_bh(&txq->lock); | ||
2342 | } | ||
2920 | } | 2343 | } |
2921 | 2344 | ||
2922 | spin_lock_irqsave(&sc->txbuflock, flags); | 2345 | if (needreset) { |
2923 | if (list_empty(&sc->txbuf)) { | 2346 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
2924 | ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); | 2347 | "TX queues stuck, resetting\n"); |
2925 | spin_unlock_irqrestore(&sc->txbuflock, flags); | 2348 | ath5k_reset(sc, NULL, true); |
2926 | ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); | ||
2927 | goto drop_packet; | ||
2928 | } | 2349 | } |
2929 | bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); | ||
2930 | list_del(&bf->list); | ||
2931 | sc->txbuf_len--; | ||
2932 | if (list_empty(&sc->txbuf)) | ||
2933 | ieee80211_stop_queues(hw); | ||
2934 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
2935 | |||
2936 | bf->skb = skb; | ||
2937 | 2350 | ||
2938 | if (ath5k_txbuf_setup(sc, bf, txq, padsize)) { | 2351 | mutex_unlock(&sc->lock); |
2939 | bf->skb = NULL; | ||
2940 | spin_lock_irqsave(&sc->txbuflock, flags); | ||
2941 | list_add_tail(&bf->list, &sc->txbuf); | ||
2942 | sc->txbuf_len++; | ||
2943 | spin_unlock_irqrestore(&sc->txbuflock, flags); | ||
2944 | goto drop_packet; | ||
2945 | } | ||
2946 | return NETDEV_TX_OK; | ||
2947 | 2352 | ||
2948 | drop_packet: | 2353 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, |
2949 | dev_kfree_skb_any(skb); | 2354 | msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); |
2950 | return NETDEV_TX_OK; | ||
2951 | } | 2355 | } |
2952 | 2356 | ||
2953 | /* | 2357 | |
2954 | * Reset the hardware. If chan is not NULL, then also pause rx/tx | 2358 | /*************************\ |
2955 | * and change to the given channel. | 2359 | * Initialization routines * |
2956 | * | 2360 | \*************************/ |
2957 | * This should be called with sc->lock. | 2361 | |
2958 | */ | 2362 | int |
2959 | static int | 2363 | ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) |
2960 | ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) | ||
2961 | { | 2364 | { |
2962 | struct ath5k_hw *ah = sc->ah; | 2365 | struct ieee80211_hw *hw = sc->hw; |
2366 | struct ath_common *common; | ||
2963 | int ret; | 2367 | int ret; |
2368 | int csz; | ||
2964 | 2369 | ||
2965 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); | 2370 | /* Initialize driver private data */ |
2371 | SET_IEEE80211_DEV(hw, sc->dev); | ||
2372 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | ||
2373 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | ||
2374 | IEEE80211_HW_SIGNAL_DBM | | ||
2375 | IEEE80211_HW_REPORTS_TX_ACK_STATUS; | ||
2966 | 2376 | ||
2967 | ath5k_hw_set_imr(ah, 0); | 2377 | hw->wiphy->interface_modes = |
2968 | synchronize_irq(sc->pdev->irq); | 2378 | BIT(NL80211_IFTYPE_AP) | |
2969 | stop_tasklets(sc); | 2379 | BIT(NL80211_IFTYPE_STATION) | |
2380 | BIT(NL80211_IFTYPE_ADHOC) | | ||
2381 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
2970 | 2382 | ||
2971 | if (chan) { | 2383 | /* both antennas can be configured as RX or TX */ |
2972 | ath5k_txq_cleanup(sc); | 2384 | hw->wiphy->available_antennas_tx = 0x3; |
2973 | ath5k_rx_stop(sc); | 2385 | hw->wiphy->available_antennas_rx = 0x3; |
2974 | 2386 | ||
2975 | sc->curchan = chan; | 2387 | hw->extra_tx_headroom = 2; |
2976 | sc->curband = &sc->sbands[chan->band]; | 2388 | hw->channel_change_time = 5000; |
2977 | } | ||
2978 | ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL); | ||
2979 | if (ret) { | ||
2980 | ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); | ||
2981 | goto err; | ||
2982 | } | ||
2983 | 2389 | ||
2984 | ret = ath5k_rx_start(sc); | 2390 | /* |
2391 | * Mark the device as detached to avoid processing | ||
2392 | * interrupts until setup is complete. | ||
2393 | */ | ||
2394 | __set_bit(ATH_STAT_INVALID, sc->status); | ||
2395 | |||
2396 | sc->opmode = NL80211_IFTYPE_STATION; | ||
2397 | sc->bintval = 1000; | ||
2398 | mutex_init(&sc->lock); | ||
2399 | spin_lock_init(&sc->rxbuflock); | ||
2400 | spin_lock_init(&sc->txbuflock); | ||
2401 | spin_lock_init(&sc->block); | ||
2402 | spin_lock_init(&sc->irqlock); | ||
2403 | |||
2404 | /* Setup interrupt handler */ | ||
2405 | ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc); | ||
2985 | if (ret) { | 2406 | if (ret) { |
2986 | ATH5K_ERR(sc, "can't start recv logic\n"); | 2407 | ATH5K_ERR(sc, "request_irq failed\n"); |
2987 | goto err; | 2408 | goto err; |
2988 | } | 2409 | } |
2989 | 2410 | ||
2990 | ath5k_ani_init(ah, ah->ah_sc->ani_state.ani_mode); | 2411 | /* If we passed the test, malloc an ath5k_hw struct */ |
2412 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | ||
2413 | if (!sc->ah) { | ||
2414 | ret = -ENOMEM; | ||
2415 | ATH5K_ERR(sc, "out of memory\n"); | ||
2416 | goto err_irq; | ||
2417 | } | ||
2991 | 2418 | ||
2992 | ah->ah_cal_next_full = jiffies; | 2419 | sc->ah->ah_sc = sc; |
2993 | ah->ah_cal_next_ani = jiffies; | 2420 | sc->ah->ah_iobase = sc->iobase; |
2994 | ah->ah_cal_next_nf = jiffies; | 2421 | common = ath5k_hw_common(sc->ah); |
2422 | common->ops = &ath5k_common_ops; | ||
2423 | common->bus_ops = bus_ops; | ||
2424 | common->ah = sc->ah; | ||
2425 | common->hw = hw; | ||
2426 | common->priv = sc; | ||
2995 | 2427 | ||
2996 | /* | 2428 | /* |
2997 | * Change channels and update the h/w rate map if we're switching; | 2429 | * Cache line size is used to size and align various |
2998 | * e.g. 11a to 11b/g. | 2430 | * structures used to communicate with the hardware. |
2999 | * | ||
3000 | * We may be doing a reset in response to an ioctl that changes the | ||
3001 | * channel so update any state that might change as a result. | ||
3002 | * | ||
3003 | * XXX needed? | ||
3004 | */ | 2431 | */ |
3005 | /* ath5k_chan_change(sc, c); */ | 2432 | ath5k_read_cachesize(common, &csz); |
2433 | common->cachelsz = csz << 2; /* convert to bytes */ | ||
3006 | 2434 | ||
3007 | ath5k_beacon_config(sc); | 2435 | spin_lock_init(&common->cc_lock); |
3008 | /* intrs are enabled by ath5k_beacon_config */ | ||
3009 | 2436 | ||
3010 | ieee80211_wake_queues(sc->hw); | 2437 | /* Initialize device */ |
2438 | ret = ath5k_hw_init(sc); | ||
2439 | if (ret) | ||
2440 | goto err_free_ah; | ||
2441 | |||
2442 | /* set up multi-rate retry capabilities */ | ||
2443 | if (sc->ah->ah_version == AR5K_AR5212) { | ||
2444 | hw->max_rates = 4; | ||
2445 | hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT, | ||
2446 | AR5K_INIT_RETRY_LONG); | ||
2447 | } | ||
2448 | |||
2449 | hw->vif_data_size = sizeof(struct ath5k_vif); | ||
2450 | |||
2451 | /* Finish private driver data initialization */ | ||
2452 | ret = ath5k_init(hw); | ||
2453 | if (ret) | ||
2454 | goto err_ah; | ||
2455 | |||
2456 | ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", | ||
2457 | ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), | ||
2458 | sc->ah->ah_mac_srev, | ||
2459 | sc->ah->ah_phy_revision); | ||
2460 | |||
2461 | if (!sc->ah->ah_single_chip) { | ||
2462 | /* Single chip radio (!RF5111) */ | ||
2463 | if (sc->ah->ah_radio_5ghz_revision && | ||
2464 | !sc->ah->ah_radio_2ghz_revision) { | ||
2465 | /* No 5GHz support -> report 2GHz radio */ | ||
2466 | if (!test_bit(AR5K_MODE_11A, | ||
2467 | sc->ah->ah_capabilities.cap_mode)) { | ||
2468 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
2469 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
2470 | sc->ah->ah_radio_5ghz_revision), | ||
2471 | sc->ah->ah_radio_5ghz_revision); | ||
2472 | /* No 2GHz support (5110 and some | ||
2473 | * 5Ghz only cards) -> report 5Ghz radio */ | ||
2474 | } else if (!test_bit(AR5K_MODE_11B, | ||
2475 | sc->ah->ah_capabilities.cap_mode)) { | ||
2476 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
2477 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
2478 | sc->ah->ah_radio_5ghz_revision), | ||
2479 | sc->ah->ah_radio_5ghz_revision); | ||
2480 | /* Multiband radio */ | ||
2481 | } else { | ||
2482 | ATH5K_INFO(sc, "RF%s multiband radio found" | ||
2483 | " (0x%x)\n", | ||
2484 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
2485 | sc->ah->ah_radio_5ghz_revision), | ||
2486 | sc->ah->ah_radio_5ghz_revision); | ||
2487 | } | ||
2488 | } | ||
2489 | /* Multi chip radio (RF5111 - RF2111) -> | ||
2490 | * report both 2GHz/5GHz radios */ | ||
2491 | else if (sc->ah->ah_radio_5ghz_revision && | ||
2492 | sc->ah->ah_radio_2ghz_revision){ | ||
2493 | ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", | ||
2494 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
2495 | sc->ah->ah_radio_5ghz_revision), | ||
2496 | sc->ah->ah_radio_5ghz_revision); | ||
2497 | ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", | ||
2498 | ath5k_chip_name(AR5K_VERSION_RAD, | ||
2499 | sc->ah->ah_radio_2ghz_revision), | ||
2500 | sc->ah->ah_radio_2ghz_revision); | ||
2501 | } | ||
2502 | } | ||
2503 | |||
2504 | ath5k_debug_init_device(sc); | ||
2505 | |||
2506 | /* ready to process interrupts */ | ||
2507 | __clear_bit(ATH_STAT_INVALID, sc->status); | ||
3011 | 2508 | ||
3012 | return 0; | 2509 | return 0; |
2510 | err_ah: | ||
2511 | ath5k_hw_deinit(sc->ah); | ||
2512 | err_free_ah: | ||
2513 | kfree(sc->ah); | ||
2514 | err_irq: | ||
2515 | free_irq(sc->irq, sc); | ||
3013 | err: | 2516 | err: |
3014 | return ret; | 2517 | return ret; |
3015 | } | 2518 | } |
3016 | 2519 | ||
3017 | static void ath5k_reset_work(struct work_struct *work) | 2520 | static int |
2521 | ath5k_stop_locked(struct ath5k_softc *sc) | ||
3018 | { | 2522 | { |
3019 | struct ath5k_softc *sc = container_of(work, struct ath5k_softc, | 2523 | struct ath5k_hw *ah = sc->ah; |
3020 | reset_work); | ||
3021 | 2524 | ||
3022 | mutex_lock(&sc->lock); | 2525 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n", |
3023 | ath5k_reset(sc, sc->curchan); | 2526 | test_bit(ATH_STAT_INVALID, sc->status)); |
3024 | mutex_unlock(&sc->lock); | ||
3025 | } | ||
3026 | 2527 | ||
3027 | static int ath5k_start(struct ieee80211_hw *hw) | 2528 | /* |
3028 | { | 2529 | * Shutdown the hardware and driver: |
3029 | return ath5k_init(hw->priv); | 2530 | * stop output from above |
3030 | } | 2531 | * disable interrupts |
2532 | * turn off timers | ||
2533 | * turn off the radio | ||
2534 | * clear transmit machinery | ||
2535 | * clear receive machinery | ||
2536 | * drain and release tx queues | ||
2537 | * reclaim beacon resources | ||
2538 | * power down hardware | ||
2539 | * | ||
2540 | * Note that some of this work is not possible if the | ||
2541 | * hardware is gone (invalid). | ||
2542 | */ | ||
2543 | ieee80211_stop_queues(sc->hw); | ||
3031 | 2544 | ||
3032 | static void ath5k_stop(struct ieee80211_hw *hw) | 2545 | if (!test_bit(ATH_STAT_INVALID, sc->status)) { |
3033 | { | 2546 | ath5k_led_off(sc); |
3034 | ath5k_stop_hw(hw->priv); | 2547 | ath5k_hw_set_imr(ah, 0); |
2548 | synchronize_irq(sc->irq); | ||
2549 | ath5k_rx_stop(sc); | ||
2550 | ath5k_hw_dma_stop(ah); | ||
2551 | ath5k_drain_tx_buffs(sc); | ||
2552 | ath5k_hw_phy_disable(ah); | ||
2553 | } | ||
2554 | |||
2555 | return 0; | ||
3035 | } | 2556 | } |
3036 | 2557 | ||
3037 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 2558 | int |
3038 | struct ieee80211_vif *vif) | 2559 | ath5k_init_hw(struct ath5k_softc *sc) |
3039 | { | 2560 | { |
3040 | struct ath5k_softc *sc = hw->priv; | 2561 | struct ath5k_hw *ah = sc->ah; |
3041 | int ret; | 2562 | struct ath_common *common = ath5k_hw_common(ah); |
2563 | int ret, i; | ||
3042 | 2564 | ||
3043 | mutex_lock(&sc->lock); | 2565 | mutex_lock(&sc->lock); |
3044 | if (sc->vif) { | ||
3045 | ret = 0; | ||
3046 | goto end; | ||
3047 | } | ||
3048 | 2566 | ||
3049 | sc->vif = vif; | 2567 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); |
3050 | 2568 | ||
3051 | switch (vif->type) { | 2569 | /* |
3052 | case NL80211_IFTYPE_AP: | 2570 | * Stop anything previously setup. This is safe |
3053 | case NL80211_IFTYPE_STATION: | 2571 | * no matter this is the first time through or not. |
3054 | case NL80211_IFTYPE_ADHOC: | 2572 | */ |
3055 | case NL80211_IFTYPE_MESH_POINT: | 2573 | ath5k_stop_locked(sc); |
3056 | case NL80211_IFTYPE_MONITOR: | 2574 | |
3057 | sc->opmode = vif->type; | 2575 | /* |
3058 | break; | 2576 | * The basic interface to setting the hardware in a good |
3059 | default: | 2577 | * state is ``reset''. On return the hardware is known to |
3060 | ret = -EOPNOTSUPP; | 2578 | * be powered up and with interrupts disabled. This must |
3061 | goto end; | 2579 | * be followed by initialization of the appropriate bits |
3062 | } | 2580 | * and then setup of the interrupt mask. |
2581 | */ | ||
2582 | sc->curchan = sc->hw->conf.channel; | ||
2583 | sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | | ||
2584 | AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | | ||
2585 | AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB; | ||
3063 | 2586 | ||
3064 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", sc->opmode); | 2587 | ret = ath5k_reset(sc, NULL, false); |
2588 | if (ret) | ||
2589 | goto done; | ||
3065 | 2590 | ||
3066 | ath5k_hw_set_lladdr(sc->ah, vif->addr); | 2591 | ath5k_rfkill_hw_start(ah); |
3067 | ath5k_mode_setup(sc); | 2592 | |
2593 | /* | ||
2594 | * Reset the key cache since some parts do not reset the | ||
2595 | * contents on initial power up or resume from suspend. | ||
2596 | */ | ||
2597 | for (i = 0; i < common->keymax; i++) | ||
2598 | ath_hw_keyreset(common, (u16) i); | ||
2599 | |||
2600 | /* Use higher rates for acks instead of base | ||
2601 | * rate */ | ||
2602 | ah->ah_ack_bitrate_high = true; | ||
2603 | |||
2604 | for (i = 0; i < ARRAY_SIZE(sc->bslot); i++) | ||
2605 | sc->bslot[i] = NULL; | ||
3068 | 2606 | ||
3069 | ret = 0; | 2607 | ret = 0; |
3070 | end: | 2608 | done: |
2609 | mmiowb(); | ||
3071 | mutex_unlock(&sc->lock); | 2610 | mutex_unlock(&sc->lock); |
2611 | |||
2612 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, | ||
2613 | msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT)); | ||
2614 | |||
3072 | return ret; | 2615 | return ret; |
3073 | } | 2616 | } |
3074 | 2617 | ||
3075 | static void | 2618 | static void stop_tasklets(struct ath5k_softc *sc) |
3076 | ath5k_remove_interface(struct ieee80211_hw *hw, | ||
3077 | struct ieee80211_vif *vif) | ||
3078 | { | 2619 | { |
3079 | struct ath5k_softc *sc = hw->priv; | 2620 | sc->rx_pending = false; |
3080 | u8 mac[ETH_ALEN] = {}; | 2621 | sc->tx_pending = false; |
3081 | 2622 | tasklet_kill(&sc->rxtq); | |
3082 | mutex_lock(&sc->lock); | 2623 | tasklet_kill(&sc->txtq); |
3083 | if (sc->vif != vif) | 2624 | tasklet_kill(&sc->calib); |
3084 | goto end; | 2625 | tasklet_kill(&sc->beacontq); |
3085 | 2626 | tasklet_kill(&sc->ani_tasklet); | |
3086 | ath5k_hw_set_lladdr(sc->ah, mac); | ||
3087 | sc->vif = NULL; | ||
3088 | end: | ||
3089 | mutex_unlock(&sc->lock); | ||
3090 | } | 2627 | } |
3091 | 2628 | ||
3092 | /* | 2629 | /* |
3093 | * TODO: Phy disable/diversity etc | 2630 | * Stop the device, grabbing the top-level lock to protect |
2631 | * against concurrent entry through ath5k_init (which can happen | ||
2632 | * if another thread does a system call and the thread doing the | ||
2633 | * stop is preempted). | ||
3094 | */ | 2634 | */ |
3095 | static int | 2635 | int |
3096 | ath5k_config(struct ieee80211_hw *hw, u32 changed) | 2636 | ath5k_stop_hw(struct ath5k_softc *sc) |
3097 | { | 2637 | { |
3098 | struct ath5k_softc *sc = hw->priv; | 2638 | int ret; |
3099 | struct ath5k_hw *ah = sc->ah; | ||
3100 | struct ieee80211_conf *conf = &hw->conf; | ||
3101 | int ret = 0; | ||
3102 | 2639 | ||
3103 | mutex_lock(&sc->lock); | 2640 | mutex_lock(&sc->lock); |
2641 | ret = ath5k_stop_locked(sc); | ||
2642 | if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { | ||
2643 | /* | ||
2644 | * Don't set the card in full sleep mode! | ||
2645 | * | ||
2646 | * a) When the device is in this state it must be carefully | ||
2647 | * woken up or references to registers in the PCI clock | ||
2648 | * domain may freeze the bus (and system). This varies | ||
2649 | * by chip and is mostly an issue with newer parts | ||
2650 | * (madwifi sources mentioned srev >= 0x78) that go to | ||
2651 | * sleep more quickly. | ||
2652 | * | ||
2653 | * b) On older chips full sleep results a weird behaviour | ||
2654 | * during wakeup. I tested various cards with srev < 0x78 | ||
2655 | * and they don't wake up after module reload, a second | ||
2656 | * module reload is needed to bring the card up again. | ||
2657 | * | ||
2658 | * Until we figure out what's going on don't enable | ||
2659 | * full chip reset on any chip (this is what Legacy HAL | ||
2660 | * and Sam's HAL do anyway). Instead Perform a full reset | ||
2661 | * on the device (same as initial state after attach) and | ||
2662 | * leave it idle (keep MAC/BB on warm reset) */ | ||
2663 | ret = ath5k_hw_on_hold(sc->ah); | ||
3104 | 2664 | ||
3105 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 2665 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, |
3106 | ret = ath5k_chan_set(sc, conf->channel); | 2666 | "putting device to sleep\n"); |
3107 | if (ret < 0) | ||
3108 | goto unlock; | ||
3109 | } | ||
3110 | |||
3111 | if ((changed & IEEE80211_CONF_CHANGE_POWER) && | ||
3112 | (sc->power_level != conf->power_level)) { | ||
3113 | sc->power_level = conf->power_level; | ||
3114 | |||
3115 | /* Half dB steps */ | ||
3116 | ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); | ||
3117 | } | 2667 | } |
3118 | 2668 | ||
3119 | /* TODO: | 2669 | mmiowb(); |
3120 | * 1) Move this on config_interface and handle each case | ||
3121 | * separately eg. when we have only one STA vif, use | ||
3122 | * AR5K_ANTMODE_SINGLE_AP | ||
3123 | * | ||
3124 | * 2) Allow the user to change antenna mode eg. when only | ||
3125 | * one antenna is present | ||
3126 | * | ||
3127 | * 3) Allow the user to set default/tx antenna when possible | ||
3128 | * | ||
3129 | * 4) Default mode should handle 90% of the cases, together | ||
3130 | * with fixed a/b and single AP modes we should be able to | ||
3131 | * handle 99%. Sectored modes are extreme cases and i still | ||
3132 | * haven't found a usage for them. If we decide to support them, | ||
3133 | * then we must allow the user to set how many tx antennas we | ||
3134 | * have available | ||
3135 | */ | ||
3136 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | ||
3137 | |||
3138 | unlock: | ||
3139 | mutex_unlock(&sc->lock); | 2670 | mutex_unlock(&sc->lock); |
3140 | return ret; | ||
3141 | } | ||
3142 | 2671 | ||
3143 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | 2672 | stop_tasklets(sc); |
3144 | struct netdev_hw_addr_list *mc_list) | ||
3145 | { | ||
3146 | u32 mfilt[2], val; | ||
3147 | u8 pos; | ||
3148 | struct netdev_hw_addr *ha; | ||
3149 | 2673 | ||
3150 | mfilt[0] = 0; | 2674 | cancel_delayed_work_sync(&sc->tx_complete_work); |
3151 | mfilt[1] = 1; | ||
3152 | 2675 | ||
3153 | netdev_hw_addr_list_for_each(ha, mc_list) { | 2676 | ath5k_rfkill_hw_stop(sc->ah); |
3154 | /* calculate XOR of eight 6-bit values */ | ||
3155 | val = get_unaligned_le32(ha->addr + 0); | ||
3156 | pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
3157 | val = get_unaligned_le32(ha->addr + 3); | ||
3158 | pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
3159 | pos &= 0x3f; | ||
3160 | mfilt[pos / 32] |= (1 << (pos % 32)); | ||
3161 | /* XXX: we might be able to just do this instead, | ||
3162 | * but not sure, needs testing, if we do use this we'd | ||
3163 | * neet to inform below to not reset the mcast */ | ||
3164 | /* ath5k_hw_set_mcast_filterindex(ah, | ||
3165 | * ha->addr[5]); */ | ||
3166 | } | ||
3167 | 2677 | ||
3168 | return ((u64)(mfilt[1]) << 32) | mfilt[0]; | 2678 | return ret; |
3169 | } | 2679 | } |
3170 | 2680 | ||
3171 | #define SUPPORTED_FIF_FLAGS \ | ||
3172 | FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ | ||
3173 | FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ | ||
3174 | FIF_BCN_PRBRESP_PROMISC | ||
3175 | /* | 2681 | /* |
3176 | * o always accept unicast, broadcast, and multicast traffic | 2682 | * Reset the hardware. If chan is not NULL, then also pause rx/tx |
3177 | * o multicast traffic for all BSSIDs will be enabled if mac80211 | 2683 | * and change to the given channel. |
3178 | * says it should be | 2684 | * |
3179 | * o maintain current state of phy ofdm or phy cck error reception. | 2685 | * This should be called with sc->lock. |
3180 | * If the hardware detects any of these type of errors then | ||
3181 | * ath5k_hw_get_rx_filter() will pass to us the respective | ||
3182 | * hardware filters to be able to receive these type of frames. | ||
3183 | * o probe request frames are accepted only when operating in | ||
3184 | * hostap, adhoc, or monitor modes | ||
3185 | * o enable promiscuous mode according to the interface state | ||
3186 | * o accept beacons: | ||
3187 | * - when operating in adhoc mode so the 802.11 layer creates | ||
3188 | * node table entries for peers, | ||
3189 | * - when operating in station mode for collecting rssi data when | ||
3190 | * the station is otherwise quiet, or | ||
3191 | * - when scanning | ||
3192 | */ | 2686 | */ |
3193 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | 2687 | static int |
3194 | unsigned int changed_flags, | 2688 | ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan, |
3195 | unsigned int *new_flags, | 2689 | bool skip_pcu) |
3196 | u64 multicast) | ||
3197 | { | 2690 | { |
3198 | struct ath5k_softc *sc = hw->priv; | ||
3199 | struct ath5k_hw *ah = sc->ah; | 2691 | struct ath5k_hw *ah = sc->ah; |
3200 | u32 mfilt[2], rfilt; | 2692 | struct ath_common *common = ath5k_hw_common(ah); |
2693 | int ret, ani_mode; | ||
2694 | bool fast; | ||
3201 | 2695 | ||
3202 | mutex_lock(&sc->lock); | 2696 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); |
3203 | 2697 | ||
3204 | mfilt[0] = multicast; | 2698 | ath5k_hw_set_imr(ah, 0); |
3205 | mfilt[1] = multicast >> 32; | 2699 | synchronize_irq(sc->irq); |
2700 | stop_tasklets(sc); | ||
3206 | 2701 | ||
3207 | /* Only deal with supported flags */ | 2702 | /* Save ani mode and disable ANI during |
3208 | changed_flags &= SUPPORTED_FIF_FLAGS; | 2703 | * reset. If we don't we might get false |
3209 | *new_flags &= SUPPORTED_FIF_FLAGS; | 2704 | * PHY error interrupts. */ |
2705 | ani_mode = ah->ah_sc->ani_state.ani_mode; | ||
2706 | ath5k_ani_init(ah, ATH5K_ANI_MODE_OFF); | ||
2707 | |||
2708 | /* We are going to empty hw queues | ||
2709 | * so we should also free any remaining | ||
2710 | * tx buffers */ | ||
2711 | ath5k_drain_tx_buffs(sc); | ||
2712 | if (chan) | ||
2713 | sc->curchan = chan; | ||
3210 | 2714 | ||
3211 | /* If HW detects any phy or radar errors, leave those filters on. | 2715 | fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0; |
3212 | * Also, always enable Unicast, Broadcasts and Multicast | ||
3213 | * XXX: move unicast, bssid broadcasts and multicast to mac80211 */ | ||
3214 | rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) | | ||
3215 | (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | | ||
3216 | AR5K_RX_FILTER_MCAST); | ||
3217 | 2716 | ||
3218 | if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { | 2717 | ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast, |
3219 | if (*new_flags & FIF_PROMISC_IN_BSS) { | 2718 | skip_pcu); |
3220 | __set_bit(ATH_STAT_PROMISC, sc->status); | 2719 | if (ret) { |
3221 | } else { | 2720 | ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); |
3222 | __clear_bit(ATH_STAT_PROMISC, sc->status); | 2721 | goto err; |
3223 | } | ||
3224 | } | 2722 | } |
3225 | 2723 | ||
3226 | if (test_bit(ATH_STAT_PROMISC, sc->status)) | 2724 | ret = ath5k_rx_start(sc); |
3227 | rfilt |= AR5K_RX_FILTER_PROM; | 2725 | if (ret) { |
3228 | 2726 | ATH5K_ERR(sc, "can't start recv logic\n"); | |
3229 | /* Note, AR5K_RX_FILTER_MCAST is already enabled */ | 2727 | goto err; |
3230 | if (*new_flags & FIF_ALLMULTI) { | ||
3231 | mfilt[0] = ~0; | ||
3232 | mfilt[1] = ~0; | ||
3233 | } | 2728 | } |
3234 | 2729 | ||
3235 | /* This is the best we can do */ | 2730 | ath5k_ani_init(ah, ani_mode); |
3236 | if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)) | ||
3237 | rfilt |= AR5K_RX_FILTER_PHYERR; | ||
3238 | 2731 | ||
3239 | /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons | 2732 | ah->ah_cal_next_full = jiffies; |
3240 | * and probes for any BSSID, this needs testing */ | 2733 | ah->ah_cal_next_ani = jiffies; |
3241 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) | 2734 | ah->ah_cal_next_nf = jiffies; |
3242 | rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ; | 2735 | ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8); |
3243 | 2736 | ||
3244 | /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not | 2737 | /* clear survey data and cycle counters */ |
3245 | * set we should only pass on control frames for this | 2738 | memset(&sc->survey, 0, sizeof(sc->survey)); |
3246 | * station. This needs testing. I believe right now this | 2739 | spin_lock_bh(&common->cc_lock); |
3247 | * enables *all* control frames, which is OK.. but | 2740 | ath_hw_cycle_counters_update(common); |
3248 | * but we should see if we can improve on granularity */ | 2741 | memset(&common->cc_survey, 0, sizeof(common->cc_survey)); |
3249 | if (*new_flags & FIF_CONTROL) | 2742 | memset(&common->cc_ani, 0, sizeof(common->cc_ani)); |
3250 | rfilt |= AR5K_RX_FILTER_CONTROL; | 2743 | spin_unlock_bh(&common->cc_lock); |
3251 | 2744 | ||
3252 | /* Additional settings per mode -- this is per ath5k */ | 2745 | /* |
2746 | * Change channels and update the h/w rate map if we're switching; | ||
2747 | * e.g. 11a to 11b/g. | ||
2748 | * | ||
2749 | * We may be doing a reset in response to an ioctl that changes the | ||
2750 | * channel so update any state that might change as a result. | ||
2751 | * | ||
2752 | * XXX needed? | ||
2753 | */ | ||
2754 | /* ath5k_chan_change(sc, c); */ | ||
3253 | 2755 | ||
3254 | /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ | 2756 | ath5k_beacon_config(sc); |
2757 | /* intrs are enabled by ath5k_beacon_config */ | ||
3255 | 2758 | ||
3256 | switch (sc->opmode) { | 2759 | ieee80211_wake_queues(sc->hw); |
3257 | case NL80211_IFTYPE_MESH_POINT: | ||
3258 | case NL80211_IFTYPE_MONITOR: | ||
3259 | rfilt |= AR5K_RX_FILTER_CONTROL | | ||
3260 | AR5K_RX_FILTER_BEACON | | ||
3261 | AR5K_RX_FILTER_PROBEREQ | | ||
3262 | AR5K_RX_FILTER_PROM; | ||
3263 | break; | ||
3264 | case NL80211_IFTYPE_AP: | ||
3265 | case NL80211_IFTYPE_ADHOC: | ||
3266 | rfilt |= AR5K_RX_FILTER_PROBEREQ | | ||
3267 | AR5K_RX_FILTER_BEACON; | ||
3268 | break; | ||
3269 | case NL80211_IFTYPE_STATION: | ||
3270 | if (sc->assoc) | ||
3271 | rfilt |= AR5K_RX_FILTER_BEACON; | ||
3272 | default: | ||
3273 | break; | ||
3274 | } | ||
3275 | 2760 | ||
3276 | /* Set filters */ | 2761 | return 0; |
3277 | ath5k_hw_set_rx_filter(ah, rfilt); | 2762 | err: |
2763 | return ret; | ||
2764 | } | ||
3278 | 2765 | ||
3279 | /* Set multicast bits */ | 2766 | static void ath5k_reset_work(struct work_struct *work) |
3280 | ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); | 2767 | { |
3281 | /* Set the cached hw filter flags, this will alter actually | 2768 | struct ath5k_softc *sc = container_of(work, struct ath5k_softc, |
3282 | * be set in HW */ | 2769 | reset_work); |
3283 | sc->filter_flags = rfilt; | ||
3284 | 2770 | ||
2771 | mutex_lock(&sc->lock); | ||
2772 | ath5k_reset(sc, NULL, true); | ||
3285 | mutex_unlock(&sc->lock); | 2773 | mutex_unlock(&sc->lock); |
3286 | } | 2774 | } |
3287 | 2775 | ||
3288 | static int | 2776 | static int |
3289 | ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 2777 | ath5k_init(struct ieee80211_hw *hw) |
3290 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | ||
3291 | struct ieee80211_key_conf *key) | ||
3292 | { | 2778 | { |
2779 | |||
3293 | struct ath5k_softc *sc = hw->priv; | 2780 | struct ath5k_softc *sc = hw->priv; |
3294 | struct ath5k_hw *ah = sc->ah; | 2781 | struct ath5k_hw *ah = sc->ah; |
3295 | struct ath_common *common = ath5k_hw_common(ah); | 2782 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); |
3296 | int ret = 0; | 2783 | struct ath5k_txq *txq; |
2784 | u8 mac[ETH_ALEN] = {}; | ||
2785 | int ret; | ||
3297 | 2786 | ||
3298 | if (modparam_nohwcrypt) | ||
3299 | return -EOPNOTSUPP; | ||
3300 | 2787 | ||
3301 | if (sc->opmode == NL80211_IFTYPE_AP) | 2788 | /* |
3302 | return -EOPNOTSUPP; | 2789 | * Check if the MAC has multi-rate retry support. |
2790 | * We do this by trying to setup a fake extended | ||
2791 | * descriptor. MACs that don't have support will | ||
2792 | * return false w/o doing anything. MACs that do | ||
2793 | * support it will return true w/o doing anything. | ||
2794 | */ | ||
2795 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | ||
3303 | 2796 | ||
3304 | switch (key->alg) { | 2797 | if (ret < 0) |
3305 | case ALG_WEP: | 2798 | goto err; |
3306 | case ALG_TKIP: | 2799 | if (ret > 0) |
3307 | break; | 2800 | __set_bit(ATH_STAT_MRRETRY, sc->status); |
3308 | case ALG_CCMP: | ||
3309 | if (sc->ah->ah_aes_support) | ||
3310 | break; | ||
3311 | 2801 | ||
3312 | return -EOPNOTSUPP; | 2802 | /* |
3313 | default: | 2803 | * Collect the channel list. The 802.11 layer |
3314 | WARN_ON(1); | 2804 | * is resposible for filtering this list based |
3315 | return -EINVAL; | 2805 | * on settings like the phy mode and regulatory |
2806 | * domain restrictions. | ||
2807 | */ | ||
2808 | ret = ath5k_setup_bands(hw); | ||
2809 | if (ret) { | ||
2810 | ATH5K_ERR(sc, "can't get channels\n"); | ||
2811 | goto err; | ||
3316 | } | 2812 | } |
3317 | 2813 | ||
3318 | mutex_lock(&sc->lock); | 2814 | /* |
2815 | * Allocate tx+rx descriptors and populate the lists. | ||
2816 | */ | ||
2817 | ret = ath5k_desc_alloc(sc); | ||
2818 | if (ret) { | ||
2819 | ATH5K_ERR(sc, "can't allocate descriptors\n"); | ||
2820 | goto err; | ||
2821 | } | ||
3319 | 2822 | ||
3320 | switch (cmd) { | 2823 | /* |
3321 | case SET_KEY: | 2824 | * Allocate hardware transmit queues: one queue for |
3322 | ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, | 2825 | * beacon frames and one data queue for each QoS |
3323 | sta ? sta->addr : NULL); | 2826 | * priority. Note that hw functions handle resetting |
3324 | if (ret) { | 2827 | * these queues at the needed time. |
3325 | ATH5K_ERR(sc, "can't set the key\n"); | 2828 | */ |
3326 | goto unlock; | 2829 | ret = ath5k_beaconq_setup(ah); |
3327 | } | 2830 | if (ret < 0) { |
3328 | __set_bit(key->keyidx, common->keymap); | 2831 | ATH5K_ERR(sc, "can't setup a beacon xmit queue\n"); |
3329 | key->hw_key_idx = key->keyidx; | 2832 | goto err_desc; |
3330 | key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV | | 2833 | } |
3331 | IEEE80211_KEY_FLAG_GENERATE_MMIC); | 2834 | sc->bhalq = ret; |
3332 | break; | 2835 | sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0); |
3333 | case DISABLE_KEY: | 2836 | if (IS_ERR(sc->cabq)) { |
3334 | ath5k_hw_reset_key(sc->ah, key->keyidx); | 2837 | ATH5K_ERR(sc, "can't setup cab queue\n"); |
3335 | __clear_bit(key->keyidx, common->keymap); | 2838 | ret = PTR_ERR(sc->cabq); |
3336 | break; | 2839 | goto err_bhal; |
3337 | default: | ||
3338 | ret = -EINVAL; | ||
3339 | goto unlock; | ||
3340 | } | 2840 | } |
3341 | 2841 | ||
3342 | unlock: | 2842 | /* 5211 and 5212 usually support 10 queues but we better rely on the |
3343 | mmiowb(); | 2843 | * capability information */ |
3344 | mutex_unlock(&sc->lock); | 2844 | if (ah->ah_capabilities.cap_queues.q_tx_num >= 6) { |
3345 | return ret; | 2845 | /* This order matches mac80211's queue priority, so we can |
3346 | } | 2846 | * directly use the mac80211 queue number without any mapping */ |
2847 | txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VO); | ||
2848 | if (IS_ERR(txq)) { | ||
2849 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
2850 | ret = PTR_ERR(txq); | ||
2851 | goto err_queues; | ||
2852 | } | ||
2853 | txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_VI); | ||
2854 | if (IS_ERR(txq)) { | ||
2855 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
2856 | ret = PTR_ERR(txq); | ||
2857 | goto err_queues; | ||
2858 | } | ||
2859 | txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); | ||
2860 | if (IS_ERR(txq)) { | ||
2861 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
2862 | ret = PTR_ERR(txq); | ||
2863 | goto err_queues; | ||
2864 | } | ||
2865 | txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); | ||
2866 | if (IS_ERR(txq)) { | ||
2867 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
2868 | ret = PTR_ERR(txq); | ||
2869 | goto err_queues; | ||
2870 | } | ||
2871 | hw->queues = 4; | ||
2872 | } else { | ||
2873 | /* older hardware (5210) can only support one data queue */ | ||
2874 | txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BE); | ||
2875 | if (IS_ERR(txq)) { | ||
2876 | ATH5K_ERR(sc, "can't setup xmit queue\n"); | ||
2877 | ret = PTR_ERR(txq); | ||
2878 | goto err_queues; | ||
2879 | } | ||
2880 | hw->queues = 1; | ||
2881 | } | ||
3347 | 2882 | ||
3348 | static int | 2883 | tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); |
3349 | ath5k_get_stats(struct ieee80211_hw *hw, | 2884 | tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); |
3350 | struct ieee80211_low_level_stats *stats) | 2885 | tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); |
3351 | { | 2886 | tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); |
3352 | struct ath5k_softc *sc = hw->priv; | 2887 | tasklet_init(&sc->ani_tasklet, ath5k_tasklet_ani, (unsigned long)sc); |
3353 | 2888 | ||
3354 | /* Force update */ | 2889 | INIT_WORK(&sc->reset_work, ath5k_reset_work); |
3355 | ath5k_hw_update_mib_counters(sc->ah); | 2890 | INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); |
3356 | 2891 | ||
3357 | stats->dot11ACKFailureCount = sc->stats.ack_fail; | 2892 | ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac); |
3358 | stats->dot11RTSFailureCount = sc->stats.rts_fail; | 2893 | if (ret) { |
3359 | stats->dot11RTSSuccessCount = sc->stats.rts_ok; | 2894 | ATH5K_ERR(sc, "unable to read address from EEPROM\n"); |
3360 | stats->dot11FCSErrorCount = sc->stats.fcs_error; | 2895 | goto err_queues; |
2896 | } | ||
3361 | 2897 | ||
3362 | return 0; | 2898 | SET_IEEE80211_PERM_ADDR(hw, mac); |
3363 | } | 2899 | memcpy(&sc->lladdr, mac, ETH_ALEN); |
2900 | /* All MAC address bits matter for ACKs */ | ||
2901 | ath5k_update_bssid_mask_and_opmode(sc, NULL); | ||
3364 | 2902 | ||
3365 | static int ath5k_get_survey(struct ieee80211_hw *hw, int idx, | 2903 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; |
3366 | struct survey_info *survey) | 2904 | ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); |
3367 | { | 2905 | if (ret) { |
3368 | struct ath5k_softc *sc = hw->priv; | 2906 | ATH5K_ERR(sc, "can't initialize regulatory system\n"); |
3369 | struct ieee80211_conf *conf = &hw->conf; | 2907 | goto err_queues; |
2908 | } | ||
3370 | 2909 | ||
3371 | if (idx != 0) | 2910 | ret = ieee80211_register_hw(hw); |
3372 | return -ENOENT; | 2911 | if (ret) { |
2912 | ATH5K_ERR(sc, "can't register ieee80211 hw\n"); | ||
2913 | goto err_queues; | ||
2914 | } | ||
3373 | 2915 | ||
3374 | survey->channel = conf->channel; | 2916 | if (!ath_is_world_regd(regulatory)) |
3375 | survey->filled = SURVEY_INFO_NOISE_DBM; | 2917 | regulatory_hint(hw->wiphy, regulatory->alpha2); |
3376 | survey->noise = sc->ah->ah_noise_floor; | ||
3377 | 2918 | ||
3378 | return 0; | 2919 | ath5k_init_leds(sc); |
3379 | } | ||
3380 | 2920 | ||
3381 | static u64 | 2921 | ath5k_sysfs_register(sc); |
3382 | ath5k_get_tsf(struct ieee80211_hw *hw) | ||
3383 | { | ||
3384 | struct ath5k_softc *sc = hw->priv; | ||
3385 | 2922 | ||
3386 | return ath5k_hw_get_tsf64(sc->ah); | 2923 | return 0; |
2924 | err_queues: | ||
2925 | ath5k_txq_release(sc); | ||
2926 | err_bhal: | ||
2927 | ath5k_hw_release_tx_queue(ah, sc->bhalq); | ||
2928 | err_desc: | ||
2929 | ath5k_desc_free(sc); | ||
2930 | err: | ||
2931 | return ret; | ||
3387 | } | 2932 | } |
3388 | 2933 | ||
3389 | static void | 2934 | void |
3390 | ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | 2935 | ath5k_deinit_softc(struct ath5k_softc *sc) |
3391 | { | 2936 | { |
3392 | struct ath5k_softc *sc = hw->priv; | 2937 | struct ieee80211_hw *hw = sc->hw; |
3393 | 2938 | ||
3394 | ath5k_hw_set_tsf64(sc->ah, tsf); | 2939 | /* |
3395 | } | 2940 | * NB: the order of these is important: |
3396 | 2941 | * o call the 802.11 layer before detaching ath5k_hw to | |
3397 | static void | 2942 | * ensure callbacks into the driver to delete global |
3398 | ath5k_reset_tsf(struct ieee80211_hw *hw) | 2943 | * key cache entries can be handled |
3399 | { | 2944 | * o reclaim the tx queue data structures after calling |
3400 | struct ath5k_softc *sc = hw->priv; | 2945 | * the 802.11 layer as we'll get called back to reclaim |
2946 | * node state and potentially want to use them | ||
2947 | * o to cleanup the tx queues the hal is called, so detach | ||
2948 | * it last | ||
2949 | * XXX: ??? detach ath5k_hw ??? | ||
2950 | * Other than that, it's straightforward... | ||
2951 | */ | ||
2952 | ieee80211_unregister_hw(hw); | ||
2953 | ath5k_desc_free(sc); | ||
2954 | ath5k_txq_release(sc); | ||
2955 | ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); | ||
2956 | ath5k_unregister_leds(sc); | ||
3401 | 2957 | ||
2958 | ath5k_sysfs_unregister(sc); | ||
3402 | /* | 2959 | /* |
3403 | * in IBSS mode we need to update the beacon timers too. | 2960 | * NB: can't reclaim these until after ieee80211_ifdetach |
3404 | * this will also reset the TSF if we call it with 0 | 2961 | * returns because we'll get called back to reclaim node |
2962 | * state and potentially want to use them. | ||
3405 | */ | 2963 | */ |
3406 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | 2964 | ath5k_hw_deinit(sc->ah); |
3407 | ath5k_beacon_update_timers(sc, 0); | 2965 | free_irq(sc->irq, sc); |
3408 | else | ||
3409 | ath5k_hw_reset_tsf(sc->ah); | ||
3410 | } | 2966 | } |
3411 | 2967 | ||
3412 | /* | 2968 | bool |
3413 | * Updates the beacon that is sent by ath5k_beacon_send. For adhoc, | 2969 | ath_any_vif_assoc(struct ath5k_softc *sc) |
3414 | * this is called only once at config_bss time, for AP we do it every | ||
3415 | * SWBA interrupt so that the TIM will reflect buffered frames. | ||
3416 | * | ||
3417 | * Called with the beacon lock. | ||
3418 | */ | ||
3419 | static int | ||
3420 | ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
3421 | { | 2970 | { |
3422 | int ret; | 2971 | struct ath5k_vif_iter_data iter_data; |
3423 | struct ath5k_softc *sc = hw->priv; | 2972 | iter_data.hw_macaddr = NULL; |
3424 | struct sk_buff *skb; | 2973 | iter_data.any_assoc = false; |
2974 | iter_data.need_set_hw_addr = false; | ||
2975 | iter_data.found_active = true; | ||
3425 | 2976 | ||
3426 | if (WARN_ON(!vif)) { | 2977 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter, |
3427 | ret = -EINVAL; | 2978 | &iter_data); |
3428 | goto out; | 2979 | return iter_data.any_assoc; |
3429 | } | ||
3430 | |||
3431 | skb = ieee80211_beacon_get(hw, vif); | ||
3432 | |||
3433 | if (!skb) { | ||
3434 | ret = -ENOMEM; | ||
3435 | goto out; | ||
3436 | } | ||
3437 | |||
3438 | ath5k_debug_dump_skb(sc, skb, "BC ", 1); | ||
3439 | |||
3440 | ath5k_txbuf_free_skb(sc, sc->bbuf); | ||
3441 | sc->bbuf->skb = skb; | ||
3442 | ret = ath5k_beacon_setup(sc, sc->bbuf); | ||
3443 | if (ret) | ||
3444 | sc->bbuf->skb = NULL; | ||
3445 | out: | ||
3446 | return ret; | ||
3447 | } | 2980 | } |
3448 | 2981 | ||
3449 | static void | 2982 | void |
3450 | set_beacon_filter(struct ieee80211_hw *hw, bool enable) | 2983 | set_beacon_filter(struct ieee80211_hw *hw, bool enable) |
3451 | { | 2984 | { |
3452 | struct ath5k_softc *sc = hw->priv; | 2985 | struct ath5k_softc *sc = hw->priv; |
@@ -3460,94 +2993,3 @@ set_beacon_filter(struct ieee80211_hw *hw, bool enable) | |||
3460 | ath5k_hw_set_rx_filter(ah, rfilt); | 2993 | ath5k_hw_set_rx_filter(ah, rfilt); |
3461 | sc->filter_flags = rfilt; | 2994 | sc->filter_flags = rfilt; |
3462 | } | 2995 | } |
3463 | |||
3464 | static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | ||
3465 | struct ieee80211_vif *vif, | ||
3466 | struct ieee80211_bss_conf *bss_conf, | ||
3467 | u32 changes) | ||
3468 | { | ||
3469 | struct ath5k_softc *sc = hw->priv; | ||
3470 | struct ath5k_hw *ah = sc->ah; | ||
3471 | struct ath_common *common = ath5k_hw_common(ah); | ||
3472 | unsigned long flags; | ||
3473 | |||
3474 | mutex_lock(&sc->lock); | ||
3475 | if (WARN_ON(sc->vif != vif)) | ||
3476 | goto unlock; | ||
3477 | |||
3478 | if (changes & BSS_CHANGED_BSSID) { | ||
3479 | /* Cache for later use during resets */ | ||
3480 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
3481 | common->curaid = 0; | ||
3482 | ath5k_hw_set_associd(ah); | ||
3483 | mmiowb(); | ||
3484 | } | ||
3485 | |||
3486 | if (changes & BSS_CHANGED_BEACON_INT) | ||
3487 | sc->bintval = bss_conf->beacon_int; | ||
3488 | |||
3489 | if (changes & BSS_CHANGED_ASSOC) { | ||
3490 | sc->assoc = bss_conf->assoc; | ||
3491 | if (sc->opmode == NL80211_IFTYPE_STATION) | ||
3492 | set_beacon_filter(hw, sc->assoc); | ||
3493 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | ||
3494 | AR5K_LED_ASSOC : AR5K_LED_INIT); | ||
3495 | if (bss_conf->assoc) { | ||
3496 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, | ||
3497 | "Bss Info ASSOC %d, bssid: %pM\n", | ||
3498 | bss_conf->aid, common->curbssid); | ||
3499 | common->curaid = bss_conf->aid; | ||
3500 | ath5k_hw_set_associd(ah); | ||
3501 | /* Once ANI is available you would start it here */ | ||
3502 | } | ||
3503 | } | ||
3504 | |||
3505 | if (changes & BSS_CHANGED_BEACON) { | ||
3506 | spin_lock_irqsave(&sc->block, flags); | ||
3507 | ath5k_beacon_update(hw, vif); | ||
3508 | spin_unlock_irqrestore(&sc->block, flags); | ||
3509 | } | ||
3510 | |||
3511 | if (changes & BSS_CHANGED_BEACON_ENABLED) | ||
3512 | sc->enable_beacon = bss_conf->enable_beacon; | ||
3513 | |||
3514 | if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | | ||
3515 | BSS_CHANGED_BEACON_INT)) | ||
3516 | ath5k_beacon_config(sc); | ||
3517 | |||
3518 | unlock: | ||
3519 | mutex_unlock(&sc->lock); | ||
3520 | } | ||
3521 | |||
3522 | static void ath5k_sw_scan_start(struct ieee80211_hw *hw) | ||
3523 | { | ||
3524 | struct ath5k_softc *sc = hw->priv; | ||
3525 | if (!sc->assoc) | ||
3526 | ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN); | ||
3527 | } | ||
3528 | |||
3529 | static void ath5k_sw_scan_complete(struct ieee80211_hw *hw) | ||
3530 | { | ||
3531 | struct ath5k_softc *sc = hw->priv; | ||
3532 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | ||
3533 | AR5K_LED_ASSOC : AR5K_LED_INIT); | ||
3534 | } | ||
3535 | |||
3536 | /** | ||
3537 | * ath5k_set_coverage_class - Set IEEE 802.11 coverage class | ||
3538 | * | ||
3539 | * @hw: struct ieee80211_hw pointer | ||
3540 | * @coverage_class: IEEE 802.11 coverage class number | ||
3541 | * | ||
3542 | * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given | ||
3543 | * coverage class. The values are persistent, they are restored after device | ||
3544 | * reset. | ||
3545 | */ | ||
3546 | static void ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | ||
3547 | { | ||
3548 | struct ath5k_softc *sc = hw->priv; | ||
3549 | |||
3550 | mutex_lock(&sc->lock); | ||
3551 | ath5k_hw_set_coverage_class(sc->ah, coverage_class); | ||
3552 | mutex_unlock(&sc->lock); | ||
3553 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index dc1241f9c4e8..b294f3305011 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -58,7 +58,9 @@ | |||
58 | 58 | ||
59 | #define ATH_RXBUF 40 /* number of RX buffers */ | 59 | #define ATH_RXBUF 40 /* number of RX buffers */ |
60 | #define ATH_TXBUF 200 /* number of TX buffers */ | 60 | #define ATH_TXBUF 200 /* number of TX buffers */ |
61 | #define ATH_BCBUF 1 /* number of beacon buffers */ | 61 | #define ATH_BCBUF 4 /* number of beacon buffers */ |
62 | #define ATH5K_TXQ_LEN_MAX (ATH_TXBUF / 4) /* bufs per queue */ | ||
63 | #define ATH5K_TXQ_LEN_LOW (ATH5K_TXQ_LEN_MAX / 2) /* low mark */ | ||
62 | 64 | ||
63 | struct ath5k_buf { | 65 | struct ath5k_buf { |
64 | struct list_head list; | 66 | struct list_head list; |
@@ -83,6 +85,10 @@ struct ath5k_txq { | |||
83 | struct list_head q; /* transmit queue */ | 85 | struct list_head q; /* transmit queue */ |
84 | spinlock_t lock; /* lock on q and link */ | 86 | spinlock_t lock; /* lock on q and link */ |
85 | bool setup; | 87 | bool setup; |
88 | int txq_len; /* number of queued buffers */ | ||
89 | int txq_max; /* max allowed num of queued buffers */ | ||
90 | bool txq_poll_mark; | ||
91 | unsigned int txq_stuck; /* informational counter */ | ||
86 | }; | 92 | }; |
87 | 93 | ||
88 | #define ATH5K_LED_MAX_NAME_LEN 31 | 94 | #define ATH5K_LED_MAX_NAME_LEN 31 |
@@ -116,6 +122,13 @@ struct ath5k_statistics { | |||
116 | /* frame errors */ | 122 | /* frame errors */ |
117 | unsigned int rx_all_count; /* all RX frames, including errors */ | 123 | unsigned int rx_all_count; /* all RX frames, including errors */ |
118 | unsigned int tx_all_count; /* all TX frames, including errors */ | 124 | unsigned int tx_all_count; /* all TX frames, including errors */ |
125 | unsigned int rx_bytes_count; /* all RX bytes, including errored pks | ||
126 | * and the MAC headers for each packet | ||
127 | */ | ||
128 | unsigned int tx_bytes_count; /* all TX bytes, including errored pkts | ||
129 | * and the MAC headers and padding for | ||
130 | * each packet. | ||
131 | */ | ||
119 | unsigned int rxerr_crc; | 132 | unsigned int rxerr_crc; |
120 | unsigned int rxerr_phy; | 133 | unsigned int rxerr_phy; |
121 | unsigned int rxerr_phy_code[32]; | 134 | unsigned int rxerr_phy_code[32]; |
@@ -146,10 +159,21 @@ struct ath5k_statistics { | |||
146 | #define ATH_CHAN_MAX (14+14+14+252+20) | 159 | #define ATH_CHAN_MAX (14+14+14+252+20) |
147 | #endif | 160 | #endif |
148 | 161 | ||
162 | struct ath5k_vif { | ||
163 | bool assoc; /* are we associated or not */ | ||
164 | enum nl80211_iftype opmode; | ||
165 | int bslot; | ||
166 | struct ath5k_buf *bbuf; /* beacon buffer */ | ||
167 | u8 lladdr[ETH_ALEN]; | ||
168 | }; | ||
169 | |||
149 | /* Software Carrier, keeps track of the driver state | 170 | /* Software Carrier, keeps track of the driver state |
150 | * associated with an instance of a device */ | 171 | * associated with an instance of a device */ |
151 | struct ath5k_softc { | 172 | struct ath5k_softc { |
152 | struct pci_dev *pdev; /* for dma mapping */ | 173 | struct pci_dev *pdev; |
174 | struct device *dev; /* for dma mapping */ | ||
175 | int irq; | ||
176 | u16 devid; | ||
153 | void __iomem *iobase; /* address of the device */ | 177 | void __iomem *iobase; /* address of the device */ |
154 | struct mutex lock; /* dev-level lock */ | 178 | struct mutex lock; /* dev-level lock */ |
155 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ | 179 | struct ieee80211_hw *hw; /* IEEE 802.11 common */ |
@@ -160,8 +184,6 @@ struct ath5k_softc { | |||
160 | enum nl80211_iftype opmode; | 184 | enum nl80211_iftype opmode; |
161 | struct ath5k_hw *ah; /* Atheros HW */ | 185 | struct ath5k_hw *ah; /* Atheros HW */ |
162 | 186 | ||
163 | struct ieee80211_supported_band *curband; | ||
164 | |||
165 | #ifdef CONFIG_ATH5K_DEBUG | 187 | #ifdef CONFIG_ATH5K_DEBUG |
166 | struct ath5k_dbg_info debug; /* debug info */ | 188 | struct ath5k_dbg_info debug; /* debug info */ |
167 | #endif /* CONFIG_ATH5K_DEBUG */ | 189 | #endif /* CONFIG_ATH5K_DEBUG */ |
@@ -171,21 +193,26 @@ struct ath5k_softc { | |||
171 | dma_addr_t desc_daddr; /* DMA (physical) address */ | 193 | dma_addr_t desc_daddr; /* DMA (physical) address */ |
172 | size_t desc_len; /* size of TX/RX descriptors */ | 194 | size_t desc_len; /* size of TX/RX descriptors */ |
173 | 195 | ||
174 | DECLARE_BITMAP(status, 5); | 196 | DECLARE_BITMAP(status, 6); |
175 | #define ATH_STAT_INVALID 0 /* disable hardware accesses */ | 197 | #define ATH_STAT_INVALID 0 /* disable hardware accesses */ |
176 | #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ | 198 | #define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ |
177 | #define ATH_STAT_PROMISC 2 | 199 | #define ATH_STAT_PROMISC 2 |
178 | #define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ | 200 | #define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ |
179 | #define ATH_STAT_STARTED 4 /* opened & irqs enabled */ | 201 | #define ATH_STAT_STARTED 4 /* opened & irqs enabled */ |
202 | #define ATH_STAT_2G_DISABLED 5 /* multiband radio without 2G */ | ||
180 | 203 | ||
181 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ | 204 | unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ |
182 | unsigned int curmode; /* current phy mode */ | ||
183 | struct ieee80211_channel *curchan; /* current h/w channel */ | 205 | struct ieee80211_channel *curchan; /* current h/w channel */ |
184 | 206 | ||
185 | struct ieee80211_vif *vif; | 207 | u16 nvifs; |
186 | 208 | ||
187 | enum ath5k_int imask; /* interrupt mask copy */ | 209 | enum ath5k_int imask; /* interrupt mask copy */ |
188 | 210 | ||
211 | spinlock_t irqlock; | ||
212 | bool rx_pending; /* rx tasklet pending */ | ||
213 | bool tx_pending; /* tx tasklet pending */ | ||
214 | |||
215 | u8 lladdr[ETH_ALEN]; | ||
189 | u8 bssidmask[ETH_ALEN]; | 216 | u8 bssidmask[ETH_ALEN]; |
190 | 217 | ||
191 | unsigned int led_pin, /* GPIO pin for driving LED */ | 218 | unsigned int led_pin, /* GPIO pin for driving LED */ |
@@ -204,7 +231,6 @@ struct ath5k_softc { | |||
204 | spinlock_t txbuflock; | 231 | spinlock_t txbuflock; |
205 | unsigned int txbuf_len; /* buf count in txbuf list */ | 232 | unsigned int txbuf_len; /* buf count in txbuf list */ |
206 | struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */ | 233 | struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */ |
207 | struct ath5k_txq *txq; /* main tx queue */ | ||
208 | struct tasklet_struct txtq; /* tx intr tasklet */ | 234 | struct tasklet_struct txtq; /* tx intr tasklet */ |
209 | struct ath5k_led tx_led; /* tx led */ | 235 | struct ath5k_led tx_led; /* tx led */ |
210 | 236 | ||
@@ -214,7 +240,10 @@ struct ath5k_softc { | |||
214 | 240 | ||
215 | spinlock_t block; /* protects beacon */ | 241 | spinlock_t block; /* protects beacon */ |
216 | struct tasklet_struct beacontq; /* beacon intr tasklet */ | 242 | struct tasklet_struct beacontq; /* beacon intr tasklet */ |
217 | struct ath5k_buf *bbuf; /* beacon buffer */ | 243 | struct list_head bcbuf; /* beacon buffer */ |
244 | struct ieee80211_vif *bslot[ATH_BCBUF]; | ||
245 | u16 num_ap_vifs; | ||
246 | u16 num_adhoc_vifs; | ||
218 | unsigned int bhalq, /* SW q for outgoing beacons */ | 247 | unsigned int bhalq, /* SW q for outgoing beacons */ |
219 | bmisscount, /* missed beacon transmits */ | 248 | bmisscount, /* missed beacon transmits */ |
220 | bintval, /* beacon interval in TU */ | 249 | bintval, /* beacon interval in TU */ |
@@ -230,8 +259,25 @@ struct ath5k_softc { | |||
230 | 259 | ||
231 | struct ath5k_ani_state ani_state; | 260 | struct ath5k_ani_state ani_state; |
232 | struct tasklet_struct ani_tasklet; /* ANI calibration */ | 261 | struct tasklet_struct ani_tasklet; /* ANI calibration */ |
262 | |||
263 | struct delayed_work tx_complete_work; | ||
264 | |||
265 | struct survey_info survey; /* collected survey info */ | ||
233 | }; | 266 | }; |
234 | 267 | ||
268 | struct ath5k_vif_iter_data { | ||
269 | const u8 *hw_macaddr; | ||
270 | u8 mask[ETH_ALEN]; | ||
271 | u8 active_mac[ETH_ALEN]; /* first active MAC */ | ||
272 | bool need_set_hw_addr; | ||
273 | bool found_active; | ||
274 | bool any_assoc; | ||
275 | enum nl80211_iftype opmode; | ||
276 | int n_stas; | ||
277 | }; | ||
278 | void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif); | ||
279 | |||
280 | |||
235 | #define ath5k_hw_hasbssidmask(_ah) \ | 281 | #define ath5k_hw_hasbssidmask(_ah) \ |
236 | (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0) | 282 | (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0) |
237 | #define ath5k_hw_hasveol(_ah) \ | 283 | #define ath5k_hw_hasveol(_ah) \ |
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c index beae519aa735..7dd88e1c3ff8 100644 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ b/drivers/net/wireless/ath/ath5k/caps.c | |||
@@ -32,24 +32,24 @@ | |||
32 | */ | 32 | */ |
33 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | 33 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah) |
34 | { | 34 | { |
35 | struct ath5k_capabilities *caps = &ah->ah_capabilities; | ||
35 | u16 ee_header; | 36 | u16 ee_header; |
36 | 37 | ||
37 | /* Capabilities stored in the EEPROM */ | 38 | /* Capabilities stored in the EEPROM */ |
38 | ee_header = ah->ah_capabilities.cap_eeprom.ee_header; | 39 | ee_header = caps->cap_eeprom.ee_header; |
39 | 40 | ||
40 | if (ah->ah_version == AR5K_AR5210) { | 41 | if (ah->ah_version == AR5K_AR5210) { |
41 | /* | 42 | /* |
42 | * Set radio capabilities | 43 | * Set radio capabilities |
43 | * (The AR5110 only supports the middle 5GHz band) | 44 | * (The AR5110 only supports the middle 5GHz band) |
44 | */ | 45 | */ |
45 | ah->ah_capabilities.cap_range.range_5ghz_min = 5120; | 46 | caps->cap_range.range_5ghz_min = 5120; |
46 | ah->ah_capabilities.cap_range.range_5ghz_max = 5430; | 47 | caps->cap_range.range_5ghz_max = 5430; |
47 | ah->ah_capabilities.cap_range.range_2ghz_min = 0; | 48 | caps->cap_range.range_2ghz_min = 0; |
48 | ah->ah_capabilities.cap_range.range_2ghz_max = 0; | 49 | caps->cap_range.range_2ghz_max = 0; |
49 | 50 | ||
50 | /* Set supported modes */ | 51 | /* Set supported modes */ |
51 | __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); | 52 | __set_bit(AR5K_MODE_11A, caps->cap_mode); |
52 | __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); | ||
53 | } else { | 53 | } else { |
54 | /* | 54 | /* |
55 | * XXX The tranceiver supports frequencies from 4920 to 6100GHz | 55 | * XXX The tranceiver supports frequencies from 4920 to 6100GHz |
@@ -57,9 +57,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
57 | * XXX current ieee80211 implementation because the IEEE | 57 | * XXX current ieee80211 implementation because the IEEE |
58 | * XXX channel mapping does not support negative channel | 58 | * XXX channel mapping does not support negative channel |
59 | * XXX numbers (2312MHz is channel -19). Of course, this | 59 | * XXX numbers (2312MHz is channel -19). Of course, this |
60 | * XXX doesn't matter because these channels are out of range | 60 | * XXX doesn't matter because these channels are out of the |
61 | * XXX but some regulation domains like MKK (Japan) will | 61 | * XXX legal range. |
62 | * XXX support frequencies somewhere around 4.8GHz. | ||
63 | */ | 62 | */ |
64 | 63 | ||
65 | /* | 64 | /* |
@@ -67,18 +66,14 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
67 | */ | 66 | */ |
68 | 67 | ||
69 | if (AR5K_EEPROM_HDR_11A(ee_header)) { | 68 | if (AR5K_EEPROM_HDR_11A(ee_header)) { |
70 | /* 4920 */ | 69 | if (ath_is_49ghz_allowed(caps->cap_eeprom.ee_regdomain)) |
71 | ah->ah_capabilities.cap_range.range_5ghz_min = 5005; | 70 | caps->cap_range.range_5ghz_min = 4920; |
72 | ah->ah_capabilities.cap_range.range_5ghz_max = 6100; | 71 | else |
72 | caps->cap_range.range_5ghz_min = 5005; | ||
73 | caps->cap_range.range_5ghz_max = 6100; | ||
73 | 74 | ||
74 | /* Set supported modes */ | 75 | /* Set supported modes */ |
75 | __set_bit(AR5K_MODE_11A, | 76 | __set_bit(AR5K_MODE_11A, caps->cap_mode); |
76 | ah->ah_capabilities.cap_mode); | ||
77 | __set_bit(AR5K_MODE_11A_TURBO, | ||
78 | ah->ah_capabilities.cap_mode); | ||
79 | if (ah->ah_version == AR5K_AR5212) | ||
80 | __set_bit(AR5K_MODE_11G_TURBO, | ||
81 | ah->ah_capabilities.cap_mode); | ||
82 | } | 77 | } |
83 | 78 | ||
84 | /* Enable 802.11b if a 2GHz capable radio (2111/5112) is | 79 | /* Enable 802.11b if a 2GHz capable radio (2111/5112) is |
@@ -87,32 +82,32 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah) | |||
87 | (AR5K_EEPROM_HDR_11G(ee_header) && | 82 | (AR5K_EEPROM_HDR_11G(ee_header) && |
88 | ah->ah_version != AR5K_AR5211)) { | 83 | ah->ah_version != AR5K_AR5211)) { |
89 | /* 2312 */ | 84 | /* 2312 */ |
90 | ah->ah_capabilities.cap_range.range_2ghz_min = 2412; | 85 | caps->cap_range.range_2ghz_min = 2412; |
91 | ah->ah_capabilities.cap_range.range_2ghz_max = 2732; | 86 | caps->cap_range.range_2ghz_max = 2732; |
92 | 87 | ||
93 | if (AR5K_EEPROM_HDR_11B(ee_header)) | 88 | if (AR5K_EEPROM_HDR_11B(ee_header)) |
94 | __set_bit(AR5K_MODE_11B, | 89 | __set_bit(AR5K_MODE_11B, caps->cap_mode); |
95 | ah->ah_capabilities.cap_mode); | ||
96 | 90 | ||
97 | if (AR5K_EEPROM_HDR_11G(ee_header) && | 91 | if (AR5K_EEPROM_HDR_11G(ee_header) && |
98 | ah->ah_version != AR5K_AR5211) | 92 | ah->ah_version != AR5K_AR5211) |
99 | __set_bit(AR5K_MODE_11G, | 93 | __set_bit(AR5K_MODE_11G, caps->cap_mode); |
100 | ah->ah_capabilities.cap_mode); | ||
101 | } | 94 | } |
102 | } | 95 | } |
103 | 96 | ||
97 | if ((ah->ah_radio_5ghz_revision & 0xf0) == AR5K_SREV_RAD_2112) | ||
98 | __clear_bit(AR5K_MODE_11A, caps->cap_mode); | ||
99 | |||
104 | /* Set number of supported TX queues */ | 100 | /* Set number of supported TX queues */ |
105 | if (ah->ah_version == AR5K_AR5210) | 101 | if (ah->ah_version == AR5K_AR5210) |
106 | ah->ah_capabilities.cap_queues.q_tx_num = | 102 | caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU; |
107 | AR5K_NUM_TX_QUEUES_NOQCU; | ||
108 | else | 103 | else |
109 | ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; | 104 | caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; |
110 | 105 | ||
111 | /* newer hardware has PHY error counters */ | 106 | /* newer hardware has PHY error counters */ |
112 | if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) | 107 | if (ah->ah_mac_srev >= AR5K_SREV_AR5213A) |
113 | ah->ah_capabilities.cap_has_phyerr_counters = true; | 108 | caps->cap_has_phyerr_counters = true; |
114 | else | 109 | else |
115 | ah->ah_capabilities.cap_has_phyerr_counters = false; | 110 | caps->cap_has_phyerr_counters = false; |
116 | 111 | ||
117 | return 0; | 112 | return 0; |
118 | } | 113 | } |
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 4cccc29964f6..0bf7313b8a17 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c | |||
@@ -71,8 +71,6 @@ module_param_named(debug, ath5k_debug, uint, 0); | |||
71 | #include "reg.h" | 71 | #include "reg.h" |
72 | #include "ani.h" | 72 | #include "ani.h" |
73 | 73 | ||
74 | static struct dentry *ath5k_global_debugfs; | ||
75 | |||
76 | static int ath5k_debugfs_open(struct inode *inode, struct file *file) | 74 | static int ath5k_debugfs_open(struct inode *inode, struct file *file) |
77 | { | 75 | { |
78 | file->private_data = inode->i_private; | 76 | file->private_data = inode->i_private; |
@@ -271,6 +269,7 @@ static const struct file_operations fops_beacon = { | |||
271 | .write = write_file_beacon, | 269 | .write = write_file_beacon, |
272 | .open = ath5k_debugfs_open, | 270 | .open = ath5k_debugfs_open, |
273 | .owner = THIS_MODULE, | 271 | .owner = THIS_MODULE, |
272 | .llseek = default_llseek, | ||
274 | }; | 273 | }; |
275 | 274 | ||
276 | 275 | ||
@@ -290,6 +289,7 @@ static const struct file_operations fops_reset = { | |||
290 | .write = write_file_reset, | 289 | .write = write_file_reset, |
291 | .open = ath5k_debugfs_open, | 290 | .open = ath5k_debugfs_open, |
292 | .owner = THIS_MODULE, | 291 | .owner = THIS_MODULE, |
292 | .llseek = noop_llseek, | ||
293 | }; | 293 | }; |
294 | 294 | ||
295 | 295 | ||
@@ -308,10 +308,10 @@ static const struct { | |||
308 | { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, | 308 | { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, |
309 | { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, | 309 | { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, |
310 | { ATH5K_DEBUG_LED, "led", "LED management" }, | 310 | { ATH5K_DEBUG_LED, "led", "LED management" }, |
311 | { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, | ||
312 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, | ||
313 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, | 311 | { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, |
312 | { ATH5K_DEBUG_DMA, "dma", "dma start/stop" }, | ||
314 | { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, | 313 | { ATH5K_DEBUG_ANI, "ani", "adaptive noise immunity" }, |
314 | { ATH5K_DEBUG_DESC, "desc", "descriptor chains" }, | ||
315 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, | 315 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, |
316 | }; | 316 | }; |
317 | 317 | ||
@@ -369,6 +369,7 @@ static const struct file_operations fops_debug = { | |||
369 | .write = write_file_debug, | 369 | .write = write_file_debug, |
370 | .open = ath5k_debugfs_open, | 370 | .open = ath5k_debugfs_open, |
371 | .owner = THIS_MODULE, | 371 | .owner = THIS_MODULE, |
372 | .llseek = default_llseek, | ||
372 | }; | 373 | }; |
373 | 374 | ||
374 | 375 | ||
@@ -480,6 +481,61 @@ static const struct file_operations fops_antenna = { | |||
480 | .write = write_file_antenna, | 481 | .write = write_file_antenna, |
481 | .open = ath5k_debugfs_open, | 482 | .open = ath5k_debugfs_open, |
482 | .owner = THIS_MODULE, | 483 | .owner = THIS_MODULE, |
484 | .llseek = default_llseek, | ||
485 | }; | ||
486 | |||
487 | /* debugfs: misc */ | ||
488 | |||
489 | static ssize_t read_file_misc(struct file *file, char __user *user_buf, | ||
490 | size_t count, loff_t *ppos) | ||
491 | { | ||
492 | struct ath5k_softc *sc = file->private_data; | ||
493 | char buf[700]; | ||
494 | unsigned int len = 0; | ||
495 | u32 filt = ath5k_hw_get_rx_filter(sc->ah); | ||
496 | |||
497 | len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n", | ||
498 | sc->bssidmask); | ||
499 | len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ", | ||
500 | filt); | ||
501 | if (filt & AR5K_RX_FILTER_UCAST) | ||
502 | len += snprintf(buf+len, sizeof(buf)-len, " UCAST"); | ||
503 | if (filt & AR5K_RX_FILTER_MCAST) | ||
504 | len += snprintf(buf+len, sizeof(buf)-len, " MCAST"); | ||
505 | if (filt & AR5K_RX_FILTER_BCAST) | ||
506 | len += snprintf(buf+len, sizeof(buf)-len, " BCAST"); | ||
507 | if (filt & AR5K_RX_FILTER_CONTROL) | ||
508 | len += snprintf(buf+len, sizeof(buf)-len, " CONTROL"); | ||
509 | if (filt & AR5K_RX_FILTER_BEACON) | ||
510 | len += snprintf(buf+len, sizeof(buf)-len, " BEACON"); | ||
511 | if (filt & AR5K_RX_FILTER_PROM) | ||
512 | len += snprintf(buf+len, sizeof(buf)-len, " PROM"); | ||
513 | if (filt & AR5K_RX_FILTER_XRPOLL) | ||
514 | len += snprintf(buf+len, sizeof(buf)-len, " XRPOLL"); | ||
515 | if (filt & AR5K_RX_FILTER_PROBEREQ) | ||
516 | len += snprintf(buf+len, sizeof(buf)-len, " PROBEREQ"); | ||
517 | if (filt & AR5K_RX_FILTER_PHYERR_5212) | ||
518 | len += snprintf(buf+len, sizeof(buf)-len, " PHYERR-5212"); | ||
519 | if (filt & AR5K_RX_FILTER_RADARERR_5212) | ||
520 | len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5212"); | ||
521 | if (filt & AR5K_RX_FILTER_PHYERR_5211) | ||
522 | snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211"); | ||
523 | if (filt & AR5K_RX_FILTER_RADARERR_5211) | ||
524 | len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211"); | ||
525 | |||
526 | len += snprintf(buf+len, sizeof(buf)-len, "\nopmode: %s (%d)\n", | ||
527 | ath_opmode_to_string(sc->opmode), sc->opmode); | ||
528 | |||
529 | if (len > sizeof(buf)) | ||
530 | len = sizeof(buf); | ||
531 | |||
532 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
533 | } | ||
534 | |||
535 | static const struct file_operations fops_misc = { | ||
536 | .read = read_file_misc, | ||
537 | .open = ath5k_debugfs_open, | ||
538 | .owner = THIS_MODULE, | ||
483 | }; | 539 | }; |
484 | 540 | ||
485 | 541 | ||
@@ -496,60 +552,64 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf, | |||
496 | 552 | ||
497 | len += snprintf(buf+len, sizeof(buf)-len, | 553 | len += snprintf(buf+len, sizeof(buf)-len, |
498 | "RX\n---------------------\n"); | 554 | "RX\n---------------------\n"); |
499 | len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n", | 555 | len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n", |
500 | st->rxerr_crc, | 556 | st->rxerr_crc, |
501 | st->rx_all_count > 0 ? | 557 | st->rx_all_count > 0 ? |
502 | st->rxerr_crc*100/st->rx_all_count : 0); | 558 | st->rxerr_crc*100/st->rx_all_count : 0); |
503 | len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n", | 559 | len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n", |
504 | st->rxerr_phy, | 560 | st->rxerr_phy, |
505 | st->rx_all_count > 0 ? | 561 | st->rx_all_count > 0 ? |
506 | st->rxerr_phy*100/st->rx_all_count : 0); | 562 | st->rxerr_phy*100/st->rx_all_count : 0); |
507 | for (i = 0; i < 32; i++) { | 563 | for (i = 0; i < 32; i++) { |
508 | if (st->rxerr_phy_code[i]) | 564 | if (st->rxerr_phy_code[i]) |
509 | len += snprintf(buf+len, sizeof(buf)-len, | 565 | len += snprintf(buf+len, sizeof(buf)-len, |
510 | " phy_err[%d]\t%d\n", | 566 | " phy_err[%u]\t%u\n", |
511 | i, st->rxerr_phy_code[i]); | 567 | i, st->rxerr_phy_code[i]); |
512 | } | 568 | } |
513 | 569 | ||
514 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", | 570 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n", |
515 | st->rxerr_fifo, | 571 | st->rxerr_fifo, |
516 | st->rx_all_count > 0 ? | 572 | st->rx_all_count > 0 ? |
517 | st->rxerr_fifo*100/st->rx_all_count : 0); | 573 | st->rxerr_fifo*100/st->rx_all_count : 0); |
518 | len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n", | 574 | len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n", |
519 | st->rxerr_decrypt, | 575 | st->rxerr_decrypt, |
520 | st->rx_all_count > 0 ? | 576 | st->rx_all_count > 0 ? |
521 | st->rxerr_decrypt*100/st->rx_all_count : 0); | 577 | st->rxerr_decrypt*100/st->rx_all_count : 0); |
522 | len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n", | 578 | len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n", |
523 | st->rxerr_mic, | 579 | st->rxerr_mic, |
524 | st->rx_all_count > 0 ? | 580 | st->rx_all_count > 0 ? |
525 | st->rxerr_mic*100/st->rx_all_count : 0); | 581 | st->rxerr_mic*100/st->rx_all_count : 0); |
526 | len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n", | 582 | len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n", |
527 | st->rxerr_proc, | 583 | st->rxerr_proc, |
528 | st->rx_all_count > 0 ? | 584 | st->rx_all_count > 0 ? |
529 | st->rxerr_proc*100/st->rx_all_count : 0); | 585 | st->rxerr_proc*100/st->rx_all_count : 0); |
530 | len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n", | 586 | len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n", |
531 | st->rxerr_jumbo, | 587 | st->rxerr_jumbo, |
532 | st->rx_all_count > 0 ? | 588 | st->rx_all_count > 0 ? |
533 | st->rxerr_jumbo*100/st->rx_all_count : 0); | 589 | st->rxerr_jumbo*100/st->rx_all_count : 0); |
534 | len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n", | 590 | len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n", |
535 | st->rx_all_count); | 591 | st->rx_all_count); |
592 | len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n", | ||
593 | st->rx_bytes_count); | ||
536 | 594 | ||
537 | len += snprintf(buf+len, sizeof(buf)-len, | 595 | len += snprintf(buf+len, sizeof(buf)-len, |
538 | "\nTX\n---------------------\n"); | 596 | "\nTX\n---------------------\n"); |
539 | len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n", | 597 | len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n", |
540 | st->txerr_retry, | 598 | st->txerr_retry, |
541 | st->tx_all_count > 0 ? | 599 | st->tx_all_count > 0 ? |
542 | st->txerr_retry*100/st->tx_all_count : 0); | 600 | st->txerr_retry*100/st->tx_all_count : 0); |
543 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n", | 601 | len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n", |
544 | st->txerr_fifo, | 602 | st->txerr_fifo, |
545 | st->tx_all_count > 0 ? | 603 | st->tx_all_count > 0 ? |
546 | st->txerr_fifo*100/st->tx_all_count : 0); | 604 | st->txerr_fifo*100/st->tx_all_count : 0); |
547 | len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n", | 605 | len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n", |
548 | st->txerr_filt, | 606 | st->txerr_filt, |
549 | st->tx_all_count > 0 ? | 607 | st->tx_all_count > 0 ? |
550 | st->txerr_filt*100/st->tx_all_count : 0); | 608 | st->txerr_filt*100/st->tx_all_count : 0); |
551 | len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n", | 609 | len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n", |
552 | st->tx_all_count); | 610 | st->tx_all_count); |
611 | len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n", | ||
612 | st->tx_bytes_count); | ||
553 | 613 | ||
554 | if (len > sizeof(buf)) | 614 | if (len > sizeof(buf)) |
555 | len = sizeof(buf); | 615 | len = sizeof(buf); |
@@ -591,6 +651,7 @@ static const struct file_operations fops_frameerrors = { | |||
591 | .write = write_file_frameerrors, | 651 | .write = write_file_frameerrors, |
592 | .open = ath5k_debugfs_open, | 652 | .open = ath5k_debugfs_open, |
593 | .owner = THIS_MODULE, | 653 | .owner = THIS_MODULE, |
654 | .llseek = default_llseek, | ||
594 | }; | 655 | }; |
595 | 656 | ||
596 | 657 | ||
@@ -656,21 +717,22 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, | |||
656 | st->mib_intr); | 717 | st->mib_intr); |
657 | len += snprintf(buf+len, sizeof(buf)-len, | 718 | len += snprintf(buf+len, sizeof(buf)-len, |
658 | "beacon RSSI average:\t%d\n", | 719 | "beacon RSSI average:\t%d\n", |
659 | sc->ah->ah_beacon_rssi_avg.avg); | 720 | (int)ewma_read(&sc->ah->ah_beacon_rssi_avg)); |
721 | |||
722 | #define CC_PRINT(_struct, _field) \ | ||
723 | _struct._field, \ | ||
724 | _struct.cycles > 0 ? \ | ||
725 | _struct._field*100/_struct.cycles : 0 | ||
726 | |||
660 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n", | 727 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n", |
661 | as->pfc_tx, | 728 | CC_PRINT(as->last_cc, tx_frame)); |
662 | as->pfc_cycles > 0 ? | ||
663 | as->pfc_tx*100/as->pfc_cycles : 0); | ||
664 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n", | 729 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n", |
665 | as->pfc_rx, | 730 | CC_PRINT(as->last_cc, rx_frame)); |
666 | as->pfc_cycles > 0 ? | ||
667 | as->pfc_rx*100/as->pfc_cycles : 0); | ||
668 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n", | 731 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n", |
669 | as->pfc_busy, | 732 | CC_PRINT(as->last_cc, rx_busy)); |
670 | as->pfc_cycles > 0 ? | 733 | #undef CC_PRINT |
671 | as->pfc_busy*100/as->pfc_cycles : 0); | ||
672 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n", | 734 | len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n", |
673 | as->pfc_cycles); | 735 | as->last_cc.cycles); |
674 | len += snprintf(buf+len, sizeof(buf)-len, | 736 | len += snprintf(buf+len, sizeof(buf)-len, |
675 | "listen time\t\t%d\tlast: %d\n", | 737 | "listen time\t\t%d\tlast: %d\n", |
676 | as->listen_time, as->last_listen); | 738 | as->listen_time, as->last_listen); |
@@ -748,6 +810,7 @@ static const struct file_operations fops_ani = { | |||
748 | .write = write_file_ani, | 810 | .write = write_file_ani, |
749 | .open = ath5k_debugfs_open, | 811 | .open = ath5k_debugfs_open, |
750 | .owner = THIS_MODULE, | 812 | .owner = THIS_MODULE, |
813 | .llseek = default_llseek, | ||
751 | }; | 814 | }; |
752 | 815 | ||
753 | 816 | ||
@@ -762,7 +825,7 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf, | |||
762 | 825 | ||
763 | struct ath5k_txq *txq; | 826 | struct ath5k_txq *txq; |
764 | struct ath5k_buf *bf, *bf0; | 827 | struct ath5k_buf *bf, *bf0; |
765 | int i, n = 0; | 828 | int i, n; |
766 | 829 | ||
767 | len += snprintf(buf+len, sizeof(buf)-len, | 830 | len += snprintf(buf+len, sizeof(buf)-len, |
768 | "available txbuffers: %d\n", sc->txbuf_len); | 831 | "available txbuffers: %d\n", sc->txbuf_len); |
@@ -776,9 +839,16 @@ static ssize_t read_file_queue(struct file *file, char __user *user_buf, | |||
776 | if (!txq->setup) | 839 | if (!txq->setup) |
777 | continue; | 840 | continue; |
778 | 841 | ||
842 | n = 0; | ||
843 | spin_lock_bh(&txq->lock); | ||
779 | list_for_each_entry_safe(bf, bf0, &txq->q, list) | 844 | list_for_each_entry_safe(bf, bf0, &txq->q, list) |
780 | n++; | 845 | n++; |
781 | len += snprintf(buf+len, sizeof(buf)-len, " len: %d\n", n); | 846 | spin_unlock_bh(&txq->lock); |
847 | |||
848 | len += snprintf(buf+len, sizeof(buf)-len, | ||
849 | " len: %d bufs: %d\n", txq->txq_len, n); | ||
850 | len += snprintf(buf+len, sizeof(buf)-len, | ||
851 | " stuck: %d\n", txq->txq_stuck); | ||
782 | } | 852 | } |
783 | 853 | ||
784 | if (len > sizeof(buf)) | 854 | if (len > sizeof(buf)) |
@@ -811,80 +881,45 @@ static const struct file_operations fops_queue = { | |||
811 | .write = write_file_queue, | 881 | .write = write_file_queue, |
812 | .open = ath5k_debugfs_open, | 882 | .open = ath5k_debugfs_open, |
813 | .owner = THIS_MODULE, | 883 | .owner = THIS_MODULE, |
884 | .llseek = default_llseek, | ||
814 | }; | 885 | }; |
815 | 886 | ||
816 | 887 | ||
817 | /* init */ | ||
818 | |||
819 | void | ||
820 | ath5k_debug_init(void) | ||
821 | { | ||
822 | ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL); | ||
823 | } | ||
824 | |||
825 | void | 888 | void |
826 | ath5k_debug_init_device(struct ath5k_softc *sc) | 889 | ath5k_debug_init_device(struct ath5k_softc *sc) |
827 | { | 890 | { |
891 | struct dentry *phydir; | ||
892 | |||
828 | sc->debug.level = ath5k_debug; | 893 | sc->debug.level = ath5k_debug; |
829 | 894 | ||
830 | sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), | 895 | phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir); |
831 | ath5k_global_debugfs); | 896 | if (!phydir) |
897 | return; | ||
832 | 898 | ||
833 | sc->debug.debugfs_debug = debugfs_create_file("debug", | 899 | debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc, |
834 | S_IWUSR | S_IRUSR, | 900 | &fops_debug); |
835 | sc->debug.debugfs_phydir, sc, &fops_debug); | ||
836 | 901 | ||
837 | sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR, | 902 | debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers); |
838 | sc->debug.debugfs_phydir, sc, &fops_registers); | ||
839 | 903 | ||
840 | sc->debug.debugfs_beacon = debugfs_create_file("beacon", | 904 | debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc, |
841 | S_IWUSR | S_IRUSR, | 905 | &fops_beacon); |
842 | sc->debug.debugfs_phydir, sc, &fops_beacon); | ||
843 | 906 | ||
844 | sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, | 907 | debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset); |
845 | sc->debug.debugfs_phydir, sc, &fops_reset); | ||
846 | 908 | ||
847 | sc->debug.debugfs_antenna = debugfs_create_file("antenna", | 909 | debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc, |
848 | S_IWUSR | S_IRUSR, | 910 | &fops_antenna); |
849 | sc->debug.debugfs_phydir, sc, &fops_antenna); | ||
850 | 911 | ||
851 | sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", | 912 | debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc); |
852 | S_IWUSR | S_IRUSR, | ||
853 | sc->debug.debugfs_phydir, sc, | ||
854 | &fops_frameerrors); | ||
855 | 913 | ||
856 | sc->debug.debugfs_ani = debugfs_create_file("ani", | 914 | debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc, |
857 | S_IWUSR | S_IRUSR, | 915 | &fops_frameerrors); |
858 | sc->debug.debugfs_phydir, sc, | ||
859 | &fops_ani); | ||
860 | 916 | ||
861 | sc->debug.debugfs_queue = debugfs_create_file("queue", | 917 | debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani); |
862 | S_IWUSR | S_IRUSR, | ||
863 | sc->debug.debugfs_phydir, sc, | ||
864 | &fops_queue); | ||
865 | } | ||
866 | 918 | ||
867 | void | 919 | debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc, |
868 | ath5k_debug_finish(void) | 920 | &fops_queue); |
869 | { | ||
870 | debugfs_remove(ath5k_global_debugfs); | ||
871 | } | 921 | } |
872 | 922 | ||
873 | void | ||
874 | ath5k_debug_finish_device(struct ath5k_softc *sc) | ||
875 | { | ||
876 | debugfs_remove(sc->debug.debugfs_debug); | ||
877 | debugfs_remove(sc->debug.debugfs_registers); | ||
878 | debugfs_remove(sc->debug.debugfs_beacon); | ||
879 | debugfs_remove(sc->debug.debugfs_reset); | ||
880 | debugfs_remove(sc->debug.debugfs_antenna); | ||
881 | debugfs_remove(sc->debug.debugfs_frameerrors); | ||
882 | debugfs_remove(sc->debug.debugfs_ani); | ||
883 | debugfs_remove(sc->debug.debugfs_queue); | ||
884 | debugfs_remove(sc->debug.debugfs_phydir); | ||
885 | } | ||
886 | |||
887 | |||
888 | /* functions used in other places */ | 923 | /* functions used in other places */ |
889 | 924 | ||
890 | void | 925 | void |
@@ -955,7 +990,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
955 | struct ath5k_rx_status rs = {}; | 990 | struct ath5k_rx_status rs = {}; |
956 | int status; | 991 | int status; |
957 | 992 | ||
958 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) | 993 | if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC))) |
959 | return; | 994 | return; |
960 | 995 | ||
961 | printk(KERN_DEBUG "rxdp %x, rxlink %p\n", | 996 | printk(KERN_DEBUG "rxdp %x, rxlink %p\n", |
@@ -972,24 +1007,6 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
972 | } | 1007 | } |
973 | 1008 | ||
974 | void | 1009 | void |
975 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
976 | struct sk_buff *skb, const char *prefix, int tx) | ||
977 | { | ||
978 | char buf[16]; | ||
979 | |||
980 | if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) || | ||
981 | (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX))))) | ||
982 | return; | ||
983 | |||
984 | snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix); | ||
985 | |||
986 | print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data, | ||
987 | min(200U, skb->len)); | ||
988 | |||
989 | printk(KERN_DEBUG "\n"); | ||
990 | } | ||
991 | |||
992 | void | ||
993 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) | 1010 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) |
994 | { | 1011 | { |
995 | struct ath5k_desc *ds = bf->desc; | 1012 | struct ath5k_desc *ds = bf->desc; |
@@ -997,7 +1014,7 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
997 | struct ath5k_tx_status ts = {}; | 1014 | struct ath5k_tx_status ts = {}; |
998 | int done; | 1015 | int done; |
999 | 1016 | ||
1000 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) | 1017 | if (likely(!(sc->debug.level & ATH5K_DEBUG_DESC))) |
1001 | return; | 1018 | return; |
1002 | 1019 | ||
1003 | done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts); | 1020 | done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts); |
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 606ae94a9157..193dd2d4ea3c 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h | |||
@@ -68,16 +68,6 @@ struct ath5k_buf; | |||
68 | 68 | ||
69 | struct ath5k_dbg_info { | 69 | struct ath5k_dbg_info { |
70 | unsigned int level; /* debug level */ | 70 | unsigned int level; /* debug level */ |
71 | /* debugfs entries */ | ||
72 | struct dentry *debugfs_phydir; | ||
73 | struct dentry *debugfs_debug; | ||
74 | struct dentry *debugfs_registers; | ||
75 | struct dentry *debugfs_beacon; | ||
76 | struct dentry *debugfs_reset; | ||
77 | struct dentry *debugfs_antenna; | ||
78 | struct dentry *debugfs_frameerrors; | ||
79 | struct dentry *debugfs_ani; | ||
80 | struct dentry *debugfs_queue; | ||
81 | }; | 71 | }; |
82 | 72 | ||
83 | /** | 73 | /** |
@@ -94,7 +84,9 @@ struct ath5k_dbg_info { | |||
94 | * @ATH5K_DEBUG_DUMP_RX: print received skb content | 84 | * @ATH5K_DEBUG_DUMP_RX: print received skb content |
95 | * @ATH5K_DEBUG_DUMP_TX: print transmit skb content | 85 | * @ATH5K_DEBUG_DUMP_TX: print transmit skb content |
96 | * @ATH5K_DEBUG_DUMPBANDS: dump bands | 86 | * @ATH5K_DEBUG_DUMPBANDS: dump bands |
87 | * @ATH5K_DEBUG_DMA: debug dma start/stop | ||
97 | * @ATH5K_DEBUG_TRACE: trace function calls | 88 | * @ATH5K_DEBUG_TRACE: trace function calls |
89 | * @ATH5K_DEBUG_DESC: descriptor setup | ||
98 | * @ATH5K_DEBUG_ANY: show at any debug level | 90 | * @ATH5K_DEBUG_ANY: show at any debug level |
99 | * | 91 | * |
100 | * The debug level is used to control the amount and type of debugging output | 92 | * The debug level is used to control the amount and type of debugging output |
@@ -113,10 +105,10 @@ enum ath5k_debug_level { | |||
113 | ATH5K_DEBUG_CALIBRATE = 0x00000020, | 105 | ATH5K_DEBUG_CALIBRATE = 0x00000020, |
114 | ATH5K_DEBUG_TXPOWER = 0x00000040, | 106 | ATH5K_DEBUG_TXPOWER = 0x00000040, |
115 | ATH5K_DEBUG_LED = 0x00000080, | 107 | ATH5K_DEBUG_LED = 0x00000080, |
116 | ATH5K_DEBUG_DUMP_RX = 0x00000100, | ||
117 | ATH5K_DEBUG_DUMP_TX = 0x00000200, | ||
118 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, | 108 | ATH5K_DEBUG_DUMPBANDS = 0x00000400, |
109 | ATH5K_DEBUG_DMA = 0x00000800, | ||
119 | ATH5K_DEBUG_ANI = 0x00002000, | 110 | ATH5K_DEBUG_ANI = 0x00002000, |
111 | ATH5K_DEBUG_DESC = 0x00004000, | ||
120 | ATH5K_DEBUG_ANY = 0xffffffff | 112 | ATH5K_DEBUG_ANY = 0xffffffff |
121 | }; | 113 | }; |
122 | 114 | ||
@@ -135,28 +127,15 @@ enum ath5k_debug_level { | |||
135 | } while (0) | 127 | } while (0) |
136 | 128 | ||
137 | void | 129 | void |
138 | ath5k_debug_init(void); | ||
139 | |||
140 | void | ||
141 | ath5k_debug_init_device(struct ath5k_softc *sc); | 130 | ath5k_debug_init_device(struct ath5k_softc *sc); |
142 | 131 | ||
143 | void | 132 | void |
144 | ath5k_debug_finish(void); | ||
145 | |||
146 | void | ||
147 | ath5k_debug_finish_device(struct ath5k_softc *sc); | ||
148 | |||
149 | void | ||
150 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); | 133 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); |
151 | 134 | ||
152 | void | 135 | void |
153 | ath5k_debug_dump_bands(struct ath5k_softc *sc); | 136 | ath5k_debug_dump_bands(struct ath5k_softc *sc); |
154 | 137 | ||
155 | void | 138 | void |
156 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
157 | struct sk_buff *skb, const char *prefix, int tx); | ||
158 | |||
159 | void | ||
160 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); | 139 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); |
161 | 140 | ||
162 | #else /* no debugging */ | 141 | #else /* no debugging */ |
@@ -171,28 +150,15 @@ ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) | |||
171 | {} | 150 | {} |
172 | 151 | ||
173 | static inline void | 152 | static inline void |
174 | ath5k_debug_init(void) {} | ||
175 | |||
176 | static inline void | ||
177 | ath5k_debug_init_device(struct ath5k_softc *sc) {} | 153 | ath5k_debug_init_device(struct ath5k_softc *sc) {} |
178 | 154 | ||
179 | static inline void | 155 | static inline void |
180 | ath5k_debug_finish(void) {} | ||
181 | |||
182 | static inline void | ||
183 | ath5k_debug_finish_device(struct ath5k_softc *sc) {} | ||
184 | |||
185 | static inline void | ||
186 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} | 156 | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} |
187 | 157 | ||
188 | static inline void | 158 | static inline void |
189 | ath5k_debug_dump_bands(struct ath5k_softc *sc) {} | 159 | ath5k_debug_dump_bands(struct ath5k_softc *sc) {} |
190 | 160 | ||
191 | static inline void | 161 | static inline void |
192 | ath5k_debug_dump_skb(struct ath5k_softc *sc, | ||
193 | struct sk_buff *skb, const char *prefix, int tx) {} | ||
194 | |||
195 | static inline void | ||
196 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} | 162 | ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} |
197 | 163 | ||
198 | #endif /* ifdef CONFIG_ATH5K_DEBUG */ | 164 | #endif /* ifdef CONFIG_ATH5K_DEBUG */ |
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 43244382f213..f82383b3ed30 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -26,9 +26,10 @@ | |||
26 | #include "debug.h" | 26 | #include "debug.h" |
27 | #include "base.h" | 27 | #include "base.h" |
28 | 28 | ||
29 | /* | 29 | |
30 | * TX Descriptors | 30 | /************************\ |
31 | */ | 31 | * TX Control descriptors * |
32 | \************************/ | ||
32 | 33 | ||
33 | /* | 34 | /* |
34 | * Initialize the 2-word tx control descriptor on 5210/5211 | 35 | * Initialize the 2-word tx control descriptor on 5210/5211 |
@@ -50,7 +51,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
50 | /* | 51 | /* |
51 | * Validate input | 52 | * Validate input |
52 | * - Zero retries don't make sense. | 53 | * - Zero retries don't make sense. |
53 | * - A zero rate will put the HW into a mode where it continously sends | 54 | * - A zero rate will put the HW into a mode where it continuously sends |
54 | * noise on the channel, so it is important to avoid this. | 55 | * noise on the channel, so it is important to avoid this. |
55 | */ | 56 | */ |
56 | if (unlikely(tx_tries0 == 0)) { | 57 | if (unlikely(tx_tries0 == 0)) { |
@@ -106,10 +107,13 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
106 | case AR5K_PKT_TYPE_BEACON: | 107 | case AR5K_PKT_TYPE_BEACON: |
107 | case AR5K_PKT_TYPE_PROBE_RESP: | 108 | case AR5K_PKT_TYPE_PROBE_RESP: |
108 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY; | 109 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY; |
110 | break; | ||
109 | case AR5K_PKT_TYPE_PIFS: | 111 | case AR5K_PKT_TYPE_PIFS: |
110 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; | 112 | frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; |
113 | break; | ||
111 | default: | 114 | default: |
112 | frame_type = type; | 115 | frame_type = type; |
116 | break; | ||
113 | } | 117 | } |
114 | 118 | ||
115 | tx_ctl->tx_control_0 |= | 119 | tx_ctl->tx_control_0 |= |
@@ -184,12 +188,18 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
184 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 188 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
185 | unsigned int frame_len; | 189 | unsigned int frame_len; |
186 | 190 | ||
191 | /* | ||
192 | * Use local variables for these to reduce load/store access on | ||
193 | * uncached memory | ||
194 | */ | ||
195 | u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0; | ||
196 | |||
187 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | 197 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
188 | 198 | ||
189 | /* | 199 | /* |
190 | * Validate input | 200 | * Validate input |
191 | * - Zero retries don't make sense. | 201 | * - Zero retries don't make sense. |
192 | * - A zero rate will put the HW into a mode where it continously sends | 202 | * - A zero rate will put the HW into a mode where it continuously sends |
193 | * noise on the channel, so it is important to avoid this. | 203 | * noise on the channel, so it is important to avoid this. |
194 | */ | 204 | */ |
195 | if (unlikely(tx_tries0 == 0)) { | 205 | if (unlikely(tx_tries0 == 0)) { |
@@ -207,8 +217,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
207 | if (tx_power > AR5K_TUNE_MAX_TXPOWER) | 217 | if (tx_power > AR5K_TUNE_MAX_TXPOWER) |
208 | tx_power = AR5K_TUNE_MAX_TXPOWER; | 218 | tx_power = AR5K_TUNE_MAX_TXPOWER; |
209 | 219 | ||
210 | /* Clear descriptor */ | 220 | /* Clear descriptor status area */ |
211 | memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); | 221 | memset(&desc->ud.ds_tx5212.tx_stat, 0, |
222 | sizeof(desc->ud.ds_tx5212.tx_stat)); | ||
212 | 223 | ||
213 | /* Setup control descriptor */ | 224 | /* Setup control descriptor */ |
214 | 225 | ||
@@ -220,7 +231,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
220 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) | 231 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) |
221 | return -EINVAL; | 232 | return -EINVAL; |
222 | 233 | ||
223 | tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; | 234 | txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; |
224 | 235 | ||
225 | /* Verify and set buffer length */ | 236 | /* Verify and set buffer length */ |
226 | 237 | ||
@@ -231,21 +242,17 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
231 | if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) | 242 | if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) |
232 | return -EINVAL; | 243 | return -EINVAL; |
233 | 244 | ||
234 | tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; | 245 | txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; |
235 | 246 | ||
236 | tx_ctl->tx_control_0 |= | 247 | txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | |
237 | AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | | 248 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); |
238 | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); | 249 | txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); |
239 | tx_ctl->tx_control_1 |= AR5K_REG_SM(type, | 250 | txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); |
240 | AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); | 251 | txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; |
241 | tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0, | ||
242 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); | ||
243 | tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
244 | 252 | ||
245 | #define _TX_FLAGS(_c, _flag) \ | 253 | #define _TX_FLAGS(_c, _flag) \ |
246 | if (flags & AR5K_TXDESC_##_flag) { \ | 254 | if (flags & AR5K_TXDESC_##_flag) { \ |
247 | tx_ctl->tx_control_##_c |= \ | 255 | txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ |
248 | AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ | ||
249 | } | 256 | } |
250 | 257 | ||
251 | _TX_FLAGS(0, CLRDMASK); | 258 | _TX_FLAGS(0, CLRDMASK); |
@@ -261,8 +268,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
261 | * WEP crap | 268 | * WEP crap |
262 | */ | 269 | */ |
263 | if (key_index != AR5K_TXKEYIX_INVALID) { | 270 | if (key_index != AR5K_TXKEYIX_INVALID) { |
264 | tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; | 271 | txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
265 | tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, | 272 | txctl1 |= AR5K_REG_SM(key_index, |
266 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); | 273 | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); |
267 | } | 274 | } |
268 | 275 | ||
@@ -273,12 +280,16 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
273 | if ((flags & AR5K_TXDESC_RTSENA) && | 280 | if ((flags & AR5K_TXDESC_RTSENA) && |
274 | (flags & AR5K_TXDESC_CTSENA)) | 281 | (flags & AR5K_TXDESC_CTSENA)) |
275 | return -EINVAL; | 282 | return -EINVAL; |
276 | tx_ctl->tx_control_2 |= rtscts_duration & | 283 | txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION; |
277 | AR5K_4W_TX_DESC_CTL2_RTS_DURATION; | 284 | txctl3 |= AR5K_REG_SM(rtscts_rate, |
278 | tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, | ||
279 | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); | 285 | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); |
280 | } | 286 | } |
281 | 287 | ||
288 | tx_ctl->tx_control_0 = txctl0; | ||
289 | tx_ctl->tx_control_1 = txctl1; | ||
290 | tx_ctl->tx_control_2 = txctl2; | ||
291 | tx_ctl->tx_control_3 = txctl3; | ||
292 | |||
282 | return 0; | 293 | return 0; |
283 | } | 294 | } |
284 | 295 | ||
@@ -299,7 +310,7 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
299 | /* | 310 | /* |
300 | * Rates can be 0 as long as the retry count is 0 too. | 311 | * Rates can be 0 as long as the retry count is 0 too. |
301 | * A zero rate and nonzero retry count will put the HW into a mode where | 312 | * A zero rate and nonzero retry count will put the HW into a mode where |
302 | * it continously sends noise on the channel, so it is important to | 313 | * it continuously sends noise on the channel, so it is important to |
303 | * avoid this. | 314 | * avoid this. |
304 | */ | 315 | */ |
305 | if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || | 316 | if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || |
@@ -335,8 +346,13 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
335 | return 0; | 346 | return 0; |
336 | } | 347 | } |
337 | 348 | ||
349 | |||
350 | /***********************\ | ||
351 | * TX Status descriptors * | ||
352 | \***********************/ | ||
353 | |||
338 | /* | 354 | /* |
339 | * Proccess the tx status descriptor on 5210/5211 | 355 | * Process the tx status descriptor on 5210/5211 |
340 | */ | 356 | */ |
341 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | 357 | static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, |
342 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) | 358 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) |
@@ -358,7 +374,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
358 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | 374 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); |
359 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | 375 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, |
360 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | 376 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); |
361 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | 377 | ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0, |
362 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | 378 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); |
363 | /*TODO: ts->ts_virtcol + test*/ | 379 | /*TODO: ts->ts_virtcol + test*/ |
364 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | 380 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, |
@@ -367,9 +383,6 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
367 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | 383 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
368 | ts->ts_antenna = 1; | 384 | ts->ts_antenna = 1; |
369 | ts->ts_status = 0; | 385 | ts->ts_status = 0; |
370 | ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, | ||
371 | AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | ||
372 | ts->ts_retry[0] = ts->ts_longretry; | ||
373 | ts->ts_final_idx = 0; | 386 | ts->ts_final_idx = 0; |
374 | 387 | ||
375 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { | 388 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { |
@@ -388,97 +401,65 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
388 | } | 401 | } |
389 | 402 | ||
390 | /* | 403 | /* |
391 | * Proccess a tx status descriptor on 5212 | 404 | * Process a tx status descriptor on 5212 |
392 | */ | 405 | */ |
393 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | 406 | static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, |
394 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) | 407 | struct ath5k_desc *desc, struct ath5k_tx_status *ts) |
395 | { | 408 | { |
396 | struct ath5k_hw_4w_tx_ctl *tx_ctl; | 409 | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
397 | struct ath5k_hw_tx_status *tx_status; | 410 | struct ath5k_hw_tx_status *tx_status; |
411 | u32 txstat0, txstat1; | ||
398 | 412 | ||
399 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; | 413 | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
400 | tx_status = &desc->ud.ds_tx5212.tx_stat; | 414 | tx_status = &desc->ud.ds_tx5212.tx_stat; |
401 | 415 | ||
416 | txstat1 = ACCESS_ONCE(tx_status->tx_status_1); | ||
417 | |||
402 | /* No frame has been send or error */ | 418 | /* No frame has been send or error */ |
403 | if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) | 419 | if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE))) |
404 | return -EINPROGRESS; | 420 | return -EINPROGRESS; |
405 | 421 | ||
422 | txstat0 = ACCESS_ONCE(tx_status->tx_status_0); | ||
423 | |||
406 | /* | 424 | /* |
407 | * Get descriptor status | 425 | * Get descriptor status |
408 | */ | 426 | */ |
409 | ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, | 427 | ts->ts_tstamp = AR5K_REG_MS(txstat0, |
410 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); | 428 | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); |
411 | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, | 429 | ts->ts_shortretry = AR5K_REG_MS(txstat0, |
412 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); | 430 | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); |
413 | ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, | 431 | ts->ts_final_retry = AR5K_REG_MS(txstat0, |
414 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); | 432 | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); |
415 | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, | 433 | ts->ts_seqnum = AR5K_REG_MS(txstat1, |
416 | AR5K_DESC_TX_STATUS1_SEQ_NUM); | 434 | AR5K_DESC_TX_STATUS1_SEQ_NUM); |
417 | ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, | 435 | ts->ts_rssi = AR5K_REG_MS(txstat1, |
418 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | 436 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
419 | ts->ts_antenna = (tx_status->tx_status_1 & | 437 | ts->ts_antenna = (txstat1 & |
420 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; | 438 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; |
421 | ts->ts_status = 0; | 439 | ts->ts_status = 0; |
422 | 440 | ||
423 | ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, | 441 | ts->ts_final_idx = AR5K_REG_MS(txstat1, |
424 | AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); | 442 | AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); |
425 | 443 | ||
426 | /* The longretry counter has the number of un-acked retries | ||
427 | * for the final rate. To get the total number of retries | ||
428 | * we have to add the retry counters for the other rates | ||
429 | * as well | ||
430 | */ | ||
431 | ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; | ||
432 | switch (ts->ts_final_idx) { | ||
433 | case 3: | ||
434 | ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
435 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); | ||
436 | |||
437 | ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, | ||
438 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); | ||
439 | ts->ts_longretry += ts->ts_retry[2]; | ||
440 | /* fall through */ | ||
441 | case 2: | ||
442 | ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
443 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); | ||
444 | |||
445 | ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, | ||
446 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | ||
447 | ts->ts_longretry += ts->ts_retry[1]; | ||
448 | /* fall through */ | ||
449 | case 1: | ||
450 | ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
451 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); | ||
452 | |||
453 | ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, | ||
454 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | ||
455 | ts->ts_longretry += ts->ts_retry[0]; | ||
456 | /* fall through */ | ||
457 | case 0: | ||
458 | ts->ts_rate[0] = tx_ctl->tx_control_3 & | ||
459 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | ||
460 | break; | ||
461 | } | ||
462 | |||
463 | /* TX error */ | 444 | /* TX error */ |
464 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { | 445 | if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { |
465 | if (tx_status->tx_status_0 & | 446 | if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) |
466 | AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) | ||
467 | ts->ts_status |= AR5K_TXERR_XRETRY; | 447 | ts->ts_status |= AR5K_TXERR_XRETRY; |
468 | 448 | ||
469 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) | 449 | if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) |
470 | ts->ts_status |= AR5K_TXERR_FIFO; | 450 | ts->ts_status |= AR5K_TXERR_FIFO; |
471 | 451 | ||
472 | if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) | 452 | if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED) |
473 | ts->ts_status |= AR5K_TXERR_FILT; | 453 | ts->ts_status |= AR5K_TXERR_FILT; |
474 | } | 454 | } |
475 | 455 | ||
476 | return 0; | 456 | return 0; |
477 | } | 457 | } |
478 | 458 | ||
479 | /* | 459 | |
480 | * RX Descriptors | 460 | /****************\ |
481 | */ | 461 | * RX Descriptors * |
462 | \****************/ | ||
482 | 463 | ||
483 | /* | 464 | /* |
484 | * Initialize an rx control descriptor | 465 | * Initialize an rx control descriptor |
@@ -512,7 +493,7 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
512 | } | 493 | } |
513 | 494 | ||
514 | /* | 495 | /* |
515 | * Proccess the rx status descriptor on 5210/5211 | 496 | * Process the rx status descriptor on 5210/5211 |
516 | */ | 497 | */ |
517 | static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | 498 | static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, |
518 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) | 499 | struct ath5k_desc *desc, struct ath5k_rx_status *rs) |
@@ -595,44 +576,44 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, | |||
595 | } | 576 | } |
596 | 577 | ||
597 | /* | 578 | /* |
598 | * Proccess the rx status descriptor on 5212 | 579 | * Process the rx status descriptor on 5212 |
599 | */ | 580 | */ |
600 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | 581 | static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, |
601 | struct ath5k_desc *desc, | 582 | struct ath5k_desc *desc, |
602 | struct ath5k_rx_status *rs) | 583 | struct ath5k_rx_status *rs) |
603 | { | 584 | { |
604 | struct ath5k_hw_rx_status *rx_status; | 585 | struct ath5k_hw_rx_status *rx_status; |
586 | u32 rxstat0, rxstat1; | ||
605 | 587 | ||
606 | rx_status = &desc->ud.ds_rx.rx_stat; | 588 | rx_status = &desc->ud.ds_rx.rx_stat; |
589 | rxstat1 = ACCESS_ONCE(rx_status->rx_status_1); | ||
607 | 590 | ||
608 | /* No frame received / not ready */ | 591 | /* No frame received / not ready */ |
609 | if (unlikely(!(rx_status->rx_status_1 & | 592 | if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE))) |
610 | AR5K_5212_RX_DESC_STATUS1_DONE))) | ||
611 | return -EINPROGRESS; | 593 | return -EINPROGRESS; |
612 | 594 | ||
613 | memset(rs, 0, sizeof(struct ath5k_rx_status)); | 595 | memset(rs, 0, sizeof(struct ath5k_rx_status)); |
596 | rxstat0 = ACCESS_ONCE(rx_status->rx_status_0); | ||
614 | 597 | ||
615 | /* | 598 | /* |
616 | * Frame receive status | 599 | * Frame receive status |
617 | */ | 600 | */ |
618 | rs->rs_datalen = rx_status->rx_status_0 & | 601 | rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN; |
619 | AR5K_5212_RX_DESC_STATUS0_DATA_LEN; | 602 | rs->rs_rssi = AR5K_REG_MS(rxstat0, |
620 | rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, | ||
621 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); | 603 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); |
622 | rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, | 604 | rs->rs_rate = AR5K_REG_MS(rxstat0, |
623 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); | 605 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); |
624 | rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, | 606 | rs->rs_antenna = AR5K_REG_MS(rxstat0, |
625 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); | 607 | AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); |
626 | rs->rs_more = !!(rx_status->rx_status_0 & | 608 | rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE); |
627 | AR5K_5212_RX_DESC_STATUS0_MORE); | 609 | rs->rs_tstamp = AR5K_REG_MS(rxstat1, |
628 | rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, | ||
629 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); | 610 | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); |
630 | 611 | ||
631 | /* | 612 | /* |
632 | * Key table status | 613 | * Key table status |
633 | */ | 614 | */ |
634 | if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) | 615 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) |
635 | rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, | 616 | rs->rs_keyix = AR5K_REG_MS(rxstat1, |
636 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); | 617 | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); |
637 | else | 618 | else |
638 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; | 619 | rs->rs_keyix = AR5K_RXKEYIX_INVALID; |
@@ -640,32 +621,32 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
640 | /* | 621 | /* |
641 | * Receive/descriptor errors | 622 | * Receive/descriptor errors |
642 | */ | 623 | */ |
643 | if (!(rx_status->rx_status_1 & | 624 | if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { |
644 | AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { | 625 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) |
645 | if (rx_status->rx_status_1 & | ||
646 | AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) | ||
647 | rs->rs_status |= AR5K_RXERR_CRC; | 626 | rs->rs_status |= AR5K_RXERR_CRC; |
648 | 627 | ||
649 | if (rx_status->rx_status_1 & | 628 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { |
650 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { | ||
651 | rs->rs_status |= AR5K_RXERR_PHY; | 629 | rs->rs_status |= AR5K_RXERR_PHY; |
652 | rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, | 630 | rs->rs_phyerr = AR5K_REG_MS(rxstat1, |
653 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); | 631 | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); |
654 | if (!ah->ah_capabilities.cap_has_phyerr_counters) | 632 | if (!ah->ah_capabilities.cap_has_phyerr_counters) |
655 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); | 633 | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); |
656 | } | 634 | } |
657 | 635 | ||
658 | if (rx_status->rx_status_1 & | 636 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) |
659 | AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) | ||
660 | rs->rs_status |= AR5K_RXERR_DECRYPT; | 637 | rs->rs_status |= AR5K_RXERR_DECRYPT; |
661 | 638 | ||
662 | if (rx_status->rx_status_1 & | 639 | if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) |
663 | AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) | ||
664 | rs->rs_status |= AR5K_RXERR_MIC; | 640 | rs->rs_status |= AR5K_RXERR_MIC; |
665 | } | 641 | } |
666 | return 0; | 642 | return 0; |
667 | } | 643 | } |
668 | 644 | ||
645 | |||
646 | /********\ | ||
647 | * Attach * | ||
648 | \********/ | ||
649 | |||
669 | /* | 650 | /* |
670 | * Init function pointers inside ath5k_hw struct | 651 | * Init function pointers inside ath5k_hw struct |
671 | */ | 652 | */ |
diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h index b2adb2a281c2..2509d0bf037d 100644 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ b/drivers/net/wireless/ath/ath5k/desc.h | |||
@@ -26,7 +26,7 @@ | |||
26 | struct ath5k_hw_rx_ctl { | 26 | struct ath5k_hw_rx_ctl { |
27 | u32 rx_control_0; /* RX control word 0 */ | 27 | u32 rx_control_0; /* RX control word 0 */ |
28 | u32 rx_control_1; /* RX control word 1 */ | 28 | u32 rx_control_1; /* RX control word 1 */ |
29 | } __packed; | 29 | } __packed __aligned(4); |
30 | 30 | ||
31 | /* RX control word 1 fields/flags */ | 31 | /* RX control word 1 fields/flags */ |
32 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ | 32 | #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ |
@@ -39,7 +39,7 @@ struct ath5k_hw_rx_ctl { | |||
39 | struct ath5k_hw_rx_status { | 39 | struct ath5k_hw_rx_status { |
40 | u32 rx_status_0; /* RX status word 0 */ | 40 | u32 rx_status_0; /* RX status word 0 */ |
41 | u32 rx_status_1; /* RX status word 1 */ | 41 | u32 rx_status_1; /* RX status word 1 */ |
42 | } __packed; | 42 | } __packed __aligned(4); |
43 | 43 | ||
44 | /* 5210/5211 */ | 44 | /* 5210/5211 */ |
45 | /* RX status word 0 fields/flags */ | 45 | /* RX status word 0 fields/flags */ |
@@ -129,7 +129,7 @@ enum ath5k_phy_error_code { | |||
129 | struct ath5k_hw_2w_tx_ctl { | 129 | struct ath5k_hw_2w_tx_ctl { |
130 | u32 tx_control_0; /* TX control word 0 */ | 130 | u32 tx_control_0; /* TX control word 0 */ |
131 | u32 tx_control_1; /* TX control word 1 */ | 131 | u32 tx_control_1; /* TX control word 1 */ |
132 | } __packed; | 132 | } __packed __aligned(4); |
133 | 133 | ||
134 | /* TX control word 0 fields/flags */ | 134 | /* TX control word 0 fields/flags */ |
135 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ | 135 | #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ |
@@ -185,7 +185,7 @@ struct ath5k_hw_4w_tx_ctl { | |||
185 | u32 tx_control_1; /* TX control word 1 */ | 185 | u32 tx_control_1; /* TX control word 1 */ |
186 | u32 tx_control_2; /* TX control word 2 */ | 186 | u32 tx_control_2; /* TX control word 2 */ |
187 | u32 tx_control_3; /* TX control word 3 */ | 187 | u32 tx_control_3; /* TX control word 3 */ |
188 | } __packed; | 188 | } __packed __aligned(4); |
189 | 189 | ||
190 | /* TX control word 0 fields/flags */ | 190 | /* TX control word 0 fields/flags */ |
191 | #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ | 191 | #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */ |
@@ -244,7 +244,7 @@ struct ath5k_hw_4w_tx_ctl { | |||
244 | struct ath5k_hw_tx_status { | 244 | struct ath5k_hw_tx_status { |
245 | u32 tx_status_0; /* TX status word 0 */ | 245 | u32 tx_status_0; /* TX status word 0 */ |
246 | u32 tx_status_1; /* TX status word 1 */ | 246 | u32 tx_status_1; /* TX status word 1 */ |
247 | } __packed; | 247 | } __packed __aligned(4); |
248 | 248 | ||
249 | /* TX status word 0 fields/flags */ | 249 | /* TX status word 0 fields/flags */ |
250 | #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 /* TX success */ | 250 | #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 /* TX success */ |
@@ -282,7 +282,7 @@ struct ath5k_hw_tx_status { | |||
282 | struct ath5k_hw_5210_tx_desc { | 282 | struct ath5k_hw_5210_tx_desc { |
283 | struct ath5k_hw_2w_tx_ctl tx_ctl; | 283 | struct ath5k_hw_2w_tx_ctl tx_ctl; |
284 | struct ath5k_hw_tx_status tx_stat; | 284 | struct ath5k_hw_tx_status tx_stat; |
285 | } __packed; | 285 | } __packed __aligned(4); |
286 | 286 | ||
287 | /* | 287 | /* |
288 | * 5212 hardware TX descriptor | 288 | * 5212 hardware TX descriptor |
@@ -290,7 +290,7 @@ struct ath5k_hw_5210_tx_desc { | |||
290 | struct ath5k_hw_5212_tx_desc { | 290 | struct ath5k_hw_5212_tx_desc { |
291 | struct ath5k_hw_4w_tx_ctl tx_ctl; | 291 | struct ath5k_hw_4w_tx_ctl tx_ctl; |
292 | struct ath5k_hw_tx_status tx_stat; | 292 | struct ath5k_hw_tx_status tx_stat; |
293 | } __packed; | 293 | } __packed __aligned(4); |
294 | 294 | ||
295 | /* | 295 | /* |
296 | * Common hardware RX descriptor | 296 | * Common hardware RX descriptor |
@@ -298,7 +298,7 @@ struct ath5k_hw_5212_tx_desc { | |||
298 | struct ath5k_hw_all_rx_desc { | 298 | struct ath5k_hw_all_rx_desc { |
299 | struct ath5k_hw_rx_ctl rx_ctl; | 299 | struct ath5k_hw_rx_ctl rx_ctl; |
300 | struct ath5k_hw_rx_status rx_stat; | 300 | struct ath5k_hw_rx_status rx_stat; |
301 | } __packed; | 301 | } __packed __aligned(4); |
302 | 302 | ||
303 | /* | 303 | /* |
304 | * Atheros hardware DMA descriptor | 304 | * Atheros hardware DMA descriptor |
@@ -313,7 +313,7 @@ struct ath5k_desc { | |||
313 | struct ath5k_hw_5212_tx_desc ds_tx5212; | 313 | struct ath5k_hw_5212_tx_desc ds_tx5212; |
314 | struct ath5k_hw_all_rx_desc ds_rx; | 314 | struct ath5k_hw_all_rx_desc ds_rx; |
315 | } ud; | 315 | } ud; |
316 | } __packed; | 316 | } __packed __aligned(4); |
317 | 317 | ||
318 | #define AR5K_RXDESC_INTREQ 0x0020 | 318 | #define AR5K_RXDESC_INTREQ 0x0020 |
319 | 319 | ||
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 484f31870ba8..21091c26a9a5 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "debug.h" | 37 | #include "debug.h" |
38 | #include "base.h" | 38 | #include "base.h" |
39 | 39 | ||
40 | |||
40 | /*********\ | 41 | /*********\ |
41 | * Receive * | 42 | * Receive * |
42 | \*********/ | 43 | \*********/ |
@@ -57,7 +58,7 @@ void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) | |||
57 | * | 58 | * |
58 | * @ah: The &struct ath5k_hw | 59 | * @ah: The &struct ath5k_hw |
59 | */ | 60 | */ |
60 | int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | 61 | static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) |
61 | { | 62 | { |
62 | unsigned int i; | 63 | unsigned int i; |
63 | 64 | ||
@@ -69,7 +70,11 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) | |||
69 | for (i = 1000; i > 0 && | 70 | for (i = 1000; i > 0 && |
70 | (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; | 71 | (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; |
71 | i--) | 72 | i--) |
72 | udelay(10); | 73 | udelay(100); |
74 | |||
75 | if (!i) | ||
76 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, | ||
77 | "failed to stop RX DMA !\n"); | ||
73 | 78 | ||
74 | return i ? 0 : -EBUSY; | 79 | return i ? 0 : -EBUSY; |
75 | } | 80 | } |
@@ -90,11 +95,18 @@ u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) | |||
90 | * @ah: The &struct ath5k_hw | 95 | * @ah: The &struct ath5k_hw |
91 | * @phys_addr: RX descriptor address | 96 | * @phys_addr: RX descriptor address |
92 | * | 97 | * |
93 | * XXX: Should we check if rx is enabled before setting rxdp ? | 98 | * Returns -EIO if rx is active |
94 | */ | 99 | */ |
95 | void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) | 100 | int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) |
96 | { | 101 | { |
102 | if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) { | ||
103 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, | ||
104 | "tried to set RXDP while rx was active !\n"); | ||
105 | return -EIO; | ||
106 | } | ||
107 | |||
97 | ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); | 108 | ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); |
109 | return 0; | ||
98 | } | 110 | } |
99 | 111 | ||
100 | 112 | ||
@@ -125,7 +137,7 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
125 | 137 | ||
126 | /* Return if queue is declared inactive */ | 138 | /* Return if queue is declared inactive */ |
127 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | 139 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) |
128 | return -EIO; | 140 | return -EINVAL; |
129 | 141 | ||
130 | if (ah->ah_version == AR5K_AR5210) { | 142 | if (ah->ah_version == AR5K_AR5210) { |
131 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | 143 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); |
@@ -173,10 +185,10 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
173 | * | 185 | * |
174 | * Stop DMA transmit on a specific hw queue and drain queue so we don't | 186 | * Stop DMA transmit on a specific hw queue and drain queue so we don't |
175 | * have any pending frames. Returns -EBUSY if we still have pending frames, | 187 | * have any pending frames. Returns -EBUSY if we still have pending frames, |
176 | * -EINVAL if queue number is out of range. | 188 | * -EINVAL if queue number is out of range or inactive. |
177 | * | 189 | * |
178 | */ | 190 | */ |
179 | int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | 191 | static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) |
180 | { | 192 | { |
181 | unsigned int i = 40; | 193 | unsigned int i = 40; |
182 | u32 tx_queue, pending; | 194 | u32 tx_queue, pending; |
@@ -185,7 +197,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
185 | 197 | ||
186 | /* Return if queue is declared inactive */ | 198 | /* Return if queue is declared inactive */ |
187 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | 199 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) |
188 | return -EIO; | 200 | return -EINVAL; |
189 | 201 | ||
190 | if (ah->ah_version == AR5K_AR5210) { | 202 | if (ah->ah_version == AR5K_AR5210) { |
191 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); | 203 | tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); |
@@ -211,12 +223,31 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
211 | ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); | 223 | ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); |
212 | ath5k_hw_reg_read(ah, AR5K_CR); | 224 | ath5k_hw_reg_read(ah, AR5K_CR); |
213 | } else { | 225 | } else { |
226 | |||
227 | /* | ||
228 | * Enable DCU early termination to quickly | ||
229 | * flush any pending frames from QCU | ||
230 | */ | ||
231 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
232 | AR5K_QCU_MISC_DCU_EARLY); | ||
233 | |||
214 | /* | 234 | /* |
215 | * Schedule TX disable and wait until queue is empty | 235 | * Schedule TX disable and wait until queue is empty |
216 | */ | 236 | */ |
217 | AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); | 237 | AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); |
218 | 238 | ||
219 | /*Check for pending frames*/ | 239 | /* Wait for queue to stop */ |
240 | for (i = 1000; i > 0 && | ||
241 | (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue) != 0); | ||
242 | i--) | ||
243 | udelay(100); | ||
244 | |||
245 | if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
246 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, | ||
247 | "queue %i didn't stop !\n", queue); | ||
248 | |||
249 | /* Check for pending frames */ | ||
250 | i = 1000; | ||
220 | do { | 251 | do { |
221 | pending = ath5k_hw_reg_read(ah, | 252 | pending = ath5k_hw_reg_read(ah, |
222 | AR5K_QUEUE_STATUS(queue)) & | 253 | AR5K_QUEUE_STATUS(queue)) & |
@@ -244,15 +275,15 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
244 | 275 | ||
245 | /* Force channel idle high */ | 276 | /* Force channel idle high */ |
246 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, | 277 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, |
247 | AR5K_DIAG_SW_CHANEL_IDLE_HIGH); | 278 | AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); |
248 | 279 | ||
249 | /* Wait a while and disable mechanism */ | 280 | /* Wait a while and disable mechanism */ |
250 | udelay(200); | 281 | udelay(400); |
251 | AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, | 282 | AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, |
252 | AR5K_QUIET_CTL1_QT_EN); | 283 | AR5K_QUIET_CTL1_QT_EN); |
253 | 284 | ||
254 | /* Re-check for pending frames */ | 285 | /* Re-check for pending frames */ |
255 | i = 40; | 286 | i = 100; |
256 | do { | 287 | do { |
257 | pending = ath5k_hw_reg_read(ah, | 288 | pending = ath5k_hw_reg_read(ah, |
258 | AR5K_QUEUE_STATUS(queue)) & | 289 | AR5K_QUEUE_STATUS(queue)) & |
@@ -261,13 +292,28 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
261 | } while (--i && pending); | 292 | } while (--i && pending); |
262 | 293 | ||
263 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, | 294 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, |
264 | AR5K_DIAG_SW_CHANEL_IDLE_HIGH); | 295 | AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); |
296 | |||
297 | if (pending) | ||
298 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, | ||
299 | "quiet mechanism didn't work q:%i !\n", | ||
300 | queue); | ||
265 | } | 301 | } |
266 | 302 | ||
303 | /* | ||
304 | * Disable DCU early termination | ||
305 | */ | ||
306 | AR5K_REG_DISABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | ||
307 | AR5K_QCU_MISC_DCU_EARLY); | ||
308 | |||
267 | /* Clear register */ | 309 | /* Clear register */ |
268 | ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); | 310 | ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); |
269 | if (pending) | 311 | if (pending) { |
312 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, | ||
313 | "tx dma didn't stop (q:%i, frm:%i) !\n", | ||
314 | queue, pending); | ||
270 | return -EBUSY; | 315 | return -EBUSY; |
316 | } | ||
271 | } | 317 | } |
272 | 318 | ||
273 | /* TODO: Check for success on 5210 else return error */ | 319 | /* TODO: Check for success on 5210 else return error */ |
@@ -275,6 +321,26 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) | |||
275 | } | 321 | } |
276 | 322 | ||
277 | /** | 323 | /** |
324 | * ath5k_hw_stop_beacon_queue - Stop beacon queue | ||
325 | * | ||
326 | * @ah The &struct ath5k_hw | ||
327 | * @queue The queue number | ||
328 | * | ||
329 | * Returns -EIO if queue didn't stop | ||
330 | */ | ||
331 | int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) | ||
332 | { | ||
333 | int ret; | ||
334 | ret = ath5k_hw_stop_tx_dma(ah, queue); | ||
335 | if (ret) { | ||
336 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_DMA, | ||
337 | "beacon queue didn't stop !\n"); | ||
338 | return -EIO; | ||
339 | } | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | /** | ||
278 | * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue | 344 | * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue |
279 | * | 345 | * |
280 | * @ah: The &struct ath5k_hw | 346 | * @ah: The &struct ath5k_hw |
@@ -377,11 +443,11 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | |||
377 | * | 443 | * |
378 | * This function increases/decreases the tx trigger level for the tx fifo | 444 | * This function increases/decreases the tx trigger level for the tx fifo |
379 | * buffer (aka FIFO threshold) that is used to indicate when PCU flushes | 445 | * buffer (aka FIFO threshold) that is used to indicate when PCU flushes |
380 | * the buffer and transmits it's data. Lowering this results sending small | 446 | * the buffer and transmits its data. Lowering this results sending small |
381 | * frames more quickly but can lead to tx underruns, raising it a lot can | 447 | * frames more quickly but can lead to tx underruns, raising it a lot can |
382 | * result other problems (i think bmiss is related). Right now we start with | 448 | * result other problems (i think bmiss is related). Right now we start with |
383 | * the lowest possible (64Bytes) and if we get tx underrun we increase it using | 449 | * the lowest possible (64Bytes) and if we get tx underrun we increase it using |
384 | * the increase flag. Returns -EIO if we have have reached maximum/minimum. | 450 | * the increase flag. Returns -EIO if we have reached maximum/minimum. |
385 | * | 451 | * |
386 | * XXX: Link this with tx DMA size ? | 452 | * XXX: Link this with tx DMA size ? |
387 | * XXX: Use it to save interrupts ? | 453 | * XXX: Use it to save interrupts ? |
@@ -427,6 +493,7 @@ done: | |||
427 | return ret; | 493 | return ret; |
428 | } | 494 | } |
429 | 495 | ||
496 | |||
430 | /*******************\ | 497 | /*******************\ |
431 | * Interrupt masking * | 498 | * Interrupt masking * |
432 | \*******************/ | 499 | \*******************/ |
@@ -688,3 +755,92 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | |||
688 | return old_mask; | 755 | return old_mask; |
689 | } | 756 | } |
690 | 757 | ||
758 | |||
759 | /********************\ | ||
760 | Init/Stop functions | ||
761 | \********************/ | ||
762 | |||
763 | /** | ||
764 | * ath5k_hw_dma_init - Initialize DMA unit | ||
765 | * | ||
766 | * @ah: The &struct ath5k_hw | ||
767 | * | ||
768 | * Set DMA size and pre-enable interrupts | ||
769 | * (driver handles tx/rx buffer setup and | ||
770 | * dma start/stop) | ||
771 | * | ||
772 | * XXX: Save/restore RXDP/TXDP registers ? | ||
773 | */ | ||
774 | void ath5k_hw_dma_init(struct ath5k_hw *ah) | ||
775 | { | ||
776 | /* | ||
777 | * Set Rx/Tx DMA Configuration | ||
778 | * | ||
779 | * Set standard DMA size (128). Note that | ||
780 | * a DMA size of 512 causes rx overruns and tx errors | ||
781 | * on pci-e cards (tested on 5424 but since rx overruns | ||
782 | * also occur on 5416/5418 with madwifi we set 128 | ||
783 | * for all PCI-E cards to be safe). | ||
784 | * | ||
785 | * XXX: need to check 5210 for this | ||
786 | * TODO: Check out tx triger level, it's always 64 on dumps but I | ||
787 | * guess we can tweak it and see how it goes ;-) | ||
788 | */ | ||
789 | if (ah->ah_version != AR5K_AR5210) { | ||
790 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | ||
791 | AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); | ||
792 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, | ||
793 | AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); | ||
794 | } | ||
795 | |||
796 | /* Pre-enable interrupts on 5211/5212*/ | ||
797 | if (ah->ah_version != AR5K_AR5210) | ||
798 | ath5k_hw_set_imr(ah, ah->ah_imr); | ||
799 | |||
800 | } | ||
801 | |||
802 | /** | ||
803 | * ath5k_hw_dma_stop - stop DMA unit | ||
804 | * | ||
805 | * @ah: The &struct ath5k_hw | ||
806 | * | ||
807 | * Stop tx/rx DMA and interrupts. Returns | ||
808 | * -EBUSY if tx or rx dma failed to stop. | ||
809 | * | ||
810 | * XXX: Sometimes DMA unit hangs and we have | ||
811 | * stuck frames on tx queues, only a reset | ||
812 | * can fix that. | ||
813 | */ | ||
814 | int ath5k_hw_dma_stop(struct ath5k_hw *ah) | ||
815 | { | ||
816 | int i, qmax, err; | ||
817 | err = 0; | ||
818 | |||
819 | /* Disable interrupts */ | ||
820 | ath5k_hw_set_imr(ah, 0); | ||
821 | |||
822 | /* Stop rx dma */ | ||
823 | err = ath5k_hw_stop_rx_dma(ah); | ||
824 | if (err) | ||
825 | return err; | ||
826 | |||
827 | /* Clear any pending interrupts | ||
828 | * and disable tx dma */ | ||
829 | if (ah->ah_version != AR5K_AR5210) { | ||
830 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); | ||
831 | qmax = AR5K_NUM_TX_QUEUES; | ||
832 | } else { | ||
833 | /* PISR/SISR Not available on 5210 */ | ||
834 | ath5k_hw_reg_read(ah, AR5K_ISR); | ||
835 | qmax = AR5K_NUM_TX_QUEUES_NOQCU; | ||
836 | } | ||
837 | |||
838 | for (i = 0; i < qmax; i++) { | ||
839 | err = ath5k_hw_stop_tx_dma(ah, i); | ||
840 | /* -EINVAL -> queue inactive */ | ||
841 | if (err && err != -EINVAL) | ||
842 | return err; | ||
843 | } | ||
844 | |||
845 | return 0; | ||
846 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index ae316fec4a6a..392771f93759 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -28,45 +28,16 @@ | |||
28 | #include "debug.h" | 28 | #include "debug.h" |
29 | #include "base.h" | 29 | #include "base.h" |
30 | 30 | ||
31 | /* | ||
32 | * Read from eeprom | ||
33 | */ | ||
34 | static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) | ||
35 | { | ||
36 | u32 status, timeout; | ||
37 | |||
38 | /* | ||
39 | * Initialize EEPROM access | ||
40 | */ | ||
41 | if (ah->ah_version == AR5K_AR5210) { | ||
42 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); | ||
43 | (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); | ||
44 | } else { | ||
45 | ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); | ||
46 | AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, | ||
47 | AR5K_EEPROM_CMD_READ); | ||
48 | } | ||
49 | |||
50 | for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { | ||
51 | status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); | ||
52 | if (status & AR5K_EEPROM_STAT_RDDONE) { | ||
53 | if (status & AR5K_EEPROM_STAT_RDERR) | ||
54 | return -EIO; | ||
55 | *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & | ||
56 | 0xffff); | ||
57 | return 0; | ||
58 | } | ||
59 | udelay(15); | ||
60 | } | ||
61 | 31 | ||
62 | return -ETIMEDOUT; | 32 | /******************\ |
63 | } | 33 | * Helper functions * |
34 | \******************/ | ||
64 | 35 | ||
65 | /* | 36 | /* |
66 | * Translate binary channel representation in EEPROM to frequency | 37 | * Translate binary channel representation in EEPROM to frequency |
67 | */ | 38 | */ |
68 | static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, | 39 | static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, |
69 | unsigned int mode) | 40 | unsigned int mode) |
70 | { | 41 | { |
71 | u16 val; | 42 | u16 val; |
72 | 43 | ||
@@ -89,6 +60,11 @@ static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, | |||
89 | return val; | 60 | return val; |
90 | } | 61 | } |
91 | 62 | ||
63 | |||
64 | /*********\ | ||
65 | * Parsers * | ||
66 | \*********/ | ||
67 | |||
92 | /* | 68 | /* |
93 | * Initialize eeprom & capabilities structs | 69 | * Initialize eeprom & capabilities structs |
94 | */ | 70 | */ |
@@ -96,7 +72,6 @@ static int | |||
96 | ath5k_eeprom_init_header(struct ath5k_hw *ah) | 72 | ath5k_eeprom_init_header(struct ath5k_hw *ah) |
97 | { | 73 | { |
98 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 74 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
99 | int ret; | ||
100 | u16 val; | 75 | u16 val; |
101 | u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; | 76 | u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; |
102 | 77 | ||
@@ -198,7 +173,7 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah) | |||
198 | * | 173 | * |
199 | * XXX: Serdes values seem to be fixed so | 174 | * XXX: Serdes values seem to be fixed so |
200 | * no need to read them here, we write them | 175 | * no need to read them here, we write them |
201 | * during ath5k_hw_attach */ | 176 | * during ath5k_hw_init */ |
202 | AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val); | 177 | AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val); |
203 | ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ? | 178 | ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ? |
204 | true : false; | 179 | true : false; |
@@ -216,7 +191,7 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, | |||
216 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 191 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
217 | u32 o = *offset; | 192 | u32 o = *offset; |
218 | u16 val; | 193 | u16 val; |
219 | int ret, i = 0; | 194 | int i = 0; |
220 | 195 | ||
221 | AR5K_EEPROM_READ(o++, val); | 196 | AR5K_EEPROM_READ(o++, val); |
222 | ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; | 197 | ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; |
@@ -276,7 +251,6 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, | |||
276 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 251 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
277 | u32 o = *offset; | 252 | u32 o = *offset; |
278 | u16 val; | 253 | u16 val; |
279 | int ret; | ||
280 | 254 | ||
281 | ee->ee_n_piers[mode] = 0; | 255 | ee->ee_n_piers[mode] = 0; |
282 | AR5K_EEPROM_READ(o++, val); | 256 | AR5K_EEPROM_READ(o++, val); |
@@ -539,7 +513,6 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, | |||
539 | int o = *offset; | 513 | int o = *offset; |
540 | int i = 0; | 514 | int i = 0; |
541 | u8 freq1, freq2; | 515 | u8 freq1, freq2; |
542 | int ret; | ||
543 | u16 val; | 516 | u16 val; |
544 | 517 | ||
545 | ee->ee_n_piers[mode] = 0; | 518 | ee->ee_n_piers[mode] = 0; |
@@ -575,7 +548,7 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) | |||
575 | { | 548 | { |
576 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 549 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
577 | struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; | 550 | struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; |
578 | int i, ret; | 551 | int i; |
579 | u16 val; | 552 | u16 val; |
580 | u8 mask; | 553 | u8 mask; |
581 | 554 | ||
@@ -647,6 +620,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) | |||
647 | return 0; | 620 | return 0; |
648 | } | 621 | } |
649 | 622 | ||
623 | |||
650 | /* | 624 | /* |
651 | * Read power calibration for RF5111 chips | 625 | * Read power calibration for RF5111 chips |
652 | * | 626 | * |
@@ -661,7 +635,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) | |||
661 | * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC | 635 | * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC |
662 | * steps that match with the power values we read from eeprom. On | 636 | * steps that match with the power values we read from eeprom. On |
663 | * older eeprom versions (< 3.2) these steps are equaly spaced at | 637 | * older eeprom versions (< 3.2) these steps are equaly spaced at |
664 | * 10% of the pcdac curve -until the curve reaches it's maximum- | 638 | * 10% of the pcdac curve -until the curve reaches its maximum- |
665 | * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) | 639 | * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) |
666 | * these 11 steps are spaced in a different way. This function returns | 640 | * these 11 steps are spaced in a different way. This function returns |
667 | * the pcdac steps based on eeprom version and curve min/max so that we | 641 | * the pcdac steps based on eeprom version and curve min/max so that we |
@@ -686,6 +660,51 @@ ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) | |||
686 | vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; | 660 | vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; |
687 | } | 661 | } |
688 | 662 | ||
663 | static int | ||
664 | ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) | ||
665 | { | ||
666 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
667 | struct ath5k_chan_pcal_info *chinfo; | ||
668 | u8 pier, pdg; | ||
669 | |||
670 | switch (mode) { | ||
671 | case AR5K_EEPROM_MODE_11A: | ||
672 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
673 | return 0; | ||
674 | chinfo = ee->ee_pwr_cal_a; | ||
675 | break; | ||
676 | case AR5K_EEPROM_MODE_11B: | ||
677 | if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) | ||
678 | return 0; | ||
679 | chinfo = ee->ee_pwr_cal_b; | ||
680 | break; | ||
681 | case AR5K_EEPROM_MODE_11G: | ||
682 | if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) | ||
683 | return 0; | ||
684 | chinfo = ee->ee_pwr_cal_g; | ||
685 | break; | ||
686 | default: | ||
687 | return -EINVAL; | ||
688 | } | ||
689 | |||
690 | for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { | ||
691 | if (!chinfo[pier].pd_curves) | ||
692 | continue; | ||
693 | |||
694 | for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) { | ||
695 | struct ath5k_pdgain_info *pd = | ||
696 | &chinfo[pier].pd_curves[pdg]; | ||
697 | |||
698 | kfree(pd->pd_step); | ||
699 | kfree(pd->pd_pwr); | ||
700 | } | ||
701 | |||
702 | kfree(chinfo[pier].pd_curves); | ||
703 | } | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | |||
689 | /* Convert RF5111 specific data to generic raw data | 708 | /* Convert RF5111 specific data to generic raw data |
690 | * used by interpolation code */ | 709 | * used by interpolation code */ |
691 | static int | 710 | static int |
@@ -710,7 +729,7 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
710 | GFP_KERNEL); | 729 | GFP_KERNEL); |
711 | 730 | ||
712 | if (!chinfo[pier].pd_curves) | 731 | if (!chinfo[pier].pd_curves) |
713 | return -ENOMEM; | 732 | goto err_out; |
714 | 733 | ||
715 | /* Only one curve for RF5111 | 734 | /* Only one curve for RF5111 |
716 | * find out which one and place | 735 | * find out which one and place |
@@ -734,12 +753,12 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
734 | pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, | 753 | pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, |
735 | sizeof(u8), GFP_KERNEL); | 754 | sizeof(u8), GFP_KERNEL); |
736 | if (!pd->pd_step) | 755 | if (!pd->pd_step) |
737 | return -ENOMEM; | 756 | goto err_out; |
738 | 757 | ||
739 | pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, | 758 | pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, |
740 | sizeof(s16), GFP_KERNEL); | 759 | sizeof(s16), GFP_KERNEL); |
741 | if (!pd->pd_pwr) | 760 | if (!pd->pd_pwr) |
742 | return -ENOMEM; | 761 | goto err_out; |
743 | 762 | ||
744 | /* Fill raw dataset | 763 | /* Fill raw dataset |
745 | * (convert power to 0.25dB units | 764 | * (convert power to 0.25dB units |
@@ -760,6 +779,10 @@ ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, | |||
760 | } | 779 | } |
761 | 780 | ||
762 | return 0; | 781 | return 0; |
782 | |||
783 | err_out: | ||
784 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
785 | return -ENOMEM; | ||
763 | } | 786 | } |
764 | 787 | ||
765 | /* Parse EEPROM data */ | 788 | /* Parse EEPROM data */ |
@@ -893,7 +916,7 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
893 | GFP_KERNEL); | 916 | GFP_KERNEL); |
894 | 917 | ||
895 | if (!chinfo[pier].pd_curves) | 918 | if (!chinfo[pier].pd_curves) |
896 | return -ENOMEM; | 919 | goto err_out; |
897 | 920 | ||
898 | /* Fill pd_curves */ | 921 | /* Fill pd_curves */ |
899 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | 922 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { |
@@ -912,14 +935,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
912 | sizeof(u8), GFP_KERNEL); | 935 | sizeof(u8), GFP_KERNEL); |
913 | 936 | ||
914 | if (!pd->pd_step) | 937 | if (!pd->pd_step) |
915 | return -ENOMEM; | 938 | goto err_out; |
916 | 939 | ||
917 | pd->pd_pwr = kcalloc(pd->pd_points, | 940 | pd->pd_pwr = kcalloc(pd->pd_points, |
918 | sizeof(s16), GFP_KERNEL); | 941 | sizeof(s16), GFP_KERNEL); |
919 | 942 | ||
920 | if (!pd->pd_pwr) | 943 | if (!pd->pd_pwr) |
921 | return -ENOMEM; | 944 | goto err_out; |
922 | |||
923 | 945 | ||
924 | /* Fill raw dataset | 946 | /* Fill raw dataset |
925 | * (all power levels are in 0.25dB units) */ | 947 | * (all power levels are in 0.25dB units) */ |
@@ -951,13 +973,13 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
951 | sizeof(u8), GFP_KERNEL); | 973 | sizeof(u8), GFP_KERNEL); |
952 | 974 | ||
953 | if (!pd->pd_step) | 975 | if (!pd->pd_step) |
954 | return -ENOMEM; | 976 | goto err_out; |
955 | 977 | ||
956 | pd->pd_pwr = kcalloc(pd->pd_points, | 978 | pd->pd_pwr = kcalloc(pd->pd_points, |
957 | sizeof(s16), GFP_KERNEL); | 979 | sizeof(s16), GFP_KERNEL); |
958 | 980 | ||
959 | if (!pd->pd_pwr) | 981 | if (!pd->pd_pwr) |
960 | return -ENOMEM; | 982 | goto err_out; |
961 | 983 | ||
962 | /* Fill raw dataset | 984 | /* Fill raw dataset |
963 | * (all power levels are in 0.25dB units) */ | 985 | * (all power levels are in 0.25dB units) */ |
@@ -980,6 +1002,10 @@ ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, | |||
980 | } | 1002 | } |
981 | 1003 | ||
982 | return 0; | 1004 | return 0; |
1005 | |||
1006 | err_out: | ||
1007 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
1008 | return -ENOMEM; | ||
983 | } | 1009 | } |
984 | 1010 | ||
985 | /* Parse EEPROM data */ | 1011 | /* Parse EEPROM data */ |
@@ -993,7 +1019,6 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) | |||
993 | u32 offset; | 1019 | u32 offset; |
994 | u8 i, c; | 1020 | u8 i, c; |
995 | u16 val; | 1021 | u16 val; |
996 | int ret; | ||
997 | u8 pd_gains = 0; | 1022 | u8 pd_gains = 0; |
998 | 1023 | ||
999 | /* Count how many curves we have and | 1024 | /* Count how many curves we have and |
@@ -1107,13 +1132,13 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) | |||
1107 | * | 1132 | * |
1108 | * To recreate the curves we read here the points and interpolate | 1133 | * To recreate the curves we read here the points and interpolate |
1109 | * later. Note that in most cases only 2 (higher and lower) curves are | 1134 | * later. Note that in most cases only 2 (higher and lower) curves are |
1110 | * used (like RF5112) but vendors have the oportunity to include all | 1135 | * used (like RF5112) but vendors have the opportunity to include all |
1111 | * 4 curves on eeprom. The final curve (higher power) has an extra | 1136 | * 4 curves on eeprom. The final curve (higher power) has an extra |
1112 | * point for better accuracy like RF5112. | 1137 | * point for better accuracy like RF5112. |
1113 | */ | 1138 | */ |
1114 | 1139 | ||
1115 | /* For RF2413 power calibration data doesn't start on a fixed location and | 1140 | /* For RF2413 power calibration data doesn't start on a fixed location and |
1116 | * if a mode is not supported, it's section is missing -not zeroed-. | 1141 | * if a mode is not supported, its section is missing -not zeroed-. |
1117 | * So we need to calculate the starting offset for each section by using | 1142 | * So we need to calculate the starting offset for each section by using |
1118 | * these two functions */ | 1143 | * these two functions */ |
1119 | 1144 | ||
@@ -1183,7 +1208,7 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, | |||
1183 | GFP_KERNEL); | 1208 | GFP_KERNEL); |
1184 | 1209 | ||
1185 | if (!chinfo[pier].pd_curves) | 1210 | if (!chinfo[pier].pd_curves) |
1186 | return -ENOMEM; | 1211 | goto err_out; |
1187 | 1212 | ||
1188 | /* Fill pd_curves */ | 1213 | /* Fill pd_curves */ |
1189 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | 1214 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { |
@@ -1204,13 +1229,13 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, | |||
1204 | sizeof(u8), GFP_KERNEL); | 1229 | sizeof(u8), GFP_KERNEL); |
1205 | 1230 | ||
1206 | if (!pd->pd_step) | 1231 | if (!pd->pd_step) |
1207 | return -ENOMEM; | 1232 | goto err_out; |
1208 | 1233 | ||
1209 | pd->pd_pwr = kcalloc(pd->pd_points, | 1234 | pd->pd_pwr = kcalloc(pd->pd_points, |
1210 | sizeof(s16), GFP_KERNEL); | 1235 | sizeof(s16), GFP_KERNEL); |
1211 | 1236 | ||
1212 | if (!pd->pd_pwr) | 1237 | if (!pd->pd_pwr) |
1213 | return -ENOMEM; | 1238 | goto err_out; |
1214 | 1239 | ||
1215 | /* Fill raw dataset | 1240 | /* Fill raw dataset |
1216 | * convert all pwr levels to | 1241 | * convert all pwr levels to |
@@ -1240,6 +1265,10 @@ ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, | |||
1240 | } | 1265 | } |
1241 | 1266 | ||
1242 | return 0; | 1267 | return 0; |
1268 | |||
1269 | err_out: | ||
1270 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
1271 | return -ENOMEM; | ||
1243 | } | 1272 | } |
1244 | 1273 | ||
1245 | /* Parse EEPROM data */ | 1274 | /* Parse EEPROM data */ |
@@ -1251,7 +1280,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) | |||
1251 | struct ath5k_chan_pcal_info *chinfo; | 1280 | struct ath5k_chan_pcal_info *chinfo; |
1252 | u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; | 1281 | u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; |
1253 | u32 offset; | 1282 | u32 offset; |
1254 | int idx, i, ret; | 1283 | int idx, i; |
1255 | u16 val; | 1284 | u16 val; |
1256 | u8 pd_gains = 0; | 1285 | u8 pd_gains = 0; |
1257 | 1286 | ||
@@ -1329,7 +1358,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) | |||
1329 | /* | 1358 | /* |
1330 | * Pd gain 0 is not the last pd gain | 1359 | * Pd gain 0 is not the last pd gain |
1331 | * so it only has 2 pd points. | 1360 | * so it only has 2 pd points. |
1332 | * Continue wih pd gain 1. | 1361 | * Continue with pd gain 1. |
1333 | */ | 1362 | */ |
1334 | pcinfo->pwr_i[1] = (val >> 10) & 0x1f; | 1363 | pcinfo->pwr_i[1] = (val >> 10) & 0x1f; |
1335 | 1364 | ||
@@ -1442,7 +1471,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) | |||
1442 | u8 *rate_target_pwr_num; | 1471 | u8 *rate_target_pwr_num; |
1443 | u32 offset; | 1472 | u32 offset; |
1444 | u16 val; | 1473 | u16 val; |
1445 | int ret, i; | 1474 | int i; |
1446 | 1475 | ||
1447 | offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); | 1476 | offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); |
1448 | rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; | 1477 | rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; |
@@ -1514,6 +1543,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) | |||
1514 | return 0; | 1543 | return 0; |
1515 | } | 1544 | } |
1516 | 1545 | ||
1546 | |||
1517 | /* | 1547 | /* |
1518 | * Read per channel calibration info from EEPROM | 1548 | * Read per channel calibration info from EEPROM |
1519 | * | 1549 | * |
@@ -1560,62 +1590,6 @@ ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) | |||
1560 | return 0; | 1590 | return 0; |
1561 | } | 1591 | } |
1562 | 1592 | ||
1563 | static int | ||
1564 | ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) | ||
1565 | { | ||
1566 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
1567 | struct ath5k_chan_pcal_info *chinfo; | ||
1568 | u8 pier, pdg; | ||
1569 | |||
1570 | switch (mode) { | ||
1571 | case AR5K_EEPROM_MODE_11A: | ||
1572 | if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) | ||
1573 | return 0; | ||
1574 | chinfo = ee->ee_pwr_cal_a; | ||
1575 | break; | ||
1576 | case AR5K_EEPROM_MODE_11B: | ||
1577 | if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) | ||
1578 | return 0; | ||
1579 | chinfo = ee->ee_pwr_cal_b; | ||
1580 | break; | ||
1581 | case AR5K_EEPROM_MODE_11G: | ||
1582 | if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) | ||
1583 | return 0; | ||
1584 | chinfo = ee->ee_pwr_cal_g; | ||
1585 | break; | ||
1586 | default: | ||
1587 | return -EINVAL; | ||
1588 | } | ||
1589 | |||
1590 | for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { | ||
1591 | if (!chinfo[pier].pd_curves) | ||
1592 | continue; | ||
1593 | |||
1594 | for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { | ||
1595 | struct ath5k_pdgain_info *pd = | ||
1596 | &chinfo[pier].pd_curves[pdg]; | ||
1597 | |||
1598 | if (pd != NULL) { | ||
1599 | kfree(pd->pd_step); | ||
1600 | kfree(pd->pd_pwr); | ||
1601 | } | ||
1602 | } | ||
1603 | |||
1604 | kfree(chinfo[pier].pd_curves); | ||
1605 | } | ||
1606 | |||
1607 | return 0; | ||
1608 | } | ||
1609 | |||
1610 | void | ||
1611 | ath5k_eeprom_detach(struct ath5k_hw *ah) | ||
1612 | { | ||
1613 | u8 mode; | ||
1614 | |||
1615 | for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) | ||
1616 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
1617 | } | ||
1618 | |||
1619 | /* Read conformance test limits used for regulatory control */ | 1593 | /* Read conformance test limits used for regulatory control */ |
1620 | static int | 1594 | static int |
1621 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) | 1595 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) |
@@ -1624,7 +1598,7 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) | |||
1624 | struct ath5k_edge_power *rep; | 1598 | struct ath5k_edge_power *rep; |
1625 | unsigned int fmask, pmask; | 1599 | unsigned int fmask, pmask; |
1626 | unsigned int ctl_mode; | 1600 | unsigned int ctl_mode; |
1627 | int ret, i, j; | 1601 | int i, j; |
1628 | u32 offset; | 1602 | u32 offset; |
1629 | u16 val; | 1603 | u16 val; |
1630 | 1604 | ||
@@ -1756,6 +1730,11 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) | |||
1756 | return ret; | 1730 | return ret; |
1757 | } | 1731 | } |
1758 | 1732 | ||
1733 | |||
1734 | /***********************\ | ||
1735 | * Init/Detach functions * | ||
1736 | \***********************/ | ||
1737 | |||
1759 | /* | 1738 | /* |
1760 | * Initialize eeprom data structure | 1739 | * Initialize eeprom data structure |
1761 | */ | 1740 | */ |
@@ -1787,35 +1766,27 @@ ath5k_eeprom_init(struct ath5k_hw *ah) | |||
1787 | return 0; | 1766 | return 0; |
1788 | } | 1767 | } |
1789 | 1768 | ||
1790 | /* | 1769 | void |
1791 | * Read the MAC address from eeprom | 1770 | ath5k_eeprom_detach(struct ath5k_hw *ah) |
1792 | */ | ||
1793 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
1794 | { | 1771 | { |
1795 | u8 mac_d[ETH_ALEN] = {}; | 1772 | u8 mode; |
1796 | u32 total, offset; | ||
1797 | u16 data; | ||
1798 | int octet, ret; | ||
1799 | |||
1800 | ret = ath5k_hw_eeprom_read(ah, 0x20, &data); | ||
1801 | if (ret) | ||
1802 | return ret; | ||
1803 | 1773 | ||
1804 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | 1774 | for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) |
1805 | ret = ath5k_hw_eeprom_read(ah, offset, &data); | 1775 | ath5k_eeprom_free_pcal_info(ah, mode); |
1806 | if (ret) | 1776 | } |
1807 | return ret; | ||
1808 | 1777 | ||
1809 | total += data; | 1778 | int |
1810 | mac_d[octet + 1] = data & 0xff; | 1779 | ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel) |
1811 | mac_d[octet] = data >> 8; | 1780 | { |
1812 | octet += 2; | 1781 | switch (channel->hw_value & CHANNEL_MODES) { |
1782 | case CHANNEL_A: | ||
1783 | case CHANNEL_XR: | ||
1784 | return AR5K_EEPROM_MODE_11A; | ||
1785 | case CHANNEL_G: | ||
1786 | return AR5K_EEPROM_MODE_11G; | ||
1787 | case CHANNEL_B: | ||
1788 | return AR5K_EEPROM_MODE_11B; | ||
1789 | default: | ||
1790 | return -1; | ||
1813 | } | 1791 | } |
1814 | |||
1815 | if (!total || total == 3 * 0xffff) | ||
1816 | return -EINVAL; | ||
1817 | |||
1818 | memcpy(mac, mac_d, ETH_ALEN); | ||
1819 | |||
1820 | return 0; | ||
1821 | } | 1792 | } |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h index c4a6d5f26af4..6511c27d938e 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ b/drivers/net/wireless/ath/ath5k/eeprom.h | |||
@@ -241,9 +241,8 @@ enum ath5k_eeprom_freq_bands{ | |||
241 | #define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250 | 241 | #define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250 |
242 | 242 | ||
243 | #define AR5K_EEPROM_READ(_o, _v) do { \ | 243 | #define AR5K_EEPROM_READ(_o, _v) do { \ |
244 | ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \ | 244 | if (!ath5k_hw_nvram_read(ah, (_o), &(_v))) \ |
245 | if (ret) \ | 245 | return -EIO; \ |
246 | return ret; \ | ||
247 | } while (0) | 246 | } while (0) |
248 | 247 | ||
249 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ | 248 | #define AR5K_EEPROM_READ_HDR(_o, _v) \ |
@@ -269,29 +268,6 @@ enum ath5k_ctl_mode { | |||
269 | AR5K_CTL_MODE_M = 15, | 268 | AR5K_CTL_MODE_M = 15, |
270 | }; | 269 | }; |
271 | 270 | ||
272 | /* Default CTL ids for the 3 main reg domains. | ||
273 | * Atheros only uses these by default but vendors | ||
274 | * can have up to 32 different CTLs for different | ||
275 | * scenarios. Note that theese values are ORed with | ||
276 | * the mode id (above) so we can have up to 24 CTL | ||
277 | * datasets out of these 3 main regdomains. That leaves | ||
278 | * 8 ids that can be used by vendors and since 0x20 is | ||
279 | * missing from HAL sources i guess this is the set of | ||
280 | * custom CTLs vendors can use. */ | ||
281 | #define AR5K_CTL_FCC 0x10 | ||
282 | #define AR5K_CTL_CUSTOM 0x20 | ||
283 | #define AR5K_CTL_ETSI 0x30 | ||
284 | #define AR5K_CTL_MKK 0x40 | ||
285 | |||
286 | /* Indicates a CTL with only mode set and | ||
287 | * no reg domain mapping, such CTLs are used | ||
288 | * for world roaming domains or simply when | ||
289 | * a reg domain is not set */ | ||
290 | #define AR5K_CTL_NO_REGDOMAIN 0xf0 | ||
291 | |||
292 | /* Indicates an empty (invalid) CTL */ | ||
293 | #define AR5K_CTL_NO_CTL 0xff | ||
294 | |||
295 | /* Per channel calibration data, used for power table setup */ | 271 | /* Per channel calibration data, used for power table setup */ |
296 | struct ath5k_chan_pcal_info_rf5111 { | 272 | struct ath5k_chan_pcal_info_rf5111 { |
297 | /* Power levels in half dbm units | 273 | /* Power levels in half dbm units |
@@ -517,3 +493,5 @@ struct ath5k_eeprom_info { | |||
517 | u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; | 493 | u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; |
518 | }; | 494 | }; |
519 | 495 | ||
496 | int | ||
497 | ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel); | ||
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c index 8fa439308828..e49340d18df4 100644 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ b/drivers/net/wireless/ath/ath5k/initvals.c | |||
@@ -44,7 +44,7 @@ struct ath5k_ini { | |||
44 | 44 | ||
45 | struct ath5k_ini_mode { | 45 | struct ath5k_ini_mode { |
46 | u16 mode_register; | 46 | u16 mode_register; |
47 | u32 mode_value[5]; | 47 | u32 mode_value[3]; |
48 | }; | 48 | }; |
49 | 49 | ||
50 | /* Initial register settings for AR5210 */ | 50 | /* Initial register settings for AR5210 */ |
@@ -391,76 +391,74 @@ static const struct ath5k_ini ar5211_ini[] = { | |||
391 | */ | 391 | */ |
392 | static const struct ath5k_ini_mode ar5211_ini_mode[] = { | 392 | static const struct ath5k_ini_mode ar5211_ini_mode[] = { |
393 | { AR5K_TXCFG, | 393 | { AR5K_TXCFG, |
394 | /* a aTurbo b g (OFDM) */ | 394 | /* A/XR B G */ |
395 | { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } }, | 395 | { 0x00000015, 0x0000001d, 0x00000015 } }, |
396 | { AR5K_QUEUE_DFS_LOCAL_IFS(0), | 396 | { AR5K_QUEUE_DFS_LOCAL_IFS(0), |
397 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 397 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
398 | { AR5K_QUEUE_DFS_LOCAL_IFS(1), | 398 | { AR5K_QUEUE_DFS_LOCAL_IFS(1), |
399 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 399 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
400 | { AR5K_QUEUE_DFS_LOCAL_IFS(2), | 400 | { AR5K_QUEUE_DFS_LOCAL_IFS(2), |
401 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 401 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
402 | { AR5K_QUEUE_DFS_LOCAL_IFS(3), | 402 | { AR5K_QUEUE_DFS_LOCAL_IFS(3), |
403 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 403 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
404 | { AR5K_QUEUE_DFS_LOCAL_IFS(4), | 404 | { AR5K_QUEUE_DFS_LOCAL_IFS(4), |
405 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 405 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
406 | { AR5K_QUEUE_DFS_LOCAL_IFS(5), | 406 | { AR5K_QUEUE_DFS_LOCAL_IFS(5), |
407 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 407 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
408 | { AR5K_QUEUE_DFS_LOCAL_IFS(6), | 408 | { AR5K_QUEUE_DFS_LOCAL_IFS(6), |
409 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 409 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
410 | { AR5K_QUEUE_DFS_LOCAL_IFS(7), | 410 | { AR5K_QUEUE_DFS_LOCAL_IFS(7), |
411 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 411 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
412 | { AR5K_QUEUE_DFS_LOCAL_IFS(8), | 412 | { AR5K_QUEUE_DFS_LOCAL_IFS(8), |
413 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 413 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
414 | { AR5K_QUEUE_DFS_LOCAL_IFS(9), | 414 | { AR5K_QUEUE_DFS_LOCAL_IFS(9), |
415 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, | 415 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
416 | { AR5K_DCU_GBL_IFS_SLOT, | 416 | { AR5K_DCU_GBL_IFS_SLOT, |
417 | { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } }, | 417 | { 0x00000168, 0x000001b8, 0x00000168 } }, |
418 | { AR5K_DCU_GBL_IFS_SIFS, | 418 | { AR5K_DCU_GBL_IFS_SIFS, |
419 | { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } }, | 419 | { 0x00000230, 0x000000b0, 0x00000230 } }, |
420 | { AR5K_DCU_GBL_IFS_EIFS, | 420 | { AR5K_DCU_GBL_IFS_EIFS, |
421 | { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } }, | 421 | { 0x00000d98, 0x00001f48, 0x00000d98 } }, |
422 | { AR5K_DCU_GBL_IFS_MISC, | 422 | { AR5K_DCU_GBL_IFS_MISC, |
423 | { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } }, | 423 | { 0x0000a0e0, 0x00005880, 0x0000a0e0 } }, |
424 | { AR5K_TIME_OUT, | 424 | { AR5K_TIME_OUT, |
425 | { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } }, | 425 | { 0x04000400, 0x20003000, 0x04000400 } }, |
426 | { AR5K_USEC_5211, | 426 | { AR5K_USEC_5211, |
427 | { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } }, | 427 | { 0x0e8d8fa7, 0x01608f95, 0x0e8d8fa7 } }, |
428 | { AR5K_PHY_TURBO, | ||
429 | { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } }, | ||
430 | { AR5K_PHY(8), | 428 | { AR5K_PHY(8), |
431 | { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } }, | 429 | { 0x02020200, 0x02010200, 0x02020200 } }, |
432 | { AR5K_PHY(9), | 430 | { AR5K_PHY_RF_CTL2, |
433 | { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } }, | 431 | { 0x00000e0e, 0x00000707, 0x00000e0e } }, |
434 | { AR5K_PHY(10), | 432 | { AR5K_PHY_RF_CTL3, |
435 | { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } }, | 433 | { 0x0a020001, 0x05010000, 0x0a020001 } }, |
436 | { AR5K_PHY(13), | 434 | { AR5K_PHY_RF_CTL4, |
437 | { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, | 435 | { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, |
438 | { AR5K_PHY(14), | 436 | { AR5K_PHY_PA_CTL, |
439 | { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } }, | 437 | { 0x00000007, 0x0000000b, 0x0000000b } }, |
440 | { AR5K_PHY(17), | 438 | { AR5K_PHY_SETTLING, |
441 | { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } }, | 439 | { 0x1372169c, 0x137216a8, 0x1372169c } }, |
442 | { AR5K_PHY(18), | 440 | { AR5K_PHY_GAIN, |
443 | { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, | 441 | { 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, |
444 | { AR5K_PHY(20), | 442 | { AR5K_PHY_DESIRED_SIZE, |
445 | { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, | 443 | { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, |
446 | { AR5K_PHY_SIG, | 444 | { AR5K_PHY_SIG, |
447 | { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, | 445 | { 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, |
448 | { AR5K_PHY_AGCCOARSE, | 446 | { AR5K_PHY_AGCCOARSE, |
449 | { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, | 447 | { 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, |
450 | { AR5K_PHY_AGCCTL, | 448 | { AR5K_PHY_AGCCTL, |
451 | { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, | 449 | { 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, |
452 | { AR5K_PHY_NF, | 450 | { AR5K_PHY_NF, |
453 | { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, | 451 | { 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, |
454 | { AR5K_PHY_RX_DELAY, | 452 | { AR5K_PHY_RX_DELAY, |
455 | { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } }, | 453 | { 0x00002710, 0x0000157c, 0x00002710 } }, |
456 | { AR5K_PHY(70), | 454 | { AR5K_PHY(70), |
457 | { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } }, | 455 | { 0x00000190, 0x00000084, 0x00000190 } }, |
458 | { AR5K_PHY_FRAME_CTL_5211, | 456 | { AR5K_PHY_FRAME_CTL_5211, |
459 | { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, | 457 | { 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, |
460 | { AR5K_PHY_PCDAC_TXPOWER_BASE, | 458 | { AR5K_PHY_PCDAC_TXPOWER_BASE, |
461 | { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, | 459 | { 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, |
462 | { AR5K_RF_BUFFER_CONTROL_4, | 460 | { AR5K_RF_BUFFER_CONTROL_4, |
463 | { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } }, | 461 | { 0x00000010, 0x00000010, 0x00000010 } }, |
464 | }; | 462 | }; |
465 | 463 | ||
466 | /* Initial register settings for AR5212 */ | 464 | /* Initial register settings for AR5212 */ |
@@ -677,89 +675,87 @@ static const struct ath5k_ini ar5212_ini_common_start[] = { | |||
677 | /* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */ | 675 | /* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */ |
678 | static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { | 676 | static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { |
679 | { AR5K_QUEUE_DFS_LOCAL_IFS(0), | 677 | { AR5K_QUEUE_DFS_LOCAL_IFS(0), |
680 | /* a/XR aTurbo b g (DYN) gTurbo */ | 678 | /* A/XR B G */ |
681 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 679 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
682 | { AR5K_QUEUE_DFS_LOCAL_IFS(1), | 680 | { AR5K_QUEUE_DFS_LOCAL_IFS(1), |
683 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 681 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
684 | { AR5K_QUEUE_DFS_LOCAL_IFS(2), | 682 | { AR5K_QUEUE_DFS_LOCAL_IFS(2), |
685 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 683 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
686 | { AR5K_QUEUE_DFS_LOCAL_IFS(3), | 684 | { AR5K_QUEUE_DFS_LOCAL_IFS(3), |
687 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 685 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
688 | { AR5K_QUEUE_DFS_LOCAL_IFS(4), | 686 | { AR5K_QUEUE_DFS_LOCAL_IFS(4), |
689 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 687 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
690 | { AR5K_QUEUE_DFS_LOCAL_IFS(5), | 688 | { AR5K_QUEUE_DFS_LOCAL_IFS(5), |
691 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 689 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
692 | { AR5K_QUEUE_DFS_LOCAL_IFS(6), | 690 | { AR5K_QUEUE_DFS_LOCAL_IFS(6), |
693 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 691 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
694 | { AR5K_QUEUE_DFS_LOCAL_IFS(7), | 692 | { AR5K_QUEUE_DFS_LOCAL_IFS(7), |
695 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 693 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
696 | { AR5K_QUEUE_DFS_LOCAL_IFS(8), | 694 | { AR5K_QUEUE_DFS_LOCAL_IFS(8), |
697 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 695 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
698 | { AR5K_QUEUE_DFS_LOCAL_IFS(9), | 696 | { AR5K_QUEUE_DFS_LOCAL_IFS(9), |
699 | { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, | 697 | { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, |
700 | { AR5K_DCU_GBL_IFS_SIFS, | 698 | { AR5K_DCU_GBL_IFS_SIFS, |
701 | { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } }, | 699 | { 0x00000230, 0x000000b0, 0x00000160 } }, |
702 | { AR5K_DCU_GBL_IFS_SLOT, | 700 | { AR5K_DCU_GBL_IFS_SLOT, |
703 | { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } }, | 701 | { 0x00000168, 0x000001b8, 0x0000018c } }, |
704 | { AR5K_DCU_GBL_IFS_EIFS, | 702 | { AR5K_DCU_GBL_IFS_EIFS, |
705 | { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } }, | 703 | { 0x00000e60, 0x00001f1c, 0x00003e38 } }, |
706 | { AR5K_DCU_GBL_IFS_MISC, | 704 | { AR5K_DCU_GBL_IFS_MISC, |
707 | { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } }, | 705 | { 0x0000a0e0, 0x00005880, 0x0000b0e0 } }, |
708 | { AR5K_TIME_OUT, | 706 | { AR5K_TIME_OUT, |
709 | { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } }, | 707 | { 0x03e803e8, 0x04200420, 0x08400840 } }, |
710 | { AR5K_PHY_TURBO, | ||
711 | { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } }, | ||
712 | { AR5K_PHY(8), | 708 | { AR5K_PHY(8), |
713 | { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } }, | 709 | { 0x02020200, 0x02010200, 0x02020200 } }, |
714 | { AR5K_PHY_RF_CTL2, | 710 | { AR5K_PHY_RF_CTL2, |
715 | { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } }, | 711 | { 0x00000e0e, 0x00000707, 0x00000e0e } }, |
716 | { AR5K_PHY_SETTLING, | 712 | { AR5K_PHY_SETTLING, |
717 | { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, | 713 | { 0x1372161c, 0x13721722, 0x137216a2 } }, |
718 | { AR5K_PHY_AGCCTL, | 714 | { AR5K_PHY_AGCCTL, |
719 | { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } }, | 715 | { 0x00009d10, 0x00009d18, 0x00009d18 } }, |
720 | { AR5K_PHY_NF, | 716 | { AR5K_PHY_NF, |
721 | { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, | 717 | { 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, |
722 | { AR5K_PHY_WEAK_OFDM_HIGH_THR, | 718 | { AR5K_PHY_WEAK_OFDM_HIGH_THR, |
723 | { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } }, | 719 | { 0x409a4190, 0x409a4190, 0x409a4190 } }, |
724 | { AR5K_PHY(70), | 720 | { AR5K_PHY(70), |
725 | { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } }, | 721 | { 0x000001b8, 0x00000084, 0x00000108 } }, |
726 | { AR5K_PHY_OFDM_SELFCORR, | 722 | { AR5K_PHY_OFDM_SELFCORR, |
727 | { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } }, | 723 | { 0x10058a05, 0x10058a05, 0x10058a05 } }, |
728 | { 0xa230, | 724 | { 0xa230, |
729 | { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } }, | 725 | { 0x00000000, 0x00000000, 0x00000108 } }, |
730 | }; | 726 | }; |
731 | 727 | ||
732 | /* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ | 728 | /* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ |
733 | static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { | 729 | static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { |
734 | { AR5K_TXCFG, | 730 | { AR5K_TXCFG, |
735 | /* a/XR aTurbo b g (DYN) gTurbo */ | 731 | /* A/XR B G */ |
736 | { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, | 732 | { 0x00008015, 0x00008015, 0x00008015 } }, |
737 | { AR5K_USEC_5211, | 733 | { AR5K_USEC_5211, |
738 | { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } }, | 734 | { 0x128d8fa7, 0x04e00f95, 0x12e00fab } }, |
739 | { AR5K_PHY_RF_CTL3, | 735 | { AR5K_PHY_RF_CTL3, |
740 | { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } }, | 736 | { 0x0a020001, 0x05010100, 0x0a020001 } }, |
741 | { AR5K_PHY_RF_CTL4, | 737 | { AR5K_PHY_RF_CTL4, |
742 | { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, | 738 | { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, |
743 | { AR5K_PHY_PA_CTL, | 739 | { AR5K_PHY_PA_CTL, |
744 | { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, | 740 | { 0x00000007, 0x0000000b, 0x0000000b } }, |
745 | { AR5K_PHY_GAIN, | 741 | { AR5K_PHY_GAIN, |
746 | { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } }, | 742 | { 0x0018da5a, 0x0018ca69, 0x0018ca69 } }, |
747 | { AR5K_PHY_DESIRED_SIZE, | 743 | { AR5K_PHY_DESIRED_SIZE, |
748 | { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, | 744 | { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, |
749 | { AR5K_PHY_SIG, | 745 | { AR5K_PHY_SIG, |
750 | { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } }, | 746 | { 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e } }, |
751 | { AR5K_PHY_AGCCOARSE, | 747 | { AR5K_PHY_AGCCOARSE, |
752 | { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } }, | 748 | { 0x3137665e, 0x3137665e, 0x3137665e } }, |
753 | { AR5K_PHY_WEAK_OFDM_LOW_THR, | 749 | { AR5K_PHY_WEAK_OFDM_LOW_THR, |
754 | { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } }, | 750 | { 0x050cb081, 0x050cb081, 0x050cb080 } }, |
755 | { AR5K_PHY_RX_DELAY, | 751 | { AR5K_PHY_RX_DELAY, |
756 | { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } }, | 752 | { 0x00002710, 0x0000157c, 0x00002af8 } }, |
757 | { AR5K_PHY_FRAME_CTL_5211, | 753 | { AR5K_PHY_FRAME_CTL_5211, |
758 | { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } }, | 754 | { 0xf7b81020, 0xf7b80d20, 0xf7b81020 } }, |
759 | { AR5K_PHY_GAIN_2GHZ, | 755 | { AR5K_PHY_GAIN_2GHZ, |
760 | { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } }, | 756 | { 0x642c416a, 0x6440416a, 0x6440416a } }, |
761 | { AR5K_PHY_CCK_RX_CTL_4, | 757 | { AR5K_PHY_CCK_RX_CTL_4, |
762 | { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, | 758 | { 0x1883800a, 0x1873800a, 0x1883800a } }, |
763 | }; | 759 | }; |
764 | 760 | ||
765 | static const struct ath5k_ini rf5111_ini_common_end[] = { | 761 | static const struct ath5k_ini rf5111_ini_common_end[] = { |
@@ -782,38 +778,38 @@ static const struct ath5k_ini rf5111_ini_common_end[] = { | |||
782 | /* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ | 778 | /* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ |
783 | static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { | 779 | static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { |
784 | { AR5K_TXCFG, | 780 | { AR5K_TXCFG, |
785 | /* a/XR aTurbo b g (DYN) gTurbo */ | 781 | /* A/XR B G */ |
786 | { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, | 782 | { 0x00008015, 0x00008015, 0x00008015 } }, |
787 | { AR5K_USEC_5211, | 783 | { AR5K_USEC_5211, |
788 | { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, | 784 | { 0x128d93a7, 0x04e01395, 0x12e013ab } }, |
789 | { AR5K_PHY_RF_CTL3, | 785 | { AR5K_PHY_RF_CTL3, |
790 | { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, | 786 | { 0x0a020001, 0x05020100, 0x0a020001 } }, |
791 | { AR5K_PHY_RF_CTL4, | 787 | { AR5K_PHY_RF_CTL4, |
792 | { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, | 788 | { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, |
793 | { AR5K_PHY_PA_CTL, | 789 | { AR5K_PHY_PA_CTL, |
794 | { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, | 790 | { 0x00000007, 0x0000000b, 0x0000000b } }, |
795 | { AR5K_PHY_GAIN, | 791 | { AR5K_PHY_GAIN, |
796 | { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } }, | 792 | { 0x0018da6d, 0x0018ca75, 0x0018ca75 } }, |
797 | { AR5K_PHY_DESIRED_SIZE, | 793 | { AR5K_PHY_DESIRED_SIZE, |
798 | { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, | 794 | { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, |
799 | { AR5K_PHY_SIG, | 795 | { AR5K_PHY_SIG, |
800 | { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } }, | 796 | { 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e } }, |
801 | { AR5K_PHY_AGCCOARSE, | 797 | { AR5K_PHY_AGCCOARSE, |
802 | { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, | 798 | { 0x3137665e, 0x3137665e, 0x3137665e } }, |
803 | { AR5K_PHY_WEAK_OFDM_LOW_THR, | 799 | { AR5K_PHY_WEAK_OFDM_LOW_THR, |
804 | { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, | 800 | { 0x050cb081, 0x050cb081, 0x050cb081 } }, |
805 | { AR5K_PHY_RX_DELAY, | 801 | { AR5K_PHY_RX_DELAY, |
806 | { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, | 802 | { 0x000007d0, 0x0000044c, 0x00000898 } }, |
807 | { AR5K_PHY_FRAME_CTL_5211, | 803 | { AR5K_PHY_FRAME_CTL_5211, |
808 | { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } }, | 804 | { 0xf7b81020, 0xf7b80d10, 0xf7b81010 } }, |
809 | { AR5K_PHY_CCKTXCTL, | 805 | { AR5K_PHY_CCKTXCTL, |
810 | { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } }, | 806 | { 0x00000000, 0x00000008, 0x00000008 } }, |
811 | { AR5K_PHY_CCK_CROSSCORR, | 807 | { AR5K_PHY_CCK_CROSSCORR, |
812 | { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, | 808 | { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, |
813 | { AR5K_PHY_GAIN_2GHZ, | 809 | { AR5K_PHY_GAIN_2GHZ, |
814 | { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } }, | 810 | { 0x642c0140, 0x6442c160, 0x6442c160 } }, |
815 | { AR5K_PHY_CCK_RX_CTL_4, | 811 | { AR5K_PHY_CCK_RX_CTL_4, |
816 | { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, | 812 | { 0x1883800a, 0x1873800a, 0x1883800a } }, |
817 | }; | 813 | }; |
818 | 814 | ||
819 | static const struct ath5k_ini rf5112_ini_common_end[] = { | 815 | static const struct ath5k_ini rf5112_ini_common_end[] = { |
@@ -833,66 +829,66 @@ static const struct ath5k_ini rf5112_ini_common_end[] = { | |||
833 | /* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ | 829 | /* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ |
834 | static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { | 830 | static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { |
835 | { AR5K_TXCFG, | 831 | { AR5K_TXCFG, |
836 | /* a/XR aTurbo b g (DYN) gTurbo */ | 832 | /* A/XR B G */ |
837 | { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, | 833 | { 0x00000015, 0x00000015, 0x00000015 } }, |
838 | { AR5K_USEC_5211, | 834 | { AR5K_USEC_5211, |
839 | { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, | 835 | { 0x128d93a7, 0x04e01395, 0x12e013ab } }, |
840 | { AR5K_PHY_RF_CTL3, | 836 | { AR5K_PHY_RF_CTL3, |
841 | { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, | 837 | { 0x0a020001, 0x05020100, 0x0a020001 } }, |
842 | { AR5K_PHY_RF_CTL4, | 838 | { AR5K_PHY_RF_CTL4, |
843 | { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, | 839 | { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, |
844 | { AR5K_PHY_PA_CTL, | 840 | { AR5K_PHY_PA_CTL, |
845 | { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, | 841 | { 0x00000007, 0x0000000b, 0x0000000b } }, |
846 | { AR5K_PHY_GAIN, | 842 | { AR5K_PHY_GAIN, |
847 | { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } }, | 843 | { 0x0018fa61, 0x001a1a63, 0x001a1a63 } }, |
848 | { AR5K_PHY_DESIRED_SIZE, | 844 | { AR5K_PHY_DESIRED_SIZE, |
849 | { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, | 845 | { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } }, |
850 | { AR5K_PHY_SIG, | 846 | { AR5K_PHY_SIG, |
851 | { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, | 847 | { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, |
852 | { AR5K_PHY_AGCCOARSE, | 848 | { AR5K_PHY_AGCCOARSE, |
853 | { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, | 849 | { 0x3139605e, 0x3139605e, 0x3139605e } }, |
854 | { AR5K_PHY_WEAK_OFDM_LOW_THR, | 850 | { AR5K_PHY_WEAK_OFDM_LOW_THR, |
855 | { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, | 851 | { 0x050cb081, 0x050cb081, 0x050cb081 } }, |
856 | { AR5K_PHY_RX_DELAY, | 852 | { AR5K_PHY_RX_DELAY, |
857 | { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, | 853 | { 0x000007d0, 0x0000044c, 0x00000898 } }, |
858 | { AR5K_PHY_FRAME_CTL_5211, | 854 | { AR5K_PHY_FRAME_CTL_5211, |
859 | { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, | 855 | { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } }, |
860 | { AR5K_PHY_CCKTXCTL, | 856 | { AR5K_PHY_CCKTXCTL, |
861 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 857 | { 0x00000000, 0x00000000, 0x00000000 } }, |
862 | { AR5K_PHY_CCK_CROSSCORR, | 858 | { AR5K_PHY_CCK_CROSSCORR, |
863 | { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, | 859 | { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, |
864 | { AR5K_PHY_GAIN_2GHZ, | 860 | { AR5K_PHY_GAIN_2GHZ, |
865 | { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } }, | 861 | { 0x002ec1e0, 0x002ac120, 0x002ac120 } }, |
866 | { AR5K_PHY_CCK_RX_CTL_4, | 862 | { AR5K_PHY_CCK_RX_CTL_4, |
867 | { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, | 863 | { 0x1883800a, 0x1863800a, 0x1883800a } }, |
868 | { 0xa300, | 864 | { 0xa300, |
869 | { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } }, | 865 | { 0x18010000, 0x18010000, 0x18010000 } }, |
870 | { 0xa304, | 866 | { 0xa304, |
871 | { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } }, | 867 | { 0x30032602, 0x30032602, 0x30032602 } }, |
872 | { 0xa308, | 868 | { 0xa308, |
873 | { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } }, | 869 | { 0x48073e06, 0x48073e06, 0x48073e06 } }, |
874 | { 0xa30c, | 870 | { 0xa30c, |
875 | { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, | 871 | { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, |
876 | { 0xa310, | 872 | { 0xa310, |
877 | { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } }, | 873 | { 0x641a600f, 0x641a600f, 0x641a600f } }, |
878 | { 0xa314, | 874 | { 0xa314, |
879 | { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, | 875 | { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, |
880 | { 0xa318, | 876 | { 0xa318, |
881 | { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, | 877 | { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, |
882 | { 0xa31c, | 878 | { 0xa31c, |
883 | { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } }, | 879 | { 0x90cf865b, 0x8ecf865b, 0x8ecf865b } }, |
884 | { 0xa320, | 880 | { 0xa320, |
885 | { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } }, | 881 | { 0x9d4f970f, 0x9b4f970f, 0x9b4f970f } }, |
886 | { 0xa324, | 882 | { 0xa324, |
887 | { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } }, | 883 | { 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f } }, |
888 | { 0xa328, | 884 | { 0xa328, |
889 | { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } }, | 885 | { 0xb55faf1f, 0xb35faf1f, 0xb35faf1f } }, |
890 | { 0xa32c, | 886 | { 0xa32c, |
891 | { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } }, | 887 | { 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f } }, |
892 | { 0xa330, | 888 | { 0xa330, |
893 | { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } }, | 889 | { 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f } }, |
894 | { 0xa334, | 890 | { 0xa334, |
895 | { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, | 891 | { 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, |
896 | }; | 892 | }; |
897 | 893 | ||
898 | static const struct ath5k_ini rf5413_ini_common_end[] = { | 894 | static const struct ath5k_ini rf5413_ini_common_end[] = { |
@@ -972,38 +968,38 @@ static const struct ath5k_ini rf5413_ini_common_end[] = { | |||
972 | /* XXX: a mode ? */ | 968 | /* XXX: a mode ? */ |
973 | static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { | 969 | static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { |
974 | { AR5K_TXCFG, | 970 | { AR5K_TXCFG, |
975 | /* a/XR aTurbo b g (DYN) gTurbo */ | 971 | /* A/XR B G */ |
976 | { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, | 972 | { 0x00000015, 0x00000015, 0x00000015 } }, |
977 | { AR5K_USEC_5211, | 973 | { AR5K_USEC_5211, |
978 | { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, | 974 | { 0x128d93a7, 0x04e01395, 0x12e013ab } }, |
979 | { AR5K_PHY_RF_CTL3, | 975 | { AR5K_PHY_RF_CTL3, |
980 | { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } }, | 976 | { 0x0a020001, 0x05020000, 0x0a020001 } }, |
981 | { AR5K_PHY_RF_CTL4, | 977 | { AR5K_PHY_RF_CTL4, |
982 | { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } }, | 978 | { 0x00000e00, 0x00000e00, 0x00000e00 } }, |
983 | { AR5K_PHY_PA_CTL, | 979 | { AR5K_PHY_PA_CTL, |
984 | { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } }, | 980 | { 0x00000002, 0x0000000a, 0x0000000a } }, |
985 | { AR5K_PHY_GAIN, | 981 | { AR5K_PHY_GAIN, |
986 | { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } }, | 982 | { 0x0018da6d, 0x001a6a64, 0x001a6a64 } }, |
987 | { AR5K_PHY_DESIRED_SIZE, | 983 | { AR5K_PHY_DESIRED_SIZE, |
988 | { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } }, | 984 | { 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da } }, |
989 | { AR5K_PHY_SIG, | 985 | { AR5K_PHY_SIG, |
990 | { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } }, | 986 | { 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e } }, |
991 | { AR5K_PHY_AGCCOARSE, | 987 | { AR5K_PHY_AGCCOARSE, |
992 | { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } }, | 988 | { 0x3137665e, 0x3137665e, 0x3139605e } }, |
993 | { AR5K_PHY_WEAK_OFDM_LOW_THR, | 989 | { AR5K_PHY_WEAK_OFDM_LOW_THR, |
994 | { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, | 990 | { 0x050cb081, 0x050cb081, 0x050cb081 } }, |
995 | { AR5K_PHY_RX_DELAY, | 991 | { AR5K_PHY_RX_DELAY, |
996 | { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, | 992 | { 0x000007d0, 0x0000044c, 0x00000898 } }, |
997 | { AR5K_PHY_FRAME_CTL_5211, | 993 | { AR5K_PHY_FRAME_CTL_5211, |
998 | { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, | 994 | { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } }, |
999 | { AR5K_PHY_CCKTXCTL, | 995 | { AR5K_PHY_CCKTXCTL, |
1000 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 996 | { 0x00000000, 0x00000000, 0x00000000 } }, |
1001 | { AR5K_PHY_CCK_CROSSCORR, | 997 | { AR5K_PHY_CCK_CROSSCORR, |
1002 | { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, | 998 | { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, |
1003 | { AR5K_PHY_GAIN_2GHZ, | 999 | { AR5K_PHY_GAIN_2GHZ, |
1004 | { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } }, | 1000 | { 0x002c0140, 0x0042c140, 0x0042c140 } }, |
1005 | { AR5K_PHY_CCK_RX_CTL_4, | 1001 | { AR5K_PHY_CCK_RX_CTL_4, |
1006 | { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, | 1002 | { 0x1883800a, 0x1863800a, 0x1883800a } }, |
1007 | }; | 1003 | }; |
1008 | 1004 | ||
1009 | static const struct ath5k_ini rf2413_ini_common_end[] = { | 1005 | static const struct ath5k_ini rf2413_ini_common_end[] = { |
@@ -1094,52 +1090,50 @@ static const struct ath5k_ini rf2413_ini_common_end[] = { | |||
1094 | /* XXX: a mode ? */ | 1090 | /* XXX: a mode ? */ |
1095 | static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { | 1091 | static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { |
1096 | { AR5K_TXCFG, | 1092 | { AR5K_TXCFG, |
1097 | /* a/XR aTurbo b g (DYN) gTurbo */ | 1093 | /* A/XR B G */ |
1098 | { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, | 1094 | { 0x00000015, 0x00000015, 0x00000015 } }, |
1099 | { AR5K_USEC_5211, | 1095 | { AR5K_USEC_5211, |
1100 | { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, | 1096 | { 0x128d93a7, 0x04e01395, 0x12e013ab } }, |
1101 | { AR5K_PHY_TURBO, | ||
1102 | { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } }, | ||
1103 | { AR5K_PHY_RF_CTL3, | 1097 | { AR5K_PHY_RF_CTL3, |
1104 | { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, | 1098 | { 0x0a020001, 0x05020100, 0x0a020001 } }, |
1105 | { AR5K_PHY_RF_CTL4, | 1099 | { AR5K_PHY_RF_CTL4, |
1106 | { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, | 1100 | { 0x00000e0e, 0x00000e0e, 0x00000e0e } }, |
1107 | { AR5K_PHY_PA_CTL, | 1101 | { AR5K_PHY_PA_CTL, |
1108 | { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } }, | 1102 | { 0x00000003, 0x0000000b, 0x0000000b } }, |
1109 | { AR5K_PHY_SETTLING, | 1103 | { AR5K_PHY_SETTLING, |
1110 | { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } }, | 1104 | { 0x1372161c, 0x13721722, 0x13721422 } }, |
1111 | { AR5K_PHY_GAIN, | 1105 | { AR5K_PHY_GAIN, |
1112 | { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } }, | 1106 | { 0x0018fa61, 0x00199a65, 0x00199a65 } }, |
1113 | { AR5K_PHY_DESIRED_SIZE, | 1107 | { AR5K_PHY_DESIRED_SIZE, |
1114 | { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, | 1108 | { 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da } }, |
1115 | { AR5K_PHY_SIG, | 1109 | { AR5K_PHY_SIG, |
1116 | { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, | 1110 | { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, |
1117 | { AR5K_PHY_AGCCOARSE, | 1111 | { AR5K_PHY_AGCCOARSE, |
1118 | { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, | 1112 | { 0x3139605e, 0x3139605e, 0x3139605e } }, |
1119 | { AR5K_PHY_WEAK_OFDM_LOW_THR, | 1113 | { AR5K_PHY_WEAK_OFDM_LOW_THR, |
1120 | { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, | 1114 | { 0x050cb081, 0x050cb081, 0x050cb081 } }, |
1121 | { AR5K_PHY_RX_DELAY, | 1115 | { AR5K_PHY_RX_DELAY, |
1122 | { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, | 1116 | { 0x000007d0, 0x0000044c, 0x00000898 } }, |
1123 | { AR5K_PHY_FRAME_CTL_5211, | 1117 | { AR5K_PHY_FRAME_CTL_5211, |
1124 | { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, | 1118 | { 0xf7b81000, 0xf7b80d00, 0xf7b81000 } }, |
1125 | { AR5K_PHY_CCKTXCTL, | 1119 | { AR5K_PHY_CCKTXCTL, |
1126 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 1120 | { 0x00000000, 0x00000000, 0x00000000 } }, |
1127 | { AR5K_PHY_CCK_CROSSCORR, | 1121 | { AR5K_PHY_CCK_CROSSCORR, |
1128 | { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, | 1122 | { 0xd6be6788, 0xd03e6788, 0xd03e6788 } }, |
1129 | { AR5K_PHY_GAIN_2GHZ, | 1123 | { AR5K_PHY_GAIN_2GHZ, |
1130 | { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } }, | 1124 | { 0x00000140, 0x0052c140, 0x0052c140 } }, |
1131 | { AR5K_PHY_CCK_RX_CTL_4, | 1125 | { AR5K_PHY_CCK_RX_CTL_4, |
1132 | { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, | 1126 | { 0x1883800a, 0x1863800a, 0x1883800a } }, |
1133 | { 0xa324, | 1127 | { 0xa324, |
1134 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, | 1128 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, |
1135 | { 0xa328, | 1129 | { 0xa328, |
1136 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, | 1130 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, |
1137 | { 0xa32c, | 1131 | { 0xa32c, |
1138 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, | 1132 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, |
1139 | { 0xa330, | 1133 | { 0xa330, |
1140 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, | 1134 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, |
1141 | { 0xa334, | 1135 | { 0xa334, |
1142 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, | 1136 | { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, |
1143 | }; | 1137 | }; |
1144 | 1138 | ||
1145 | static const struct ath5k_ini rf2425_ini_common_end[] = { | 1139 | static const struct ath5k_ini rf2425_ini_common_end[] = { |
@@ -1368,15 +1362,15 @@ static const struct ath5k_ini rf5112_ini_bbgain[] = { | |||
1368 | * Write initial register dump | 1362 | * Write initial register dump |
1369 | */ | 1363 | */ |
1370 | static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, | 1364 | static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, |
1371 | const struct ath5k_ini *ini_regs, bool change_channel) | 1365 | const struct ath5k_ini *ini_regs, bool skip_pcu) |
1372 | { | 1366 | { |
1373 | unsigned int i; | 1367 | unsigned int i; |
1374 | 1368 | ||
1375 | /* Write initial registers */ | 1369 | /* Write initial registers */ |
1376 | for (i = 0; i < size; i++) { | 1370 | for (i = 0; i < size; i++) { |
1377 | /* On channel change there is | 1371 | /* Skip PCU registers if |
1378 | * no need to mess with PCU */ | 1372 | * requested */ |
1379 | if (change_channel && | 1373 | if (skip_pcu && |
1380 | ini_regs[i].ini_register >= AR5K_PCU_MIN && | 1374 | ini_regs[i].ini_register >= AR5K_PCU_MIN && |
1381 | ini_regs[i].ini_register <= AR5K_PCU_MAX) | 1375 | ini_regs[i].ini_register <= AR5K_PCU_MAX) |
1382 | continue; | 1376 | continue; |
@@ -1409,7 +1403,7 @@ static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, | |||
1409 | 1403 | ||
1410 | } | 1404 | } |
1411 | 1405 | ||
1412 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | 1406 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) |
1413 | { | 1407 | { |
1414 | /* | 1408 | /* |
1415 | * Write initial register settings | 1409 | * Write initial register settings |
@@ -1427,7 +1421,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1427 | * Write initial settings common for all modes | 1421 | * Write initial settings common for all modes |
1428 | */ | 1422 | */ |
1429 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start), | 1423 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start), |
1430 | ar5212_ini_common_start, change_channel); | 1424 | ar5212_ini_common_start, skip_pcu); |
1431 | 1425 | ||
1432 | /* Second set of mode-specific settings */ | 1426 | /* Second set of mode-specific settings */ |
1433 | switch (ah->ah_radio) { | 1427 | switch (ah->ah_radio) { |
@@ -1439,12 +1433,12 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1439 | 1433 | ||
1440 | ath5k_hw_ini_registers(ah, | 1434 | ath5k_hw_ini_registers(ah, |
1441 | ARRAY_SIZE(rf5111_ini_common_end), | 1435 | ARRAY_SIZE(rf5111_ini_common_end), |
1442 | rf5111_ini_common_end, change_channel); | 1436 | rf5111_ini_common_end, skip_pcu); |
1443 | 1437 | ||
1444 | /* Baseband gain table */ | 1438 | /* Baseband gain table */ |
1445 | ath5k_hw_ini_registers(ah, | 1439 | ath5k_hw_ini_registers(ah, |
1446 | ARRAY_SIZE(rf5111_ini_bbgain), | 1440 | ARRAY_SIZE(rf5111_ini_bbgain), |
1447 | rf5111_ini_bbgain, change_channel); | 1441 | rf5111_ini_bbgain, skip_pcu); |
1448 | 1442 | ||
1449 | break; | 1443 | break; |
1450 | case AR5K_RF5112: | 1444 | case AR5K_RF5112: |
@@ -1455,11 +1449,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1455 | 1449 | ||
1456 | ath5k_hw_ini_registers(ah, | 1450 | ath5k_hw_ini_registers(ah, |
1457 | ARRAY_SIZE(rf5112_ini_common_end), | 1451 | ARRAY_SIZE(rf5112_ini_common_end), |
1458 | rf5112_ini_common_end, change_channel); | 1452 | rf5112_ini_common_end, skip_pcu); |
1459 | 1453 | ||
1460 | ath5k_hw_ini_registers(ah, | 1454 | ath5k_hw_ini_registers(ah, |
1461 | ARRAY_SIZE(rf5112_ini_bbgain), | 1455 | ARRAY_SIZE(rf5112_ini_bbgain), |
1462 | rf5112_ini_bbgain, change_channel); | 1456 | rf5112_ini_bbgain, skip_pcu); |
1463 | 1457 | ||
1464 | break; | 1458 | break; |
1465 | case AR5K_RF5413: | 1459 | case AR5K_RF5413: |
@@ -1470,11 +1464,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1470 | 1464 | ||
1471 | ath5k_hw_ini_registers(ah, | 1465 | ath5k_hw_ini_registers(ah, |
1472 | ARRAY_SIZE(rf5413_ini_common_end), | 1466 | ARRAY_SIZE(rf5413_ini_common_end), |
1473 | rf5413_ini_common_end, change_channel); | 1467 | rf5413_ini_common_end, skip_pcu); |
1474 | 1468 | ||
1475 | ath5k_hw_ini_registers(ah, | 1469 | ath5k_hw_ini_registers(ah, |
1476 | ARRAY_SIZE(rf5112_ini_bbgain), | 1470 | ARRAY_SIZE(rf5112_ini_bbgain), |
1477 | rf5112_ini_bbgain, change_channel); | 1471 | rf5112_ini_bbgain, skip_pcu); |
1478 | 1472 | ||
1479 | break; | 1473 | break; |
1480 | case AR5K_RF2316: | 1474 | case AR5K_RF2316: |
@@ -1486,7 +1480,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1486 | 1480 | ||
1487 | ath5k_hw_ini_registers(ah, | 1481 | ath5k_hw_ini_registers(ah, |
1488 | ARRAY_SIZE(rf2413_ini_common_end), | 1482 | ARRAY_SIZE(rf2413_ini_common_end), |
1489 | rf2413_ini_common_end, change_channel); | 1483 | rf2413_ini_common_end, skip_pcu); |
1490 | 1484 | ||
1491 | /* Override settings from rf2413_ini_common_end */ | 1485 | /* Override settings from rf2413_ini_common_end */ |
1492 | if (ah->ah_radio == AR5K_RF2316) { | 1486 | if (ah->ah_radio == AR5K_RF2316) { |
@@ -1498,9 +1492,32 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1498 | 1492 | ||
1499 | ath5k_hw_ini_registers(ah, | 1493 | ath5k_hw_ini_registers(ah, |
1500 | ARRAY_SIZE(rf5112_ini_bbgain), | 1494 | ARRAY_SIZE(rf5112_ini_bbgain), |
1501 | rf5112_ini_bbgain, change_channel); | 1495 | rf5112_ini_bbgain, skip_pcu); |
1502 | break; | 1496 | break; |
1503 | case AR5K_RF2317: | 1497 | case AR5K_RF2317: |
1498 | |||
1499 | ath5k_hw_ini_mode_registers(ah, | ||
1500 | ARRAY_SIZE(rf2413_ini_mode_end), | ||
1501 | rf2413_ini_mode_end, mode); | ||
1502 | |||
1503 | ath5k_hw_ini_registers(ah, | ||
1504 | ARRAY_SIZE(rf2425_ini_common_end), | ||
1505 | rf2425_ini_common_end, skip_pcu); | ||
1506 | |||
1507 | /* Override settings from rf2413_ini_mode_end */ | ||
1508 | ath5k_hw_reg_write(ah, 0x00180a65, AR5K_PHY_GAIN); | ||
1509 | |||
1510 | /* Override settings from rf2413_ini_common_end */ | ||
1511 | ath5k_hw_reg_write(ah, 0x00004000, AR5K_PHY_AGC); | ||
1512 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TPC_RG5, | ||
1513 | AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP, 0xa); | ||
1514 | ath5k_hw_reg_write(ah, 0x800000a8, 0x8140); | ||
1515 | ath5k_hw_reg_write(ah, 0x000000ff, 0x9958); | ||
1516 | |||
1517 | ath5k_hw_ini_registers(ah, | ||
1518 | ARRAY_SIZE(rf5112_ini_bbgain), | ||
1519 | rf5112_ini_bbgain, skip_pcu); | ||
1520 | break; | ||
1504 | case AR5K_RF2425: | 1521 | case AR5K_RF2425: |
1505 | 1522 | ||
1506 | ath5k_hw_ini_mode_registers(ah, | 1523 | ath5k_hw_ini_mode_registers(ah, |
@@ -1509,11 +1526,11 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1509 | 1526 | ||
1510 | ath5k_hw_ini_registers(ah, | 1527 | ath5k_hw_ini_registers(ah, |
1511 | ARRAY_SIZE(rf2425_ini_common_end), | 1528 | ARRAY_SIZE(rf2425_ini_common_end), |
1512 | rf2425_ini_common_end, change_channel); | 1529 | rf2425_ini_common_end, skip_pcu); |
1513 | 1530 | ||
1514 | ath5k_hw_ini_registers(ah, | 1531 | ath5k_hw_ini_registers(ah, |
1515 | ARRAY_SIZE(rf5112_ini_bbgain), | 1532 | ARRAY_SIZE(rf5112_ini_bbgain), |
1516 | rf5112_ini_bbgain, change_channel); | 1533 | rf5112_ini_bbgain, skip_pcu); |
1517 | break; | 1534 | break; |
1518 | default: | 1535 | default: |
1519 | return -EINVAL; | 1536 | return -EINVAL; |
@@ -1538,17 +1555,17 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) | |||
1538 | * Write initial settings common for all modes | 1555 | * Write initial settings common for all modes |
1539 | */ | 1556 | */ |
1540 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini), | 1557 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini), |
1541 | ar5211_ini, change_channel); | 1558 | ar5211_ini, skip_pcu); |
1542 | 1559 | ||
1543 | /* AR5211 only comes with 5111 */ | 1560 | /* AR5211 only comes with 5111 */ |
1544 | 1561 | ||
1545 | /* Baseband gain table */ | 1562 | /* Baseband gain table */ |
1546 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), | 1563 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), |
1547 | rf5111_ini_bbgain, change_channel); | 1564 | rf5111_ini_bbgain, skip_pcu); |
1548 | /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */ | 1565 | /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */ |
1549 | } else if (ah->ah_version == AR5K_AR5210) { | 1566 | } else if (ah->ah_version == AR5K_AR5210) { |
1550 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini), | 1567 | ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini), |
1551 | ar5210_ini, change_channel); | 1568 | ar5210_ini, skip_pcu); |
1552 | } | 1569 | } |
1553 | 1570 | ||
1554 | return 0; | 1571 | return 0; |
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c index 67aa52e9bf94..576edf2965dc 100644 --- a/drivers/net/wireless/ath/ath5k/led.c +++ b/drivers/net/wireless/ath/ath5k/led.c | |||
@@ -133,7 +133,7 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, | |||
133 | led->led_dev.default_trigger = trigger; | 133 | led->led_dev.default_trigger = trigger; |
134 | led->led_dev.brightness_set = ath5k_led_brightness_set; | 134 | led->led_dev.brightness_set = ath5k_led_brightness_set; |
135 | 135 | ||
136 | err = led_classdev_register(&sc->pdev->dev, &led->led_dev); | 136 | err = led_classdev_register(sc->dev, &led->led_dev); |
137 | if (err) { | 137 | if (err) { |
138 | ATH5K_WARN(sc, "could not register LED %s\n", name); | 138 | ATH5K_WARN(sc, "could not register LED %s\n", name); |
139 | led->sc = NULL; | 139 | led->sc = NULL; |
@@ -161,11 +161,20 @@ int ath5k_init_leds(struct ath5k_softc *sc) | |||
161 | { | 161 | { |
162 | int ret = 0; | 162 | int ret = 0; |
163 | struct ieee80211_hw *hw = sc->hw; | 163 | struct ieee80211_hw *hw = sc->hw; |
164 | #ifndef CONFIG_ATHEROS_AR231X | ||
164 | struct pci_dev *pdev = sc->pdev; | 165 | struct pci_dev *pdev = sc->pdev; |
166 | #endif | ||
165 | char name[ATH5K_LED_MAX_NAME_LEN + 1]; | 167 | char name[ATH5K_LED_MAX_NAME_LEN + 1]; |
166 | const struct pci_device_id *match; | 168 | const struct pci_device_id *match; |
167 | 169 | ||
170 | if (!sc->pdev) | ||
171 | return 0; | ||
172 | |||
173 | #ifdef CONFIG_ATHEROS_AR231X | ||
174 | match = NULL; | ||
175 | #else | ||
168 | match = pci_match_id(&ath5k_led_devices[0], pdev); | 176 | match = pci_match_id(&ath5k_led_devices[0], pdev); |
177 | #endif | ||
169 | if (match) { | 178 | if (match) { |
170 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | 179 | __set_bit(ATH_STAT_LEDSOFT, sc->status); |
171 | sc->led_pin = ATH_PIN(match->driver_data); | 180 | sc->led_pin = ATH_PIN(match->driver_data); |
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c new file mode 100644 index 000000000000..807bd6440169 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -0,0 +1,833 @@ | |||
1 | /*- | ||
2 | * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting | ||
3 | * Copyright (c) 2004-2005 Atheros Communications, Inc. | ||
4 | * Copyright (c) 2006 Devicescape Software, Inc. | ||
5 | * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com> | ||
6 | * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu> | ||
7 | * Copyright (c) 2010 Bruno Randolf <br1@einfach.org> | ||
8 | * | ||
9 | * All rights reserved. | ||
10 | * | ||
11 | * Redistribution and use in source and binary forms, with or without | ||
12 | * modification, are permitted provided that the following conditions | ||
13 | * are met: | ||
14 | * 1. Redistributions of source code must retain the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer, | ||
16 | * without modification. | ||
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
18 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
19 | * redistribution must be conditioned upon including a substantially | ||
20 | * similar Disclaimer requirement for further binary redistribution. | ||
21 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
22 | * of any contributors may be used to endorse or promote products derived | ||
23 | * from this software without specific prior written permission. | ||
24 | * | ||
25 | * Alternatively, this software may be distributed under the terms of the | ||
26 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
27 | * Software Foundation. | ||
28 | * | ||
29 | * NO WARRANTY | ||
30 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
31 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
32 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
33 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
34 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
35 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
36 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
37 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
38 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
39 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
40 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
41 | * | ||
42 | */ | ||
43 | |||
44 | #include <asm/unaligned.h> | ||
45 | |||
46 | #include "base.h" | ||
47 | #include "reg.h" | ||
48 | |||
49 | extern int ath5k_modparam_nohwcrypt; | ||
50 | |||
51 | /********************\ | ||
52 | * Mac80211 functions * | ||
53 | \********************/ | ||
54 | |||
55 | static void | ||
56 | ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
57 | { | ||
58 | struct ath5k_softc *sc = hw->priv; | ||
59 | u16 qnum = skb_get_queue_mapping(skb); | ||
60 | |||
61 | if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) { | ||
62 | dev_kfree_skb_any(skb); | ||
63 | return; | ||
64 | } | ||
65 | |||
66 | ath5k_tx_queue(hw, skb, &sc->txqs[qnum]); | ||
67 | } | ||
68 | |||
69 | |||
70 | static int | ||
71 | ath5k_start(struct ieee80211_hw *hw) | ||
72 | { | ||
73 | return ath5k_init_hw(hw->priv); | ||
74 | } | ||
75 | |||
76 | |||
77 | static void | ||
78 | ath5k_stop(struct ieee80211_hw *hw) | ||
79 | { | ||
80 | ath5k_stop_hw(hw->priv); | ||
81 | } | ||
82 | |||
83 | |||
84 | static int | ||
85 | ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
86 | { | ||
87 | struct ath5k_softc *sc = hw->priv; | ||
88 | int ret; | ||
89 | struct ath5k_vif *avf = (void *)vif->drv_priv; | ||
90 | |||
91 | mutex_lock(&sc->lock); | ||
92 | |||
93 | if ((vif->type == NL80211_IFTYPE_AP || | ||
94 | vif->type == NL80211_IFTYPE_ADHOC) | ||
95 | && (sc->num_ap_vifs + sc->num_adhoc_vifs) >= ATH_BCBUF) { | ||
96 | ret = -ELNRNG; | ||
97 | goto end; | ||
98 | } | ||
99 | |||
100 | /* Don't allow other interfaces if one ad-hoc is configured. | ||
101 | * TODO: Fix the problems with ad-hoc and multiple other interfaces. | ||
102 | * We would need to operate the HW in ad-hoc mode to allow TSF updates | ||
103 | * for the IBSS, but this breaks with additional AP or STA interfaces | ||
104 | * at the moment. */ | ||
105 | if (sc->num_adhoc_vifs || | ||
106 | (sc->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { | ||
107 | ATH5K_ERR(sc, "Only one single ad-hoc interface is allowed.\n"); | ||
108 | ret = -ELNRNG; | ||
109 | goto end; | ||
110 | } | ||
111 | |||
112 | switch (vif->type) { | ||
113 | case NL80211_IFTYPE_AP: | ||
114 | case NL80211_IFTYPE_STATION: | ||
115 | case NL80211_IFTYPE_ADHOC: | ||
116 | case NL80211_IFTYPE_MESH_POINT: | ||
117 | avf->opmode = vif->type; | ||
118 | break; | ||
119 | default: | ||
120 | ret = -EOPNOTSUPP; | ||
121 | goto end; | ||
122 | } | ||
123 | |||
124 | sc->nvifs++; | ||
125 | ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "add interface mode %d\n", avf->opmode); | ||
126 | |||
127 | /* Assign the vap/adhoc to a beacon xmit slot. */ | ||
128 | if ((avf->opmode == NL80211_IFTYPE_AP) || | ||
129 | (avf->opmode == NL80211_IFTYPE_ADHOC) || | ||
130 | (avf->opmode == NL80211_IFTYPE_MESH_POINT)) { | ||
131 | int slot; | ||
132 | |||
133 | WARN_ON(list_empty(&sc->bcbuf)); | ||
134 | avf->bbuf = list_first_entry(&sc->bcbuf, struct ath5k_buf, | ||
135 | list); | ||
136 | list_del(&avf->bbuf->list); | ||
137 | |||
138 | avf->bslot = 0; | ||
139 | for (slot = 0; slot < ATH_BCBUF; slot++) { | ||
140 | if (!sc->bslot[slot]) { | ||
141 | avf->bslot = slot; | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | BUG_ON(sc->bslot[avf->bslot] != NULL); | ||
146 | sc->bslot[avf->bslot] = vif; | ||
147 | if (avf->opmode == NL80211_IFTYPE_AP) | ||
148 | sc->num_ap_vifs++; | ||
149 | else if (avf->opmode == NL80211_IFTYPE_ADHOC) | ||
150 | sc->num_adhoc_vifs++; | ||
151 | } | ||
152 | |||
153 | /* Any MAC address is fine, all others are included through the | ||
154 | * filter. | ||
155 | */ | ||
156 | memcpy(&sc->lladdr, vif->addr, ETH_ALEN); | ||
157 | ath5k_hw_set_lladdr(sc->ah, vif->addr); | ||
158 | |||
159 | memcpy(&avf->lladdr, vif->addr, ETH_ALEN); | ||
160 | |||
161 | ath5k_update_bssid_mask_and_opmode(sc, vif); | ||
162 | ret = 0; | ||
163 | end: | ||
164 | mutex_unlock(&sc->lock); | ||
165 | return ret; | ||
166 | } | ||
167 | |||
168 | |||
169 | static void | ||
170 | ath5k_remove_interface(struct ieee80211_hw *hw, | ||
171 | struct ieee80211_vif *vif) | ||
172 | { | ||
173 | struct ath5k_softc *sc = hw->priv; | ||
174 | struct ath5k_vif *avf = (void *)vif->drv_priv; | ||
175 | unsigned int i; | ||
176 | |||
177 | mutex_lock(&sc->lock); | ||
178 | sc->nvifs--; | ||
179 | |||
180 | if (avf->bbuf) { | ||
181 | ath5k_txbuf_free_skb(sc, avf->bbuf); | ||
182 | list_add_tail(&avf->bbuf->list, &sc->bcbuf); | ||
183 | for (i = 0; i < ATH_BCBUF; i++) { | ||
184 | if (sc->bslot[i] == vif) { | ||
185 | sc->bslot[i] = NULL; | ||
186 | break; | ||
187 | } | ||
188 | } | ||
189 | avf->bbuf = NULL; | ||
190 | } | ||
191 | if (avf->opmode == NL80211_IFTYPE_AP) | ||
192 | sc->num_ap_vifs--; | ||
193 | else if (avf->opmode == NL80211_IFTYPE_ADHOC) | ||
194 | sc->num_adhoc_vifs--; | ||
195 | |||
196 | ath5k_update_bssid_mask_and_opmode(sc, NULL); | ||
197 | mutex_unlock(&sc->lock); | ||
198 | } | ||
199 | |||
200 | |||
201 | /* | ||
202 | * TODO: Phy disable/diversity etc | ||
203 | */ | ||
204 | static int | ||
205 | ath5k_config(struct ieee80211_hw *hw, u32 changed) | ||
206 | { | ||
207 | struct ath5k_softc *sc = hw->priv; | ||
208 | struct ath5k_hw *ah = sc->ah; | ||
209 | struct ieee80211_conf *conf = &hw->conf; | ||
210 | int ret = 0; | ||
211 | int i; | ||
212 | |||
213 | mutex_lock(&sc->lock); | ||
214 | |||
215 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
216 | ret = ath5k_chan_set(sc, conf->channel); | ||
217 | if (ret < 0) | ||
218 | goto unlock; | ||
219 | } | ||
220 | |||
221 | if ((changed & IEEE80211_CONF_CHANGE_POWER) && | ||
222 | (sc->power_level != conf->power_level)) { | ||
223 | sc->power_level = conf->power_level; | ||
224 | |||
225 | /* Half dB steps */ | ||
226 | ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); | ||
227 | } | ||
228 | |||
229 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { | ||
230 | ah->ah_retry_long = conf->long_frame_max_tx_count; | ||
231 | ah->ah_retry_short = conf->short_frame_max_tx_count; | ||
232 | |||
233 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) | ||
234 | ath5k_hw_set_tx_retry_limits(ah, i); | ||
235 | } | ||
236 | |||
237 | /* TODO: | ||
238 | * 1) Move this on config_interface and handle each case | ||
239 | * separately eg. when we have only one STA vif, use | ||
240 | * AR5K_ANTMODE_SINGLE_AP | ||
241 | * | ||
242 | * 2) Allow the user to change antenna mode eg. when only | ||
243 | * one antenna is present | ||
244 | * | ||
245 | * 3) Allow the user to set default/tx antenna when possible | ||
246 | * | ||
247 | * 4) Default mode should handle 90% of the cases, together | ||
248 | * with fixed a/b and single AP modes we should be able to | ||
249 | * handle 99%. Sectored modes are extreme cases and i still | ||
250 | * haven't found a usage for them. If we decide to support them, | ||
251 | * then we must allow the user to set how many tx antennas we | ||
252 | * have available | ||
253 | */ | ||
254 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | ||
255 | |||
256 | unlock: | ||
257 | mutex_unlock(&sc->lock); | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | |||
262 | static void | ||
263 | ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
264 | struct ieee80211_bss_conf *bss_conf, u32 changes) | ||
265 | { | ||
266 | struct ath5k_vif *avf = (void *)vif->drv_priv; | ||
267 | struct ath5k_softc *sc = hw->priv; | ||
268 | struct ath5k_hw *ah = sc->ah; | ||
269 | struct ath_common *common = ath5k_hw_common(ah); | ||
270 | unsigned long flags; | ||
271 | |||
272 | mutex_lock(&sc->lock); | ||
273 | |||
274 | if (changes & BSS_CHANGED_BSSID) { | ||
275 | /* Cache for later use during resets */ | ||
276 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
277 | common->curaid = 0; | ||
278 | ath5k_hw_set_bssid(ah); | ||
279 | mmiowb(); | ||
280 | } | ||
281 | |||
282 | if (changes & BSS_CHANGED_BEACON_INT) | ||
283 | sc->bintval = bss_conf->beacon_int; | ||
284 | |||
285 | if (changes & BSS_CHANGED_ERP_SLOT) { | ||
286 | int slot_time; | ||
287 | |||
288 | ah->ah_short_slot = bss_conf->use_short_slot; | ||
289 | slot_time = ath5k_hw_get_default_slottime(ah) + | ||
290 | 3 * ah->ah_coverage_class; | ||
291 | ath5k_hw_set_ifs_intervals(ah, slot_time); | ||
292 | } | ||
293 | |||
294 | if (changes & BSS_CHANGED_ASSOC) { | ||
295 | avf->assoc = bss_conf->assoc; | ||
296 | if (bss_conf->assoc) | ||
297 | sc->assoc = bss_conf->assoc; | ||
298 | else | ||
299 | sc->assoc = ath_any_vif_assoc(sc); | ||
300 | |||
301 | if (sc->opmode == NL80211_IFTYPE_STATION) | ||
302 | set_beacon_filter(hw, sc->assoc); | ||
303 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | ||
304 | AR5K_LED_ASSOC : AR5K_LED_INIT); | ||
305 | if (bss_conf->assoc) { | ||
306 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, | ||
307 | "Bss Info ASSOC %d, bssid: %pM\n", | ||
308 | bss_conf->aid, common->curbssid); | ||
309 | common->curaid = bss_conf->aid; | ||
310 | ath5k_hw_set_bssid(ah); | ||
311 | /* Once ANI is available you would start it here */ | ||
312 | } | ||
313 | } | ||
314 | |||
315 | if (changes & BSS_CHANGED_BEACON) { | ||
316 | spin_lock_irqsave(&sc->block, flags); | ||
317 | ath5k_beacon_update(hw, vif); | ||
318 | spin_unlock_irqrestore(&sc->block, flags); | ||
319 | } | ||
320 | |||
321 | if (changes & BSS_CHANGED_BEACON_ENABLED) | ||
322 | sc->enable_beacon = bss_conf->enable_beacon; | ||
323 | |||
324 | if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | | ||
325 | BSS_CHANGED_BEACON_INT)) | ||
326 | ath5k_beacon_config(sc); | ||
327 | |||
328 | mutex_unlock(&sc->lock); | ||
329 | } | ||
330 | |||
331 | |||
332 | static u64 | ||
333 | ath5k_prepare_multicast(struct ieee80211_hw *hw, | ||
334 | struct netdev_hw_addr_list *mc_list) | ||
335 | { | ||
336 | u32 mfilt[2], val; | ||
337 | u8 pos; | ||
338 | struct netdev_hw_addr *ha; | ||
339 | |||
340 | mfilt[0] = 0; | ||
341 | mfilt[1] = 1; | ||
342 | |||
343 | netdev_hw_addr_list_for_each(ha, mc_list) { | ||
344 | /* calculate XOR of eight 6-bit values */ | ||
345 | val = get_unaligned_le32(ha->addr + 0); | ||
346 | pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
347 | val = get_unaligned_le32(ha->addr + 3); | ||
348 | pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
349 | pos &= 0x3f; | ||
350 | mfilt[pos / 32] |= (1 << (pos % 32)); | ||
351 | /* XXX: we might be able to just do this instead, | ||
352 | * but not sure, needs testing, if we do use this we'd | ||
353 | * neet to inform below to not reset the mcast */ | ||
354 | /* ath5k_hw_set_mcast_filterindex(ah, | ||
355 | * ha->addr[5]); */ | ||
356 | } | ||
357 | |||
358 | return ((u64)(mfilt[1]) << 32) | mfilt[0]; | ||
359 | } | ||
360 | |||
361 | |||
362 | /* | ||
363 | * o always accept unicast, broadcast, and multicast traffic | ||
364 | * o multicast traffic for all BSSIDs will be enabled if mac80211 | ||
365 | * says it should be | ||
366 | * o maintain current state of phy ofdm or phy cck error reception. | ||
367 | * If the hardware detects any of these type of errors then | ||
368 | * ath5k_hw_get_rx_filter() will pass to us the respective | ||
369 | * hardware filters to be able to receive these type of frames. | ||
370 | * o probe request frames are accepted only when operating in | ||
371 | * hostap, adhoc, or monitor modes | ||
372 | * o enable promiscuous mode according to the interface state | ||
373 | * o accept beacons: | ||
374 | * - when operating in adhoc mode so the 802.11 layer creates | ||
375 | * node table entries for peers, | ||
376 | * - when operating in station mode for collecting rssi data when | ||
377 | * the station is otherwise quiet, or | ||
378 | * - when scanning | ||
379 | */ | ||
380 | static void | ||
381 | ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, | ||
382 | unsigned int *new_flags, u64 multicast) | ||
383 | { | ||
384 | #define SUPPORTED_FIF_FLAGS \ | ||
385 | (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ | ||
386 | FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ | ||
387 | FIF_BCN_PRBRESP_PROMISC) | ||
388 | |||
389 | struct ath5k_softc *sc = hw->priv; | ||
390 | struct ath5k_hw *ah = sc->ah; | ||
391 | u32 mfilt[2], rfilt; | ||
392 | struct ath5k_vif_iter_data iter_data; /* to count STA interfaces */ | ||
393 | |||
394 | mutex_lock(&sc->lock); | ||
395 | |||
396 | mfilt[0] = multicast; | ||
397 | mfilt[1] = multicast >> 32; | ||
398 | |||
399 | /* Only deal with supported flags */ | ||
400 | changed_flags &= SUPPORTED_FIF_FLAGS; | ||
401 | *new_flags &= SUPPORTED_FIF_FLAGS; | ||
402 | |||
403 | /* If HW detects any phy or radar errors, leave those filters on. | ||
404 | * Also, always enable Unicast, Broadcasts and Multicast | ||
405 | * XXX: move unicast, bssid broadcasts and multicast to mac80211 */ | ||
406 | rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) | | ||
407 | (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | | ||
408 | AR5K_RX_FILTER_MCAST); | ||
409 | |||
410 | if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { | ||
411 | if (*new_flags & FIF_PROMISC_IN_BSS) | ||
412 | __set_bit(ATH_STAT_PROMISC, sc->status); | ||
413 | else | ||
414 | __clear_bit(ATH_STAT_PROMISC, sc->status); | ||
415 | } | ||
416 | |||
417 | if (test_bit(ATH_STAT_PROMISC, sc->status)) | ||
418 | rfilt |= AR5K_RX_FILTER_PROM; | ||
419 | |||
420 | /* Note, AR5K_RX_FILTER_MCAST is already enabled */ | ||
421 | if (*new_flags & FIF_ALLMULTI) { | ||
422 | mfilt[0] = ~0; | ||
423 | mfilt[1] = ~0; | ||
424 | } | ||
425 | |||
426 | /* This is the best we can do */ | ||
427 | if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)) | ||
428 | rfilt |= AR5K_RX_FILTER_PHYERR; | ||
429 | |||
430 | /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons | ||
431 | * and probes for any BSSID */ | ||
432 | if ((*new_flags & FIF_BCN_PRBRESP_PROMISC) || (sc->nvifs > 1)) | ||
433 | rfilt |= AR5K_RX_FILTER_BEACON; | ||
434 | |||
435 | /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not | ||
436 | * set we should only pass on control frames for this | ||
437 | * station. This needs testing. I believe right now this | ||
438 | * enables *all* control frames, which is OK.. but | ||
439 | * but we should see if we can improve on granularity */ | ||
440 | if (*new_flags & FIF_CONTROL) | ||
441 | rfilt |= AR5K_RX_FILTER_CONTROL; | ||
442 | |||
443 | /* Additional settings per mode -- this is per ath5k */ | ||
444 | |||
445 | /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ | ||
446 | |||
447 | switch (sc->opmode) { | ||
448 | case NL80211_IFTYPE_MESH_POINT: | ||
449 | rfilt |= AR5K_RX_FILTER_CONTROL | | ||
450 | AR5K_RX_FILTER_BEACON | | ||
451 | AR5K_RX_FILTER_PROBEREQ | | ||
452 | AR5K_RX_FILTER_PROM; | ||
453 | break; | ||
454 | case NL80211_IFTYPE_AP: | ||
455 | case NL80211_IFTYPE_ADHOC: | ||
456 | rfilt |= AR5K_RX_FILTER_PROBEREQ | | ||
457 | AR5K_RX_FILTER_BEACON; | ||
458 | break; | ||
459 | case NL80211_IFTYPE_STATION: | ||
460 | if (sc->assoc) | ||
461 | rfilt |= AR5K_RX_FILTER_BEACON; | ||
462 | default: | ||
463 | break; | ||
464 | } | ||
465 | |||
466 | iter_data.hw_macaddr = NULL; | ||
467 | iter_data.n_stas = 0; | ||
468 | iter_data.need_set_hw_addr = false; | ||
469 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter, | ||
470 | &iter_data); | ||
471 | |||
472 | /* Set up RX Filter */ | ||
473 | if (iter_data.n_stas > 1) { | ||
474 | /* If you have multiple STA interfaces connected to | ||
475 | * different APs, ARPs are not received (most of the time?) | ||
476 | * Enabling PROMISC appears to fix that probem. | ||
477 | */ | ||
478 | rfilt |= AR5K_RX_FILTER_PROM; | ||
479 | } | ||
480 | |||
481 | /* Set filters */ | ||
482 | ath5k_hw_set_rx_filter(ah, rfilt); | ||
483 | |||
484 | /* Set multicast bits */ | ||
485 | ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); | ||
486 | /* Set the cached hw filter flags, this will later actually | ||
487 | * be set in HW */ | ||
488 | sc->filter_flags = rfilt; | ||
489 | |||
490 | mutex_unlock(&sc->lock); | ||
491 | } | ||
492 | |||
493 | |||
494 | static int | ||
495 | ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | ||
496 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | ||
497 | struct ieee80211_key_conf *key) | ||
498 | { | ||
499 | struct ath5k_softc *sc = hw->priv; | ||
500 | struct ath5k_hw *ah = sc->ah; | ||
501 | struct ath_common *common = ath5k_hw_common(ah); | ||
502 | int ret = 0; | ||
503 | |||
504 | if (ath5k_modparam_nohwcrypt) | ||
505 | return -EOPNOTSUPP; | ||
506 | |||
507 | switch (key->cipher) { | ||
508 | case WLAN_CIPHER_SUITE_WEP40: | ||
509 | case WLAN_CIPHER_SUITE_WEP104: | ||
510 | case WLAN_CIPHER_SUITE_TKIP: | ||
511 | break; | ||
512 | case WLAN_CIPHER_SUITE_CCMP: | ||
513 | if (common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM) | ||
514 | break; | ||
515 | return -EOPNOTSUPP; | ||
516 | default: | ||
517 | WARN_ON(1); | ||
518 | return -EINVAL; | ||
519 | } | ||
520 | |||
521 | mutex_lock(&sc->lock); | ||
522 | |||
523 | switch (cmd) { | ||
524 | case SET_KEY: | ||
525 | ret = ath_key_config(common, vif, sta, key); | ||
526 | if (ret >= 0) { | ||
527 | key->hw_key_idx = ret; | ||
528 | /* push IV and Michael MIC generation to stack */ | ||
529 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
530 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) | ||
531 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
532 | if (key->cipher == WLAN_CIPHER_SUITE_CCMP) | ||
533 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | ||
534 | ret = 0; | ||
535 | } | ||
536 | break; | ||
537 | case DISABLE_KEY: | ||
538 | ath_key_delete(common, key); | ||
539 | break; | ||
540 | default: | ||
541 | ret = -EINVAL; | ||
542 | } | ||
543 | |||
544 | mmiowb(); | ||
545 | mutex_unlock(&sc->lock); | ||
546 | return ret; | ||
547 | } | ||
548 | |||
549 | |||
550 | static void | ||
551 | ath5k_sw_scan_start(struct ieee80211_hw *hw) | ||
552 | { | ||
553 | struct ath5k_softc *sc = hw->priv; | ||
554 | if (!sc->assoc) | ||
555 | ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN); | ||
556 | } | ||
557 | |||
558 | |||
559 | static void | ||
560 | ath5k_sw_scan_complete(struct ieee80211_hw *hw) | ||
561 | { | ||
562 | struct ath5k_softc *sc = hw->priv; | ||
563 | ath5k_hw_set_ledstate(sc->ah, sc->assoc ? | ||
564 | AR5K_LED_ASSOC : AR5K_LED_INIT); | ||
565 | } | ||
566 | |||
567 | |||
568 | static int | ||
569 | ath5k_get_stats(struct ieee80211_hw *hw, | ||
570 | struct ieee80211_low_level_stats *stats) | ||
571 | { | ||
572 | struct ath5k_softc *sc = hw->priv; | ||
573 | |||
574 | /* Force update */ | ||
575 | ath5k_hw_update_mib_counters(sc->ah); | ||
576 | |||
577 | stats->dot11ACKFailureCount = sc->stats.ack_fail; | ||
578 | stats->dot11RTSFailureCount = sc->stats.rts_fail; | ||
579 | stats->dot11RTSSuccessCount = sc->stats.rts_ok; | ||
580 | stats->dot11FCSErrorCount = sc->stats.fcs_error; | ||
581 | |||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | |||
586 | static int | ||
587 | ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue, | ||
588 | const struct ieee80211_tx_queue_params *params) | ||
589 | { | ||
590 | struct ath5k_softc *sc = hw->priv; | ||
591 | struct ath5k_hw *ah = sc->ah; | ||
592 | struct ath5k_txq_info qi; | ||
593 | int ret = 0; | ||
594 | |||
595 | if (queue >= ah->ah_capabilities.cap_queues.q_tx_num) | ||
596 | return 0; | ||
597 | |||
598 | mutex_lock(&sc->lock); | ||
599 | |||
600 | ath5k_hw_get_tx_queueprops(ah, queue, &qi); | ||
601 | |||
602 | qi.tqi_aifs = params->aifs; | ||
603 | qi.tqi_cw_min = params->cw_min; | ||
604 | qi.tqi_cw_max = params->cw_max; | ||
605 | qi.tqi_burst_time = params->txop; | ||
606 | |||
607 | ATH5K_DBG(sc, ATH5K_DEBUG_ANY, | ||
608 | "Configure tx [queue %d], " | ||
609 | "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", | ||
610 | queue, params->aifs, params->cw_min, | ||
611 | params->cw_max, params->txop); | ||
612 | |||
613 | if (ath5k_hw_set_tx_queueprops(ah, queue, &qi)) { | ||
614 | ATH5K_ERR(sc, | ||
615 | "Unable to update hardware queue %u!\n", queue); | ||
616 | ret = -EIO; | ||
617 | } else | ||
618 | ath5k_hw_reset_tx_queue(ah, queue); | ||
619 | |||
620 | mutex_unlock(&sc->lock); | ||
621 | |||
622 | return ret; | ||
623 | } | ||
624 | |||
625 | |||
626 | static u64 | ||
627 | ath5k_get_tsf(struct ieee80211_hw *hw) | ||
628 | { | ||
629 | struct ath5k_softc *sc = hw->priv; | ||
630 | |||
631 | return ath5k_hw_get_tsf64(sc->ah); | ||
632 | } | ||
633 | |||
634 | |||
635 | static void | ||
636 | ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | ||
637 | { | ||
638 | struct ath5k_softc *sc = hw->priv; | ||
639 | |||
640 | ath5k_hw_set_tsf64(sc->ah, tsf); | ||
641 | } | ||
642 | |||
643 | |||
644 | static void | ||
645 | ath5k_reset_tsf(struct ieee80211_hw *hw) | ||
646 | { | ||
647 | struct ath5k_softc *sc = hw->priv; | ||
648 | |||
649 | /* | ||
650 | * in IBSS mode we need to update the beacon timers too. | ||
651 | * this will also reset the TSF if we call it with 0 | ||
652 | */ | ||
653 | if (sc->opmode == NL80211_IFTYPE_ADHOC) | ||
654 | ath5k_beacon_update_timers(sc, 0); | ||
655 | else | ||
656 | ath5k_hw_reset_tsf(sc->ah); | ||
657 | } | ||
658 | |||
659 | |||
660 | static int | ||
661 | ath5k_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey) | ||
662 | { | ||
663 | struct ath5k_softc *sc = hw->priv; | ||
664 | struct ieee80211_conf *conf = &hw->conf; | ||
665 | struct ath_common *common = ath5k_hw_common(sc->ah); | ||
666 | struct ath_cycle_counters *cc = &common->cc_survey; | ||
667 | unsigned int div = common->clockrate * 1000; | ||
668 | |||
669 | if (idx != 0) | ||
670 | return -ENOENT; | ||
671 | |||
672 | spin_lock_bh(&common->cc_lock); | ||
673 | ath_hw_cycle_counters_update(common); | ||
674 | if (cc->cycles > 0) { | ||
675 | sc->survey.channel_time += cc->cycles / div; | ||
676 | sc->survey.channel_time_busy += cc->rx_busy / div; | ||
677 | sc->survey.channel_time_rx += cc->rx_frame / div; | ||
678 | sc->survey.channel_time_tx += cc->tx_frame / div; | ||
679 | } | ||
680 | memset(cc, 0, sizeof(*cc)); | ||
681 | spin_unlock_bh(&common->cc_lock); | ||
682 | |||
683 | memcpy(survey, &sc->survey, sizeof(*survey)); | ||
684 | |||
685 | survey->channel = conf->channel; | ||
686 | survey->noise = sc->ah->ah_noise_floor; | ||
687 | survey->filled = SURVEY_INFO_NOISE_DBM | | ||
688 | SURVEY_INFO_CHANNEL_TIME | | ||
689 | SURVEY_INFO_CHANNEL_TIME_BUSY | | ||
690 | SURVEY_INFO_CHANNEL_TIME_RX | | ||
691 | SURVEY_INFO_CHANNEL_TIME_TX; | ||
692 | |||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | |||
697 | /** | ||
698 | * ath5k_set_coverage_class - Set IEEE 802.11 coverage class | ||
699 | * | ||
700 | * @hw: struct ieee80211_hw pointer | ||
701 | * @coverage_class: IEEE 802.11 coverage class number | ||
702 | * | ||
703 | * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given | ||
704 | * coverage class. The values are persistent, they are restored after device | ||
705 | * reset. | ||
706 | */ | ||
707 | static void | ||
708 | ath5k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | ||
709 | { | ||
710 | struct ath5k_softc *sc = hw->priv; | ||
711 | |||
712 | mutex_lock(&sc->lock); | ||
713 | ath5k_hw_set_coverage_class(sc->ah, coverage_class); | ||
714 | mutex_unlock(&sc->lock); | ||
715 | } | ||
716 | |||
717 | |||
718 | static int | ||
719 | ath5k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) | ||
720 | { | ||
721 | struct ath5k_softc *sc = hw->priv; | ||
722 | |||
723 | if (tx_ant == 1 && rx_ant == 1) | ||
724 | ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_A); | ||
725 | else if (tx_ant == 2 && rx_ant == 2) | ||
726 | ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_FIXED_B); | ||
727 | else if ((tx_ant & 3) == 3 && (rx_ant & 3) == 3) | ||
728 | ath5k_hw_set_antenna_mode(sc->ah, AR5K_ANTMODE_DEFAULT); | ||
729 | else | ||
730 | return -EINVAL; | ||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | |||
735 | static int | ||
736 | ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) | ||
737 | { | ||
738 | struct ath5k_softc *sc = hw->priv; | ||
739 | |||
740 | switch (sc->ah->ah_ant_mode) { | ||
741 | case AR5K_ANTMODE_FIXED_A: | ||
742 | *tx_ant = 1; *rx_ant = 1; break; | ||
743 | case AR5K_ANTMODE_FIXED_B: | ||
744 | *tx_ant = 2; *rx_ant = 2; break; | ||
745 | case AR5K_ANTMODE_DEFAULT: | ||
746 | *tx_ant = 3; *rx_ant = 3; break; | ||
747 | } | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | |||
752 | static void ath5k_get_ringparam(struct ieee80211_hw *hw, | ||
753 | u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) | ||
754 | { | ||
755 | struct ath5k_softc *sc = hw->priv; | ||
756 | |||
757 | *tx = sc->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max; | ||
758 | |||
759 | *tx_max = ATH5K_TXQ_LEN_MAX; | ||
760 | *rx = *rx_max = ATH_RXBUF; | ||
761 | } | ||
762 | |||
763 | |||
764 | static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx) | ||
765 | { | ||
766 | struct ath5k_softc *sc = hw->priv; | ||
767 | u16 qnum; | ||
768 | |||
769 | /* only support setting tx ring size for now */ | ||
770 | if (rx != ATH_RXBUF) | ||
771 | return -EINVAL; | ||
772 | |||
773 | /* restrict tx ring size min/max */ | ||
774 | if (!tx || tx > ATH5K_TXQ_LEN_MAX) | ||
775 | return -EINVAL; | ||
776 | |||
777 | for (qnum = 0; qnum < ARRAY_SIZE(sc->txqs); qnum++) { | ||
778 | if (!sc->txqs[qnum].setup) | ||
779 | continue; | ||
780 | if (sc->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN || | ||
781 | sc->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX) | ||
782 | continue; | ||
783 | |||
784 | sc->txqs[qnum].txq_max = tx; | ||
785 | if (sc->txqs[qnum].txq_len >= sc->txqs[qnum].txq_max) | ||
786 | ieee80211_stop_queue(hw, sc->txqs[qnum].qnum); | ||
787 | } | ||
788 | |||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | |||
793 | const struct ieee80211_ops ath5k_hw_ops = { | ||
794 | .tx = ath5k_tx, | ||
795 | .start = ath5k_start, | ||
796 | .stop = ath5k_stop, | ||
797 | .add_interface = ath5k_add_interface, | ||
798 | /* .change_interface = not implemented */ | ||
799 | .remove_interface = ath5k_remove_interface, | ||
800 | .config = ath5k_config, | ||
801 | .bss_info_changed = ath5k_bss_info_changed, | ||
802 | .prepare_multicast = ath5k_prepare_multicast, | ||
803 | .configure_filter = ath5k_configure_filter, | ||
804 | /* .set_tim = not implemented */ | ||
805 | .set_key = ath5k_set_key, | ||
806 | /* .update_tkip_key = not implemented */ | ||
807 | /* .hw_scan = not implemented */ | ||
808 | .sw_scan_start = ath5k_sw_scan_start, | ||
809 | .sw_scan_complete = ath5k_sw_scan_complete, | ||
810 | .get_stats = ath5k_get_stats, | ||
811 | /* .get_tkip_seq = not implemented */ | ||
812 | /* .set_frag_threshold = not implemented */ | ||
813 | /* .set_rts_threshold = not implemented */ | ||
814 | /* .sta_add = not implemented */ | ||
815 | /* .sta_remove = not implemented */ | ||
816 | /* .sta_notify = not implemented */ | ||
817 | .conf_tx = ath5k_conf_tx, | ||
818 | .get_tsf = ath5k_get_tsf, | ||
819 | .set_tsf = ath5k_set_tsf, | ||
820 | .reset_tsf = ath5k_reset_tsf, | ||
821 | /* .tx_last_beacon = not implemented */ | ||
822 | /* .ampdu_action = not needed */ | ||
823 | .get_survey = ath5k_get_survey, | ||
824 | .set_coverage_class = ath5k_set_coverage_class, | ||
825 | /* .rfkill_poll = not implemented */ | ||
826 | /* .flush = not implemented */ | ||
827 | /* .channel_switch = not implemented */ | ||
828 | /* .napi_poll = not implemented */ | ||
829 | .set_antenna = ath5k_set_antenna, | ||
830 | .get_antenna = ath5k_get_antenna, | ||
831 | .set_ringparam = ath5k_set_ringparam, | ||
832 | .get_ringparam = ath5k_get_ringparam, | ||
833 | }; | ||
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c new file mode 100644 index 000000000000..f2c0c236392f --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/pci.c | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/nl80211.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/pci-aspm.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include "../ath.h" | ||
22 | #include "ath5k.h" | ||
23 | #include "debug.h" | ||
24 | #include "base.h" | ||
25 | #include "reg.h" | ||
26 | |||
27 | /* Known PCI ids */ | ||
28 | static DEFINE_PCI_DEVICE_TABLE(ath5k_pci_id_table) = { | ||
29 | { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ | ||
30 | { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ | ||
31 | { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ | ||
32 | { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ | ||
33 | { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ | ||
34 | { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ | ||
35 | { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ | ||
36 | { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ | ||
37 | { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ | ||
38 | { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ | ||
39 | { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ | ||
40 | { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ | ||
41 | { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ | ||
42 | { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ | ||
43 | { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ | ||
44 | { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ | ||
45 | { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ | ||
46 | { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ | ||
47 | { 0 } | ||
48 | }; | ||
49 | MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); | ||
50 | |||
51 | /* return bus cachesize in 4B word units */ | ||
52 | static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz) | ||
53 | { | ||
54 | struct ath5k_softc *sc = (struct ath5k_softc *) common->priv; | ||
55 | u8 u8tmp; | ||
56 | |||
57 | pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, &u8tmp); | ||
58 | *csz = (int)u8tmp; | ||
59 | |||
60 | /* | ||
61 | * This check was put in to avoid "unpleasant" consequences if | ||
62 | * the bootrom has not fully initialized all PCI devices. | ||
63 | * Sometimes the cache line size register is not set | ||
64 | */ | ||
65 | |||
66 | if (*csz == 0) | ||
67 | *csz = L1_CACHE_BYTES >> 2; /* Use the default size */ | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Read from eeprom | ||
72 | */ | ||
73 | static bool | ||
74 | ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data) | ||
75 | { | ||
76 | struct ath5k_hw *ah = (struct ath5k_hw *) common->ah; | ||
77 | u32 status, timeout; | ||
78 | |||
79 | /* | ||
80 | * Initialize EEPROM access | ||
81 | */ | ||
82 | if (ah->ah_version == AR5K_AR5210) { | ||
83 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); | ||
84 | (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); | ||
85 | } else { | ||
86 | ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); | ||
87 | AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, | ||
88 | AR5K_EEPROM_CMD_READ); | ||
89 | } | ||
90 | |||
91 | for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { | ||
92 | status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); | ||
93 | if (status & AR5K_EEPROM_STAT_RDDONE) { | ||
94 | if (status & AR5K_EEPROM_STAT_RDERR) | ||
95 | return false; | ||
96 | *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & | ||
97 | 0xffff); | ||
98 | return true; | ||
99 | } | ||
100 | udelay(15); | ||
101 | } | ||
102 | |||
103 | return false; | ||
104 | } | ||
105 | |||
106 | int ath5k_hw_read_srev(struct ath5k_hw *ah) | ||
107 | { | ||
108 | ah->ah_mac_srev = ath5k_hw_reg_read(ah, AR5K_SREV); | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Read the MAC address from eeprom or platform_data | ||
114 | */ | ||
115 | static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
116 | { | ||
117 | u8 mac_d[ETH_ALEN] = {}; | ||
118 | u32 total, offset; | ||
119 | u16 data; | ||
120 | int octet; | ||
121 | |||
122 | AR5K_EEPROM_READ(0x20, data); | ||
123 | |||
124 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | ||
125 | AR5K_EEPROM_READ(offset, data); | ||
126 | |||
127 | total += data; | ||
128 | mac_d[octet + 1] = data & 0xff; | ||
129 | mac_d[octet] = data >> 8; | ||
130 | octet += 2; | ||
131 | } | ||
132 | |||
133 | if (!total || total == 3 * 0xffff) | ||
134 | return -EINVAL; | ||
135 | |||
136 | memcpy(mac, mac_d, ETH_ALEN); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | |||
142 | /* Common ath_bus_opts structure */ | ||
143 | static const struct ath_bus_ops ath_pci_bus_ops = { | ||
144 | .ath_bus_type = ATH_PCI, | ||
145 | .read_cachesize = ath5k_pci_read_cachesize, | ||
146 | .eeprom_read = ath5k_pci_eeprom_read, | ||
147 | .eeprom_read_mac = ath5k_pci_eeprom_read_mac, | ||
148 | }; | ||
149 | |||
150 | /********************\ | ||
151 | * PCI Initialization * | ||
152 | \********************/ | ||
153 | |||
154 | static int __devinit | ||
155 | ath5k_pci_probe(struct pci_dev *pdev, | ||
156 | const struct pci_device_id *id) | ||
157 | { | ||
158 | void __iomem *mem; | ||
159 | struct ath5k_softc *sc; | ||
160 | struct ieee80211_hw *hw; | ||
161 | int ret; | ||
162 | u8 csz; | ||
163 | |||
164 | /* | ||
165 | * L0s needs to be disabled on all ath5k cards. | ||
166 | * | ||
167 | * For distributions shipping with CONFIG_PCIEASPM (this will be enabled | ||
168 | * by default in the future in 2.6.36) this will also mean both L1 and | ||
169 | * L0s will be disabled when a pre 1.1 PCIe device is detected. We do | ||
170 | * know L1 works correctly even for all ath5k pre 1.1 PCIe devices | ||
171 | * though but cannot currently undue the effect of a blacklist, for | ||
172 | * details you can read pcie_aspm_sanity_check() and see how it adjusts | ||
173 | * the device link capability. | ||
174 | * | ||
175 | * It may be possible in the future to implement some PCI API to allow | ||
176 | * drivers to override blacklists for pre 1.1 PCIe but for now it is | ||
177 | * best to accept that both L0s and L1 will be disabled completely for | ||
178 | * distributions shipping with CONFIG_PCIEASPM rather than having this | ||
179 | * issue present. Motivation for adding this new API will be to help | ||
180 | * with power consumption for some of these devices. | ||
181 | */ | ||
182 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); | ||
183 | |||
184 | ret = pci_enable_device(pdev); | ||
185 | if (ret) { | ||
186 | dev_err(&pdev->dev, "can't enable device\n"); | ||
187 | goto err; | ||
188 | } | ||
189 | |||
190 | /* XXX 32-bit addressing only */ | ||
191 | ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
192 | if (ret) { | ||
193 | dev_err(&pdev->dev, "32-bit DMA not available\n"); | ||
194 | goto err_dis; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * Cache line size is used to size and align various | ||
199 | * structures used to communicate with the hardware. | ||
200 | */ | ||
201 | pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); | ||
202 | if (csz == 0) { | ||
203 | /* | ||
204 | * Linux 2.4.18 (at least) writes the cache line size | ||
205 | * register as a 16-bit wide register which is wrong. | ||
206 | * We must have this setup properly for rx buffer | ||
207 | * DMA to work so force a reasonable value here if it | ||
208 | * comes up zero. | ||
209 | */ | ||
210 | csz = L1_CACHE_BYTES >> 2; | ||
211 | pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); | ||
212 | } | ||
213 | /* | ||
214 | * The default setting of latency timer yields poor results, | ||
215 | * set it to the value used by other systems. It may be worth | ||
216 | * tweaking this setting more. | ||
217 | */ | ||
218 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); | ||
219 | |||
220 | /* Enable bus mastering */ | ||
221 | pci_set_master(pdev); | ||
222 | |||
223 | /* | ||
224 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
225 | * PCI Tx retries from interfering with C3 CPU state. | ||
226 | */ | ||
227 | pci_write_config_byte(pdev, 0x41, 0); | ||
228 | |||
229 | ret = pci_request_region(pdev, 0, "ath5k"); | ||
230 | if (ret) { | ||
231 | dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); | ||
232 | goto err_dis; | ||
233 | } | ||
234 | |||
235 | mem = pci_iomap(pdev, 0, 0); | ||
236 | if (!mem) { | ||
237 | dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; | ||
238 | ret = -EIO; | ||
239 | goto err_reg; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * Allocate hw (mac80211 main struct) | ||
244 | * and hw->priv (driver private data) | ||
245 | */ | ||
246 | hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); | ||
247 | if (hw == NULL) { | ||
248 | dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); | ||
249 | ret = -ENOMEM; | ||
250 | goto err_map; | ||
251 | } | ||
252 | |||
253 | dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); | ||
254 | |||
255 | sc = hw->priv; | ||
256 | sc->hw = hw; | ||
257 | sc->pdev = pdev; | ||
258 | sc->dev = &pdev->dev; | ||
259 | sc->irq = pdev->irq; | ||
260 | sc->devid = id->device; | ||
261 | sc->iobase = mem; /* So we can unmap it on detach */ | ||
262 | |||
263 | /* Initialize */ | ||
264 | ret = ath5k_init_softc(sc, &ath_pci_bus_ops); | ||
265 | if (ret) | ||
266 | goto err_free; | ||
267 | |||
268 | /* Set private data */ | ||
269 | pci_set_drvdata(pdev, hw); | ||
270 | |||
271 | return 0; | ||
272 | err_free: | ||
273 | ieee80211_free_hw(hw); | ||
274 | err_map: | ||
275 | pci_iounmap(pdev, mem); | ||
276 | err_reg: | ||
277 | pci_release_region(pdev, 0); | ||
278 | err_dis: | ||
279 | pci_disable_device(pdev); | ||
280 | err: | ||
281 | return ret; | ||
282 | } | ||
283 | |||
284 | static void __devexit | ||
285 | ath5k_pci_remove(struct pci_dev *pdev) | ||
286 | { | ||
287 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
288 | struct ath5k_softc *sc = hw->priv; | ||
289 | |||
290 | ath5k_deinit_softc(sc); | ||
291 | pci_iounmap(pdev, sc->iobase); | ||
292 | pci_release_region(pdev, 0); | ||
293 | pci_disable_device(pdev); | ||
294 | ieee80211_free_hw(hw); | ||
295 | } | ||
296 | |||
297 | #ifdef CONFIG_PM_SLEEP | ||
298 | static int ath5k_pci_suspend(struct device *dev) | ||
299 | { | ||
300 | struct pci_dev *pdev = to_pci_dev(dev); | ||
301 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
302 | struct ath5k_softc *sc = hw->priv; | ||
303 | |||
304 | ath5k_led_off(sc); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int ath5k_pci_resume(struct device *dev) | ||
309 | { | ||
310 | struct pci_dev *pdev = to_pci_dev(dev); | ||
311 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | ||
312 | struct ath5k_softc *sc = hw->priv; | ||
313 | |||
314 | /* | ||
315 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
316 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
317 | * PCI Tx retries from interfering with C3 CPU state | ||
318 | */ | ||
319 | pci_write_config_byte(pdev, 0x41, 0); | ||
320 | |||
321 | ath5k_led_enable(sc); | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static SIMPLE_DEV_PM_OPS(ath5k_pm_ops, ath5k_pci_suspend, ath5k_pci_resume); | ||
326 | #define ATH5K_PM_OPS (&ath5k_pm_ops) | ||
327 | #else | ||
328 | #define ATH5K_PM_OPS NULL | ||
329 | #endif /* CONFIG_PM_SLEEP */ | ||
330 | |||
331 | static struct pci_driver ath5k_pci_driver = { | ||
332 | .name = KBUILD_MODNAME, | ||
333 | .id_table = ath5k_pci_id_table, | ||
334 | .probe = ath5k_pci_probe, | ||
335 | .remove = __devexit_p(ath5k_pci_remove), | ||
336 | .driver.pm = ATH5K_PM_OPS, | ||
337 | }; | ||
338 | |||
339 | /* | ||
340 | * Module init/exit functions | ||
341 | */ | ||
342 | static int __init | ||
343 | init_ath5k_pci(void) | ||
344 | { | ||
345 | int ret; | ||
346 | |||
347 | ret = pci_register_driver(&ath5k_pci_driver); | ||
348 | if (ret) { | ||
349 | printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); | ||
350 | return ret; | ||
351 | } | ||
352 | |||
353 | return 0; | ||
354 | } | ||
355 | |||
356 | static void __exit | ||
357 | exit_ath5k_pci(void) | ||
358 | { | ||
359 | pci_unregister_driver(&ath5k_pci_driver); | ||
360 | } | ||
361 | |||
362 | module_init(init_ath5k_pci); | ||
363 | module_exit(exit_ath5k_pci); | ||
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 86fdb6ddfaaa..712a9ac4000e 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -31,87 +31,169 @@ | |||
31 | #include "debug.h" | 31 | #include "debug.h" |
32 | #include "base.h" | 32 | #include "base.h" |
33 | 33 | ||
34 | /* | ||
35 | * AR5212+ can use higher rates for ack transmition | ||
36 | * based on current tx rate instead of the base rate. | ||
37 | * It does this to better utilize channel usage. | ||
38 | * This is a mapping between G rates (that cover both | ||
39 | * CCK and OFDM) and ack rates that we use when setting | ||
40 | * rate -> duration table. This mapping is hw-based so | ||
41 | * don't change anything. | ||
42 | * | ||
43 | * To enable this functionality we must set | ||
44 | * ah->ah_ack_bitrate_high to true else base rate is | ||
45 | * used (1Mb for CCK, 6Mb for OFDM). | ||
46 | */ | ||
47 | static const unsigned int ack_rates_high[] = | ||
48 | /* Tx -> ACK */ | ||
49 | /* 1Mb -> 1Mb */ { 0, | ||
50 | /* 2MB -> 2Mb */ 1, | ||
51 | /* 5.5Mb -> 2Mb */ 1, | ||
52 | /* 11Mb -> 2Mb */ 1, | ||
53 | /* 6Mb -> 6Mb */ 4, | ||
54 | /* 9Mb -> 6Mb */ 4, | ||
55 | /* 12Mb -> 12Mb */ 6, | ||
56 | /* 18Mb -> 12Mb */ 6, | ||
57 | /* 24Mb -> 24Mb */ 8, | ||
58 | /* 36Mb -> 24Mb */ 8, | ||
59 | /* 48Mb -> 24Mb */ 8, | ||
60 | /* 54Mb -> 24Mb */ 8 }; | ||
61 | |||
34 | /*******************\ | 62 | /*******************\ |
35 | * Generic functions * | 63 | * Helper functions * |
36 | \*******************/ | 64 | \*******************/ |
37 | 65 | ||
38 | /** | 66 | /** |
39 | * ath5k_hw_set_opmode - Set PCU operating mode | 67 | * ath5k_hw_get_frame_duration - Get tx time of a frame |
40 | * | 68 | * |
41 | * @ah: The &struct ath5k_hw | 69 | * @ah: The &struct ath5k_hw |
42 | * @op_mode: &enum nl80211_iftype operating mode | 70 | * @len: Frame's length in bytes |
71 | * @rate: The @struct ieee80211_rate | ||
43 | * | 72 | * |
44 | * Initialize PCU for the various operating modes (AP/STA etc) | 73 | * Calculate tx duration of a frame given it's rate and length |
74 | * It extends ieee80211_generic_frame_duration for non standard | ||
75 | * bwmodes. | ||
45 | */ | 76 | */ |
46 | int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | 77 | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, |
78 | int len, struct ieee80211_rate *rate, bool shortpre) | ||
47 | { | 79 | { |
48 | struct ath_common *common = ath5k_hw_common(ah); | 80 | struct ath5k_softc *sc = ah->ah_sc; |
49 | u32 pcu_reg, beacon_reg, low_id, high_id; | 81 | int sifs, preamble, plcp_bits, sym_time; |
82 | int bitrate, bits, symbols, symbol_bits; | ||
83 | int dur; | ||
84 | |||
85 | /* Fallback */ | ||
86 | if (!ah->ah_bwmode) { | ||
87 | __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw, | ||
88 | NULL, len, rate); | ||
89 | |||
90 | /* subtract difference between long and short preamble */ | ||
91 | dur = le16_to_cpu(raw_dur); | ||
92 | if (shortpre) | ||
93 | dur -= 96; | ||
94 | |||
95 | return dur; | ||
96 | } | ||
50 | 97 | ||
51 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); | 98 | bitrate = rate->bitrate; |
99 | preamble = AR5K_INIT_OFDM_PREAMPLE_TIME; | ||
100 | plcp_bits = AR5K_INIT_OFDM_PLCP_BITS; | ||
101 | sym_time = AR5K_INIT_OFDM_SYMBOL_TIME; | ||
52 | 102 | ||
53 | /* Preserve rest settings */ | 103 | switch (ah->ah_bwmode) { |
54 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | 104 | case AR5K_BWMODE_40MHZ: |
55 | pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP | 105 | sifs = AR5K_INIT_SIFS_TURBO; |
56 | | AR5K_STA_ID1_KEYSRCH_MODE | 106 | preamble = AR5K_INIT_OFDM_PREAMBLE_TIME_MIN; |
57 | | (ah->ah_version == AR5K_AR5210 ? | 107 | break; |
58 | (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); | 108 | case AR5K_BWMODE_10MHZ: |
109 | sifs = AR5K_INIT_SIFS_HALF_RATE; | ||
110 | preamble *= 2; | ||
111 | sym_time *= 2; | ||
112 | break; | ||
113 | case AR5K_BWMODE_5MHZ: | ||
114 | sifs = AR5K_INIT_SIFS_QUARTER_RATE; | ||
115 | preamble *= 4; | ||
116 | sym_time *= 4; | ||
117 | break; | ||
118 | default: | ||
119 | sifs = AR5K_INIT_SIFS_DEFAULT_BG; | ||
120 | break; | ||
121 | } | ||
59 | 122 | ||
60 | beacon_reg = 0; | 123 | bits = plcp_bits + (len << 3); |
124 | /* Bit rate is in 100Kbits */ | ||
125 | symbol_bits = bitrate * sym_time; | ||
126 | symbols = DIV_ROUND_UP(bits * 10, symbol_bits); | ||
61 | 127 | ||
62 | switch (op_mode) { | 128 | dur = sifs + preamble + (sym_time * symbols); |
63 | case NL80211_IFTYPE_ADHOC: | ||
64 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; | ||
65 | beacon_reg |= AR5K_BCR_ADHOC; | ||
66 | if (ah->ah_version == AR5K_AR5210) | ||
67 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
68 | else | ||
69 | AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | ||
70 | break; | ||
71 | 129 | ||
72 | case NL80211_IFTYPE_AP: | 130 | return dur; |
73 | case NL80211_IFTYPE_MESH_POINT: | 131 | } |
74 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; | ||
75 | beacon_reg |= AR5K_BCR_AP; | ||
76 | if (ah->ah_version == AR5K_AR5210) | ||
77 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
78 | else | ||
79 | AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | ||
80 | break; | ||
81 | 132 | ||
82 | case NL80211_IFTYPE_STATION: | 133 | /** |
83 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | 134 | * ath5k_hw_get_default_slottime - Get the default slot time for current mode |
84 | | (ah->ah_version == AR5K_AR5210 ? | 135 | * |
85 | AR5K_STA_ID1_PWR_SV : 0); | 136 | * @ah: The &struct ath5k_hw |
86 | case NL80211_IFTYPE_MONITOR: | 137 | */ |
87 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | 138 | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) |
88 | | (ah->ah_version == AR5K_AR5210 ? | 139 | { |
89 | AR5K_STA_ID1_NO_PSPOLL : 0); | 140 | struct ieee80211_channel *channel = ah->ah_current_channel; |
90 | break; | 141 | unsigned int slot_time; |
91 | 142 | ||
143 | switch (ah->ah_bwmode) { | ||
144 | case AR5K_BWMODE_40MHZ: | ||
145 | slot_time = AR5K_INIT_SLOT_TIME_TURBO; | ||
146 | break; | ||
147 | case AR5K_BWMODE_10MHZ: | ||
148 | slot_time = AR5K_INIT_SLOT_TIME_HALF_RATE; | ||
149 | break; | ||
150 | case AR5K_BWMODE_5MHZ: | ||
151 | slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE; | ||
152 | break; | ||
153 | case AR5K_BWMODE_DEFAULT: | ||
92 | default: | 154 | default: |
93 | return -EINVAL; | 155 | slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; |
156 | if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot) | ||
157 | slot_time = AR5K_INIT_SLOT_TIME_B; | ||
158 | break; | ||
94 | } | 159 | } |
95 | 160 | ||
96 | /* | 161 | return slot_time; |
97 | * Set PCU registers | 162 | } |
98 | */ | ||
99 | low_id = get_unaligned_le32(common->macaddr); | ||
100 | high_id = get_unaligned_le16(common->macaddr + 4); | ||
101 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | ||
102 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | ||
103 | 163 | ||
104 | /* | 164 | /** |
105 | * Set Beacon Control Register on 5210 | 165 | * ath5k_hw_get_default_sifs - Get the default SIFS for current mode |
106 | */ | 166 | * |
107 | if (ah->ah_version == AR5K_AR5210) | 167 | * @ah: The &struct ath5k_hw |
108 | ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); | 168 | */ |
169 | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | ||
170 | { | ||
171 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
172 | unsigned int sifs; | ||
109 | 173 | ||
110 | return 0; | 174 | switch (ah->ah_bwmode) { |
175 | case AR5K_BWMODE_40MHZ: | ||
176 | sifs = AR5K_INIT_SIFS_TURBO; | ||
177 | break; | ||
178 | case AR5K_BWMODE_10MHZ: | ||
179 | sifs = AR5K_INIT_SIFS_HALF_RATE; | ||
180 | break; | ||
181 | case AR5K_BWMODE_5MHZ: | ||
182 | sifs = AR5K_INIT_SIFS_QUARTER_RATE; | ||
183 | break; | ||
184 | case AR5K_BWMODE_DEFAULT: | ||
185 | sifs = AR5K_INIT_SIFS_DEFAULT_BG; | ||
186 | default: | ||
187 | if (channel->hw_value & CHANNEL_5GHZ) | ||
188 | sifs = AR5K_INIT_SIFS_DEFAULT_A; | ||
189 | break; | ||
190 | } | ||
191 | |||
192 | return sifs; | ||
111 | } | 193 | } |
112 | 194 | ||
113 | /** | 195 | /** |
114 | * ath5k_hw_update - Update MIB counters (mac layer statistics) | 196 | * ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics) |
115 | * | 197 | * |
116 | * @ah: The &struct ath5k_hw | 198 | * @ah: The &struct ath5k_hw |
117 | * | 199 | * |
@@ -133,35 +215,72 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) | |||
133 | stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); | 215 | stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); |
134 | } | 216 | } |
135 | 217 | ||
218 | |||
219 | /******************\ | ||
220 | * ACK/CTS Timeouts * | ||
221 | \******************/ | ||
222 | |||
136 | /** | 223 | /** |
137 | * ath5k_hw_set_ack_bitrate - set bitrate for ACKs | 224 | * ath5k_hw_write_rate_duration - fill rate code to duration table |
138 | * | 225 | * |
139 | * @ah: The &struct ath5k_hw | 226 | * @ah: the &struct ath5k_hw |
140 | * @high: Flag to determine if we want to use high transmition rate | 227 | * @mode: one of enum ath5k_driver_mode |
141 | * for ACKs or not | 228 | * |
229 | * Write the rate code to duration table upon hw reset. This is a helper for | ||
230 | * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on | ||
231 | * the hardware, based on current mode, for each rate. The rates which are | ||
232 | * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have | ||
233 | * different rate code so we write their value twice (one for long preamble | ||
234 | * and one for short). | ||
235 | * | ||
236 | * Note: Band doesn't matter here, if we set the values for OFDM it works | ||
237 | * on both a and g modes. So all we have to do is set values for all g rates | ||
238 | * that include all OFDM and CCK rates. | ||
142 | * | 239 | * |
143 | * If high flag is set, we tell hw to use a set of control rates based on | ||
144 | * the current transmition rate (check out control_rates array inside reset.c). | ||
145 | * If not hw just uses the lowest rate available for the current modulation | ||
146 | * scheme being used (1Mbit for CCK and 6Mbits for OFDM). | ||
147 | */ | 240 | */ |
148 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | 241 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) |
149 | { | 242 | { |
150 | if (ah->ah_version != AR5K_AR5212) | 243 | struct ath5k_softc *sc = ah->ah_sc; |
151 | return; | 244 | struct ieee80211_rate *rate; |
152 | else { | 245 | unsigned int i; |
153 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; | 246 | /* 802.11g covers both OFDM and CCK */ |
154 | if (high) | 247 | u8 band = IEEE80211_BAND_2GHZ; |
155 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); | 248 | |
249 | /* Write rate duration table */ | ||
250 | for (i = 0; i < sc->sbands[band].n_bitrates; i++) { | ||
251 | u32 reg; | ||
252 | u16 tx_time; | ||
253 | |||
254 | if (ah->ah_ack_bitrate_high) | ||
255 | rate = &sc->sbands[band].bitrates[ack_rates_high[i]]; | ||
256 | /* CCK -> 1Mb */ | ||
257 | else if (i < 4) | ||
258 | rate = &sc->sbands[band].bitrates[0]; | ||
259 | /* OFDM -> 6Mb */ | ||
156 | else | 260 | else |
157 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | 261 | rate = &sc->sbands[band].bitrates[4]; |
158 | } | ||
159 | } | ||
160 | 262 | ||
263 | /* Set ACK timeout */ | ||
264 | reg = AR5K_RATE_DUR(rate->hw_value); | ||
161 | 265 | ||
162 | /******************\ | 266 | /* An ACK frame consists of 10 bytes. If you add the FCS, |
163 | * ACK/CTS Timeouts * | 267 | * which ieee80211_generic_frame_duration() adds, |
164 | \******************/ | 268 | * its 14 bytes. Note we use the control rate and not the |
269 | * actual rate for this rate. See mac80211 tx.c | ||
270 | * ieee80211_duration() for a brief description of | ||
271 | * what rate we should choose to TX ACKs. */ | ||
272 | tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); | ||
273 | |||
274 | ath5k_hw_reg_write(ah, tx_time, reg); | ||
275 | |||
276 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | ||
277 | continue; | ||
278 | |||
279 | tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true); | ||
280 | ath5k_hw_reg_write(ah, tx_time, | ||
281 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | ||
282 | } | ||
283 | } | ||
165 | 284 | ||
166 | /** | 285 | /** |
167 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU | 286 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU |
@@ -199,85 +318,10 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
199 | return 0; | 318 | return 0; |
200 | } | 319 | } |
201 | 320 | ||
202 | /** | ||
203 | * ath5k_hw_htoclock - Translate usec to hw clock units | ||
204 | * | ||
205 | * @ah: The &struct ath5k_hw | ||
206 | * @usec: value in microseconds | ||
207 | */ | ||
208 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) | ||
209 | { | ||
210 | return usec * ath5k_hw_get_clockrate(ah); | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * ath5k_hw_clocktoh - Translate hw clock units to usec | ||
215 | * @clock: value in hw clock units | ||
216 | */ | ||
217 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | ||
218 | { | ||
219 | return clock / ath5k_hw_get_clockrate(ah); | ||
220 | } | ||
221 | |||
222 | /** | ||
223 | * ath5k_hw_get_clockrate - Get the clock rate for current mode | ||
224 | * | ||
225 | * @ah: The &struct ath5k_hw | ||
226 | */ | ||
227 | unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) | ||
228 | { | ||
229 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
230 | int clock; | ||
231 | |||
232 | if (channel->hw_value & CHANNEL_5GHZ) | ||
233 | clock = 40; /* 802.11a */ | ||
234 | else if (channel->hw_value & CHANNEL_CCK) | ||
235 | clock = 22; /* 802.11b */ | ||
236 | else | ||
237 | clock = 44; /* 802.11g */ | ||
238 | |||
239 | /* Clock rate in turbo modes is twice the normal rate */ | ||
240 | if (channel->hw_value & CHANNEL_TURBO) | ||
241 | clock *= 2; | ||
242 | |||
243 | return clock; | ||
244 | } | ||
245 | 321 | ||
246 | /** | 322 | /*******************\ |
247 | * ath5k_hw_get_default_slottime - Get the default slot time for current mode | 323 | * RX filter Control * |
248 | * | 324 | \*******************/ |
249 | * @ah: The &struct ath5k_hw | ||
250 | */ | ||
251 | static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | ||
252 | { | ||
253 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
254 | |||
255 | if (channel->hw_value & CHANNEL_TURBO) | ||
256 | return 6; /* both turbo modes */ | ||
257 | |||
258 | if (channel->hw_value & CHANNEL_CCK) | ||
259 | return 20; /* 802.11b */ | ||
260 | |||
261 | return 9; /* 802.11 a/g */ | ||
262 | } | ||
263 | |||
264 | /** | ||
265 | * ath5k_hw_get_default_sifs - Get the default SIFS for current mode | ||
266 | * | ||
267 | * @ah: The &struct ath5k_hw | ||
268 | */ | ||
269 | static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | ||
270 | { | ||
271 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
272 | |||
273 | if (channel->hw_value & CHANNEL_TURBO) | ||
274 | return 8; /* both turbo modes */ | ||
275 | |||
276 | if (channel->hw_value & CHANNEL_5GHZ) | ||
277 | return 16; /* 802.11a */ | ||
278 | |||
279 | return 10; /* 802.11 b/g */ | ||
280 | } | ||
281 | 325 | ||
282 | /** | 326 | /** |
283 | * ath5k_hw_set_lladdr - Set station id | 327 | * ath5k_hw_set_lladdr - Set station id |
@@ -308,27 +352,26 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | |||
308 | } | 352 | } |
309 | 353 | ||
310 | /** | 354 | /** |
311 | * ath5k_hw_set_associd - Set BSSID for association | 355 | * ath5k_hw_set_bssid - Set current BSSID on hw |
312 | * | 356 | * |
313 | * @ah: The &struct ath5k_hw | 357 | * @ah: The &struct ath5k_hw |
314 | * @bssid: BSSID | ||
315 | * @assoc_id: Assoc id | ||
316 | * | 358 | * |
317 | * Sets the BSSID which trigers the "SME Join" operation | 359 | * Sets the current BSSID and BSSID mask we have from the |
360 | * common struct into the hardware | ||
318 | */ | 361 | */ |
319 | void ath5k_hw_set_associd(struct ath5k_hw *ah) | 362 | void ath5k_hw_set_bssid(struct ath5k_hw *ah) |
320 | { | 363 | { |
321 | struct ath_common *common = ath5k_hw_common(ah); | 364 | struct ath_common *common = ath5k_hw_common(ah); |
322 | u16 tim_offset = 0; | 365 | u16 tim_offset = 0; |
323 | 366 | ||
324 | /* | 367 | /* |
325 | * Set simple BSSID mask on 5212 | 368 | * Set BSSID mask on 5212 |
326 | */ | 369 | */ |
327 | if (ah->ah_version == AR5K_AR5212) | 370 | if (ah->ah_version == AR5K_AR5212) |
328 | ath_hw_setbssidmask(common); | 371 | ath_hw_setbssidmask(common); |
329 | 372 | ||
330 | /* | 373 | /* |
331 | * Set BSSID which triggers the "SME Join" operation | 374 | * Set BSSID |
332 | */ | 375 | */ |
333 | ath5k_hw_reg_write(ah, | 376 | ath5k_hw_reg_write(ah, |
334 | get_unaligned_le32(common->curbssid), | 377 | get_unaligned_le32(common->curbssid), |
@@ -360,39 +403,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | |||
360 | ath_hw_setbssidmask(common); | 403 | ath_hw_setbssidmask(common); |
361 | } | 404 | } |
362 | 405 | ||
363 | /************\ | ||
364 | * RX Control * | ||
365 | \************/ | ||
366 | |||
367 | /** | ||
368 | * ath5k_hw_start_rx_pcu - Start RX engine | ||
369 | * | ||
370 | * @ah: The &struct ath5k_hw | ||
371 | * | ||
372 | * Starts RX engine on PCU so that hw can process RXed frames | ||
373 | * (ACK etc). | ||
374 | * | ||
375 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | ||
376 | */ | ||
377 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | ||
378 | { | ||
379 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
380 | } | ||
381 | |||
382 | /** | ||
383 | * at5k_hw_stop_rx_pcu - Stop RX engine | ||
384 | * | ||
385 | * @ah: The &struct ath5k_hw | ||
386 | * | ||
387 | * Stops RX engine on PCU | ||
388 | * | ||
389 | * TODO: Detach ANI here | ||
390 | */ | ||
391 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | ||
392 | { | ||
393 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
394 | } | ||
395 | |||
396 | /* | 406 | /* |
397 | * Set multicast filter | 407 | * Set multicast filter |
398 | */ | 408 | */ |
@@ -455,7 +465,7 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) | |||
455 | } | 465 | } |
456 | 466 | ||
457 | /* | 467 | /* |
458 | * The AR5210 uses promiscous mode to detect radar activity | 468 | * The AR5210 uses promiscuous mode to detect radar activity |
459 | */ | 469 | */ |
460 | if (ah->ah_version == AR5K_AR5210 && | 470 | if (ah->ah_version == AR5K_AR5210 && |
461 | (filter & AR5K_RX_FILTER_RADARERR)) { | 471 | (filter & AR5K_RX_FILTER_RADARERR)) { |
@@ -496,6 +506,10 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | |||
496 | { | 506 | { |
497 | u32 tsf_lower, tsf_upper1, tsf_upper2; | 507 | u32 tsf_lower, tsf_upper1, tsf_upper2; |
498 | int i; | 508 | int i; |
509 | unsigned long flags; | ||
510 | |||
511 | /* This code is time critical - we don't want to be interrupted here */ | ||
512 | local_irq_save(flags); | ||
499 | 513 | ||
500 | /* | 514 | /* |
501 | * While reading TSF upper and then lower part, the clock is still | 515 | * While reading TSF upper and then lower part, the clock is still |
@@ -518,6 +532,8 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) | |||
518 | tsf_upper1 = tsf_upper2; | 532 | tsf_upper1 = tsf_upper2; |
519 | } | 533 | } |
520 | 534 | ||
535 | local_irq_restore(flags); | ||
536 | |||
521 | WARN_ON( i == ATH5K_MAX_TSF_READ ); | 537 | WARN_ON( i == ATH5K_MAX_TSF_READ ); |
522 | 538 | ||
523 | return (((u64)tsf_upper1 << 32) | tsf_lower); | 539 | return (((u64)tsf_upper1 << 32) | tsf_lower); |
@@ -601,7 +617,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
601 | /* Timer3 marks the end of our ATIM window | 617 | /* Timer3 marks the end of our ATIM window |
602 | * a zero length window is not allowed because | 618 | * a zero length window is not allowed because |
603 | * we 'll get no beacons */ | 619 | * we 'll get no beacons */ |
604 | timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); | 620 | timer3 = next_beacon + 1; |
605 | 621 | ||
606 | /* | 622 | /* |
607 | * Set the beacon register and enable all timers. | 623 | * Set the beacon register and enable all timers. |
@@ -641,218 +657,281 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) | |||
641 | 657 | ||
642 | } | 658 | } |
643 | 659 | ||
660 | /** | ||
661 | * ath5k_check_timer_win - Check if timer B is timer A + window | ||
662 | * | ||
663 | * @a: timer a (before b) | ||
664 | * @b: timer b (after a) | ||
665 | * @window: difference between a and b | ||
666 | * @intval: timers are increased by this interval | ||
667 | * | ||
668 | * This helper function checks if timer B is timer A + window and covers | ||
669 | * cases where timer A or B might have already been updated or wrapped | ||
670 | * around (Timers are 16 bit). | ||
671 | * | ||
672 | * Returns true if O.K. | ||
673 | */ | ||
674 | static inline bool | ||
675 | ath5k_check_timer_win(int a, int b, int window, int intval) | ||
676 | { | ||
677 | /* | ||
678 | * 1.) usually B should be A + window | ||
679 | * 2.) A already updated, B not updated yet | ||
680 | * 3.) A already updated and has wrapped around | ||
681 | * 4.) B has wrapped around | ||
682 | */ | ||
683 | if ((b - a == window) || /* 1.) */ | ||
684 | (a - b == intval - window) || /* 2.) */ | ||
685 | ((a | 0x10000) - b == intval - window) || /* 3.) */ | ||
686 | ((b | 0x10000) - a == window)) /* 4.) */ | ||
687 | return true; /* O.K. */ | ||
688 | return false; | ||
689 | } | ||
644 | 690 | ||
645 | /*********************\ | 691 | /** |
646 | * Key table functions * | 692 | * ath5k_hw_check_beacon_timers - Check if the beacon timers are correct |
647 | \*********************/ | 693 | * |
648 | 694 | * @ah: The &struct ath5k_hw | |
649 | /* | 695 | * @intval: beacon interval |
650 | * Reset a key entry on the table | 696 | * |
697 | * This is a workaround for IBSS mode: | ||
698 | * | ||
699 | * The need for this function arises from the fact that we have 4 separate | ||
700 | * HW timer registers (TIMER0 - TIMER3), which are closely related to the | ||
701 | * next beacon target time (NBTT), and that the HW updates these timers | ||
702 | * separately based on the current TSF value. The hardware increments each | ||
703 | * timer by the beacon interval, when the local TSF converted to TU is equal | ||
704 | * to the value stored in the timer. | ||
705 | * | ||
706 | * The reception of a beacon with the same BSSID can update the local HW TSF | ||
707 | * at any time - this is something we can't avoid. If the TSF jumps to a | ||
708 | * time which is later than the time stored in a timer, this timer will not | ||
709 | * be updated until the TSF in TU wraps around at 16 bit (the size of the | ||
710 | * timers) and reaches the time which is stored in the timer. | ||
711 | * | ||
712 | * The problem is that these timers are closely related to TIMER0 (NBTT) and | ||
713 | * that they define a time "window". When the TSF jumps between two timers | ||
714 | * (e.g. ATIM and NBTT), the one in the past will be left behind (not | ||
715 | * updated), while the one in the future will be updated every beacon | ||
716 | * interval. This causes the window to get larger, until the TSF wraps | ||
717 | * around as described above and the timer which was left behind gets | ||
718 | * updated again. But - because the beacon interval is usually not an exact | ||
719 | * divisor of the size of the timers (16 bit), an unwanted "window" between | ||
720 | * these timers has developed! | ||
721 | * | ||
722 | * This is especially important with the ATIM window, because during | ||
723 | * the ATIM window only ATIM frames and no data frames are allowed to be | ||
724 | * sent, which creates transmission pauses after each beacon. This symptom | ||
725 | * has been described as "ramping ping" because ping times increase linearly | ||
726 | * for some time and then drop down again. A wrong window on the DMA beacon | ||
727 | * timer has the same effect, so we check for these two conditions. | ||
728 | * | ||
729 | * Returns true if O.K. | ||
651 | */ | 730 | */ |
652 | int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | 731 | bool |
732 | ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval) | ||
653 | { | 733 | { |
654 | unsigned int i, type; | 734 | unsigned int nbtt, atim, dma; |
655 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; | ||
656 | 735 | ||
657 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | 736 | nbtt = ath5k_hw_reg_read(ah, AR5K_TIMER0); |
737 | atim = ath5k_hw_reg_read(ah, AR5K_TIMER3); | ||
738 | dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3; | ||
658 | 739 | ||
659 | type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); | 740 | /* NOTE: SWBA is different. Having a wrong window there does not |
741 | * stop us from sending data and this condition is catched thru | ||
742 | * other means (SWBA interrupt) */ | ||
660 | 743 | ||
661 | for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) | 744 | if (ath5k_check_timer_win(nbtt, atim, 1, intval) && |
662 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); | 745 | ath5k_check_timer_win(dma, nbtt, AR5K_TUNE_DMA_BEACON_RESP, |
746 | intval)) | ||
747 | return true; /* O.K. */ | ||
748 | return false; | ||
749 | } | ||
663 | 750 | ||
664 | /* Reset associated MIC entry if TKIP | 751 | /** |
665 | * is enabled located at offset (entry + 64) */ | 752 | * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class |
666 | if (type == AR5K_KEYTABLE_TYPE_TKIP) { | 753 | * |
667 | AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE); | 754 | * @ah: The &struct ath5k_hw |
668 | for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) | 755 | * @coverage_class: IEEE 802.11 coverage class number |
669 | ath5k_hw_reg_write(ah, 0, | 756 | * |
670 | AR5K_KEYTABLE_OFF(micentry, i)); | 757 | * Sets IFS intervals and ACK/CTS timeouts for given coverage class. |
671 | } | 758 | */ |
759 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | ||
760 | { | ||
761 | /* As defined by IEEE 802.11-2007 17.3.8.6 */ | ||
762 | int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; | ||
763 | int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time; | ||
764 | int cts_timeout = ack_timeout; | ||
672 | 765 | ||
673 | /* | 766 | ath5k_hw_set_ifs_intervals(ah, slot_time); |
674 | * Set NULL encryption on AR5212+ | 767 | ath5k_hw_set_ack_timeout(ah, ack_timeout); |
675 | * | 768 | ath5k_hw_set_cts_timeout(ah, cts_timeout); |
676 | * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) | ||
677 | * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 | ||
678 | * | ||
679 | * Note2: Windows driver (ndiswrapper) sets this to | ||
680 | * 0x00000714 instead of 0x00000007 | ||
681 | */ | ||
682 | if (ah->ah_version >= AR5K_AR5211) { | ||
683 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | ||
684 | AR5K_KEYTABLE_TYPE(entry)); | ||
685 | 769 | ||
686 | if (type == AR5K_KEYTABLE_TYPE_TKIP) { | 770 | ah->ah_coverage_class = coverage_class; |
687 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | 771 | } |
688 | AR5K_KEYTABLE_TYPE(micentry)); | ||
689 | } | ||
690 | } | ||
691 | 772 | ||
692 | return 0; | 773 | /***************************\ |
774 | * Init/Start/Stop functions * | ||
775 | \***************************/ | ||
776 | |||
777 | /** | ||
778 | * ath5k_hw_start_rx_pcu - Start RX engine | ||
779 | * | ||
780 | * @ah: The &struct ath5k_hw | ||
781 | * | ||
782 | * Starts RX engine on PCU so that hw can process RXed frames | ||
783 | * (ACK etc). | ||
784 | * | ||
785 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | ||
786 | */ | ||
787 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | ||
788 | { | ||
789 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
693 | } | 790 | } |
694 | 791 | ||
695 | static | 792 | /** |
696 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) | 793 | * at5k_hw_stop_rx_pcu - Stop RX engine |
794 | * | ||
795 | * @ah: The &struct ath5k_hw | ||
796 | * | ||
797 | * Stops RX engine on PCU | ||
798 | */ | ||
799 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | ||
697 | { | 800 | { |
698 | switch (key->alg) { | 801 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); |
699 | case ALG_TKIP: | ||
700 | return AR5K_KEYTABLE_TYPE_TKIP; | ||
701 | case ALG_CCMP: | ||
702 | return AR5K_KEYTABLE_TYPE_CCM; | ||
703 | case ALG_WEP: | ||
704 | if (key->keylen == WLAN_KEY_LEN_WEP40) | ||
705 | return AR5K_KEYTABLE_TYPE_40; | ||
706 | else if (key->keylen == WLAN_KEY_LEN_WEP104) | ||
707 | return AR5K_KEYTABLE_TYPE_104; | ||
708 | return -EINVAL; | ||
709 | default: | ||
710 | return -EINVAL; | ||
711 | } | ||
712 | return -EINVAL; | ||
713 | } | 802 | } |
714 | 803 | ||
715 | /* | 804 | /** |
716 | * Set a key entry on the table | 805 | * ath5k_hw_set_opmode - Set PCU operating mode |
806 | * | ||
807 | * @ah: The &struct ath5k_hw | ||
808 | * @op_mode: &enum nl80211_iftype operating mode | ||
809 | * | ||
810 | * Configure PCU for the various operating modes (AP/STA etc) | ||
717 | */ | 811 | */ |
718 | int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | 812 | int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) |
719 | const struct ieee80211_key_conf *key, const u8 *mac) | ||
720 | { | 813 | { |
721 | unsigned int i; | 814 | struct ath_common *common = ath5k_hw_common(ah); |
722 | int keylen; | 815 | u32 pcu_reg, beacon_reg, low_id, high_id; |
723 | __le32 key_v[5] = {}; | ||
724 | __le32 key0 = 0, key1 = 0; | ||
725 | __le32 *rxmic, *txmic; | ||
726 | int keytype; | ||
727 | u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; | ||
728 | bool is_tkip; | ||
729 | const u8 *key_ptr; | ||
730 | 816 | ||
731 | is_tkip = (key->alg == ALG_TKIP); | 817 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); |
732 | 818 | ||
733 | /* | 819 | /* Preserve rest settings */ |
734 | * key->keylen comes in from mac80211 in bytes. | 820 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; |
735 | * TKIP is 128 bit + 128 bit mic | 821 | pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP |
736 | */ | 822 | | AR5K_STA_ID1_KEYSRCH_MODE |
737 | keylen = (is_tkip) ? (128 / 8) : key->keylen; | 823 | | (ah->ah_version == AR5K_AR5210 ? |
824 | (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); | ||
738 | 825 | ||
739 | if (entry > AR5K_KEYTABLE_SIZE || | 826 | beacon_reg = 0; |
740 | (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) | ||
741 | return -EOPNOTSUPP; | ||
742 | 827 | ||
743 | if (unlikely(keylen > 16)) | 828 | switch (op_mode) { |
744 | return -EOPNOTSUPP; | 829 | case NL80211_IFTYPE_ADHOC: |
830 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; | ||
831 | beacon_reg |= AR5K_BCR_ADHOC; | ||
832 | if (ah->ah_version == AR5K_AR5210) | ||
833 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
834 | else | ||
835 | AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | ||
836 | break; | ||
745 | 837 | ||
746 | keytype = ath5k_keycache_type(key); | 838 | case NL80211_IFTYPE_AP: |
747 | if (keytype < 0) | 839 | case NL80211_IFTYPE_MESH_POINT: |
748 | return keytype; | 840 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; |
841 | beacon_reg |= AR5K_BCR_AP; | ||
842 | if (ah->ah_version == AR5K_AR5210) | ||
843 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
844 | else | ||
845 | AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | ||
846 | break; | ||
749 | 847 | ||
750 | /* | 848 | case NL80211_IFTYPE_STATION: |
751 | * each key block is 6 bytes wide, written as pairs of | 849 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE |
752 | * alternating 32 and 16 bit le values. | 850 | | (ah->ah_version == AR5K_AR5210 ? |
753 | */ | 851 | AR5K_STA_ID1_PWR_SV : 0); |
754 | key_ptr = key->key; | 852 | case NL80211_IFTYPE_MONITOR: |
755 | for (i = 0; keylen >= 6; keylen -= 6) { | 853 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE |
756 | memcpy(&key_v[i], key_ptr, 6); | 854 | | (ah->ah_version == AR5K_AR5210 ? |
757 | i += 2; | 855 | AR5K_STA_ID1_NO_PSPOLL : 0); |
758 | key_ptr += 6; | 856 | break; |
759 | } | ||
760 | if (keylen) | ||
761 | memcpy(&key_v[i], key_ptr, keylen); | ||
762 | 857 | ||
763 | /* intentionally corrupt key until mic is installed */ | 858 | default: |
764 | if (is_tkip) { | 859 | return -EINVAL; |
765 | key0 = key_v[0] = ~key_v[0]; | ||
766 | key1 = key_v[1] = ~key_v[1]; | ||
767 | } | 860 | } |
768 | 861 | ||
769 | for (i = 0; i < ARRAY_SIZE(key_v); i++) | 862 | /* |
770 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), | 863 | * Set PCU registers |
771 | AR5K_KEYTABLE_OFF(entry, i)); | 864 | */ |
772 | 865 | low_id = get_unaligned_le32(common->macaddr); | |
773 | ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); | 866 | high_id = get_unaligned_le16(common->macaddr + 4); |
774 | 867 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | |
775 | if (is_tkip) { | 868 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); |
776 | /* Install rx/tx MIC */ | ||
777 | rxmic = (__le32 *) &key->key[16]; | ||
778 | txmic = (__le32 *) &key->key[24]; | ||
779 | 869 | ||
780 | if (ah->ah_combined_mic) { | 870 | /* |
781 | key_v[0] = rxmic[0]; | 871 | * Set Beacon Control Register on 5210 |
782 | key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16); | 872 | */ |
783 | key_v[2] = rxmic[1]; | 873 | if (ah->ah_version == AR5K_AR5210) |
784 | key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff); | 874 | ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); |
785 | key_v[4] = txmic[1]; | ||
786 | } else { | ||
787 | key_v[0] = rxmic[0]; | ||
788 | key_v[1] = 0; | ||
789 | key_v[2] = rxmic[1]; | ||
790 | key_v[3] = 0; | ||
791 | key_v[4] = 0; | ||
792 | } | ||
793 | for (i = 0; i < ARRAY_SIZE(key_v); i++) | ||
794 | ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), | ||
795 | AR5K_KEYTABLE_OFF(micentry, i)); | ||
796 | |||
797 | ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, | ||
798 | AR5K_KEYTABLE_TYPE(micentry)); | ||
799 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry)); | ||
800 | ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry)); | ||
801 | |||
802 | /* restore first 2 words of key */ | ||
803 | ath5k_hw_reg_write(ah, le32_to_cpu(~key0), | ||
804 | AR5K_KEYTABLE_OFF(entry, 0)); | ||
805 | ath5k_hw_reg_write(ah, le32_to_cpu(~key1), | ||
806 | AR5K_KEYTABLE_OFF(entry, 1)); | ||
807 | } | ||
808 | 875 | ||
809 | return ath5k_hw_set_key_lladdr(ah, entry, mac); | 876 | return 0; |
810 | } | 877 | } |
811 | 878 | ||
812 | int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) | 879 | void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
880 | u8 mode) | ||
813 | { | 881 | { |
814 | u32 low_id, high_id; | 882 | /* Set bssid and bssid mask */ |
815 | 883 | ath5k_hw_set_bssid(ah); | |
816 | /* Invalid entry (key table overflow) */ | ||
817 | AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); | ||
818 | 884 | ||
819 | /* | 885 | /* Set PCU config */ |
820 | * MAC may be NULL if it's a broadcast key. In this case no need to | 886 | ath5k_hw_set_opmode(ah, op_mode); |
821 | * to compute get_unaligned_le32 and get_unaligned_le16 as we | ||
822 | * already know it. | ||
823 | */ | ||
824 | if (!mac) { | ||
825 | low_id = 0xffffffff; | ||
826 | high_id = 0xffff | AR5K_KEYTABLE_VALID; | ||
827 | } else { | ||
828 | low_id = get_unaligned_le32(mac); | ||
829 | high_id = get_unaligned_le16(mac + 4) | AR5K_KEYTABLE_VALID; | ||
830 | } | ||
831 | 887 | ||
832 | ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); | 888 | /* Write rate duration table only on AR5212 and if |
833 | ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); | 889 | * virtual interface has already been brought up |
890 | * XXX: rethink this after new mode changes to | ||
891 | * mac80211 are integrated */ | ||
892 | if (ah->ah_version == AR5K_AR5212 && | ||
893 | ah->ah_sc->nvifs) | ||
894 | ath5k_hw_write_rate_duration(ah); | ||
834 | 895 | ||
835 | return 0; | 896 | /* Set RSSI/BRSSI thresholds |
836 | } | 897 | * |
898 | * Note: If we decide to set this value | ||
899 | * dynamicaly, have in mind that when AR5K_RSSI_THR | ||
900 | * register is read it might return 0x40 if we haven't | ||
901 | * wrote anything to it plus BMISS RSSI threshold is zeroed. | ||
902 | * So doing a save/restore procedure here isn't the right | ||
903 | * choice. Instead store it on ath5k_hw */ | ||
904 | ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | | ||
905 | AR5K_TUNE_BMISS_THRES << | ||
906 | AR5K_RSSI_THR_BMISS_S), | ||
907 | AR5K_RSSI_THR); | ||
908 | |||
909 | /* MIC QoS support */ | ||
910 | if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { | ||
911 | ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); | ||
912 | ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); | ||
913 | } | ||
837 | 914 | ||
838 | /** | 915 | /* QoS NOACK Policy */ |
839 | * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class | 916 | if (ah->ah_version == AR5K_AR5212) { |
840 | * | 917 | ath5k_hw_reg_write(ah, |
841 | * @ah: The &struct ath5k_hw | 918 | AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | |
842 | * @coverage_class: IEEE 802.11 coverage class number | 919 | AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | |
843 | * | 920 | AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), |
844 | * Sets slot time, ACK timeout and CTS timeout for given coverage class. | 921 | AR5K_QOS_NOACK); |
845 | */ | 922 | } |
846 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | ||
847 | { | ||
848 | /* As defined by IEEE 802.11-2007 17.3.8.6 */ | ||
849 | int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; | ||
850 | int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time; | ||
851 | int cts_timeout = ack_timeout; | ||
852 | 923 | ||
853 | ath5k_hw_set_slot_time(ah, slot_time); | 924 | /* Restore slot time and ACK timeouts */ |
854 | ath5k_hw_set_ack_timeout(ah, ack_timeout); | 925 | if (ah->ah_coverage_class > 0) |
855 | ath5k_hw_set_cts_timeout(ah, cts_timeout); | 926 | ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); |
856 | 927 | ||
857 | ah->ah_coverage_class = coverage_class; | 928 | /* Set ACK bitrate mode (see ack_rates_high) */ |
929 | if (ah->ah_version == AR5K_AR5212) { | ||
930 | u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; | ||
931 | if (ah->ah_ack_bitrate_high) | ||
932 | AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); | ||
933 | else | ||
934 | AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); | ||
935 | } | ||
936 | return; | ||
858 | } | 937 | } |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 6284c389ba18..55441913344d 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -29,6 +29,95 @@ | |||
29 | #include "rfbuffer.h" | 29 | #include "rfbuffer.h" |
30 | #include "rfgain.h" | 30 | #include "rfgain.h" |
31 | 31 | ||
32 | |||
33 | /******************\ | ||
34 | * Helper functions * | ||
35 | \******************/ | ||
36 | |||
37 | /* | ||
38 | * Get the PHY Chip revision | ||
39 | */ | ||
40 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | ||
41 | { | ||
42 | unsigned int i; | ||
43 | u32 srev; | ||
44 | u16 ret; | ||
45 | |||
46 | /* | ||
47 | * Set the radio chip access register | ||
48 | */ | ||
49 | switch (chan) { | ||
50 | case CHANNEL_2GHZ: | ||
51 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); | ||
52 | break; | ||
53 | case CHANNEL_5GHZ: | ||
54 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
55 | break; | ||
56 | default: | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | mdelay(2); | ||
61 | |||
62 | /* ...wait until PHY is ready and read the selected radio revision */ | ||
63 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | ||
64 | |||
65 | for (i = 0; i < 8; i++) | ||
66 | ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); | ||
67 | |||
68 | if (ah->ah_version == AR5K_AR5210) { | ||
69 | srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; | ||
70 | ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; | ||
71 | } else { | ||
72 | srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; | ||
73 | ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | | ||
74 | ((srev & 0x0f) << 4), 8); | ||
75 | } | ||
76 | |||
77 | /* Reset to the 5GHz mode */ | ||
78 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
79 | |||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Check if a channel is supported | ||
85 | */ | ||
86 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) | ||
87 | { | ||
88 | /* Check if the channel is in our supported range */ | ||
89 | if (flags & CHANNEL_2GHZ) { | ||
90 | if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && | ||
91 | (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) | ||
92 | return true; | ||
93 | } else if (flags & CHANNEL_5GHZ) | ||
94 | if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && | ||
95 | (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) | ||
96 | return true; | ||
97 | |||
98 | return false; | ||
99 | } | ||
100 | |||
101 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | ||
102 | struct ieee80211_channel *channel) | ||
103 | { | ||
104 | u8 refclk_freq; | ||
105 | |||
106 | if ((ah->ah_radio == AR5K_RF5112) || | ||
107 | (ah->ah_radio == AR5K_RF5413) || | ||
108 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
109 | refclk_freq = 40; | ||
110 | else | ||
111 | refclk_freq = 32; | ||
112 | |||
113 | if ((channel->center_freq % refclk_freq != 0) && | ||
114 | ((channel->center_freq % refclk_freq < 10) || | ||
115 | (channel->center_freq % refclk_freq > 22))) | ||
116 | return true; | ||
117 | else | ||
118 | return false; | ||
119 | } | ||
120 | |||
32 | /* | 121 | /* |
33 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER | 122 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER |
34 | */ | 123 | */ |
@@ -110,12 +199,124 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
110 | return data; | 199 | return data; |
111 | } | 200 | } |
112 | 201 | ||
202 | /** | ||
203 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | ||
204 | * | ||
205 | * @ah: the &struct ath5k_hw | ||
206 | * @channel: the currently set channel upon reset | ||
207 | * | ||
208 | * Write the delta slope coefficient (used on pilot tracking ?) for OFDM | ||
209 | * operation on the AR5212 upon reset. This is a helper for ath5k_hw_phy_init. | ||
210 | * | ||
211 | * Since delta slope is floating point we split it on its exponent and | ||
212 | * mantissa and provide these values on hw. | ||
213 | * | ||
214 | * For more infos i think this patent is related | ||
215 | * http://www.freepatentsonline.com/7184495.html | ||
216 | */ | ||
217 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | ||
218 | struct ieee80211_channel *channel) | ||
219 | { | ||
220 | /* Get exponent and mantissa and set it */ | ||
221 | u32 coef_scaled, coef_exp, coef_man, | ||
222 | ds_coef_exp, ds_coef_man, clock; | ||
223 | |||
224 | BUG_ON(!(ah->ah_version == AR5K_AR5212) || | ||
225 | !(channel->hw_value & CHANNEL_OFDM)); | ||
226 | |||
227 | /* Get coefficient | ||
228 | * ALGO: coef = (5 * clock / carrier_freq) / 2 | ||
229 | * we scale coef by shifting clock value by 24 for | ||
230 | * better precision since we use integers */ | ||
231 | switch (ah->ah_bwmode) { | ||
232 | case AR5K_BWMODE_40MHZ: | ||
233 | clock = 40 * 2; | ||
234 | break; | ||
235 | case AR5K_BWMODE_10MHZ: | ||
236 | clock = 40 / 2; | ||
237 | break; | ||
238 | case AR5K_BWMODE_5MHZ: | ||
239 | clock = 40 / 4; | ||
240 | break; | ||
241 | default: | ||
242 | clock = 40; | ||
243 | break; | ||
244 | } | ||
245 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; | ||
246 | |||
247 | /* Get exponent | ||
248 | * ALGO: coef_exp = 14 - highest set bit position */ | ||
249 | coef_exp = ilog2(coef_scaled); | ||
250 | |||
251 | /* Doesn't make sense if it's zero*/ | ||
252 | if (!coef_scaled || !coef_exp) | ||
253 | return -EINVAL; | ||
254 | |||
255 | /* Note: we've shifted coef_scaled by 24 */ | ||
256 | coef_exp = 14 - (coef_exp - 24); | ||
257 | |||
258 | |||
259 | /* Get mantissa (significant digits) | ||
260 | * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ | ||
261 | coef_man = coef_scaled + | ||
262 | (1 << (24 - coef_exp - 1)); | ||
263 | |||
264 | /* Calculate delta slope coefficient exponent | ||
265 | * and mantissa (remove scaling) and set them on hw */ | ||
266 | ds_coef_man = coef_man >> (24 - coef_exp); | ||
267 | ds_coef_exp = coef_exp - 16; | ||
268 | |||
269 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
270 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | ||
271 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
272 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | ||
278 | { | ||
279 | /*Just a try M.F.*/ | ||
280 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
281 | |||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Wait for synth to settle | ||
287 | */ | ||
288 | static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah, | ||
289 | struct ieee80211_channel *channel) | ||
290 | { | ||
291 | /* | ||
292 | * On 5211+ read activation -> rx delay | ||
293 | * and use it (100ns steps). | ||
294 | */ | ||
295 | if (ah->ah_version != AR5K_AR5210) { | ||
296 | u32 delay; | ||
297 | delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
298 | AR5K_PHY_RX_DELAY_M; | ||
299 | delay = (channel->hw_value & CHANNEL_CCK) ? | ||
300 | ((delay << 2) / 22) : (delay / 10); | ||
301 | if (ah->ah_bwmode == AR5K_BWMODE_10MHZ) | ||
302 | delay = delay << 1; | ||
303 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ) | ||
304 | delay = delay << 2; | ||
305 | /* XXX: /2 on turbo ? Let's be safe | ||
306 | * for now */ | ||
307 | udelay(100 + delay); | ||
308 | } else { | ||
309 | mdelay(1); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | |||
113 | /**********************\ | 314 | /**********************\ |
114 | * RF Gain optimization * | 315 | * RF Gain optimization * |
115 | \**********************/ | 316 | \**********************/ |
116 | 317 | ||
117 | /* | 318 | /* |
118 | * This code is used to optimize rf gain on different environments | 319 | * This code is used to optimize RF gain on different environments |
119 | * (temperature mostly) based on feedback from a power detector. | 320 | * (temperature mostly) based on feedback from a power detector. |
120 | * | 321 | * |
121 | * It's only used on RF5111 and RF5112, later RF chips seem to have | 322 | * It's only used on RF5111 and RF5112, later RF chips seem to have |
@@ -134,11 +335,11 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
134 | * http://madwifi-project.org/ticket/1659 | 335 | * http://madwifi-project.org/ticket/1659 |
135 | * with various measurements and diagrams | 336 | * with various measurements and diagrams |
136 | * | 337 | * |
137 | * TODO: Deal with power drops due to probes by setting an apropriate | 338 | * TODO: Deal with power drops due to probes by setting an appropriate |
138 | * tx power on the probe packets ! Make this part of the calibration process. | 339 | * tx power on the probe packets ! Make this part of the calibration process. |
139 | */ | 340 | */ |
140 | 341 | ||
141 | /* Initialize ah_gain durring attach */ | 342 | /* Initialize ah_gain during attach */ |
142 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) | 343 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) |
143 | { | 344 | { |
144 | /* Initialize the gain optimization values */ | 345 | /* Initialize the gain optimization values */ |
@@ -302,7 +503,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | |||
302 | } | 503 | } |
303 | 504 | ||
304 | /* Perform gain_F adjustment by choosing the right set | 505 | /* Perform gain_F adjustment by choosing the right set |
305 | * of parameters from rf gain optimization ladder */ | 506 | * of parameters from RF gain optimization ladder */ |
306 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) | 507 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) |
307 | { | 508 | { |
308 | const struct ath5k_gain_opt *go; | 509 | const struct ath5k_gain_opt *go; |
@@ -367,7 +568,7 @@ done: | |||
367 | return ret; | 568 | return ret; |
368 | } | 569 | } |
369 | 570 | ||
370 | /* Main callback for thermal rf gain calibration engine | 571 | /* Main callback for thermal RF gain calibration engine |
371 | * Check for a new gain reading and schedule an adjustment | 572 | * Check for a new gain reading and schedule an adjustment |
372 | * if needed. | 573 | * if needed. |
373 | * | 574 | * |
@@ -433,13 +634,13 @@ done: | |||
433 | return ah->ah_gain.g_state; | 634 | return ah->ah_gain.g_state; |
434 | } | 635 | } |
435 | 636 | ||
436 | /* Write initial rf gain table to set the RF sensitivity | 637 | /* Write initial RF gain table to set the RF sensitivity |
437 | * this one works on all RF chips and has nothing to do | 638 | * this one works on all RF chips and has nothing to do |
438 | * with gain_F calibration */ | 639 | * with gain_F calibration */ |
439 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | 640 | static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, enum ieee80211_band band) |
440 | { | 641 | { |
441 | const struct ath5k_ini_rfgain *ath5k_rfg; | 642 | const struct ath5k_ini_rfgain *ath5k_rfg; |
442 | unsigned int i, size; | 643 | unsigned int i, size, index; |
443 | 644 | ||
444 | switch (ah->ah_radio) { | 645 | switch (ah->ah_radio) { |
445 | case AR5K_RF5111: | 646 | case AR5K_RF5111: |
@@ -471,17 +672,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
471 | return -EINVAL; | 672 | return -EINVAL; |
472 | } | 673 | } |
473 | 674 | ||
474 | switch (freq) { | 675 | index = (band == IEEE80211_BAND_2GHZ) ? 1 : 0; |
475 | case AR5K_INI_RFGAIN_2GHZ: | ||
476 | case AR5K_INI_RFGAIN_5GHZ: | ||
477 | break; | ||
478 | default: | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | 676 | ||
482 | for (i = 0; i < size; i++) { | 677 | for (i = 0; i < size; i++) { |
483 | AR5K_REG_WAIT(i); | 678 | AR5K_REG_WAIT(i); |
484 | ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq], | 679 | ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[index], |
485 | (u32)ath5k_rfg[i].rfg_register); | 680 | (u32)ath5k_rfg[i].rfg_register); |
486 | } | 681 | } |
487 | 682 | ||
@@ -494,12 +689,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
494 | * RF Registers setup * | 689 | * RF Registers setup * |
495 | \********************/ | 690 | \********************/ |
496 | 691 | ||
497 | |||
498 | /* | 692 | /* |
499 | * Setup RF registers by writing rf buffer on hw | 693 | * Setup RF registers by writing RF buffer on hw |
500 | */ | 694 | */ |
501 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 695 | static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, |
502 | unsigned int mode) | 696 | struct ieee80211_channel *channel, unsigned int mode) |
503 | { | 697 | { |
504 | const struct ath5k_rf_reg *rf_regs; | 698 | const struct ath5k_rf_reg *rf_regs; |
505 | const struct ath5k_ini_rfbuffer *ini_rfb; | 699 | const struct ath5k_ini_rfbuffer *ini_rfb; |
@@ -571,7 +765,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
571 | return -EINVAL; | 765 | return -EINVAL; |
572 | } | 766 | } |
573 | 767 | ||
574 | /* If it's the first time we set rf buffer, allocate | 768 | /* If it's the first time we set RF buffer, allocate |
575 | * ah->ah_rf_banks based on ah->ah_rf_banks_size | 769 | * ah->ah_rf_banks based on ah->ah_rf_banks_size |
576 | * we set above */ | 770 | * we set above */ |
577 | if (ah->ah_rf_banks == NULL) { | 771 | if (ah->ah_rf_banks == NULL) { |
@@ -652,6 +846,11 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
652 | 846 | ||
653 | g_step = &go->go_step[ah->ah_gain.g_step_idx]; | 847 | g_step = &go->go_step[ah->ah_gain.g_step_idx]; |
654 | 848 | ||
849 | /* Set turbo mode (N/A on RF5413) */ | ||
850 | if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) && | ||
851 | (ah->ah_radio != AR5K_RF5413)) | ||
852 | ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_TURBO, false); | ||
853 | |||
655 | /* Bank Modifications (chip-specific) */ | 854 | /* Bank Modifications (chip-specific) */ |
656 | if (ah->ah_radio == AR5K_RF5111) { | 855 | if (ah->ah_radio == AR5K_RF5111) { |
657 | 856 | ||
@@ -691,7 +890,23 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
691 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], | 890 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], |
692 | AR5K_RF_PLO_SEL, true); | 891 | AR5K_RF_PLO_SEL, true); |
693 | 892 | ||
694 | /* TODO: Half/quarter channel support */ | 893 | /* Tweak power detectors for half/quarter rate support */ |
894 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || | ||
895 | ah->ah_bwmode == AR5K_BWMODE_10MHZ) { | ||
896 | u8 wait_i; | ||
897 | |||
898 | ath5k_hw_rfb_op(ah, rf_regs, 0x1f, | ||
899 | AR5K_RF_WAIT_S, true); | ||
900 | |||
901 | wait_i = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? | ||
902 | 0x1f : 0x10; | ||
903 | |||
904 | ath5k_hw_rfb_op(ah, rf_regs, wait_i, | ||
905 | AR5K_RF_WAIT_I, true); | ||
906 | ath5k_hw_rfb_op(ah, rf_regs, 3, | ||
907 | AR5K_RF_MAX_TIME, true); | ||
908 | |||
909 | } | ||
695 | } | 910 | } |
696 | 911 | ||
697 | if (ah->ah_radio == AR5K_RF5112) { | 912 | if (ah->ah_radio == AR5K_RF5112) { |
@@ -789,8 +1004,20 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
789 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], | 1004 | ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], |
790 | AR5K_RF_GAIN_I, true); | 1005 | AR5K_RF_GAIN_I, true); |
791 | 1006 | ||
792 | /* TODO: Half/quarter channel support */ | 1007 | /* Tweak power detector for half/quarter rates */ |
1008 | if (ah->ah_bwmode == AR5K_BWMODE_5MHZ || | ||
1009 | ah->ah_bwmode == AR5K_BWMODE_10MHZ) { | ||
1010 | u8 pd_delay; | ||
1011 | |||
1012 | pd_delay = (ah->ah_bwmode == AR5K_BWMODE_5MHZ) ? | ||
1013 | 0xf : 0x8; | ||
1014 | |||
1015 | ath5k_hw_rfb_op(ah, rf_regs, pd_delay, | ||
1016 | AR5K_RF_PD_PERIOD_A, true); | ||
1017 | ath5k_hw_rfb_op(ah, rf_regs, 0xf, | ||
1018 | AR5K_RF_PD_DELAY_A, true); | ||
793 | 1019 | ||
1020 | } | ||
794 | } | 1021 | } |
795 | 1022 | ||
796 | if (ah->ah_radio == AR5K_RF5413 && | 1023 | if (ah->ah_radio == AR5K_RF5413 && |
@@ -822,25 +1049,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
822 | \**************************/ | 1049 | \**************************/ |
823 | 1050 | ||
824 | /* | 1051 | /* |
825 | * Check if a channel is supported | 1052 | * Conversion needed for RF5110 |
826 | */ | ||
827 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) | ||
828 | { | ||
829 | /* Check if the channel is in our supported range */ | ||
830 | if (flags & CHANNEL_2GHZ) { | ||
831 | if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && | ||
832 | (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) | ||
833 | return true; | ||
834 | } else if (flags & CHANNEL_5GHZ) | ||
835 | if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && | ||
836 | (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) | ||
837 | return true; | ||
838 | |||
839 | return false; | ||
840 | } | ||
841 | |||
842 | /* | ||
843 | * Convertion needed for RF5110 | ||
844 | */ | 1053 | */ |
845 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) | 1054 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) |
846 | { | 1055 | { |
@@ -879,7 +1088,7 @@ static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, | |||
879 | } | 1088 | } |
880 | 1089 | ||
881 | /* | 1090 | /* |
882 | * Convertion needed for 5111 | 1091 | * Conversion needed for 5111 |
883 | */ | 1092 | */ |
884 | static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, | 1093 | static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, |
885 | struct ath5k_athchan_2ghz *athchan) | 1094 | struct ath5k_athchan_2ghz *athchan) |
@@ -1045,7 +1254,8 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | |||
1045 | /* | 1254 | /* |
1046 | * Set a channel on the radio chip | 1255 | * Set a channel on the radio chip |
1047 | */ | 1256 | */ |
1048 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | 1257 | static int ath5k_hw_channel(struct ath5k_hw *ah, |
1258 | struct ieee80211_channel *channel) | ||
1049 | { | 1259 | { |
1050 | int ret; | 1260 | int ret; |
1051 | /* | 1261 | /* |
@@ -1071,6 +1281,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1071 | case AR5K_RF5111: | 1281 | case AR5K_RF5111: |
1072 | ret = ath5k_hw_rf5111_channel(ah, channel); | 1282 | ret = ath5k_hw_rf5111_channel(ah, channel); |
1073 | break; | 1283 | break; |
1284 | case AR5K_RF2317: | ||
1074 | case AR5K_RF2425: | 1285 | case AR5K_RF2425: |
1075 | ret = ath5k_hw_rf2425_channel(ah, channel); | 1286 | ret = ath5k_hw_rf2425_channel(ah, channel); |
1076 | break; | 1287 | break; |
@@ -1092,7 +1303,6 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1092 | } | 1303 | } |
1093 | 1304 | ||
1094 | ah->ah_current_channel = channel; | 1305 | ah->ah_current_channel = channel; |
1095 | ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; | ||
1096 | 1306 | ||
1097 | return 0; | 1307 | return 0; |
1098 | } | 1308 | } |
@@ -1101,18 +1311,12 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
1101 | PHY calibration | 1311 | PHY calibration |
1102 | \*****************/ | 1312 | \*****************/ |
1103 | 1313 | ||
1104 | static int sign_extend(int val, const int nbits) | ||
1105 | { | ||
1106 | int order = BIT(nbits-1); | ||
1107 | return (val ^ order) - order; | ||
1108 | } | ||
1109 | |||
1110 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) | 1314 | static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah) |
1111 | { | 1315 | { |
1112 | s32 val; | 1316 | s32 val; |
1113 | 1317 | ||
1114 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); | 1318 | val = ath5k_hw_reg_read(ah, AR5K_PHY_NF); |
1115 | return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9); | 1319 | return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8); |
1116 | } | 1320 | } |
1117 | 1321 | ||
1118 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) | 1322 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah) |
@@ -1180,22 +1384,7 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) | |||
1180 | return; | 1384 | return; |
1181 | } | 1385 | } |
1182 | 1386 | ||
1183 | switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) { | 1387 | ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); |
1184 | case CHANNEL_A: | ||
1185 | case CHANNEL_T: | ||
1186 | case CHANNEL_XR: | ||
1187 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
1188 | break; | ||
1189 | case CHANNEL_G: | ||
1190 | case CHANNEL_TG: | ||
1191 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
1192 | break; | ||
1193 | default: | ||
1194 | case CHANNEL_B: | ||
1195 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1196 | break; | ||
1197 | } | ||
1198 | |||
1199 | 1388 | ||
1200 | /* completed NF calibration, test threshold */ | 1389 | /* completed NF calibration, test threshold */ |
1201 | nf = ath5k_hw_read_measured_noise_floor(ah); | 1390 | nf = ath5k_hw_read_measured_noise_floor(ah); |
@@ -1257,7 +1446,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1257 | * Disable beacons and RX/TX queues, wait | 1446 | * Disable beacons and RX/TX queues, wait |
1258 | */ | 1447 | */ |
1259 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, | 1448 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, |
1260 | AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); | 1449 | AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); |
1261 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); | 1450 | beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); |
1262 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); | 1451 | ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); |
1263 | 1452 | ||
@@ -1336,7 +1525,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, | |||
1336 | * Re-enable RX/TX and beacons | 1525 | * Re-enable RX/TX and beacons |
1337 | */ | 1526 | */ |
1338 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, | 1527 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, |
1339 | AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); | 1528 | AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); |
1340 | ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); | 1529 | ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); |
1341 | 1530 | ||
1342 | return 0; | 1531 | return 0; |
@@ -1377,7 +1566,7 @@ ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) | |||
1377 | 1566 | ||
1378 | /* protect against divide by 0 and loss of sign bits */ | 1567 | /* protect against divide by 0 and loss of sign bits */ |
1379 | if (i_coffd == 0 || q_coffd < 2) | 1568 | if (i_coffd == 0 || q_coffd < 2) |
1380 | return -1; | 1569 | return 0; |
1381 | 1570 | ||
1382 | i_coff = (-iq_corr) / i_coffd; | 1571 | i_coff = (-iq_corr) / i_coffd; |
1383 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ | 1572 | i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ |
@@ -1424,31 +1613,12 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | |||
1424 | return ret; | 1613 | return ret; |
1425 | } | 1614 | } |
1426 | 1615 | ||
1616 | |||
1427 | /***************************\ | 1617 | /***************************\ |
1428 | * Spur mitigation functions * | 1618 | * Spur mitigation functions * |
1429 | \***************************/ | 1619 | \***************************/ |
1430 | 1620 | ||
1431 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1621 | static void |
1432 | struct ieee80211_channel *channel) | ||
1433 | { | ||
1434 | u8 refclk_freq; | ||
1435 | |||
1436 | if ((ah->ah_radio == AR5K_RF5112) || | ||
1437 | (ah->ah_radio == AR5K_RF5413) || | ||
1438 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
1439 | refclk_freq = 40; | ||
1440 | else | ||
1441 | refclk_freq = 32; | ||
1442 | |||
1443 | if ((channel->center_freq % refclk_freq != 0) && | ||
1444 | ((channel->center_freq % refclk_freq < 10) || | ||
1445 | (channel->center_freq % refclk_freq > 22))) | ||
1446 | return true; | ||
1447 | else | ||
1448 | return false; | ||
1449 | } | ||
1450 | |||
1451 | void | ||
1452 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | 1622 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, |
1453 | struct ieee80211_channel *channel) | 1623 | struct ieee80211_channel *channel) |
1454 | { | 1624 | { |
@@ -1477,7 +1647,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1477 | spur_chan_fbin = AR5K_EEPROM_NO_SPUR; | 1647 | spur_chan_fbin = AR5K_EEPROM_NO_SPUR; |
1478 | spur_detection_window = AR5K_SPUR_CHAN_WIDTH; | 1648 | spur_detection_window = AR5K_SPUR_CHAN_WIDTH; |
1479 | /* XXX: Half/Quarter channels ?*/ | 1649 | /* XXX: Half/Quarter channels ?*/ |
1480 | if (channel->hw_value & CHANNEL_TURBO) | 1650 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
1481 | spur_detection_window *= 2; | 1651 | spur_detection_window *= 2; |
1482 | 1652 | ||
1483 | for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { | 1653 | for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { |
@@ -1506,32 +1676,43 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1506 | * Calculate deltas: | 1676 | * Calculate deltas: |
1507 | * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 | 1677 | * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 |
1508 | * spur_delta_phase -> spur_offset / chip_freq << 11 | 1678 | * spur_delta_phase -> spur_offset / chip_freq << 11 |
1509 | * Note: Both values have 100KHz resolution | 1679 | * Note: Both values have 100Hz resolution |
1510 | */ | 1680 | */ |
1511 | /* XXX: Half/Quarter rate channels ? */ | 1681 | switch (ah->ah_bwmode) { |
1512 | switch (channel->hw_value) { | 1682 | case AR5K_BWMODE_40MHZ: |
1513 | case CHANNEL_A: | ||
1514 | /* Both sample_freq and chip_freq are 40MHz */ | ||
1515 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1516 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
1517 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1518 | break; | ||
1519 | case CHANNEL_G: | ||
1520 | /* sample_freq -> 40MHz chip_freq -> 44MHz | ||
1521 | * (for b compatibility) */ | ||
1522 | spur_freq_sigma_delta = (spur_offset << 8) / 55; | ||
1523 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1524 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1525 | break; | ||
1526 | case CHANNEL_T: | ||
1527 | case CHANNEL_TG: | ||
1528 | /* Both sample_freq and chip_freq are 80MHz */ | 1683 | /* Both sample_freq and chip_freq are 80MHz */ |
1529 | spur_delta_phase = (spur_offset << 16) / 25; | 1684 | spur_delta_phase = (spur_offset << 16) / 25; |
1530 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | 1685 | spur_freq_sigma_delta = (spur_delta_phase >> 10); |
1531 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz; | 1686 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz * 2; |
1532 | break; | 1687 | break; |
1688 | case AR5K_BWMODE_10MHZ: | ||
1689 | /* Both sample_freq and chip_freq are 20MHz (?) */ | ||
1690 | spur_delta_phase = (spur_offset << 18) / 25; | ||
1691 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
1692 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 2; | ||
1693 | case AR5K_BWMODE_5MHZ: | ||
1694 | /* Both sample_freq and chip_freq are 10MHz (?) */ | ||
1695 | spur_delta_phase = (spur_offset << 19) / 25; | ||
1696 | spur_freq_sigma_delta = (spur_delta_phase >> 10); | ||
1697 | symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; | ||
1533 | default: | 1698 | default: |
1534 | return; | 1699 | if (channel->hw_value == CHANNEL_A) { |
1700 | /* Both sample_freq and chip_freq are 40MHz */ | ||
1701 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1702 | spur_freq_sigma_delta = | ||
1703 | (spur_delta_phase >> 10); | ||
1704 | symbol_width = | ||
1705 | AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1706 | } else { | ||
1707 | /* sample_freq -> 40MHz chip_freq -> 44MHz | ||
1708 | * (for b compatibility) */ | ||
1709 | spur_delta_phase = (spur_offset << 17) / 25; | ||
1710 | spur_freq_sigma_delta = | ||
1711 | (spur_offset << 8) / 55; | ||
1712 | symbol_width = | ||
1713 | AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; | ||
1714 | } | ||
1715 | break; | ||
1535 | } | 1716 | } |
1536 | 1717 | ||
1537 | /* Calculate pilot and magnitude masks */ | 1718 | /* Calculate pilot and magnitude masks */ |
@@ -1582,7 +1763,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1582 | else if (curr_sym_off >= 31 && curr_sym_off <= 46) | 1763 | else if (curr_sym_off >= 31 && curr_sym_off <= 46) |
1583 | mag_mask[2] |= | 1764 | mag_mask[2] |= |
1584 | plt_mag_map << (curr_sym_off - 31) * 2; | 1765 | plt_mag_map << (curr_sym_off - 31) * 2; |
1585 | else if (curr_sym_off >= 46 && curr_sym_off <= 53) | 1766 | else if (curr_sym_off >= 47 && curr_sym_off <= 53) |
1586 | mag_mask[3] |= | 1767 | mag_mask[3] |= |
1587 | plt_mag_map << (curr_sym_off - 47) * 2; | 1768 | plt_mag_map << (curr_sym_off - 47) * 2; |
1588 | 1769 | ||
@@ -1671,63 +1852,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1671 | } | 1852 | } |
1672 | } | 1853 | } |
1673 | 1854 | ||
1674 | /********************\ | ||
1675 | Misc PHY functions | ||
1676 | \********************/ | ||
1677 | |||
1678 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | ||
1679 | { | ||
1680 | /*Just a try M.F.*/ | ||
1681 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
1682 | |||
1683 | return 0; | ||
1684 | } | ||
1685 | |||
1686 | /* | ||
1687 | * Get the PHY Chip revision | ||
1688 | */ | ||
1689 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | ||
1690 | { | ||
1691 | unsigned int i; | ||
1692 | u32 srev; | ||
1693 | u16 ret; | ||
1694 | |||
1695 | /* | ||
1696 | * Set the radio chip access register | ||
1697 | */ | ||
1698 | switch (chan) { | ||
1699 | case CHANNEL_2GHZ: | ||
1700 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); | ||
1701 | break; | ||
1702 | case CHANNEL_5GHZ: | ||
1703 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
1704 | break; | ||
1705 | default: | ||
1706 | return 0; | ||
1707 | } | ||
1708 | |||
1709 | mdelay(2); | ||
1710 | |||
1711 | /* ...wait until PHY is ready and read the selected radio revision */ | ||
1712 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | ||
1713 | |||
1714 | for (i = 0; i < 8; i++) | ||
1715 | ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); | ||
1716 | |||
1717 | if (ah->ah_version == AR5K_AR5210) { | ||
1718 | srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; | ||
1719 | ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; | ||
1720 | } else { | ||
1721 | srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; | ||
1722 | ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | | ||
1723 | ((srev & 0x0f) << 4), 8); | ||
1724 | } | ||
1725 | |||
1726 | /* Reset to the 5GHz mode */ | ||
1727 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
1728 | |||
1729 | return ret; | ||
1730 | } | ||
1731 | 1855 | ||
1732 | /*****************\ | 1856 | /*****************\ |
1733 | * Antenna control * | 1857 | * Antenna control * |
@@ -1821,7 +1945,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1821 | struct ieee80211_channel *channel = ah->ah_current_channel; | 1945 | struct ieee80211_channel *channel = ah->ah_current_channel; |
1822 | bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; | 1946 | bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; |
1823 | bool use_def_for_sg; | 1947 | bool use_def_for_sg; |
1824 | u8 def_ant, tx_ant, ee_mode; | 1948 | int ee_mode; |
1949 | u8 def_ant, tx_ant; | ||
1825 | u32 sta_id1 = 0; | 1950 | u32 sta_id1 = 0; |
1826 | 1951 | ||
1827 | /* if channel is not initialized yet we can't set the antennas | 1952 | /* if channel is not initialized yet we can't set the antennas |
@@ -1833,20 +1958,8 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) | |||
1833 | 1958 | ||
1834 | def_ant = ah->ah_def_ant; | 1959 | def_ant = ah->ah_def_ant; |
1835 | 1960 | ||
1836 | switch (channel->hw_value & CHANNEL_MODES) { | 1961 | ee_mode = ath5k_eeprom_mode_from_channel(channel); |
1837 | case CHANNEL_A: | 1962 | if (ee_mode < 0) { |
1838 | case CHANNEL_T: | ||
1839 | case CHANNEL_XR: | ||
1840 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
1841 | break; | ||
1842 | case CHANNEL_G: | ||
1843 | case CHANNEL_TG: | ||
1844 | ee_mode = AR5K_EEPROM_MODE_11G; | ||
1845 | break; | ||
1846 | case CHANNEL_B: | ||
1847 | ee_mode = AR5K_EEPROM_MODE_11B; | ||
1848 | break; | ||
1849 | default: | ||
1850 | ATH5K_ERR(ah->ah_sc, | 1963 | ATH5K_ERR(ah->ah_sc, |
1851 | "invalid channel: %d\n", channel->center_freq); | 1964 | "invalid channel: %d\n", channel->center_freq); |
1852 | return; | 1965 | return; |
@@ -2088,7 +2201,7 @@ ath5k_create_power_curve(s16 pmin, s16 pmax, | |||
2088 | /* | 2201 | /* |
2089 | * Get the surrounding per-channel power calibration piers | 2202 | * Get the surrounding per-channel power calibration piers |
2090 | * for a given frequency so that we can interpolate between | 2203 | * for a given frequency so that we can interpolate between |
2091 | * them and come up with an apropriate dataset for our current | 2204 | * them and come up with an appropriate dataset for our current |
2092 | * channel. | 2205 | * channel. |
2093 | */ | 2206 | */ |
2094 | static void | 2207 | static void |
@@ -2274,20 +2387,20 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, | |||
2274 | 2387 | ||
2275 | switch (channel->hw_value & CHANNEL_MODES) { | 2388 | switch (channel->hw_value & CHANNEL_MODES) { |
2276 | case CHANNEL_A: | 2389 | case CHANNEL_A: |
2277 | ctl_mode |= AR5K_CTL_11A; | 2390 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
2391 | ctl_mode |= AR5K_CTL_TURBO; | ||
2392 | else | ||
2393 | ctl_mode |= AR5K_CTL_11A; | ||
2278 | break; | 2394 | break; |
2279 | case CHANNEL_G: | 2395 | case CHANNEL_G: |
2280 | ctl_mode |= AR5K_CTL_11G; | 2396 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
2397 | ctl_mode |= AR5K_CTL_TURBOG; | ||
2398 | else | ||
2399 | ctl_mode |= AR5K_CTL_11G; | ||
2281 | break; | 2400 | break; |
2282 | case CHANNEL_B: | 2401 | case CHANNEL_B: |
2283 | ctl_mode |= AR5K_CTL_11B; | 2402 | ctl_mode |= AR5K_CTL_11B; |
2284 | break; | 2403 | break; |
2285 | case CHANNEL_T: | ||
2286 | ctl_mode |= AR5K_CTL_TURBO; | ||
2287 | break; | ||
2288 | case CHANNEL_TG: | ||
2289 | ctl_mode |= AR5K_CTL_TURBOG; | ||
2290 | break; | ||
2291 | case CHANNEL_XR: | 2404 | case CHANNEL_XR: |
2292 | /* Fall through */ | 2405 | /* Fall through */ |
2293 | default: | 2406 | default: |
@@ -2481,7 +2594,7 @@ ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, | |||
2481 | 2594 | ||
2482 | /* Write PCDAC values on hw */ | 2595 | /* Write PCDAC values on hw */ |
2483 | static void | 2596 | static void |
2484 | ath5k_setup_pcdac_table(struct ath5k_hw *ah) | 2597 | ath5k_write_pcdac_table(struct ath5k_hw *ah) |
2485 | { | 2598 | { |
2486 | u8 *pcdac_out = ah->ah_txpower.txp_pd_table; | 2599 | u8 *pcdac_out = ah->ah_txpower.txp_pd_table; |
2487 | int i; | 2600 | int i; |
@@ -2505,7 +2618,7 @@ ath5k_setup_pcdac_table(struct ath5k_hw *ah) | |||
2505 | /* | 2618 | /* |
2506 | * Set the gain boundaries and create final Power to PDADC table | 2619 | * Set the gain boundaries and create final Power to PDADC table |
2507 | * | 2620 | * |
2508 | * We can have up to 4 pd curves, we need to do a simmilar process | 2621 | * We can have up to 4 pd curves, we need to do a similar process |
2509 | * as we do for RF5112. This time we don't have an edge_flag but we | 2622 | * as we do for RF5112. This time we don't have an edge_flag but we |
2510 | * set the gain boundaries on a separate register. | 2623 | * set the gain boundaries on a separate register. |
2511 | */ | 2624 | */ |
@@ -2630,10 +2743,12 @@ ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, | |||
2630 | 2743 | ||
2631 | /* Write PDADC values on hw */ | 2744 | /* Write PDADC values on hw */ |
2632 | static void | 2745 | static void |
2633 | ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, | 2746 | ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode) |
2634 | u8 pdcurves, u8 *pdg_to_idx) | ||
2635 | { | 2747 | { |
2748 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
2636 | u8 *pdadc_out = ah->ah_txpower.txp_pd_table; | 2749 | u8 *pdadc_out = ah->ah_txpower.txp_pd_table; |
2750 | u8 *pdg_to_idx = ee->ee_pdc_to_idx[ee_mode]; | ||
2751 | u8 pdcurves = ee->ee_pd_gains[ee_mode]; | ||
2637 | u32 reg; | 2752 | u32 reg; |
2638 | u8 i; | 2753 | u8 i; |
2639 | 2754 | ||
@@ -2711,13 +2826,13 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2711 | u32 target = channel->center_freq; | 2826 | u32 target = channel->center_freq; |
2712 | int pdg, i; | 2827 | int pdg, i; |
2713 | 2828 | ||
2714 | /* Get surounding freq piers for this channel */ | 2829 | /* Get surrounding freq piers for this channel */ |
2715 | ath5k_get_chan_pcal_surrounding_piers(ah, channel, | 2830 | ath5k_get_chan_pcal_surrounding_piers(ah, channel, |
2716 | &pcinfo_L, | 2831 | &pcinfo_L, |
2717 | &pcinfo_R); | 2832 | &pcinfo_R); |
2718 | 2833 | ||
2719 | /* Loop over pd gain curves on | 2834 | /* Loop over pd gain curves on |
2720 | * surounding freq piers by index */ | 2835 | * surrounding freq piers by index */ |
2721 | for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { | 2836 | for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { |
2722 | 2837 | ||
2723 | /* Fill curves in reverse order | 2838 | /* Fill curves in reverse order |
@@ -2808,7 +2923,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2808 | } | 2923 | } |
2809 | 2924 | ||
2810 | /* Interpolate between curves | 2925 | /* Interpolate between curves |
2811 | * of surounding freq piers to | 2926 | * of surrounding freq piers to |
2812 | * get the final curve for this | 2927 | * get the final curve for this |
2813 | * pd gain. Re-use tmpL for interpolation | 2928 | * pd gain. Re-use tmpL for interpolation |
2814 | * output */ | 2929 | * output */ |
@@ -2832,7 +2947,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2832 | 2947 | ||
2833 | /* Fill min and max power levels for this | 2948 | /* Fill min and max power levels for this |
2834 | * channel by interpolating the values on | 2949 | * channel by interpolating the values on |
2835 | * surounding channels to complete the dataset */ | 2950 | * surrounding channels to complete the dataset */ |
2836 | ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, | 2951 | ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, |
2837 | (s16) pcinfo_L->freq, | 2952 | (s16) pcinfo_L->freq, |
2838 | (s16) pcinfo_R->freq, | 2953 | (s16) pcinfo_R->freq, |
@@ -2843,8 +2958,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2843 | (s16) pcinfo_R->freq, | 2958 | (s16) pcinfo_R->freq, |
2844 | pcinfo_L->max_pwr, pcinfo_R->max_pwr); | 2959 | pcinfo_L->max_pwr, pcinfo_R->max_pwr); |
2845 | 2960 | ||
2846 | /* We are ready to go, fill PCDAC/PDADC | 2961 | /* Fill PCDAC/PDADC table */ |
2847 | * table and write settings on hardware */ | ||
2848 | switch (type) { | 2962 | switch (type) { |
2849 | case AR5K_PWRTABLE_LINEAR_PCDAC: | 2963 | case AR5K_PWRTABLE_LINEAR_PCDAC: |
2850 | /* For RF5112 we can have one or two curves | 2964 | /* For RF5112 we can have one or two curves |
@@ -2857,9 +2971,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2857 | * match max power value with max | 2971 | * match max power value with max |
2858 | * table index */ | 2972 | * table index */ |
2859 | ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); | 2973 | ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); |
2860 | |||
2861 | /* Write settings on hw */ | ||
2862 | ath5k_setup_pcdac_table(ah); | ||
2863 | break; | 2974 | break; |
2864 | case AR5K_PWRTABLE_PWR_TO_PCDAC: | 2975 | case AR5K_PWRTABLE_PWR_TO_PCDAC: |
2865 | /* We are done for RF5111 since it has only | 2976 | /* We are done for RF5111 since it has only |
@@ -2869,9 +2980,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2869 | /* No rate powertable adjustment for RF5111 */ | 2980 | /* No rate powertable adjustment for RF5111 */ |
2870 | ah->ah_txpower.txp_min_idx = 0; | 2981 | ah->ah_txpower.txp_min_idx = 0; |
2871 | ah->ah_txpower.txp_offset = 0; | 2982 | ah->ah_txpower.txp_offset = 0; |
2872 | |||
2873 | /* Write settings on hw */ | ||
2874 | ath5k_setup_pcdac_table(ah); | ||
2875 | break; | 2983 | break; |
2876 | case AR5K_PWRTABLE_PWR_TO_PDADC: | 2984 | case AR5K_PWRTABLE_PWR_TO_PDADC: |
2877 | /* Set PDADC boundaries and fill | 2985 | /* Set PDADC boundaries and fill |
@@ -2879,9 +2987,6 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2879 | ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, | 2987 | ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, |
2880 | ee->ee_pd_gains[ee_mode]); | 2988 | ee->ee_pd_gains[ee_mode]); |
2881 | 2989 | ||
2882 | /* Write settings on hw */ | ||
2883 | ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx); | ||
2884 | |||
2885 | /* Set txp.offset, note that table_min | 2990 | /* Set txp.offset, note that table_min |
2886 | * can be negative */ | 2991 | * can be negative */ |
2887 | ah->ah_txpower.txp_offset = table_min[0]; | 2992 | ah->ah_txpower.txp_offset = table_min[0]; |
@@ -2890,9 +2995,20 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah, | |||
2890 | return -EINVAL; | 2995 | return -EINVAL; |
2891 | } | 2996 | } |
2892 | 2997 | ||
2998 | ah->ah_txpower.txp_setup = true; | ||
2999 | |||
2893 | return 0; | 3000 | return 0; |
2894 | } | 3001 | } |
2895 | 3002 | ||
3003 | /* Write power table for current channel to hw */ | ||
3004 | static void | ||
3005 | ath5k_write_channel_powertable(struct ath5k_hw *ah, u8 ee_mode, u8 type) | ||
3006 | { | ||
3007 | if (type == AR5K_PWRTABLE_PWR_TO_PDADC) | ||
3008 | ath5k_write_pwr_to_pdadc_table(ah, ee_mode); | ||
3009 | else | ||
3010 | ath5k_write_pcdac_table(ah); | ||
3011 | } | ||
2896 | 3012 | ||
2897 | /* | 3013 | /* |
2898 | * Per-rate tx power setting | 3014 | * Per-rate tx power setting |
@@ -2981,19 +3097,21 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, | |||
2981 | 3097 | ||
2982 | /* Min/max in 0.25dB units */ | 3098 | /* Min/max in 0.25dB units */ |
2983 | ah->ah_txpower.txp_min_pwr = 2 * rates[7]; | 3099 | ah->ah_txpower.txp_min_pwr = 2 * rates[7]; |
2984 | ah->ah_txpower.txp_max_pwr = 2 * rates[0]; | 3100 | ah->ah_txpower.txp_cur_pwr = 2 * rates[0]; |
2985 | ah->ah_txpower.txp_ofdm = rates[7]; | 3101 | ah->ah_txpower.txp_ofdm = rates[7]; |
2986 | } | 3102 | } |
2987 | 3103 | ||
2988 | 3104 | ||
2989 | /* | 3105 | /* |
2990 | * Set transmition power | 3106 | * Set transmission power |
2991 | */ | 3107 | */ |
2992 | int | 3108 | static int |
2993 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 3109 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
2994 | u8 ee_mode, u8 txpower) | 3110 | u8 txpower) |
2995 | { | 3111 | { |
2996 | struct ath5k_rate_pcal_info rate_info; | 3112 | struct ath5k_rate_pcal_info rate_info; |
3113 | struct ieee80211_channel *curr_channel = ah->ah_current_channel; | ||
3114 | int ee_mode; | ||
2997 | u8 type; | 3115 | u8 type; |
2998 | int ret; | 3116 | int ret; |
2999 | 3117 | ||
@@ -3002,14 +3120,18 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3002 | return -EINVAL; | 3120 | return -EINVAL; |
3003 | } | 3121 | } |
3004 | 3122 | ||
3005 | /* Reset TX power values */ | 3123 | ee_mode = ath5k_eeprom_mode_from_channel(channel); |
3006 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | 3124 | if (ee_mode < 0) { |
3007 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | 3125 | ATH5K_ERR(ah->ah_sc, |
3008 | ah->ah_txpower.txp_min_pwr = 0; | 3126 | "invalid channel: %d\n", channel->center_freq); |
3009 | ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER; | 3127 | return -EINVAL; |
3128 | } | ||
3010 | 3129 | ||
3011 | /* Initialize TX power table */ | 3130 | /* Initialize TX power table */ |
3012 | switch (ah->ah_radio) { | 3131 | switch (ah->ah_radio) { |
3132 | case AR5K_RF5110: | ||
3133 | /* TODO */ | ||
3134 | return 0; | ||
3013 | case AR5K_RF5111: | 3135 | case AR5K_RF5111: |
3014 | type = AR5K_PWRTABLE_PWR_TO_PCDAC; | 3136 | type = AR5K_PWRTABLE_PWR_TO_PCDAC; |
3015 | break; | 3137 | break; |
@@ -3027,24 +3149,37 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3027 | return -EINVAL; | 3149 | return -EINVAL; |
3028 | } | 3150 | } |
3029 | 3151 | ||
3030 | /* FIXME: Only on channel/mode change */ | 3152 | /* |
3031 | ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); | 3153 | * If we don't change channel/mode skip tx powertable calculation |
3032 | if (ret) | 3154 | * and use the cached one. |
3033 | return ret; | 3155 | */ |
3156 | if (!ah->ah_txpower.txp_setup || | ||
3157 | (channel->hw_value != curr_channel->hw_value) || | ||
3158 | (channel->center_freq != curr_channel->center_freq)) { | ||
3159 | /* Reset TX power values */ | ||
3160 | memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); | ||
3161 | ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; | ||
3162 | |||
3163 | /* Calculate the powertable */ | ||
3164 | ret = ath5k_setup_channel_powertable(ah, channel, | ||
3165 | ee_mode, type); | ||
3166 | if (ret) | ||
3167 | return ret; | ||
3168 | } | ||
3169 | |||
3170 | /* Write table on hw */ | ||
3171 | ath5k_write_channel_powertable(ah, ee_mode, type); | ||
3034 | 3172 | ||
3035 | /* Limit max power if we have a CTL available */ | 3173 | /* Limit max power if we have a CTL available */ |
3036 | ath5k_get_max_ctl_power(ah, channel); | 3174 | ath5k_get_max_ctl_power(ah, channel); |
3037 | 3175 | ||
3038 | /* FIXME: Tx power limit for this regdomain | ||
3039 | * XXX: Mac80211/CRDA will do that anyway ? */ | ||
3040 | |||
3041 | /* FIXME: Antenna reduction stuff */ | 3176 | /* FIXME: Antenna reduction stuff */ |
3042 | 3177 | ||
3043 | /* FIXME: Limit power on turbo modes */ | 3178 | /* FIXME: Limit power on turbo modes */ |
3044 | 3179 | ||
3045 | /* FIXME: TPC scale reduction */ | 3180 | /* FIXME: TPC scale reduction */ |
3046 | 3181 | ||
3047 | /* Get surounding channels for per-rate power table | 3182 | /* Get surrounding channels for per-rate power table |
3048 | * calibration */ | 3183 | * calibration */ |
3049 | ath5k_get_rate_pcal_data(ah, channel, &rate_info); | 3184 | ath5k_get_rate_pcal_data(ah, channel, &rate_info); |
3050 | 3185 | ||
@@ -3088,31 +3223,223 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3088 | 3223 | ||
3089 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | 3224 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) |
3090 | { | 3225 | { |
3091 | /*Just a try M.F.*/ | 3226 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, |
3092 | struct ieee80211_channel *channel = ah->ah_current_channel; | 3227 | "changing txpower to %d\n", txpower); |
3093 | u8 ee_mode; | ||
3094 | 3228 | ||
3095 | switch (channel->hw_value & CHANNEL_MODES) { | 3229 | return ath5k_hw_txpower(ah, ah->ah_current_channel, txpower); |
3096 | case CHANNEL_A: | 3230 | } |
3097 | case CHANNEL_T: | 3231 | |
3098 | case CHANNEL_XR: | 3232 | /*************\ |
3099 | ee_mode = AR5K_EEPROM_MODE_11A; | 3233 | Init function |
3100 | break; | 3234 | \*************/ |
3101 | case CHANNEL_G: | 3235 | |
3102 | case CHANNEL_TG: | 3236 | int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
3103 | ee_mode = AR5K_EEPROM_MODE_11G; | 3237 | u8 mode, bool fast) |
3104 | break; | 3238 | { |
3105 | case CHANNEL_B: | 3239 | struct ieee80211_channel *curr_channel; |
3106 | ee_mode = AR5K_EEPROM_MODE_11B; | 3240 | int ret, i; |
3107 | break; | 3241 | u32 phy_tst1; |
3108 | default: | 3242 | ret = 0; |
3109 | ATH5K_ERR(ah->ah_sc, | 3243 | |
3110 | "invalid channel: %d\n", channel->center_freq); | 3244 | /* |
3245 | * Sanity check for fast flag | ||
3246 | * Don't try fast channel change when changing modulation | ||
3247 | * mode/band. We check for chip compatibility on | ||
3248 | * ath5k_hw_reset. | ||
3249 | */ | ||
3250 | curr_channel = ah->ah_current_channel; | ||
3251 | if (fast && (channel->hw_value != curr_channel->hw_value)) | ||
3111 | return -EINVAL; | 3252 | return -EINVAL; |
3253 | |||
3254 | /* | ||
3255 | * On fast channel change we only set the synth parameters | ||
3256 | * while PHY is running, enable calibration and skip the rest. | ||
3257 | */ | ||
3258 | if (fast) { | ||
3259 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, | ||
3260 | AR5K_PHY_RFBUS_REQ_REQUEST); | ||
3261 | for (i = 0; i < 100; i++) { | ||
3262 | if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT)) | ||
3263 | break; | ||
3264 | udelay(5); | ||
3265 | } | ||
3266 | /* Failed */ | ||
3267 | if (i >= 100) | ||
3268 | return -EIO; | ||
3269 | |||
3270 | /* Set channel and wait for synth */ | ||
3271 | ret = ath5k_hw_channel(ah, channel); | ||
3272 | if (ret) | ||
3273 | return ret; | ||
3274 | |||
3275 | ath5k_hw_wait_for_synth(ah, channel); | ||
3112 | } | 3276 | } |
3113 | 3277 | ||
3114 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, | 3278 | /* |
3115 | "changing txpower to %d\n", txpower); | 3279 | * Set TX power |
3280 | * | ||
3281 | * Note: We need to do that before we set | ||
3282 | * RF buffer settings on 5211/5212+ so that we | ||
3283 | * properly set curve indices. | ||
3284 | */ | ||
3285 | ret = ath5k_hw_txpower(ah, channel, ah->ah_txpower.txp_cur_pwr ? | ||
3286 | ah->ah_txpower.txp_cur_pwr / 2 : AR5K_TUNE_MAX_TXPOWER); | ||
3287 | if (ret) | ||
3288 | return ret; | ||
3289 | |||
3290 | /* Write OFDM timings on 5212*/ | ||
3291 | if (ah->ah_version == AR5K_AR5212 && | ||
3292 | channel->hw_value & CHANNEL_OFDM) { | ||
3293 | |||
3294 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | ||
3295 | if (ret) | ||
3296 | return ret; | ||
3297 | |||
3298 | /* Spur info is available only from EEPROM versions | ||
3299 | * greater than 5.3, but the EEPROM routines will use | ||
3300 | * static values for older versions */ | ||
3301 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | ||
3302 | ath5k_hw_set_spur_mitigation_filter(ah, | ||
3303 | channel); | ||
3304 | } | ||
3305 | |||
3306 | /* If we used fast channel switching | ||
3307 | * we are done, release RF bus and | ||
3308 | * fire up NF calibration. | ||
3309 | * | ||
3310 | * Note: Only NF calibration due to | ||
3311 | * channel change, not AGC calibration | ||
3312 | * since AGC is still running ! | ||
3313 | */ | ||
3314 | if (fast) { | ||
3315 | /* | ||
3316 | * Release RF Bus grant | ||
3317 | */ | ||
3318 | AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, | ||
3319 | AR5K_PHY_RFBUS_REQ_REQUEST); | ||
3320 | |||
3321 | /* | ||
3322 | * Start NF calibration | ||
3323 | */ | ||
3324 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
3325 | AR5K_PHY_AGCCTL_NF); | ||
3116 | 3326 | ||
3117 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); | 3327 | return ret; |
3328 | } | ||
3329 | |||
3330 | /* | ||
3331 | * For 5210 we do all initialization using | ||
3332 | * initvals, so we don't have to modify | ||
3333 | * any settings (5210 also only supports | ||
3334 | * a/aturbo modes) | ||
3335 | */ | ||
3336 | if (ah->ah_version != AR5K_AR5210) { | ||
3337 | |||
3338 | /* | ||
3339 | * Write initial RF gain settings | ||
3340 | * This should work for both 5111/5112 | ||
3341 | */ | ||
3342 | ret = ath5k_hw_rfgain_init(ah, channel->band); | ||
3343 | if (ret) | ||
3344 | return ret; | ||
3345 | |||
3346 | mdelay(1); | ||
3347 | |||
3348 | /* | ||
3349 | * Write RF buffer | ||
3350 | */ | ||
3351 | ret = ath5k_hw_rfregs_init(ah, channel, mode); | ||
3352 | if (ret) | ||
3353 | return ret; | ||
3354 | |||
3355 | /*Enable/disable 802.11b mode on 5111 | ||
3356 | (enable 2111 frequency converter + CCK)*/ | ||
3357 | if (ah->ah_radio == AR5K_RF5111) { | ||
3358 | if (mode == AR5K_MODE_11B) | ||
3359 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | ||
3360 | AR5K_TXCFG_B_MODE); | ||
3361 | else | ||
3362 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | ||
3363 | AR5K_TXCFG_B_MODE); | ||
3364 | } | ||
3365 | |||
3366 | } else if (ah->ah_version == AR5K_AR5210) { | ||
3367 | mdelay(1); | ||
3368 | /* Disable phy and wait */ | ||
3369 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
3370 | mdelay(1); | ||
3371 | } | ||
3372 | |||
3373 | /* Set channel on PHY */ | ||
3374 | ret = ath5k_hw_channel(ah, channel); | ||
3375 | if (ret) | ||
3376 | return ret; | ||
3377 | |||
3378 | /* | ||
3379 | * Enable the PHY and wait until completion | ||
3380 | * This includes BaseBand and Synthesizer | ||
3381 | * activation. | ||
3382 | */ | ||
3383 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
3384 | |||
3385 | ath5k_hw_wait_for_synth(ah, channel); | ||
3386 | |||
3387 | /* | ||
3388 | * Perform ADC test to see if baseband is ready | ||
3389 | * Set tx hold and check adc test register | ||
3390 | */ | ||
3391 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | ||
3392 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | ||
3393 | for (i = 0; i <= 20; i++) { | ||
3394 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | ||
3395 | break; | ||
3396 | udelay(200); | ||
3397 | } | ||
3398 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); | ||
3399 | |||
3400 | /* | ||
3401 | * Start automatic gain control calibration | ||
3402 | * | ||
3403 | * During AGC calibration RX path is re-routed to | ||
3404 | * a power detector so we don't receive anything. | ||
3405 | * | ||
3406 | * This method is used to calibrate some static offsets | ||
3407 | * used together with on-the fly I/Q calibration (the | ||
3408 | * one performed via ath5k_hw_phy_calibrate), which doesn't | ||
3409 | * interrupt rx path. | ||
3410 | * | ||
3411 | * While rx path is re-routed to the power detector we also | ||
3412 | * start a noise floor calibration to measure the | ||
3413 | * card's noise floor (the noise we measure when we are not | ||
3414 | * transmitting or receiving anything). | ||
3415 | * | ||
3416 | * If we are in a noisy environment, AGC calibration may time | ||
3417 | * out and/or noise floor calibration might timeout. | ||
3418 | */ | ||
3419 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
3420 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); | ||
3421 | |||
3422 | /* At the same time start I/Q calibration for QAM constellation | ||
3423 | * -no need for CCK- */ | ||
3424 | ah->ah_calibration = false; | ||
3425 | if (!(mode == AR5K_MODE_11B)) { | ||
3426 | ah->ah_calibration = true; | ||
3427 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
3428 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
3429 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
3430 | AR5K_PHY_IQ_RUN); | ||
3431 | } | ||
3432 | |||
3433 | /* Wait for gain calibration to finish (we check for I/Q calibration | ||
3434 | * during ath5k_phy_calibrate) */ | ||
3435 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
3436 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | ||
3437 | ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", | ||
3438 | channel->center_freq); | ||
3439 | } | ||
3440 | |||
3441 | /* Restore antenna mode */ | ||
3442 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | ||
3443 | |||
3444 | return ret; | ||
3118 | } | 3445 | } |
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 4186ff4c6e9c..b18c5021aac3 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -25,6 +25,68 @@ Queue Control Unit, DFS Control Unit Functions | |||
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | #include "base.h" | 26 | #include "base.h" |
27 | 27 | ||
28 | |||
29 | /******************\ | ||
30 | * Helper functions * | ||
31 | \******************/ | ||
32 | |||
33 | /* | ||
34 | * Get number of pending frames | ||
35 | * for a specific queue [5211+] | ||
36 | */ | ||
37 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | ||
38 | { | ||
39 | u32 pending; | ||
40 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
41 | |||
42 | /* Return if queue is declared inactive */ | ||
43 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
44 | return false; | ||
45 | |||
46 | /* XXX: How about AR5K_CFG_TXCNT ? */ | ||
47 | if (ah->ah_version == AR5K_AR5210) | ||
48 | return false; | ||
49 | |||
50 | pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); | ||
51 | pending &= AR5K_QCU_STS_FRMPENDCNT; | ||
52 | |||
53 | /* It's possible to have no frames pending even if TXE | ||
54 | * is set. To indicate that q has not stopped return | ||
55 | * true */ | ||
56 | if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
57 | return true; | ||
58 | |||
59 | return pending; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Set a transmit queue inactive | ||
64 | */ | ||
65 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
66 | { | ||
67 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) | ||
68 | return; | ||
69 | |||
70 | /* This queue will be skipped in further operations */ | ||
71 | ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; | ||
72 | /*For SIMR setup*/ | ||
73 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Make sure cw is a power of 2 minus 1 and smaller than 1024 | ||
78 | */ | ||
79 | static u16 ath5k_cw_validate(u16 cw_req) | ||
80 | { | ||
81 | u32 cw = 1; | ||
82 | cw_req = min(cw_req, (u16)1023); | ||
83 | |||
84 | while (cw < cw_req) | ||
85 | cw = (cw << 1) | 1; | ||
86 | |||
87 | return cw; | ||
88 | } | ||
89 | |||
28 | /* | 90 | /* |
29 | * Get properties for a transmit queue | 91 | * Get properties for a transmit queue |
30 | */ | 92 | */ |
@@ -39,21 +101,41 @@ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | |||
39 | * Set properties for a transmit queue | 101 | * Set properties for a transmit queue |
40 | */ | 102 | */ |
41 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | 103 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, |
42 | const struct ath5k_txq_info *queue_info) | 104 | const struct ath5k_txq_info *qinfo) |
43 | { | 105 | { |
106 | struct ath5k_txq_info *qi; | ||
107 | |||
44 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 108 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
45 | 109 | ||
46 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | 110 | qi = &ah->ah_txq[queue]; |
111 | |||
112 | if (qi->tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
47 | return -EIO; | 113 | return -EIO; |
48 | 114 | ||
49 | memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info)); | 115 | /* copy and validate values */ |
116 | qi->tqi_type = qinfo->tqi_type; | ||
117 | qi->tqi_subtype = qinfo->tqi_subtype; | ||
118 | qi->tqi_flags = qinfo->tqi_flags; | ||
119 | /* | ||
120 | * According to the docs: Although the AIFS field is 8 bit wide, | ||
121 | * the maximum supported value is 0xFC. Setting it higher than that | ||
122 | * will cause the DCU to hang. | ||
123 | */ | ||
124 | qi->tqi_aifs = min(qinfo->tqi_aifs, (u8)0xFC); | ||
125 | qi->tqi_cw_min = ath5k_cw_validate(qinfo->tqi_cw_min); | ||
126 | qi->tqi_cw_max = ath5k_cw_validate(qinfo->tqi_cw_max); | ||
127 | qi->tqi_cbr_period = qinfo->tqi_cbr_period; | ||
128 | qi->tqi_cbr_overflow_limit = qinfo->tqi_cbr_overflow_limit; | ||
129 | qi->tqi_burst_time = qinfo->tqi_burst_time; | ||
130 | qi->tqi_ready_time = qinfo->tqi_ready_time; | ||
50 | 131 | ||
51 | /*XXX: Is this supported on 5210 ?*/ | 132 | /*XXX: Is this supported on 5210 ?*/ |
52 | if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && | 133 | /*XXX: Is this correct for AR5K_WME_AC_VI,VO ???*/ |
53 | ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || | 134 | if ((qinfo->tqi_type == AR5K_TX_QUEUE_DATA && |
54 | (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || | 135 | ((qinfo->tqi_subtype == AR5K_WME_AC_VI) || |
55 | queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) | 136 | (qinfo->tqi_subtype == AR5K_WME_AC_VO))) || |
56 | ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; | 137 | qinfo->tqi_type == AR5K_TX_QUEUE_UAPSD) |
138 | qi->tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; | ||
57 | 139 | ||
58 | return 0; | 140 | return 0; |
59 | } | 141 | } |
@@ -70,8 +152,8 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | |||
70 | /* | 152 | /* |
71 | * Get queue by type | 153 | * Get queue by type |
72 | */ | 154 | */ |
73 | /*5210 only has 2 queues*/ | 155 | /* 5210 only has 2 queues */ |
74 | if (ah->ah_version == AR5K_AR5210) { | 156 | if (ah->ah_capabilities.cap_queues.q_tx_num == 2) { |
75 | switch (queue_type) { | 157 | switch (queue_type) { |
76 | case AR5K_TX_QUEUE_DATA: | 158 | case AR5K_TX_QUEUE_DATA: |
77 | queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; | 159 | queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; |
@@ -138,392 +220,431 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | |||
138 | return queue; | 220 | return queue; |
139 | } | 221 | } |
140 | 222 | ||
141 | /* | ||
142 | * Get number of pending frames | ||
143 | * for a specific queue [5211+] | ||
144 | */ | ||
145 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | ||
146 | { | ||
147 | u32 pending; | ||
148 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
149 | |||
150 | /* Return if queue is declared inactive */ | ||
151 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
152 | return false; | ||
153 | |||
154 | /* XXX: How about AR5K_CFG_TXCNT ? */ | ||
155 | if (ah->ah_version == AR5K_AR5210) | ||
156 | return false; | ||
157 | |||
158 | pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); | ||
159 | pending &= AR5K_QCU_STS_FRMPENDCNT; | ||
160 | |||
161 | /* It's possible to have no frames pending even if TXE | ||
162 | * is set. To indicate that q has not stopped return | ||
163 | * true */ | ||
164 | if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
165 | return true; | ||
166 | 223 | ||
167 | return pending; | 224 | /*******************************\ |
168 | } | 225 | * Single QCU/DCU initialization * |
226 | \*******************************/ | ||
169 | 227 | ||
170 | /* | 228 | /* |
171 | * Set a transmit queue inactive | 229 | * Set tx retry limits on DCU |
172 | */ | 230 | */ |
173 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | 231 | void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, |
232 | unsigned int queue) | ||
174 | { | 233 | { |
175 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) | 234 | /* Single data queue on AR5210 */ |
176 | return; | 235 | if (ah->ah_version == AR5K_AR5210) { |
236 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | ||
177 | 237 | ||
178 | /* This queue will be skipped in further operations */ | 238 | if (queue > 0) |
179 | ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; | 239 | return; |
180 | /*For SIMR setup*/ | 240 | |
181 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); | 241 | ath5k_hw_reg_write(ah, |
242 | (tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | ||
243 | | AR5K_REG_SM(ah->ah_retry_long, | ||
244 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) | ||
245 | | AR5K_REG_SM(ah->ah_retry_short, | ||
246 | AR5K_NODCU_RETRY_LMT_SSH_RETRY) | ||
247 | | AR5K_REG_SM(ah->ah_retry_long, | ||
248 | AR5K_NODCU_RETRY_LMT_LG_RETRY) | ||
249 | | AR5K_REG_SM(ah->ah_retry_short, | ||
250 | AR5K_NODCU_RETRY_LMT_SH_RETRY), | ||
251 | AR5K_NODCU_RETRY_LMT); | ||
252 | /* DCU on AR5211+ */ | ||
253 | } else { | ||
254 | ath5k_hw_reg_write(ah, | ||
255 | AR5K_REG_SM(ah->ah_retry_long, | ||
256 | AR5K_DCU_RETRY_LMT_RTS) | ||
257 | | AR5K_REG_SM(ah->ah_retry_long, | ||
258 | AR5K_DCU_RETRY_LMT_STA_RTS) | ||
259 | | AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short), | ||
260 | AR5K_DCU_RETRY_LMT_STA_DATA), | ||
261 | AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); | ||
262 | } | ||
182 | } | 263 | } |
183 | 264 | ||
184 | /* | 265 | /** |
185 | * Set DFS properties for a transmit queue on DCU | 266 | * ath5k_hw_reset_tx_queue - Initialize a single hw queue |
267 | * | ||
268 | * @ah The &struct ath5k_hw | ||
269 | * @queue The hw queue number | ||
270 | * | ||
271 | * Set DFS properties for the given transmit queue on DCU | ||
272 | * and configures all queue-specific parameters. | ||
186 | */ | 273 | */ |
187 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | 274 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) |
188 | { | 275 | { |
189 | u32 cw_min, cw_max, retry_lg, retry_sh; | ||
190 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; | 276 | struct ath5k_txq_info *tq = &ah->ah_txq[queue]; |
191 | 277 | ||
192 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | 278 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
193 | 279 | ||
194 | tq = &ah->ah_txq[queue]; | 280 | tq = &ah->ah_txq[queue]; |
195 | 281 | ||
196 | if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) | 282 | /* Skip if queue inactive or if we are on AR5210 |
283 | * that doesn't have QCU/DCU */ | ||
284 | if ((ah->ah_version == AR5K_AR5210) || | ||
285 | (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)) | ||
197 | return 0; | 286 | return 0; |
198 | 287 | ||
199 | if (ah->ah_version == AR5K_AR5210) { | ||
200 | /* Only handle data queues, others will be ignored */ | ||
201 | if (tq->tqi_type != AR5K_TX_QUEUE_DATA) | ||
202 | return 0; | ||
203 | |||
204 | /* Set Slot time */ | ||
205 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
206 | AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, | ||
207 | AR5K_SLOT_TIME); | ||
208 | /* Set ACK_CTS timeout */ | ||
209 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
210 | AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : | ||
211 | AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); | ||
212 | /* Set Transmit Latency */ | ||
213 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
214 | AR5K_INIT_TRANSMIT_LATENCY_TURBO : | ||
215 | AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); | ||
216 | |||
217 | /* Set IFS0 */ | ||
218 | if (ah->ah_turbo) { | ||
219 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + | ||
220 | (ah->ah_aifs + tq->tqi_aifs) * | ||
221 | AR5K_INIT_SLOT_TIME_TURBO) << | ||
222 | AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, | ||
223 | AR5K_IFS0); | ||
224 | } else { | ||
225 | ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + | ||
226 | (ah->ah_aifs + tq->tqi_aifs) * | ||
227 | AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | | ||
228 | AR5K_INIT_SIFS, AR5K_IFS0); | ||
229 | } | ||
230 | |||
231 | /* Set IFS1 */ | ||
232 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
233 | AR5K_INIT_PROTO_TIME_CNTRL_TURBO : | ||
234 | AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); | ||
235 | /* Set AR5K_PHY_SETTLING */ | ||
236 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
237 | (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) | ||
238 | | 0x38 : | ||
239 | (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) | ||
240 | | 0x1C, | ||
241 | AR5K_PHY_SETTLING); | ||
242 | /* Set Frame Control Register */ | ||
243 | ath5k_hw_reg_write(ah, ah->ah_turbo ? | ||
244 | (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | | ||
245 | AR5K_PHY_TURBO_SHORT | 0x2020) : | ||
246 | (AR5K_PHY_FRAME_CTL_INI | 0x1020), | ||
247 | AR5K_PHY_FRAME_CTL_5210); | ||
248 | } | ||
249 | |||
250 | /* | 288 | /* |
251 | * Calculate cwmin/max by channel mode | 289 | * Set contention window (cw_min/cw_max) |
290 | * and arbitrated interframe space (aifs)... | ||
252 | */ | 291 | */ |
253 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; | 292 | ath5k_hw_reg_write(ah, |
254 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; | 293 | AR5K_REG_SM(tq->tqi_cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | |
255 | ah->ah_aifs = AR5K_TUNE_AIFS; | 294 | AR5K_REG_SM(tq->tqi_cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | |
256 | /*XR is only supported on 5212*/ | 295 | AR5K_REG_SM(tq->tqi_aifs, AR5K_DCU_LCL_IFS_AIFS), |
257 | if (IS_CHAN_XR(ah->ah_current_channel) && | 296 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); |
258 | ah->ah_version == AR5K_AR5212) { | ||
259 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; | ||
260 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; | ||
261 | ah->ah_aifs = AR5K_TUNE_AIFS_XR; | ||
262 | /*B mode is not supported on 5210*/ | ||
263 | } else if (IS_CHAN_B(ah->ah_current_channel) && | ||
264 | ah->ah_version != AR5K_AR5210) { | ||
265 | cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; | ||
266 | cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; | ||
267 | ah->ah_aifs = AR5K_TUNE_AIFS_11B; | ||
268 | } | ||
269 | 297 | ||
270 | cw_min = 1; | 298 | /* |
271 | while (cw_min < ah->ah_cw_min) | 299 | * Set tx retry limits for this queue |
272 | cw_min = (cw_min << 1) | 1; | 300 | */ |
301 | ath5k_hw_set_tx_retry_limits(ah, queue); | ||
273 | 302 | ||
274 | cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : | ||
275 | ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); | ||
276 | cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : | ||
277 | ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); | ||
278 | 303 | ||
279 | /* | 304 | /* |
280 | * Calculate and set retry limits | 305 | * Set misc registers |
281 | */ | 306 | */ |
282 | if (ah->ah_software_retry) { | ||
283 | /* XXX Need to test this */ | ||
284 | retry_lg = ah->ah_limit_tx_retries; | ||
285 | retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? | ||
286 | AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg; | ||
287 | } else { | ||
288 | retry_lg = AR5K_INIT_LG_RETRY; | ||
289 | retry_sh = AR5K_INIT_SH_RETRY; | ||
290 | } | ||
291 | 307 | ||
292 | /*No QCU/DCU [5210]*/ | 308 | /* Enable DCU to wait for next fragment from QCU */ |
293 | if (ah->ah_version == AR5K_AR5210) { | 309 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), |
294 | ath5k_hw_reg_write(ah, | 310 | AR5K_DCU_MISC_FRAG_WAIT); |
295 | (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) | ||
296 | | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | ||
297 | AR5K_NODCU_RETRY_LMT_SLG_RETRY) | ||
298 | | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | ||
299 | AR5K_NODCU_RETRY_LMT_SSH_RETRY) | ||
300 | | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) | ||
301 | | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), | ||
302 | AR5K_NODCU_RETRY_LMT); | ||
303 | } else { | ||
304 | /*QCU/DCU [5211+]*/ | ||
305 | ath5k_hw_reg_write(ah, | ||
306 | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, | ||
307 | AR5K_DCU_RETRY_LMT_SLG_RETRY) | | ||
308 | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, | ||
309 | AR5K_DCU_RETRY_LMT_SSH_RETRY) | | ||
310 | AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | | ||
311 | AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), | ||
312 | AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); | ||
313 | 311 | ||
314 | /*===Rest is also for QCU/DCU only [5211+]===*/ | 312 | /* On Maui and Spirit use the global seqnum on DCU */ |
313 | if (ah->ah_mac_version < AR5K_SREV_AR5211) | ||
314 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
315 | AR5K_DCU_MISC_SEQNUM_CTL); | ||
316 | |||
317 | /* Constant bit rate period */ | ||
318 | if (tq->tqi_cbr_period) { | ||
319 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, | ||
320 | AR5K_QCU_CBRCFG_INTVAL) | | ||
321 | AR5K_REG_SM(tq->tqi_cbr_overflow_limit, | ||
322 | AR5K_QCU_CBRCFG_ORN_THRES), | ||
323 | AR5K_QUEUE_CBRCFG(queue)); | ||
315 | 324 | ||
316 | /* | ||
317 | * Set initial content window (cw_min/cw_max) | ||
318 | * and arbitrated interframe space (aifs)... | ||
319 | */ | ||
320 | ath5k_hw_reg_write(ah, | ||
321 | AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | | ||
322 | AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | | ||
323 | AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, | ||
324 | AR5K_DCU_LCL_IFS_AIFS), | ||
325 | AR5K_QUEUE_DFS_LOCAL_IFS(queue)); | ||
326 | |||
327 | /* | ||
328 | * Set misc registers | ||
329 | */ | ||
330 | /* Enable DCU early termination for this queue */ | ||
331 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | 325 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
332 | AR5K_QCU_MISC_DCU_EARLY); | 326 | AR5K_QCU_MISC_FRSHED_CBR); |
333 | 327 | ||
334 | /* Enable DCU to wait for next fragment from QCU */ | 328 | if (tq->tqi_cbr_overflow_limit) |
335 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
336 | AR5K_DCU_MISC_FRAG_WAIT); | ||
337 | |||
338 | /* On Maui and Spirit use the global seqnum on DCU */ | ||
339 | if (ah->ah_mac_version < AR5K_SREV_AR5211) | ||
340 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | ||
341 | AR5K_DCU_MISC_SEQNUM_CTL); | ||
342 | |||
343 | if (tq->tqi_cbr_period) { | ||
344 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, | ||
345 | AR5K_QCU_CBRCFG_INTVAL) | | ||
346 | AR5K_REG_SM(tq->tqi_cbr_overflow_limit, | ||
347 | AR5K_QCU_CBRCFG_ORN_THRES), | ||
348 | AR5K_QUEUE_CBRCFG(queue)); | ||
349 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | 329 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
350 | AR5K_QCU_MISC_FRSHED_CBR); | ||
351 | if (tq->tqi_cbr_overflow_limit) | ||
352 | AR5K_REG_ENABLE_BITS(ah, | ||
353 | AR5K_QUEUE_MISC(queue), | ||
354 | AR5K_QCU_MISC_CBR_THRES_ENABLE); | 330 | AR5K_QCU_MISC_CBR_THRES_ENABLE); |
355 | } | 331 | } |
356 | 332 | ||
357 | if (tq->tqi_ready_time && | 333 | /* Ready time interval */ |
358 | (tq->tqi_type != AR5K_TX_QUEUE_CAB)) | 334 | if (tq->tqi_ready_time && (tq->tqi_type != AR5K_TX_QUEUE_CAB)) |
359 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, | 335 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, |
360 | AR5K_QCU_RDYTIMECFG_INTVAL) | | 336 | AR5K_QCU_RDYTIMECFG_INTVAL) | |
361 | AR5K_QCU_RDYTIMECFG_ENABLE, | 337 | AR5K_QCU_RDYTIMECFG_ENABLE, |
362 | AR5K_QUEUE_RDYTIMECFG(queue)); | 338 | AR5K_QUEUE_RDYTIMECFG(queue)); |
363 | 339 | ||
364 | if (tq->tqi_burst_time) { | 340 | if (tq->tqi_burst_time) { |
365 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, | 341 | ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, |
366 | AR5K_DCU_CHAN_TIME_DUR) | | 342 | AR5K_DCU_CHAN_TIME_DUR) | |
367 | AR5K_DCU_CHAN_TIME_ENABLE, | 343 | AR5K_DCU_CHAN_TIME_ENABLE, |
368 | AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); | 344 | AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); |
369 | 345 | ||
370 | if (tq->tqi_flags | 346 | if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) |
371 | & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) | 347 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
372 | AR5K_REG_ENABLE_BITS(ah, | ||
373 | AR5K_QUEUE_MISC(queue), | ||
374 | AR5K_QCU_MISC_RDY_VEOL_POLICY); | 348 | AR5K_QCU_MISC_RDY_VEOL_POLICY); |
375 | } | 349 | } |
376 | 350 | ||
377 | if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) | 351 | /* Enable/disable Post frame backoff */ |
378 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, | 352 | if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) |
379 | AR5K_QUEUE_DFS_MISC(queue)); | 353 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, |
354 | AR5K_QUEUE_DFS_MISC(queue)); | ||
380 | 355 | ||
381 | if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) | 356 | /* Enable/disable fragmentation burst backoff */ |
382 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, | 357 | if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) |
383 | AR5K_QUEUE_DFS_MISC(queue)); | 358 | ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, |
359 | AR5K_QUEUE_DFS_MISC(queue)); | ||
384 | 360 | ||
385 | /* | 361 | /* |
386 | * Set registers by queue type | 362 | * Set registers by queue type |
387 | */ | 363 | */ |
388 | switch (tq->tqi_type) { | 364 | switch (tq->tqi_type) { |
389 | case AR5K_TX_QUEUE_BEACON: | 365 | case AR5K_TX_QUEUE_BEACON: |
390 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | 366 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
391 | AR5K_QCU_MISC_FRSHED_DBA_GT | | 367 | AR5K_QCU_MISC_FRSHED_DBA_GT | |
392 | AR5K_QCU_MISC_CBREXP_BCN_DIS | | 368 | AR5K_QCU_MISC_CBREXP_BCN_DIS | |
393 | AR5K_QCU_MISC_BCN_ENABLE); | 369 | AR5K_QCU_MISC_BCN_ENABLE); |
394 | 370 | ||
395 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | 371 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), |
396 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | 372 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << |
397 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | | 373 | AR5K_DCU_MISC_ARBLOCK_CTL_S) | |
398 | AR5K_DCU_MISC_ARBLOCK_IGNORE | | 374 | AR5K_DCU_MISC_ARBLOCK_IGNORE | |
399 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | | 375 | AR5K_DCU_MISC_POST_FR_BKOFF_DIS | |
400 | AR5K_DCU_MISC_BCN_ENABLE); | 376 | AR5K_DCU_MISC_BCN_ENABLE); |
401 | break; | 377 | break; |
402 | 378 | ||
403 | case AR5K_TX_QUEUE_CAB: | 379 | case AR5K_TX_QUEUE_CAB: |
404 | /* XXX: use BCN_SENT_GT, if we can figure out how */ | 380 | /* XXX: use BCN_SENT_GT, if we can figure out how */ |
405 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | 381 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
406 | AR5K_QCU_MISC_FRSHED_DBA_GT | | 382 | AR5K_QCU_MISC_FRSHED_DBA_GT | |
407 | AR5K_QCU_MISC_CBREXP_DIS | | 383 | AR5K_QCU_MISC_CBREXP_DIS | |
408 | AR5K_QCU_MISC_CBREXP_BCN_DIS); | 384 | AR5K_QCU_MISC_CBREXP_BCN_DIS); |
409 | 385 | ||
410 | ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - | 386 | ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - |
411 | (AR5K_TUNE_SW_BEACON_RESP - | 387 | (AR5K_TUNE_SW_BEACON_RESP - |
412 | AR5K_TUNE_DMA_BEACON_RESP) - | 388 | AR5K_TUNE_DMA_BEACON_RESP) - |
413 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | | 389 | AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | |
414 | AR5K_QCU_RDYTIMECFG_ENABLE, | 390 | AR5K_QCU_RDYTIMECFG_ENABLE, |
415 | AR5K_QUEUE_RDYTIMECFG(queue)); | 391 | AR5K_QUEUE_RDYTIMECFG(queue)); |
416 | 392 | ||
417 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), | 393 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), |
418 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << | 394 | (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << |
419 | AR5K_DCU_MISC_ARBLOCK_CTL_S)); | 395 | AR5K_DCU_MISC_ARBLOCK_CTL_S)); |
420 | break; | 396 | break; |
421 | 397 | ||
422 | case AR5K_TX_QUEUE_UAPSD: | 398 | case AR5K_TX_QUEUE_UAPSD: |
423 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), | 399 | AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), |
424 | AR5K_QCU_MISC_CBREXP_DIS); | 400 | AR5K_QCU_MISC_CBREXP_DIS); |
425 | break; | 401 | break; |
426 | 402 | ||
427 | case AR5K_TX_QUEUE_DATA: | 403 | case AR5K_TX_QUEUE_DATA: |
428 | default: | 404 | default: |
429 | break; | 405 | break; |
430 | } | ||
431 | |||
432 | /* TODO: Handle frame compression */ | ||
433 | |||
434 | /* | ||
435 | * Enable interrupts for this tx queue | ||
436 | * in the secondary interrupt mask registers | ||
437 | */ | ||
438 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) | ||
439 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); | ||
440 | |||
441 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) | ||
442 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); | ||
443 | |||
444 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) | ||
445 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); | ||
446 | |||
447 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) | ||
448 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); | ||
449 | |||
450 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) | ||
451 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); | ||
452 | |||
453 | if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) | ||
454 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); | ||
455 | |||
456 | if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) | ||
457 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); | ||
458 | |||
459 | if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) | ||
460 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); | ||
461 | |||
462 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) | ||
463 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); | ||
464 | |||
465 | /* Update secondary interrupt mask registers */ | ||
466 | |||
467 | /* Filter out inactive queues */ | ||
468 | ah->ah_txq_imr_txok &= ah->ah_txq_status; | ||
469 | ah->ah_txq_imr_txerr &= ah->ah_txq_status; | ||
470 | ah->ah_txq_imr_txurn &= ah->ah_txq_status; | ||
471 | ah->ah_txq_imr_txdesc &= ah->ah_txq_status; | ||
472 | ah->ah_txq_imr_txeol &= ah->ah_txq_status; | ||
473 | ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; | ||
474 | ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; | ||
475 | ah->ah_txq_imr_qtrig &= ah->ah_txq_status; | ||
476 | ah->ah_txq_imr_nofrm &= ah->ah_txq_status; | ||
477 | |||
478 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, | ||
479 | AR5K_SIMR0_QCU_TXOK) | | ||
480 | AR5K_REG_SM(ah->ah_txq_imr_txdesc, | ||
481 | AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); | ||
482 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, | ||
483 | AR5K_SIMR1_QCU_TXERR) | | ||
484 | AR5K_REG_SM(ah->ah_txq_imr_txeol, | ||
485 | AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); | ||
486 | /* Update simr2 but don't overwrite rest simr2 settings */ | ||
487 | AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); | ||
488 | AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, | ||
489 | AR5K_REG_SM(ah->ah_txq_imr_txurn, | ||
490 | AR5K_SIMR2_QCU_TXURN)); | ||
491 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, | ||
492 | AR5K_SIMR3_QCBRORN) | | ||
493 | AR5K_REG_SM(ah->ah_txq_imr_cbrurn, | ||
494 | AR5K_SIMR3_QCBRURN), AR5K_SIMR3); | ||
495 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, | ||
496 | AR5K_SIMR4_QTRIG), AR5K_SIMR4); | ||
497 | /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ | ||
498 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, | ||
499 | AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); | ||
500 | /* No queue has TXNOFRM enabled, disable the interrupt | ||
501 | * by setting AR5K_TXNOFRM to zero */ | ||
502 | if (ah->ah_txq_imr_nofrm == 0) | ||
503 | ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); | ||
504 | |||
505 | /* Set QCU mask for this DCU to save power */ | ||
506 | AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); | ||
507 | } | 406 | } |
508 | 407 | ||
408 | /* TODO: Handle frame compression */ | ||
409 | |||
410 | /* | ||
411 | * Enable interrupts for this tx queue | ||
412 | * in the secondary interrupt mask registers | ||
413 | */ | ||
414 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) | ||
415 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); | ||
416 | |||
417 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) | ||
418 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); | ||
419 | |||
420 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) | ||
421 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); | ||
422 | |||
423 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) | ||
424 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); | ||
425 | |||
426 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) | ||
427 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); | ||
428 | |||
429 | if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) | ||
430 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); | ||
431 | |||
432 | if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) | ||
433 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); | ||
434 | |||
435 | if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) | ||
436 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); | ||
437 | |||
438 | if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) | ||
439 | AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); | ||
440 | |||
441 | /* Update secondary interrupt mask registers */ | ||
442 | |||
443 | /* Filter out inactive queues */ | ||
444 | ah->ah_txq_imr_txok &= ah->ah_txq_status; | ||
445 | ah->ah_txq_imr_txerr &= ah->ah_txq_status; | ||
446 | ah->ah_txq_imr_txurn &= ah->ah_txq_status; | ||
447 | ah->ah_txq_imr_txdesc &= ah->ah_txq_status; | ||
448 | ah->ah_txq_imr_txeol &= ah->ah_txq_status; | ||
449 | ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; | ||
450 | ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; | ||
451 | ah->ah_txq_imr_qtrig &= ah->ah_txq_status; | ||
452 | ah->ah_txq_imr_nofrm &= ah->ah_txq_status; | ||
453 | |||
454 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, | ||
455 | AR5K_SIMR0_QCU_TXOK) | | ||
456 | AR5K_REG_SM(ah->ah_txq_imr_txdesc, | ||
457 | AR5K_SIMR0_QCU_TXDESC), | ||
458 | AR5K_SIMR0); | ||
459 | |||
460 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, | ||
461 | AR5K_SIMR1_QCU_TXERR) | | ||
462 | AR5K_REG_SM(ah->ah_txq_imr_txeol, | ||
463 | AR5K_SIMR1_QCU_TXEOL), | ||
464 | AR5K_SIMR1); | ||
465 | |||
466 | /* Update SIMR2 but don't overwrite rest simr2 settings */ | ||
467 | AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); | ||
468 | AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, | ||
469 | AR5K_REG_SM(ah->ah_txq_imr_txurn, | ||
470 | AR5K_SIMR2_QCU_TXURN)); | ||
471 | |||
472 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, | ||
473 | AR5K_SIMR3_QCBRORN) | | ||
474 | AR5K_REG_SM(ah->ah_txq_imr_cbrurn, | ||
475 | AR5K_SIMR3_QCBRURN), | ||
476 | AR5K_SIMR3); | ||
477 | |||
478 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, | ||
479 | AR5K_SIMR4_QTRIG), AR5K_SIMR4); | ||
480 | |||
481 | /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ | ||
482 | ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, | ||
483 | AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); | ||
484 | |||
485 | /* No queue has TXNOFRM enabled, disable the interrupt | ||
486 | * by setting AR5K_TXNOFRM to zero */ | ||
487 | if (ah->ah_txq_imr_nofrm == 0) | ||
488 | ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); | ||
489 | |||
490 | /* Set QCU mask for this DCU to save power */ | ||
491 | AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); | ||
492 | |||
509 | return 0; | 493 | return 0; |
510 | } | 494 | } |
511 | 495 | ||
512 | /* | 496 | |
513 | * Set slot time on DCU | 497 | /**************************\ |
498 | * Global QCU/DCU functions * | ||
499 | \**************************/ | ||
500 | |||
501 | /** | ||
502 | * ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU | ||
503 | * | ||
504 | * @ah The &struct ath5k_hw | ||
505 | * @slot_time Slot time in us | ||
506 | * | ||
507 | * Sets the global IFS intervals on DCU (also works on AR5210) for | ||
508 | * the given slot time and the current bwmode. | ||
514 | */ | 509 | */ |
515 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | 510 | int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time) |
516 | { | 511 | { |
512 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
513 | struct ath5k_softc *sc = ah->ah_sc; | ||
514 | struct ieee80211_rate *rate; | ||
515 | u32 ack_tx_time, eifs, eifs_clock, sifs, sifs_clock; | ||
517 | u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); | 516 | u32 slot_time_clock = ath5k_hw_htoclock(ah, slot_time); |
518 | 517 | ||
519 | if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) | 518 | if (slot_time < 6 || slot_time_clock > AR5K_SLOT_TIME_MAX) |
520 | return -EINVAL; | 519 | return -EINVAL; |
521 | 520 | ||
522 | if (ah->ah_version == AR5K_AR5210) | 521 | sifs = ath5k_hw_get_default_sifs(ah); |
523 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); | 522 | sifs_clock = ath5k_hw_htoclock(ah, sifs - 2); |
523 | |||
524 | /* EIFS | ||
525 | * Txtime of ack at lowest rate + SIFS + DIFS | ||
526 | * (DIFS = SIFS + 2 * Slot time) | ||
527 | * | ||
528 | * Note: HAL has some predefined values for EIFS | ||
529 | * Turbo: (37 + 2 * 6) | ||
530 | * Default: (74 + 2 * 9) | ||
531 | * Half: (149 + 2 * 13) | ||
532 | * Quarter: (298 + 2 * 21) | ||
533 | * | ||
534 | * (74 + 2 * 6) for AR5210 default and turbo ! | ||
535 | * | ||
536 | * According to the formula we have | ||
537 | * ack_tx_time = 25 for turbo and | ||
538 | * ack_tx_time = 42.5 * clock multiplier | ||
539 | * for default/half/quarter. | ||
540 | * | ||
541 | * This can't be right, 42 is what we would get | ||
542 | * from ath5k_hw_get_frame_dur_for_bwmode or | ||
543 | * ieee80211_generic_frame_duration for zero frame | ||
544 | * length and without SIFS ! | ||
545 | * | ||
546 | * Also we have different lowest rate for 802.11a | ||
547 | */ | ||
548 | if (channel->hw_value & CHANNEL_5GHZ) | ||
549 | rate = &sc->sbands[IEEE80211_BAND_5GHZ].bitrates[0]; | ||
524 | else | 550 | else |
525 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); | 551 | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; |
552 | |||
553 | ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); | ||
554 | |||
555 | /* ack_tx_time includes an SIFS already */ | ||
556 | eifs = ack_tx_time + sifs + 2 * slot_time; | ||
557 | eifs_clock = ath5k_hw_htoclock(ah, eifs); | ||
558 | |||
559 | /* Set IFS settings on AR5210 */ | ||
560 | if (ah->ah_version == AR5K_AR5210) { | ||
561 | u32 pifs, pifs_clock, difs, difs_clock; | ||
562 | |||
563 | /* Set slot time */ | ||
564 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_SLOT_TIME); | ||
565 | |||
566 | /* Set EIFS */ | ||
567 | eifs_clock = AR5K_REG_SM(eifs_clock, AR5K_IFS1_EIFS); | ||
568 | |||
569 | /* PIFS = Slot time + SIFS */ | ||
570 | pifs = slot_time + sifs; | ||
571 | pifs_clock = ath5k_hw_htoclock(ah, pifs); | ||
572 | pifs_clock = AR5K_REG_SM(pifs_clock, AR5K_IFS1_PIFS); | ||
573 | |||
574 | /* DIFS = SIFS + 2 * Slot time */ | ||
575 | difs = sifs + 2 * slot_time; | ||
576 | difs_clock = ath5k_hw_htoclock(ah, difs); | ||
577 | |||
578 | /* Set SIFS/DIFS */ | ||
579 | ath5k_hw_reg_write(ah, (difs_clock << | ||
580 | AR5K_IFS0_DIFS_S) | sifs_clock, | ||
581 | AR5K_IFS0); | ||
582 | |||
583 | /* Set PIFS/EIFS and preserve AR5K_INIT_CARR_SENSE_EN */ | ||
584 | ath5k_hw_reg_write(ah, pifs_clock | eifs_clock | | ||
585 | (AR5K_INIT_CARR_SENSE_EN << AR5K_IFS1_CS_EN_S), | ||
586 | AR5K_IFS1); | ||
587 | |||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | /* Set IFS slot time */ | ||
592 | ath5k_hw_reg_write(ah, slot_time_clock, AR5K_DCU_GBL_IFS_SLOT); | ||
593 | |||
594 | /* Set EIFS interval */ | ||
595 | ath5k_hw_reg_write(ah, eifs_clock, AR5K_DCU_GBL_IFS_EIFS); | ||
596 | |||
597 | /* Set SIFS interval in usecs */ | ||
598 | AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, | ||
599 | AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC, | ||
600 | sifs); | ||
601 | |||
602 | /* Set SIFS interval in clock cycles */ | ||
603 | ath5k_hw_reg_write(ah, sifs_clock, AR5K_DCU_GBL_IFS_SIFS); | ||
526 | 604 | ||
527 | return 0; | 605 | return 0; |
528 | } | 606 | } |
529 | 607 | ||
608 | |||
609 | int ath5k_hw_init_queues(struct ath5k_hw *ah) | ||
610 | { | ||
611 | int i, ret; | ||
612 | |||
613 | /* TODO: HW Compression support for data queues */ | ||
614 | /* TODO: Burst prefetch for data queues */ | ||
615 | |||
616 | /* | ||
617 | * Reset queues and start beacon timers at the end of the reset routine | ||
618 | * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping | ||
619 | * Note: If we want we can assign multiple qcus on one dcu. | ||
620 | */ | ||
621 | if (ah->ah_version != AR5K_AR5210) | ||
622 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { | ||
623 | ret = ath5k_hw_reset_tx_queue(ah, i); | ||
624 | if (ret) { | ||
625 | ATH5K_ERR(ah->ah_sc, | ||
626 | "failed to reset TX queue #%d\n", i); | ||
627 | return ret; | ||
628 | } | ||
629 | } | ||
630 | else | ||
631 | /* No QCU/DCU on AR5210, just set tx | ||
632 | * retry limits. We set IFS parameters | ||
633 | * on ath5k_hw_set_ifs_intervals */ | ||
634 | ath5k_hw_set_tx_retry_limits(ah, 0); | ||
635 | |||
636 | /* Set the turbo flag when operating on 40MHz */ | ||
637 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) | ||
638 | AR5K_REG_ENABLE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, | ||
639 | AR5K_DCU_GBL_IFS_MISC_TURBO_MODE); | ||
640 | |||
641 | /* If we didn't set IFS timings through | ||
642 | * ath5k_hw_set_coverage_class make sure | ||
643 | * we set them here */ | ||
644 | if (!ah->ah_coverage_class) { | ||
645 | unsigned int slot_time = ath5k_hw_get_default_slottime(ah); | ||
646 | ath5k_hw_set_ifs_intervals(ah, slot_time); | ||
647 | } | ||
648 | |||
649 | return 0; | ||
650 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 55b4ac6d236f..d12b827033c1 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -26,7 +26,6 @@ | |||
26 | * Atheros presentations and papers like these: | 26 | * Atheros presentations and papers like these: |
27 | * | 27 | * |
28 | * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf | 28 | * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf |
29 | * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf | ||
30 | * | 29 | * |
31 | * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf | 30 | * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf |
32 | * | 31 | * |
@@ -133,8 +132,8 @@ | |||
133 | * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR | 132 | * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR |
134 | * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning | 133 | * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning |
135 | * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR). | 134 | * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR). |
136 | * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i | 135 | * So SNAPPEDBCRVALID should also stand for "snapped BCR -values- valid", so i |
137 | * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what | 136 | * renamed it to SNAPSHOTSVALID to make more sense. I really have no idea what |
138 | * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR. | 137 | * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR. |
139 | */ | 138 | */ |
140 | #define AR5K_BSR 0x002c /* Register Address */ | 139 | #define AR5K_BSR 0x002c /* Register Address */ |
@@ -284,7 +283,7 @@ | |||
284 | */ | 283 | */ |
285 | #define AR5K_ISR 0x001c /* Register Address [5210] */ | 284 | #define AR5K_ISR 0x001c /* Register Address [5210] */ |
286 | #define AR5K_PISR 0x0080 /* Register Address [5211+] */ | 285 | #define AR5K_PISR 0x0080 /* Register Address [5211+] */ |
287 | #define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */ | 286 | #define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly received */ |
288 | #define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */ | 287 | #define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */ |
289 | #define AR5K_ISR_RXERR 0x00000004 /* Receive error */ | 288 | #define AR5K_ISR_RXERR 0x00000004 /* Receive error */ |
290 | #define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */ | 289 | #define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */ |
@@ -373,12 +372,12 @@ | |||
373 | /* | 372 | /* |
374 | * Interrupt Mask Registers | 373 | * Interrupt Mask Registers |
375 | * | 374 | * |
376 | * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary | 375 | * As with ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary |
377 | * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match. | 376 | * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match. |
378 | */ | 377 | */ |
379 | #define AR5K_IMR 0x0020 /* Register Address [5210] */ | 378 | #define AR5K_IMR 0x0020 /* Register Address [5210] */ |
380 | #define AR5K_PIMR 0x00a0 /* Register Address [5211+] */ | 379 | #define AR5K_PIMR 0x00a0 /* Register Address [5211+] */ |
381 | #define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/ | 380 | #define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly received*/ |
382 | #define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/ | 381 | #define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/ |
383 | #define AR5K_IMR_RXERR 0x00000004 /* Receive error*/ | 382 | #define AR5K_IMR_RXERR 0x00000004 /* Receive error*/ |
384 | #define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/ | 383 | #define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/ |
@@ -687,16 +686,15 @@ | |||
687 | 686 | ||
688 | /* | 687 | /* |
689 | * DCU retry limit registers | 688 | * DCU retry limit registers |
689 | * all these fields don't allow zero values | ||
690 | */ | 690 | */ |
691 | #define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */ | 691 | #define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */ |
692 | #define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ | 692 | #define AR5K_DCU_RETRY_LMT_RTS 0x0000000f /* RTS failure limit. Transmission fails if no CTS is received for this number of times */ |
693 | #define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0 | 693 | #define AR5K_DCU_RETRY_LMT_RTS_S 0 |
694 | #define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */ | 694 | #define AR5K_DCU_RETRY_LMT_STA_RTS 0x00003f00 /* STA RTS failure limit. If exceeded CW reset */ |
695 | #define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4 | 695 | #define AR5K_DCU_RETRY_LMT_STA_RTS_S 8 |
696 | #define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */ | 696 | #define AR5K_DCU_RETRY_LMT_STA_DATA 0x000fc000 /* STA data failure limit. If exceeded CW reset. */ |
697 | #define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8 | 697 | #define AR5K_DCU_RETRY_LMT_STA_DATA_S 14 |
698 | #define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */ | ||
699 | #define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14 | ||
700 | #define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q) | 698 | #define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q) |
701 | 699 | ||
702 | /* | 700 | /* |
@@ -788,6 +786,7 @@ | |||
788 | #define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */ | 786 | #define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */ |
789 | #define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */ | 787 | #define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */ |
790 | #define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */ | 788 | #define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */ |
789 | #define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC_S 4 | ||
791 | #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */ | 790 | #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */ |
792 | #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10 | 791 | #define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10 |
793 | #define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */ | 792 | #define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */ |
@@ -896,7 +895,7 @@ | |||
896 | #define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */ | 895 | #define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */ |
897 | #define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */ | 896 | #define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */ |
898 | #define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */ | 897 | #define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */ |
899 | #define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/ | 898 | #define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even with pending interrupts*/ |
900 | #define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */ | 899 | #define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */ |
901 | #define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */ | 900 | #define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */ |
902 | #define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */ | 901 | #define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */ |
@@ -1064,7 +1063,7 @@ | |||
1064 | /* | 1063 | /* |
1065 | * EEPROM command register | 1064 | * EEPROM command register |
1066 | */ | 1065 | */ |
1067 | #define AR5K_EEPROM_CMD 0x6008 /* Register Addres */ | 1066 | #define AR5K_EEPROM_CMD 0x6008 /* Register Address */ |
1068 | #define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */ | 1067 | #define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */ |
1069 | #define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */ | 1068 | #define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */ |
1070 | #define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */ | 1069 | #define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */ |
@@ -1084,7 +1083,7 @@ | |||
1084 | /* | 1083 | /* |
1085 | * EEPROM config register | 1084 | * EEPROM config register |
1086 | */ | 1085 | */ |
1087 | #define AR5K_EEPROM_CFG 0x6010 /* Register Addres */ | 1086 | #define AR5K_EEPROM_CFG 0x6010 /* Register Address */ |
1088 | #define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */ | 1087 | #define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */ |
1089 | #define AR5K_EEPROM_CFG_SIZE_AUTO 0 | 1088 | #define AR5K_EEPROM_CFG_SIZE_AUTO 0 |
1090 | #define AR5K_EEPROM_CFG_SIZE_4KBIT 1 | 1089 | #define AR5K_EEPROM_CFG_SIZE_4KBIT 1 |
@@ -1126,7 +1125,7 @@ | |||
1126 | * Second station id register (Upper 16 bits of MAC address + PCU settings) | 1125 | * Second station id register (Upper 16 bits of MAC address + PCU settings) |
1127 | */ | 1126 | */ |
1128 | #define AR5K_STA_ID1 0x8004 /* Register Address */ | 1127 | #define AR5K_STA_ID1 0x8004 /* Register Address */ |
1129 | #define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */ | 1128 | #define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC address */ |
1130 | #define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ | 1129 | #define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ |
1131 | #define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ | 1130 | #define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ |
1132 | #define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ | 1131 | #define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ |
@@ -1312,7 +1311,7 @@ | |||
1312 | #define AR5K_IFS1_EIFS 0x03fff000 | 1311 | #define AR5K_IFS1_EIFS 0x03fff000 |
1313 | #define AR5K_IFS1_EIFS_S 12 | 1312 | #define AR5K_IFS1_EIFS_S 12 |
1314 | #define AR5K_IFS1_CS_EN 0x04000000 | 1313 | #define AR5K_IFS1_CS_EN 0x04000000 |
1315 | 1314 | #define AR5K_IFS1_CS_EN_S 26 | |
1316 | 1315 | ||
1317 | /* | 1316 | /* |
1318 | * CFP duration register | 1317 | * CFP duration register |
@@ -1387,10 +1386,9 @@ | |||
1387 | 1386 | ||
1388 | 1387 | ||
1389 | /* | 1388 | /* |
1390 | * PCU control register | 1389 | * PCU Diagnostic register |
1391 | * | 1390 | * |
1392 | * Only DIS_RX is used in the code, the rest i guess are | 1391 | * Used for tweaking/diagnostics. |
1393 | * for tweaking/diagnostics. | ||
1394 | */ | 1392 | */ |
1395 | #define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */ | 1393 | #define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */ |
1396 | #define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */ | 1394 | #define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */ |
@@ -1399,22 +1397,22 @@ | |||
1399 | #define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */ | 1397 | #define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */ |
1400 | #define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */ | 1398 | #define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */ |
1401 | #define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */ | 1399 | #define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */ |
1402 | #define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */ | 1400 | #define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable HW encryption */ |
1403 | #define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */ | 1401 | #define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable HW decryption */ |
1404 | #define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */ | 1402 | #define AR5K_DIAG_SW_DIS_TX_5210 0x00000020 /* Disable transmit [5210] */ |
1405 | #define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */ | 1403 | #define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable receive */ |
1406 | #define AR5K_DIAG_SW_DIS_RX_5211 0x00000020 | 1404 | #define AR5K_DIAG_SW_DIS_RX_5211 0x00000020 |
1407 | #define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \ | 1405 | #define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \ |
1408 | AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211) | 1406 | AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211) |
1409 | #define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */ | 1407 | #define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* TX Data Loopback (i guess it goes with DIS_TX) [5210] */ |
1410 | #define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040 | 1408 | #define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040 |
1411 | #define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \ | 1409 | #define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \ |
1412 | AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211) | 1410 | AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211) |
1413 | #define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */ | 1411 | #define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Generate invalid TX FCS */ |
1414 | #define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080 | 1412 | #define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080 |
1415 | #define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \ | 1413 | #define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \ |
1416 | AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211) | 1414 | AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211) |
1417 | #define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */ | 1415 | #define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Add 56 bytes of channel info before the frame data in the RX buffer */ |
1418 | #define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100 | 1416 | #define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100 |
1419 | #define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ | 1417 | #define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ |
1420 | AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) | 1418 | AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) |
@@ -1426,17 +1424,17 @@ | |||
1426 | #define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */ | 1424 | #define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */ |
1427 | #define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */ | 1425 | #define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */ |
1428 | #define AR5K_DIAG_SW_SCRAM_SEED_S 10 | 1426 | #define AR5K_DIAG_SW_SCRAM_SEED_S 10 |
1429 | #define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */ | 1427 | #define AR5K_DIAG_SW_DIS_SEQ_INC_5210 0x00040000 /* Disable seqnum increment (?)[5210] */ |
1430 | #define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000 | 1428 | #define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000 |
1431 | #define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */ | 1429 | #define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */ |
1432 | #define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \ | 1430 | #define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \ |
1433 | AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) | 1431 | AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) |
1434 | #define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */ | 1432 | #define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */ |
1435 | #define AR5K_DIAG_SW_OBSPT_S 18 | 1433 | #define AR5K_DIAG_SW_OBSPT_S 18 |
1436 | #define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ | 1434 | #define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x00100000 /* Ignore carrier sense */ |
1437 | #define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ | 1435 | #define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x00200000 /* Ignore virtual carrier sense */ |
1438 | #define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */ | 1436 | #define AR5K_DIAG_SW_CHANNEL_IDLE_HIGH 0x00400000 /* Force channel idle high */ |
1439 | #define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ | 1437 | #define AR5K_DIAG_SW_PHEAR_ME 0x00800000 /* ??? */ |
1440 | 1438 | ||
1441 | /* | 1439 | /* |
1442 | * TSF (clock) register (lower 32 bits) | 1440 | * TSF (clock) register (lower 32 bits) |
@@ -1822,50 +1820,8 @@ | |||
1822 | 1820 | ||
1823 | /*===5212 end===*/ | 1821 | /*===5212 end===*/ |
1824 | 1822 | ||
1825 | /* | ||
1826 | * Key table (WEP) register | ||
1827 | */ | ||
1828 | #define AR5K_KEYTABLE_0_5210 0x9000 | ||
1829 | #define AR5K_KEYTABLE_0_5211 0x8800 | ||
1830 | #define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5)) | ||
1831 | #define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5)) | ||
1832 | #define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \ | ||
1833 | AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n)) | ||
1834 | #define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2)) | ||
1835 | #define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5) | ||
1836 | #define AR5K_KEYTABLE_TYPE_40 0x00000000 | ||
1837 | #define AR5K_KEYTABLE_TYPE_104 0x00000001 | ||
1838 | #define AR5K_KEYTABLE_TYPE_128 0x00000003 | ||
1839 | #define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */ | ||
1840 | #define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */ | ||
1841 | #define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */ | ||
1842 | #define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */ | ||
1843 | #define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */ | ||
1844 | #define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6) | ||
1845 | #define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7) | ||
1846 | #define AR5K_KEYTABLE_VALID 0x00008000 | ||
1847 | |||
1848 | /* If key type is TKIP and MIC is enabled | ||
1849 | * MIC key goes in offset entry + 64 */ | ||
1850 | #define AR5K_KEYTABLE_MIC_OFFSET 64 | ||
1851 | |||
1852 | /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit | ||
1853 | * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit | ||
1854 | * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit | ||
1855 | * | ||
1856 | * Some vendors have introduced bigger WEP keys to address | ||
1857 | * security vulnerabilities in WEP. This includes: | ||
1858 | * | ||
1859 | * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit | ||
1860 | * | ||
1861 | * We can expand this if we find ar5k Atheros cards with a larger | ||
1862 | * key table size. | ||
1863 | */ | ||
1864 | #define AR5K_KEYTABLE_SIZE_5210 64 | 1823 | #define AR5K_KEYTABLE_SIZE_5210 64 |
1865 | #define AR5K_KEYTABLE_SIZE_5211 128 | 1824 | #define AR5K_KEYTABLE_SIZE_5211 128 |
1866 | #define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \ | ||
1867 | AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211) | ||
1868 | |||
1869 | 1825 | ||
1870 | /*===PHY REGISTERS===*/ | 1826 | /*===PHY REGISTERS===*/ |
1871 | 1827 | ||
@@ -1911,7 +1867,7 @@ | |||
1911 | #define AR5K_PHY_TURBO 0x9804 /* Register Address */ | 1867 | #define AR5K_PHY_TURBO 0x9804 /* Register Address */ |
1912 | #define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ | 1868 | #define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ |
1913 | #define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ | 1869 | #define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ |
1914 | #define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */ | 1870 | #define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo */ |
1915 | 1871 | ||
1916 | /* | 1872 | /* |
1917 | * PHY agility command register | 1873 | * PHY agility command register |
@@ -2102,6 +2058,7 @@ | |||
2102 | 2058 | ||
2103 | #define AR5K_PHY_SCAL 0x9878 | 2059 | #define AR5K_PHY_SCAL 0x9878 |
2104 | #define AR5K_PHY_SCAL_32MHZ 0x0000000e | 2060 | #define AR5K_PHY_SCAL_32MHZ 0x0000000e |
2061 | #define AR5K_PHY_SCAL_32MHZ_5311 0x00000008 | ||
2105 | #define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a | 2062 | #define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a |
2106 | #define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032 | 2063 | #define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032 |
2107 | 2064 | ||
@@ -2288,6 +2245,8 @@ | |||
2288 | #define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \ | 2245 | #define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \ |
2289 | AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211) | 2246 | AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211) |
2290 | /*---[5111+]---*/ | 2247 | /*---[5111+]---*/ |
2248 | #define AR5K_PHY_FRAME_CTL_WIN_LEN 0x00000003 /* Force window length (?) */ | ||
2249 | #define AR5K_PHY_FRAME_CTL_WIN_LEN_S 0 | ||
2291 | #define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */ | 2250 | #define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */ |
2292 | #define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 | 2251 | #define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 |
2293 | #define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */ | 2252 | #define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */ |
@@ -2602,3 +2561,28 @@ | |||
2602 | */ | 2561 | */ |
2603 | #define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280 | 2562 | #define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280 |
2604 | #define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2)) | 2563 | #define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2)) |
2564 | |||
2565 | /* | ||
2566 | * Platform registers for WiSoC | ||
2567 | */ | ||
2568 | #define AR5K_AR5312_RESET 0xbc003020 | ||
2569 | #define AR5K_AR5312_RESET_BB0_COLD 0x00000004 | ||
2570 | #define AR5K_AR5312_RESET_BB1_COLD 0x00000200 | ||
2571 | #define AR5K_AR5312_RESET_WMAC0 0x00002000 | ||
2572 | #define AR5K_AR5312_RESET_BB0_WARM 0x00004000 | ||
2573 | #define AR5K_AR5312_RESET_WMAC1 0x00020000 | ||
2574 | #define AR5K_AR5312_RESET_BB1_WARM 0x00040000 | ||
2575 | |||
2576 | #define AR5K_AR5312_ENABLE 0xbc003080 | ||
2577 | #define AR5K_AR5312_ENABLE_WLAN0 0x00000001 | ||
2578 | #define AR5K_AR5312_ENABLE_WLAN1 0x00000008 | ||
2579 | |||
2580 | #define AR5K_AR2315_RESET 0xb1000004 | ||
2581 | #define AR5K_AR2315_RESET_WMAC 0x00000001 | ||
2582 | #define AR5K_AR2315_RESET_BB_WARM 0x00000002 | ||
2583 | |||
2584 | #define AR5K_AR2315_AHB_ARB_CTL 0xb1000008 | ||
2585 | #define AR5K_AR2315_AHB_ARB_CTL_WLAN 0x00000002 | ||
2586 | |||
2587 | #define AR5K_AR2315_BYTESWAP 0xb100000c | ||
2588 | #define AR5K_AR2315_BYTESWAP_WMAC 0x00000002 | ||
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 498aa28ea9e6..126a4eab35f3 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -27,11 +27,17 @@ | |||
27 | 27 | ||
28 | #include <linux/pci.h> /* To determine if a card is pci-e */ | 28 | #include <linux/pci.h> /* To determine if a card is pci-e */ |
29 | #include <linux/log2.h> | 29 | #include <linux/log2.h> |
30 | #include <linux/platform_device.h> | ||
30 | #include "ath5k.h" | 31 | #include "ath5k.h" |
31 | #include "reg.h" | 32 | #include "reg.h" |
32 | #include "base.h" | 33 | #include "base.h" |
33 | #include "debug.h" | 34 | #include "debug.h" |
34 | 35 | ||
36 | |||
37 | /******************\ | ||
38 | * Helper functions * | ||
39 | \******************/ | ||
40 | |||
35 | /* | 41 | /* |
36 | * Check if a register write has been completed | 42 | * Check if a register write has been completed |
37 | */ | 43 | */ |
@@ -53,146 +59,272 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | |||
53 | return (i <= 0) ? -EAGAIN : 0; | 59 | return (i <= 0) ? -EAGAIN : 0; |
54 | } | 60 | } |
55 | 61 | ||
62 | |||
63 | /*************************\ | ||
64 | * Clock related functions * | ||
65 | \*************************/ | ||
66 | |||
56 | /** | 67 | /** |
57 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | 68 | * ath5k_hw_htoclock - Translate usec to hw clock units |
58 | * | 69 | * |
59 | * @ah: the &struct ath5k_hw | 70 | * @ah: The &struct ath5k_hw |
60 | * @channel: the currently set channel upon reset | 71 | * @usec: value in microseconds |
61 | * | 72 | */ |
62 | * Write the delta slope coefficient (used on pilot tracking ?) for OFDM | 73 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) |
63 | * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset(). | 74 | { |
75 | struct ath_common *common = ath5k_hw_common(ah); | ||
76 | return usec * common->clockrate; | ||
77 | } | ||
78 | |||
79 | /** | ||
80 | * ath5k_hw_clocktoh - Translate hw clock units to usec | ||
81 | * @clock: value in hw clock units | ||
82 | */ | ||
83 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | ||
84 | { | ||
85 | struct ath_common *common = ath5k_hw_common(ah); | ||
86 | return clock / common->clockrate; | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * ath5k_hw_init_core_clock - Initialize core clock | ||
64 | * | 91 | * |
65 | * Since delta slope is floating point we split it on its exponent and | 92 | * @ah The &struct ath5k_hw |
66 | * mantissa and provide these values on hw. | ||
67 | * | 93 | * |
68 | * For more infos i think this patent is related | 94 | * Initialize core clock parameters (usec, usec32, latencies etc). |
69 | * http://www.freepatentsonline.com/7184495.html | ||
70 | */ | 95 | */ |
71 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | 96 | static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) |
72 | struct ieee80211_channel *channel) | ||
73 | { | 97 | { |
74 | /* Get exponent and mantissa and set it */ | 98 | struct ieee80211_channel *channel = ah->ah_current_channel; |
75 | u32 coef_scaled, coef_exp, coef_man, | 99 | struct ath_common *common = ath5k_hw_common(ah); |
76 | ds_coef_exp, ds_coef_man, clock; | 100 | u32 usec_reg, txlat, rxlat, usec, clock, sclock, txf2txs; |
77 | |||
78 | BUG_ON(!(ah->ah_version == AR5K_AR5212) || | ||
79 | !(channel->hw_value & CHANNEL_OFDM)); | ||
80 | |||
81 | /* Get coefficient | ||
82 | * ALGO: coef = (5 * clock / carrier_freq) / 2 | ||
83 | * we scale coef by shifting clock value by 24 for | ||
84 | * better precision since we use integers */ | ||
85 | /* TODO: Half/quarter rate */ | ||
86 | clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; | ||
87 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; | ||
88 | |||
89 | /* Get exponent | ||
90 | * ALGO: coef_exp = 14 - highest set bit position */ | ||
91 | coef_exp = ilog2(coef_scaled); | ||
92 | |||
93 | /* Doesn't make sense if it's zero*/ | ||
94 | if (!coef_scaled || !coef_exp) | ||
95 | return -EINVAL; | ||
96 | 101 | ||
97 | /* Note: we've shifted coef_scaled by 24 */ | 102 | /* |
98 | coef_exp = 14 - (coef_exp - 24); | 103 | * Set core clock frequency |
104 | */ | ||
105 | if (channel->hw_value & CHANNEL_5GHZ) | ||
106 | clock = 40; /* 802.11a */ | ||
107 | else if (channel->hw_value & CHANNEL_CCK) | ||
108 | clock = 22; /* 802.11b */ | ||
109 | else | ||
110 | clock = 44; /* 802.11g */ | ||
99 | 111 | ||
112 | /* Use clock multiplier for non-default | ||
113 | * bwmode */ | ||
114 | switch (ah->ah_bwmode) { | ||
115 | case AR5K_BWMODE_40MHZ: | ||
116 | clock *= 2; | ||
117 | break; | ||
118 | case AR5K_BWMODE_10MHZ: | ||
119 | clock /= 2; | ||
120 | break; | ||
121 | case AR5K_BWMODE_5MHZ: | ||
122 | clock /= 4; | ||
123 | break; | ||
124 | default: | ||
125 | break; | ||
126 | } | ||
127 | |||
128 | common->clockrate = clock; | ||
100 | 129 | ||
101 | /* Get mantissa (significant digits) | 130 | /* |
102 | * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ | 131 | * Set USEC parameters |
103 | coef_man = coef_scaled + | 132 | */ |
104 | (1 << (24 - coef_exp - 1)); | 133 | /* Set USEC counter on PCU*/ |
134 | usec = clock - 1; | ||
135 | usec = AR5K_REG_SM(usec, AR5K_USEC_1); | ||
105 | 136 | ||
106 | /* Calculate delta slope coefficient exponent | 137 | /* Set usec duration on DCU */ |
107 | * and mantissa (remove scaling) and set them on hw */ | 138 | if (ah->ah_version != AR5K_AR5210) |
108 | ds_coef_man = coef_man >> (24 - coef_exp); | 139 | AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, |
109 | ds_coef_exp = coef_exp - 16; | 140 | AR5K_DCU_GBL_IFS_MISC_USEC_DUR, |
141 | clock); | ||
110 | 142 | ||
111 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | 143 | /* Set 32MHz USEC counter */ |
112 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | 144 | if ((ah->ah_radio == AR5K_RF5112) || |
113 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | 145 | (ah->ah_radio == AR5K_RF5413) || |
114 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | 146 | (ah->ah_radio == AR5K_RF2316) || |
147 | (ah->ah_radio == AR5K_RF2317)) | ||
148 | /* Remain on 40MHz clock ? */ | ||
149 | sclock = 40 - 1; | ||
150 | else | ||
151 | sclock = 32 - 1; | ||
152 | sclock = AR5K_REG_SM(sclock, AR5K_USEC_32); | ||
115 | 153 | ||
116 | return 0; | 154 | /* |
117 | } | 155 | * Set tx/rx latencies |
156 | */ | ||
157 | usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); | ||
158 | txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211); | ||
159 | rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211); | ||
118 | 160 | ||
161 | /* | ||
162 | * Set default Tx frame to Tx data start delay | ||
163 | */ | ||
164 | txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; | ||
119 | 165 | ||
120 | /* | 166 | /* |
121 | * index into rates for control rates, we can set it up like this because | 167 | * 5210 initvals don't include usec settings |
122 | * this is only used for AR5212 and we know it supports G mode | 168 | * so we need to use magic values here for |
123 | */ | 169 | * tx/rx latencies |
124 | static const unsigned int control_rates[] = | 170 | */ |
125 | { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; | 171 | if (ah->ah_version == AR5K_AR5210) { |
172 | /* same for turbo */ | ||
173 | txlat = AR5K_INIT_TX_LATENCY_5210; | ||
174 | rxlat = AR5K_INIT_RX_LATENCY_5210; | ||
175 | } | ||
126 | 176 | ||
127 | /** | 177 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { |
128 | * ath5k_hw_write_rate_duration - fill rate code to duration table | 178 | /* 5311 has different tx/rx latency masks |
129 | * | 179 | * from 5211, since we deal 5311 the same |
130 | * @ah: the &struct ath5k_hw | 180 | * as 5211 when setting initvals, shift |
131 | * @mode: one of enum ath5k_driver_mode | 181 | * values here to their proper locations |
132 | * | 182 | * |
133 | * Write the rate code to duration table upon hw reset. This is a helper for | 183 | * Note: Initvals indicate tx/rx/ latencies |
134 | * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on | 184 | * are the same for turbo mode */ |
135 | * the hardware, based on current mode, for each rate. The rates which are | 185 | txlat = AR5K_REG_SM(txlat, AR5K_USEC_TX_LATENCY_5210); |
136 | * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have | 186 | rxlat = AR5K_REG_SM(rxlat, AR5K_USEC_RX_LATENCY_5210); |
137 | * different rate code so we write their value twice (one for long preample | 187 | } else |
138 | * and one for short). | 188 | switch (ah->ah_bwmode) { |
189 | case AR5K_BWMODE_10MHZ: | ||
190 | txlat = AR5K_REG_SM(txlat * 2, | ||
191 | AR5K_USEC_TX_LATENCY_5211); | ||
192 | rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX, | ||
193 | AR5K_USEC_RX_LATENCY_5211); | ||
194 | txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_10MHZ; | ||
195 | break; | ||
196 | case AR5K_BWMODE_5MHZ: | ||
197 | txlat = AR5K_REG_SM(txlat * 4, | ||
198 | AR5K_USEC_TX_LATENCY_5211); | ||
199 | rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX, | ||
200 | AR5K_USEC_RX_LATENCY_5211); | ||
201 | txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_5MHZ; | ||
202 | break; | ||
203 | case AR5K_BWMODE_40MHZ: | ||
204 | txlat = AR5K_INIT_TX_LAT_MIN; | ||
205 | rxlat = AR5K_REG_SM(rxlat / 2, | ||
206 | AR5K_USEC_RX_LATENCY_5211); | ||
207 | txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; | ||
208 | break; | ||
209 | default: | ||
210 | break; | ||
211 | } | ||
212 | |||
213 | usec_reg = (usec | sclock | txlat | rxlat); | ||
214 | ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC); | ||
215 | |||
216 | /* On 5112 set tx frane to tx data start delay */ | ||
217 | if (ah->ah_radio == AR5K_RF5112) { | ||
218 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2, | ||
219 | AR5K_PHY_RF_CTL2_TXF2TXD_START, | ||
220 | txf2txs); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * If there is an external 32KHz crystal available, use it | ||
226 | * as ref. clock instead of 32/40MHz clock and baseband clocks | ||
227 | * to save power during sleep or restore normal 32/40MHz | ||
228 | * operation. | ||
139 | * | 229 | * |
140 | * Note: Band doesn't matter here, if we set the values for OFDM it works | 230 | * XXX: When operating on 32KHz certain PHY registers (27 - 31, |
141 | * on both a and g modes. So all we have to do is set values for all g rates | 231 | * 123 - 127) require delay on access. |
142 | * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ | ||
143 | * quarter rate mode, we need to use another set of bitrates (that's why we | ||
144 | * need the mode parameter) but we don't handle these proprietary modes yet. | ||
145 | */ | 232 | */ |
146 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, | 233 | static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) |
147 | unsigned int mode) | ||
148 | { | 234 | { |
149 | struct ath5k_softc *sc = ah->ah_sc; | 235 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
150 | struct ieee80211_rate *rate; | 236 | u32 scal, spending; |
151 | unsigned int i; | 237 | |
238 | /* Only set 32KHz settings if we have an external | ||
239 | * 32KHz crystal present */ | ||
240 | if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || | ||
241 | AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && | ||
242 | enable) { | ||
152 | 243 | ||
153 | /* Write rate duration table */ | 244 | /* 1 usec/cycle */ |
154 | for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { | 245 | AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); |
155 | u32 reg; | 246 | /* Set up tsf increment on each cycle */ |
156 | u16 tx_time; | 247 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); |
157 | 248 | ||
158 | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; | 249 | /* Set baseband sleep control registers |
250 | * and sleep control rate */ | ||
251 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); | ||
159 | 252 | ||
160 | /* Set ACK timeout */ | 253 | if ((ah->ah_radio == AR5K_RF5112) || |
161 | reg = AR5K_RATE_DUR(rate->hw_value); | 254 | (ah->ah_radio == AR5K_RF5413) || |
255 | (ah->ah_radio == AR5K_RF2316) || | ||
256 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
257 | spending = 0x14; | ||
258 | else | ||
259 | spending = 0x18; | ||
260 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); | ||
162 | 261 | ||
163 | /* An ACK frame consists of 10 bytes. If you add the FCS, | 262 | if ((ah->ah_radio == AR5K_RF5112) || |
164 | * which ieee80211_generic_frame_duration() adds, | 263 | (ah->ah_radio == AR5K_RF5413) || |
165 | * its 14 bytes. Note we use the control rate and not the | 264 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { |
166 | * actual rate for this rate. See mac80211 tx.c | 265 | ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); |
167 | * ieee80211_duration() for a brief description of | 266 | ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); |
168 | * what rate we should choose to TX ACKs. */ | 267 | ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); |
169 | tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, | 268 | ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); |
170 | sc->vif, 10, rate)); | 269 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, |
270 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); | ||
271 | } else { | ||
272 | ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); | ||
273 | ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); | ||
274 | ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); | ||
275 | ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); | ||
276 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | ||
277 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); | ||
278 | } | ||
171 | 279 | ||
172 | ath5k_hw_reg_write(ah, tx_time, reg); | 280 | /* Enable sleep clock operation */ |
281 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, | ||
282 | AR5K_PCICFG_SLEEP_CLOCK_EN); | ||
173 | 283 | ||
174 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | 284 | } else { |
175 | continue; | ||
176 | 285 | ||
177 | /* | 286 | /* Disable sleep clock operation and |
178 | * We're not distinguishing short preamble here, | 287 | * restore default parameters */ |
179 | * This is true, all we'll get is a longer value here | 288 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, |
180 | * which is not necessarilly bad. We could use | 289 | AR5K_PCICFG_SLEEP_CLOCK_EN); |
181 | * export ieee80211_frame_duration() but that needs to be | 290 | |
182 | * fixed first to be properly used by mac802111 drivers: | 291 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, |
183 | * | 292 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); |
184 | * - remove erp stuff and let the routine figure ofdm | 293 | |
185 | * erp rates | 294 | /* Set DAC/ADC delays */ |
186 | * - remove passing argument ieee80211_local as | 295 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); |
187 | * drivers don't have access to it | 296 | ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); |
188 | * - move drivers using ieee80211_generic_frame_duration() | 297 | |
189 | * to this | 298 | if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) |
190 | */ | 299 | scal = AR5K_PHY_SCAL_32MHZ_2417; |
191 | ath5k_hw_reg_write(ah, tx_time, | 300 | else if (ee->ee_is_hb63) |
192 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | 301 | scal = AR5K_PHY_SCAL_32MHZ_HB63; |
302 | else | ||
303 | scal = AR5K_PHY_SCAL_32MHZ; | ||
304 | ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); | ||
305 | |||
306 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); | ||
307 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); | ||
308 | |||
309 | if ((ah->ah_radio == AR5K_RF5112) || | ||
310 | (ah->ah_radio == AR5K_RF5413) || | ||
311 | (ah->ah_radio == AR5K_RF2316) || | ||
312 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
313 | spending = 0x14; | ||
314 | else | ||
315 | spending = 0x18; | ||
316 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); | ||
317 | |||
318 | /* Set up tsf increment on each cycle */ | ||
319 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); | ||
193 | } | 320 | } |
194 | } | 321 | } |
195 | 322 | ||
323 | |||
324 | /*********************\ | ||
325 | * Reset/Sleep control * | ||
326 | \*********************/ | ||
327 | |||
196 | /* | 328 | /* |
197 | * Reset chipset | 329 | * Reset chipset |
198 | */ | 330 | */ |
@@ -236,6 +368,64 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |||
236 | } | 368 | } |
237 | 369 | ||
238 | /* | 370 | /* |
371 | * Reset AHB chipset | ||
372 | * AR5K_RESET_CTL_PCU flag resets WMAC | ||
373 | * AR5K_RESET_CTL_BASEBAND flag resets WBB | ||
374 | */ | ||
375 | static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | ||
376 | { | ||
377 | u32 mask = flags ? flags : ~0U; | ||
378 | volatile u32 *reg; | ||
379 | u32 regval; | ||
380 | u32 val = 0; | ||
381 | |||
382 | /* ah->ah_mac_srev is not available at this point yet */ | ||
383 | if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) { | ||
384 | reg = (u32 *) AR5K_AR2315_RESET; | ||
385 | if (mask & AR5K_RESET_CTL_PCU) | ||
386 | val |= AR5K_AR2315_RESET_WMAC; | ||
387 | if (mask & AR5K_RESET_CTL_BASEBAND) | ||
388 | val |= AR5K_AR2315_RESET_BB_WARM; | ||
389 | } else { | ||
390 | reg = (u32 *) AR5K_AR5312_RESET; | ||
391 | if (to_platform_device(ah->ah_sc->dev)->id == 0) { | ||
392 | if (mask & AR5K_RESET_CTL_PCU) | ||
393 | val |= AR5K_AR5312_RESET_WMAC0; | ||
394 | if (mask & AR5K_RESET_CTL_BASEBAND) | ||
395 | val |= AR5K_AR5312_RESET_BB0_COLD | | ||
396 | AR5K_AR5312_RESET_BB0_WARM; | ||
397 | } else { | ||
398 | if (mask & AR5K_RESET_CTL_PCU) | ||
399 | val |= AR5K_AR5312_RESET_WMAC1; | ||
400 | if (mask & AR5K_RESET_CTL_BASEBAND) | ||
401 | val |= AR5K_AR5312_RESET_BB1_COLD | | ||
402 | AR5K_AR5312_RESET_BB1_WARM; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | /* Put BB/MAC into reset */ | ||
407 | regval = __raw_readl(reg); | ||
408 | __raw_writel(regval | val, reg); | ||
409 | regval = __raw_readl(reg); | ||
410 | udelay(100); | ||
411 | |||
412 | /* Bring BB/MAC out of reset */ | ||
413 | __raw_writel(regval & ~val, reg); | ||
414 | regval = __raw_readl(reg); | ||
415 | |||
416 | /* | ||
417 | * Reset configuration register (for hw byte-swap). Note that this | ||
418 | * is only set for big endian. We do the necessary magic in | ||
419 | * AR5K_INIT_CFG. | ||
420 | */ | ||
421 | if ((flags & AR5K_RESET_CTL_PCU) == 0) | ||
422 | ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | |||
428 | /* | ||
239 | * Sleep control | 429 | * Sleep control |
240 | */ | 430 | */ |
241 | static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | 431 | static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, |
@@ -326,7 +516,7 @@ commit: | |||
326 | * register). After this MAC and Baseband are | 516 | * register). After this MAC and Baseband are |
327 | * disabled and a full reset is needed to come | 517 | * disabled and a full reset is needed to come |
328 | * back. This way we save as much power as possible | 518 | * back. This way we save as much power as possible |
329 | * without puting the card on full sleep. | 519 | * without putting the card on full sleep. |
330 | */ | 520 | */ |
331 | int ath5k_hw_on_hold(struct ath5k_hw *ah) | 521 | int ath5k_hw_on_hold(struct ath5k_hw *ah) |
332 | { | 522 | { |
@@ -334,6 +524,9 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
334 | u32 bus_flags; | 524 | u32 bus_flags; |
335 | int ret; | 525 | int ret; |
336 | 526 | ||
527 | if (ath5k_get_bus_type(ah) == ATH_AHB) | ||
528 | return 0; | ||
529 | |||
337 | /* Make sure device is awake */ | 530 | /* Make sure device is awake */ |
338 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 531 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); |
339 | if (ret) { | 532 | if (ret) { |
@@ -344,12 +537,12 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
344 | /* | 537 | /* |
345 | * Put chipset on warm reset... | 538 | * Put chipset on warm reset... |
346 | * | 539 | * |
347 | * Note: puting PCI core on warm reset on PCI-E cards | 540 | * Note: putting PCI core on warm reset on PCI-E cards |
348 | * results card to hang and always return 0xffff... so | 541 | * results card to hang and always return 0xffff... so |
349 | * we ingore that flag for PCI-E cards. On PCI cards | 542 | * we ingore that flag for PCI-E cards. On PCI cards |
350 | * this flag gets cleared after 64 PCI clocks. | 543 | * this flag gets cleared after 64 PCI clocks. |
351 | */ | 544 | */ |
352 | bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; | 545 | bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI; |
353 | 546 | ||
354 | if (ah->ah_version == AR5K_AR5210) { | 547 | if (ah->ah_version == AR5K_AR5210) { |
355 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | 548 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | |
@@ -378,7 +571,6 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
378 | 571 | ||
379 | /* | 572 | /* |
380 | * Bring up MAC + PHY Chips and program PLL | 573 | * Bring up MAC + PHY Chips and program PLL |
381 | * TODO: Half/Quarter rate support | ||
382 | */ | 574 | */ |
383 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | 575 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) |
384 | { | 576 | { |
@@ -390,22 +582,24 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
390 | mode = 0; | 582 | mode = 0; |
391 | clock = 0; | 583 | clock = 0; |
392 | 584 | ||
393 | /* Wakeup the device */ | 585 | if ((ath5k_get_bus_type(ah) != ATH_AHB) || !initial) { |
394 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 586 | /* Wakeup the device */ |
395 | if (ret) { | 587 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); |
396 | ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); | 588 | if (ret) { |
397 | return ret; | 589 | ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); |
590 | return ret; | ||
591 | } | ||
398 | } | 592 | } |
399 | 593 | ||
400 | /* | 594 | /* |
401 | * Put chipset on warm reset... | 595 | * Put chipset on warm reset... |
402 | * | 596 | * |
403 | * Note: puting PCI core on warm reset on PCI-E cards | 597 | * Note: putting PCI core on warm reset on PCI-E cards |
404 | * results card to hang and always return 0xffff... so | 598 | * results card to hang and always return 0xffff... so |
405 | * we ingore that flag for PCI-E cards. On PCI cards | 599 | * we ingore that flag for PCI-E cards. On PCI cards |
406 | * this flag gets cleared after 64 PCI clocks. | 600 | * this flag gets cleared after 64 PCI clocks. |
407 | */ | 601 | */ |
408 | bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; | 602 | bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI; |
409 | 603 | ||
410 | if (ah->ah_version == AR5K_AR5210) { | 604 | if (ah->ah_version == AR5K_AR5210) { |
411 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | 605 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | |
@@ -413,8 +607,12 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
413 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); | 607 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); |
414 | mdelay(2); | 608 | mdelay(2); |
415 | } else { | 609 | } else { |
416 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | 610 | if (ath5k_get_bus_type(ah) == ATH_AHB) |
417 | AR5K_RESET_CTL_BASEBAND | bus_flags); | 611 | ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | |
612 | AR5K_RESET_CTL_BASEBAND); | ||
613 | else | ||
614 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | ||
615 | AR5K_RESET_CTL_BASEBAND | bus_flags); | ||
418 | } | 616 | } |
419 | 617 | ||
420 | if (ret) { | 618 | if (ret) { |
@@ -429,9 +627,15 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
429 | return ret; | 627 | return ret; |
430 | } | 628 | } |
431 | 629 | ||
432 | /* ...clear reset control register and pull device out of | 630 | /* ...reset configuration regiter on Wisoc ... |
433 | * warm reset */ | 631 | * ...clear reset control register and pull device out of |
434 | if (ath5k_hw_nic_reset(ah, 0)) { | 632 | * warm reset on others */ |
633 | if (ath5k_get_bus_type(ah) == ATH_AHB) | ||
634 | ret = ath5k_hw_wisoc_reset(ah, 0); | ||
635 | else | ||
636 | ret = ath5k_hw_nic_reset(ah, 0); | ||
637 | |||
638 | if (ret) { | ||
435 | ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); | 639 | ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); |
436 | return -EIO; | 640 | return -EIO; |
437 | } | 641 | } |
@@ -466,7 +670,8 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
466 | * CCK headers) operation. We need to test | 670 | * CCK headers) operation. We need to test |
467 | * this, 5211 might support ofdm-only g after | 671 | * this, 5211 might support ofdm-only g after |
468 | * all, there are also initial register values | 672 | * all, there are also initial register values |
469 | * in the code for g mode (see initvals.c). */ | 673 | * in the code for g mode (see initvals.c). |
674 | */ | ||
470 | if (ah->ah_version == AR5K_AR5211) | 675 | if (ah->ah_version == AR5K_AR5211) |
471 | mode |= AR5K_PHY_MODE_MOD_OFDM; | 676 | mode |= AR5K_PHY_MODE_MOD_OFDM; |
472 | else | 677 | else |
@@ -479,6 +684,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
479 | } else if (flags & CHANNEL_5GHZ) { | 684 | } else if (flags & CHANNEL_5GHZ) { |
480 | mode |= AR5K_PHY_MODE_FREQ_5GHZ; | 685 | mode |= AR5K_PHY_MODE_FREQ_5GHZ; |
481 | 686 | ||
687 | /* Different PLL setting for 5413 */ | ||
482 | if (ah->ah_radio == AR5K_RF5413) | 688 | if (ah->ah_radio == AR5K_RF5413) |
483 | clock = AR5K_PHY_PLL_40MHZ_5413; | 689 | clock = AR5K_PHY_PLL_40MHZ_5413; |
484 | else | 690 | else |
@@ -496,12 +702,29 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
496 | return -EINVAL; | 702 | return -EINVAL; |
497 | } | 703 | } |
498 | 704 | ||
499 | if (flags & CHANNEL_TURBO) | 705 | /*XXX: Can bwmode be used with dynamic mode ? |
500 | turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; | 706 | * (I don't think it supports 44MHz) */ |
707 | /* On 2425 initvals TURBO_SHORT is not pressent */ | ||
708 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) { | ||
709 | turbo = AR5K_PHY_TURBO_MODE | | ||
710 | (ah->ah_radio == AR5K_RF2425) ? 0 : | ||
711 | AR5K_PHY_TURBO_SHORT; | ||
712 | } else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) { | ||
713 | if (ah->ah_radio == AR5K_RF5413) { | ||
714 | mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ? | ||
715 | AR5K_PHY_MODE_HALF_RATE : | ||
716 | AR5K_PHY_MODE_QUARTER_RATE; | ||
717 | } else if (ah->ah_version == AR5K_AR5212) { | ||
718 | clock |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ? | ||
719 | AR5K_PHY_PLL_HALF_RATE : | ||
720 | AR5K_PHY_PLL_QUARTER_RATE; | ||
721 | } | ||
722 | } | ||
723 | |||
501 | } else { /* Reset the device */ | 724 | } else { /* Reset the device */ |
502 | 725 | ||
503 | /* ...enable Atheros turbo mode if requested */ | 726 | /* ...enable Atheros turbo mode if requested */ |
504 | if (flags & CHANNEL_TURBO) | 727 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) |
505 | ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, | 728 | ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, |
506 | AR5K_PHY_TURBO); | 729 | AR5K_PHY_TURBO); |
507 | } | 730 | } |
@@ -522,107 +745,10 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
522 | return 0; | 745 | return 0; |
523 | } | 746 | } |
524 | 747 | ||
525 | /* | ||
526 | * If there is an external 32KHz crystal available, use it | ||
527 | * as ref. clock instead of 32/40MHz clock and baseband clocks | ||
528 | * to save power during sleep or restore normal 32/40MHz | ||
529 | * operation. | ||
530 | * | ||
531 | * XXX: When operating on 32KHz certain PHY registers (27 - 31, | ||
532 | * 123 - 127) require delay on access. | ||
533 | */ | ||
534 | static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | ||
535 | { | ||
536 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
537 | u32 scal, spending, usec32; | ||
538 | |||
539 | /* Only set 32KHz settings if we have an external | ||
540 | * 32KHz crystal present */ | ||
541 | if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || | ||
542 | AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && | ||
543 | enable) { | ||
544 | |||
545 | /* 1 usec/cycle */ | ||
546 | AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); | ||
547 | /* Set up tsf increment on each cycle */ | ||
548 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); | ||
549 | |||
550 | /* Set baseband sleep control registers | ||
551 | * and sleep control rate */ | ||
552 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); | ||
553 | |||
554 | if ((ah->ah_radio == AR5K_RF5112) || | ||
555 | (ah->ah_radio == AR5K_RF5413) || | ||
556 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
557 | spending = 0x14; | ||
558 | else | ||
559 | spending = 0x18; | ||
560 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); | ||
561 | |||
562 | if ((ah->ah_radio == AR5K_RF5112) || | ||
563 | (ah->ah_radio == AR5K_RF5413) || | ||
564 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { | ||
565 | ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); | ||
566 | ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); | ||
567 | ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); | ||
568 | ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); | ||
569 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | ||
570 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); | ||
571 | } else { | ||
572 | ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); | ||
573 | ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); | ||
574 | ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); | ||
575 | ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); | ||
576 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | ||
577 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); | ||
578 | } | ||
579 | |||
580 | /* Enable sleep clock operation */ | ||
581 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, | ||
582 | AR5K_PCICFG_SLEEP_CLOCK_EN); | ||
583 | |||
584 | } else { | ||
585 | |||
586 | /* Disable sleep clock operation and | ||
587 | * restore default parameters */ | ||
588 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, | ||
589 | AR5K_PCICFG_SLEEP_CLOCK_EN); | ||
590 | |||
591 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | ||
592 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); | ||
593 | |||
594 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); | ||
595 | ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); | ||
596 | |||
597 | if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) | ||
598 | scal = AR5K_PHY_SCAL_32MHZ_2417; | ||
599 | else if (ee->ee_is_hb63) | ||
600 | scal = AR5K_PHY_SCAL_32MHZ_HB63; | ||
601 | else | ||
602 | scal = AR5K_PHY_SCAL_32MHZ; | ||
603 | ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); | ||
604 | |||
605 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); | ||
606 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); | ||
607 | 748 | ||
608 | if ((ah->ah_radio == AR5K_RF5112) || | 749 | /**************************************\ |
609 | (ah->ah_radio == AR5K_RF5413) || | 750 | * Post-initvals register modifications * |
610 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | 751 | \**************************************/ |
611 | spending = 0x14; | ||
612 | else | ||
613 | spending = 0x18; | ||
614 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); | ||
615 | |||
616 | if ((ah->ah_radio == AR5K_RF5112) || | ||
617 | (ah->ah_radio == AR5K_RF5413)) | ||
618 | usec32 = 39; | ||
619 | else | ||
620 | usec32 = 31; | ||
621 | AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32); | ||
622 | |||
623 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); | ||
624 | } | ||
625 | } | ||
626 | 752 | ||
627 | /* TODO: Half/Quarter rate */ | 753 | /* TODO: Half/Quarter rate */ |
628 | static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | 754 | static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, |
@@ -663,22 +789,10 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | |||
663 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | 789 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, |
664 | AR5K_TXCFG_DCU_DBL_BUF_DIS); | 790 | AR5K_TXCFG_DCU_DBL_BUF_DIS); |
665 | 791 | ||
666 | /* Set DAC/ADC delays */ | ||
667 | if (ah->ah_version == AR5K_AR5212) { | ||
668 | u32 scal; | ||
669 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
670 | if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) | ||
671 | scal = AR5K_PHY_SCAL_32MHZ_2417; | ||
672 | else if (ee->ee_is_hb63) | ||
673 | scal = AR5K_PHY_SCAL_32MHZ_HB63; | ||
674 | else | ||
675 | scal = AR5K_PHY_SCAL_32MHZ; | ||
676 | ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); | ||
677 | } | ||
678 | |||
679 | /* Set fast ADC */ | 792 | /* Set fast ADC */ |
680 | if ((ah->ah_radio == AR5K_RF5413) || | 793 | if ((ah->ah_radio == AR5K_RF5413) || |
681 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { | 794 | (ah->ah_radio == AR5K_RF2317) || |
795 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { | ||
682 | u32 fast_adc = true; | 796 | u32 fast_adc = true; |
683 | 797 | ||
684 | if (channel->center_freq == 2462 || | 798 | if (channel->center_freq == 2462 || |
@@ -706,33 +820,68 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | |||
706 | } | 820 | } |
707 | 821 | ||
708 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { | 822 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { |
709 | u32 usec_reg; | ||
710 | /* 5311 has different tx/rx latency masks | ||
711 | * from 5211, since we deal 5311 the same | ||
712 | * as 5211 when setting initvals, shift | ||
713 | * values here to their proper locations */ | ||
714 | usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); | ||
715 | ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 | | ||
716 | AR5K_USEC_32 | | ||
717 | AR5K_USEC_TX_LATENCY_5211 | | ||
718 | AR5K_REG_SM(29, | ||
719 | AR5K_USEC_RX_LATENCY_5210)), | ||
720 | AR5K_USEC_5211); | ||
721 | /* Clear QCU/DCU clock gating register */ | 823 | /* Clear QCU/DCU clock gating register */ |
722 | ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT); | 824 | ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT); |
723 | /* Set DAC/ADC delays */ | 825 | /* Set DAC/ADC delays */ |
724 | ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL); | 826 | ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ_5311, |
827 | AR5K_PHY_SCAL); | ||
725 | /* Enable PCU FIFO corruption ECO */ | 828 | /* Enable PCU FIFO corruption ECO */ |
726 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, | 829 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, |
727 | AR5K_DIAG_SW_ECO_ENABLE); | 830 | AR5K_DIAG_SW_ECO_ENABLE); |
728 | } | 831 | } |
832 | |||
833 | if (ah->ah_bwmode) { | ||
834 | /* Increase PHY switch and AGC settling time | ||
835 | * on turbo mode (ath5k_hw_commit_eeprom_settings | ||
836 | * will override settling time if available) */ | ||
837 | if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) { | ||
838 | |||
839 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, | ||
840 | AR5K_PHY_SETTLING_AGC, | ||
841 | AR5K_AGC_SETTLING_TURBO); | ||
842 | |||
843 | /* XXX: Initvals indicate we only increase | ||
844 | * switch time on AR5212, 5211 and 5210 | ||
845 | * only change agc time (bug?) */ | ||
846 | if (ah->ah_version == AR5K_AR5212) | ||
847 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, | ||
848 | AR5K_PHY_SETTLING_SWITCH, | ||
849 | AR5K_SWITCH_SETTLING_TURBO); | ||
850 | |||
851 | if (ah->ah_version == AR5K_AR5210) { | ||
852 | /* Set Frame Control Register */ | ||
853 | ath5k_hw_reg_write(ah, | ||
854 | (AR5K_PHY_FRAME_CTL_INI | | ||
855 | AR5K_PHY_TURBO_MODE | | ||
856 | AR5K_PHY_TURBO_SHORT | 0x2020), | ||
857 | AR5K_PHY_FRAME_CTL_5210); | ||
858 | } | ||
859 | /* On 5413 PHY force window length for half/quarter rate*/ | ||
860 | } else if ((ah->ah_mac_srev >= AR5K_SREV_AR5424) && | ||
861 | (ah->ah_mac_srev <= AR5K_SREV_AR5414)) { | ||
862 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL_5211, | ||
863 | AR5K_PHY_FRAME_CTL_WIN_LEN, | ||
864 | 3); | ||
865 | } | ||
866 | } else if (ah->ah_version == AR5K_AR5210) { | ||
867 | /* Set Frame Control Register for normal operation */ | ||
868 | ath5k_hw_reg_write(ah, (AR5K_PHY_FRAME_CTL_INI | 0x1020), | ||
869 | AR5K_PHY_FRAME_CTL_5210); | ||
870 | } | ||
729 | } | 871 | } |
730 | 872 | ||
731 | static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | 873 | static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, |
732 | struct ieee80211_channel *channel, u8 ee_mode) | 874 | struct ieee80211_channel *channel) |
733 | { | 875 | { |
734 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 876 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
735 | s16 cck_ofdm_pwr_delta; | 877 | s16 cck_ofdm_pwr_delta; |
878 | u8 ee_mode; | ||
879 | |||
880 | /* TODO: Add support for AR5210 EEPROM */ | ||
881 | if (ah->ah_version == AR5K_AR5210) | ||
882 | return; | ||
883 | |||
884 | ee_mode = ath5k_eeprom_mode_from_channel(channel); | ||
736 | 885 | ||
737 | /* Adjust power delta for channel 14 */ | 886 | /* Adjust power delta for channel 14 */ |
738 | if (channel->center_freq == 2484) | 887 | if (channel->center_freq == 2484) |
@@ -772,7 +921,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
772 | AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), | 921 | AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), |
773 | AR5K_PHY_NFTHRES); | 922 | AR5K_PHY_NFTHRES); |
774 | 923 | ||
775 | if ((channel->hw_value & CHANNEL_TURBO) && | 924 | if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) && |
776 | (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) { | 925 | (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) { |
777 | /* Switch settling time (Turbo) */ | 926 | /* Switch settling time (Turbo) */ |
778 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, | 927 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, |
@@ -870,143 +1019,175 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
870 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); | 1019 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); |
871 | } | 1020 | } |
872 | 1021 | ||
873 | /* | 1022 | |
874 | * Main reset function | 1023 | /*********************\ |
875 | */ | 1024 | * Main reset function * |
1025 | \*********************/ | ||
1026 | |||
876 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 1027 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
877 | struct ieee80211_channel *channel, bool change_channel) | 1028 | struct ieee80211_channel *channel, bool fast, bool skip_pcu) |
878 | { | 1029 | { |
879 | struct ath_common *common = ath5k_hw_common(ah); | 1030 | u32 s_seq[10], s_led[3], tsf_up, tsf_lo; |
880 | u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo; | 1031 | u8 mode; |
881 | u32 phy_tst1; | ||
882 | u8 mode, freq, ee_mode; | ||
883 | int i, ret; | 1032 | int i, ret; |
884 | 1033 | ||
885 | ee_mode = 0; | ||
886 | staid1_flags = 0; | ||
887 | tsf_up = 0; | 1034 | tsf_up = 0; |
888 | tsf_lo = 0; | 1035 | tsf_lo = 0; |
889 | freq = 0; | ||
890 | mode = 0; | 1036 | mode = 0; |
891 | 1037 | ||
892 | /* | 1038 | /* |
893 | * Save some registers before a reset | 1039 | * Sanity check for fast flag |
1040 | * Fast channel change only available | ||
1041 | * on AR2413/AR5413. | ||
894 | */ | 1042 | */ |
895 | /*DCU/Antenna selection not available on 5210*/ | 1043 | if (fast && (ah->ah_radio != AR5K_RF2413) && |
896 | if (ah->ah_version != AR5K_AR5210) { | 1044 | (ah->ah_radio != AR5K_RF5413)) |
1045 | fast = 0; | ||
897 | 1046 | ||
898 | switch (channel->hw_value & CHANNEL_MODES) { | 1047 | /* Disable sleep clock operation |
899 | case CHANNEL_A: | 1048 | * to avoid register access delay on certain |
900 | mode = AR5K_MODE_11A; | 1049 | * PHY registers */ |
901 | freq = AR5K_INI_RFGAIN_5GHZ; | 1050 | if (ah->ah_version == AR5K_AR5212) |
902 | ee_mode = AR5K_EEPROM_MODE_11A; | 1051 | ath5k_hw_set_sleep_clock(ah, false); |
903 | break; | 1052 | |
904 | case CHANNEL_G: | 1053 | /* |
905 | mode = AR5K_MODE_11G; | 1054 | * Stop PCU |
906 | freq = AR5K_INI_RFGAIN_2GHZ; | 1055 | */ |
907 | ee_mode = AR5K_EEPROM_MODE_11G; | 1056 | ath5k_hw_stop_rx_pcu(ah); |
908 | break; | 1057 | |
909 | case CHANNEL_B: | 1058 | /* |
910 | mode = AR5K_MODE_11B; | 1059 | * Stop DMA |
911 | freq = AR5K_INI_RFGAIN_2GHZ; | 1060 | * |
912 | ee_mode = AR5K_EEPROM_MODE_11B; | 1061 | * Note: If DMA didn't stop continue |
913 | break; | 1062 | * since only a reset will fix it. |
914 | case CHANNEL_T: | 1063 | */ |
915 | mode = AR5K_MODE_11A_TURBO; | 1064 | ret = ath5k_hw_dma_stop(ah); |
916 | freq = AR5K_INI_RFGAIN_5GHZ; | 1065 | |
917 | ee_mode = AR5K_EEPROM_MODE_11A; | 1066 | /* RF Bus grant won't work if we have pending |
918 | break; | 1067 | * frames */ |
919 | case CHANNEL_TG: | 1068 | if (ret && fast) { |
920 | if (ah->ah_version == AR5K_AR5211) { | 1069 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, |
921 | ATH5K_ERR(ah->ah_sc, | 1070 | "DMA didn't stop, falling back to normal reset\n"); |
922 | "TurboG mode not available on 5211"); | 1071 | fast = 0; |
923 | return -EINVAL; | 1072 | /* Non fatal, just continue with |
924 | } | 1073 | * normal reset */ |
925 | mode = AR5K_MODE_11G_TURBO; | 1074 | ret = 0; |
926 | freq = AR5K_INI_RFGAIN_2GHZ; | 1075 | } |
927 | ee_mode = AR5K_EEPROM_MODE_11G; | 1076 | |
928 | break; | 1077 | switch (channel->hw_value & CHANNEL_MODES) { |
929 | case CHANNEL_XR: | 1078 | case CHANNEL_A: |
930 | if (ah->ah_version == AR5K_AR5211) { | 1079 | mode = AR5K_MODE_11A; |
931 | ATH5K_ERR(ah->ah_sc, | 1080 | break; |
932 | "XR mode not available on 5211"); | 1081 | case CHANNEL_G: |
933 | return -EINVAL; | 1082 | |
934 | } | 1083 | if (ah->ah_version <= AR5K_AR5211) { |
935 | mode = AR5K_MODE_XR; | ||
936 | freq = AR5K_INI_RFGAIN_5GHZ; | ||
937 | ee_mode = AR5K_EEPROM_MODE_11A; | ||
938 | break; | ||
939 | default: | ||
940 | ATH5K_ERR(ah->ah_sc, | 1084 | ATH5K_ERR(ah->ah_sc, |
941 | "invalid channel: %d\n", channel->center_freq); | 1085 | "G mode not available on 5210/5211"); |
942 | return -EINVAL; | 1086 | return -EINVAL; |
943 | } | 1087 | } |
944 | 1088 | ||
945 | if (change_channel) { | 1089 | mode = AR5K_MODE_11G; |
946 | /* | 1090 | break; |
947 | * Save frame sequence count | 1091 | case CHANNEL_B: |
948 | * For revs. after Oahu, only save | ||
949 | * seq num for DCU 0 (Global seq num) | ||
950 | */ | ||
951 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { | ||
952 | 1092 | ||
953 | for (i = 0; i < 10; i++) | 1093 | if (ah->ah_version < AR5K_AR5211) { |
954 | s_seq[i] = ath5k_hw_reg_read(ah, | 1094 | ATH5K_ERR(ah->ah_sc, |
955 | AR5K_QUEUE_DCU_SEQNUM(i)); | 1095 | "B mode not available on 5210"); |
1096 | return -EINVAL; | ||
1097 | } | ||
956 | 1098 | ||
957 | } else { | 1099 | mode = AR5K_MODE_11B; |
958 | s_seq[0] = ath5k_hw_reg_read(ah, | 1100 | break; |
959 | AR5K_QUEUE_DCU_SEQNUM(0)); | 1101 | case CHANNEL_XR: |
960 | } | 1102 | if (ah->ah_version == AR5K_AR5211) { |
1103 | ATH5K_ERR(ah->ah_sc, | ||
1104 | "XR mode not available on 5211"); | ||
1105 | return -EINVAL; | ||
1106 | } | ||
1107 | mode = AR5K_MODE_XR; | ||
1108 | break; | ||
1109 | default: | ||
1110 | ATH5K_ERR(ah->ah_sc, | ||
1111 | "invalid channel: %d\n", channel->center_freq); | ||
1112 | return -EINVAL; | ||
1113 | } | ||
961 | 1114 | ||
962 | /* TSF accelerates on AR5211 durring reset | 1115 | /* |
963 | * As a workaround save it here and restore | 1116 | * If driver requested fast channel change and DMA has stopped |
964 | * it later so that it's back in time after | 1117 | * go on. If it fails continue with a normal reset. |
965 | * reset. This way it'll get re-synced on the | 1118 | */ |
966 | * next beacon without breaking ad-hoc. | 1119 | if (fast) { |
967 | * | 1120 | ret = ath5k_hw_phy_init(ah, channel, mode, true); |
968 | * On AR5212 TSF is almost preserved across a | 1121 | if (ret) { |
969 | * reset so it stays back in time anyway and | 1122 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, |
970 | * we don't have to save/restore it. | 1123 | "fast chan change failed, falling back to normal reset\n"); |
971 | * | 1124 | /* Non fatal, can happen eg. |
972 | * XXX: Since this breaks power saving we have | 1125 | * on mode change */ |
973 | * to disable power saving until we receive the | 1126 | ret = 0; |
974 | * next beacon, so we can resync beacon timers */ | 1127 | } else { |
975 | if (ah->ah_version == AR5K_AR5211) { | 1128 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET, |
976 | tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | 1129 | "fast chan change successful\n"); |
977 | tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); | 1130 | return 0; |
978 | } | ||
979 | } | 1131 | } |
1132 | } | ||
1133 | |||
1134 | /* | ||
1135 | * Save some registers before a reset | ||
1136 | */ | ||
1137 | if (ah->ah_version != AR5K_AR5210) { | ||
1138 | /* | ||
1139 | * Save frame sequence count | ||
1140 | * For revs. after Oahu, only save | ||
1141 | * seq num for DCU 0 (Global seq num) | ||
1142 | */ | ||
1143 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { | ||
980 | 1144 | ||
981 | if (ah->ah_version == AR5K_AR5212) { | 1145 | for (i = 0; i < 10; i++) |
982 | /* Restore normal 32/40MHz clock operation | 1146 | s_seq[i] = ath5k_hw_reg_read(ah, |
983 | * to avoid register access delay on certain | 1147 | AR5K_QUEUE_DCU_SEQNUM(i)); |
984 | * PHY registers */ | ||
985 | ath5k_hw_set_sleep_clock(ah, false); | ||
986 | 1148 | ||
987 | /* Since we are going to write rf buffer | 1149 | } else { |
988 | * check if we have any pending gain_F | 1150 | s_seq[0] = ath5k_hw_reg_read(ah, |
989 | * optimization settings */ | 1151 | AR5K_QUEUE_DCU_SEQNUM(0)); |
990 | if (change_channel && ah->ah_rf_banks != NULL) | 1152 | } |
991 | ath5k_hw_gainf_calibrate(ah); | 1153 | |
1154 | /* TSF accelerates on AR5211 during reset | ||
1155 | * As a workaround save it here and restore | ||
1156 | * it later so that it's back in time after | ||
1157 | * reset. This way it'll get re-synced on the | ||
1158 | * next beacon without breaking ad-hoc. | ||
1159 | * | ||
1160 | * On AR5212 TSF is almost preserved across a | ||
1161 | * reset so it stays back in time anyway and | ||
1162 | * we don't have to save/restore it. | ||
1163 | * | ||
1164 | * XXX: Since this breaks power saving we have | ||
1165 | * to disable power saving until we receive the | ||
1166 | * next beacon, so we can resync beacon timers */ | ||
1167 | if (ah->ah_version == AR5K_AR5211) { | ||
1168 | tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); | ||
1169 | tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); | ||
992 | } | 1170 | } |
993 | } | 1171 | } |
994 | 1172 | ||
1173 | |||
995 | /*GPIOs*/ | 1174 | /*GPIOs*/ |
996 | s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & | 1175 | s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & |
997 | AR5K_PCICFG_LEDSTATE; | 1176 | AR5K_PCICFG_LEDSTATE; |
998 | s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); | 1177 | s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); |
999 | s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); | 1178 | s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); |
1000 | 1179 | ||
1001 | /* AR5K_STA_ID1 flags, only preserve antenna | 1180 | |
1002 | * settings and ack/cts rate mode */ | 1181 | /* |
1003 | staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & | 1182 | * Since we are going to write rf buffer |
1004 | (AR5K_STA_ID1_DEFAULT_ANTENNA | | 1183 | * check if we have any pending gain_F |
1005 | AR5K_STA_ID1_DESC_ANTENNA | | 1184 | * optimization settings |
1006 | AR5K_STA_ID1_RTS_DEF_ANTENNA | | 1185 | */ |
1007 | AR5K_STA_ID1_ACKCTS_6MB | | 1186 | if (ah->ah_version == AR5K_AR5212 && |
1008 | AR5K_STA_ID1_BASE_RATE_11B | | 1187 | (ah->ah_radio <= AR5K_RF5112)) { |
1009 | AR5K_STA_ID1_SELFGEN_DEF_ANT); | 1188 | if (!fast && ah->ah_rf_banks != NULL) |
1189 | ath5k_hw_gainf_calibrate(ah); | ||
1190 | } | ||
1010 | 1191 | ||
1011 | /* Wakeup the device */ | 1192 | /* Wakeup the device */ |
1012 | ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); | 1193 | ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); |
@@ -1021,121 +1202,42 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1021 | AR5K_PHY(0)); | 1202 | AR5K_PHY(0)); |
1022 | 1203 | ||
1023 | /* Write initial settings */ | 1204 | /* Write initial settings */ |
1024 | ret = ath5k_hw_write_initvals(ah, mode, change_channel); | 1205 | ret = ath5k_hw_write_initvals(ah, mode, skip_pcu); |
1025 | if (ret) | 1206 | if (ret) |
1026 | return ret; | 1207 | return ret; |
1027 | 1208 | ||
1209 | /* Initialize core clock settings */ | ||
1210 | ath5k_hw_init_core_clock(ah); | ||
1211 | |||
1028 | /* | 1212 | /* |
1029 | * 5211/5212 Specific | 1213 | * Tweak initval settings for revised |
1214 | * chipsets and add some more config | ||
1215 | * bits | ||
1030 | */ | 1216 | */ |
1031 | if (ah->ah_version != AR5K_AR5210) { | 1217 | ath5k_hw_tweak_initval_settings(ah, channel); |
1032 | |||
1033 | /* | ||
1034 | * Write initial RF gain settings | ||
1035 | * This should work for both 5111/5112 | ||
1036 | */ | ||
1037 | ret = ath5k_hw_rfgain_init(ah, freq); | ||
1038 | if (ret) | ||
1039 | return ret; | ||
1040 | |||
1041 | mdelay(1); | ||
1042 | |||
1043 | /* | ||
1044 | * Tweak initval settings for revised | ||
1045 | * chipsets and add some more config | ||
1046 | * bits | ||
1047 | */ | ||
1048 | ath5k_hw_tweak_initval_settings(ah, channel); | ||
1049 | |||
1050 | /* | ||
1051 | * Set TX power | ||
1052 | */ | ||
1053 | ret = ath5k_hw_txpower(ah, channel, ee_mode, | ||
1054 | ah->ah_txpower.txp_max_pwr / 2); | ||
1055 | if (ret) | ||
1056 | return ret; | ||
1057 | |||
1058 | /* Write rate duration table only on AR5212 and if | ||
1059 | * virtual interface has already been brought up | ||
1060 | * XXX: rethink this after new mode changes to | ||
1061 | * mac80211 are integrated */ | ||
1062 | if (ah->ah_version == AR5K_AR5212 && | ||
1063 | ah->ah_sc->vif != NULL) | ||
1064 | ath5k_hw_write_rate_duration(ah, mode); | ||
1065 | |||
1066 | /* | ||
1067 | * Write RF buffer | ||
1068 | */ | ||
1069 | ret = ath5k_hw_rfregs_init(ah, channel, mode); | ||
1070 | if (ret) | ||
1071 | return ret; | ||
1072 | |||
1073 | |||
1074 | /* Write OFDM timings on 5212*/ | ||
1075 | if (ah->ah_version == AR5K_AR5212 && | ||
1076 | channel->hw_value & CHANNEL_OFDM) { | ||
1077 | 1218 | ||
1078 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | 1219 | /* Commit values from EEPROM */ |
1079 | if (ret) | 1220 | ath5k_hw_commit_eeprom_settings(ah, channel); |
1080 | return ret; | ||
1081 | 1221 | ||
1082 | /* Spur info is available only from EEPROM versions | ||
1083 | * bigger than 5.3 but but the EEPOM routines will use | ||
1084 | * static values for older versions */ | ||
1085 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | ||
1086 | ath5k_hw_set_spur_mitigation_filter(ah, | ||
1087 | channel); | ||
1088 | } | ||
1089 | |||
1090 | /*Enable/disable 802.11b mode on 5111 | ||
1091 | (enable 2111 frequency converter + CCK)*/ | ||
1092 | if (ah->ah_radio == AR5K_RF5111) { | ||
1093 | if (mode == AR5K_MODE_11B) | ||
1094 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | ||
1095 | AR5K_TXCFG_B_MODE); | ||
1096 | else | ||
1097 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | ||
1098 | AR5K_TXCFG_B_MODE); | ||
1099 | } | ||
1100 | |||
1101 | /* Commit values from EEPROM */ | ||
1102 | ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode); | ||
1103 | |||
1104 | } else { | ||
1105 | /* | ||
1106 | * For 5210 we do all initialization using | ||
1107 | * initvals, so we don't have to modify | ||
1108 | * any settings (5210 also only supports | ||
1109 | * a/aturbo modes) | ||
1110 | */ | ||
1111 | mdelay(1); | ||
1112 | /* Disable phy and wait */ | ||
1113 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
1114 | mdelay(1); | ||
1115 | } | ||
1116 | 1222 | ||
1117 | /* | 1223 | /* |
1118 | * Restore saved values | 1224 | * Restore saved values |
1119 | */ | 1225 | */ |
1120 | 1226 | ||
1121 | /*DCU/Antenna selection not available on 5210*/ | 1227 | /* Seqnum, TSF */ |
1122 | if (ah->ah_version != AR5K_AR5210) { | 1228 | if (ah->ah_version != AR5K_AR5210) { |
1229 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { | ||
1230 | for (i = 0; i < 10; i++) | ||
1231 | ath5k_hw_reg_write(ah, s_seq[i], | ||
1232 | AR5K_QUEUE_DCU_SEQNUM(i)); | ||
1233 | } else { | ||
1234 | ath5k_hw_reg_write(ah, s_seq[0], | ||
1235 | AR5K_QUEUE_DCU_SEQNUM(0)); | ||
1236 | } | ||
1123 | 1237 | ||
1124 | if (change_channel) { | 1238 | if (ah->ah_version == AR5K_AR5211) { |
1125 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { | 1239 | ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); |
1126 | for (i = 0; i < 10; i++) | 1240 | ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); |
1127 | ath5k_hw_reg_write(ah, s_seq[i], | ||
1128 | AR5K_QUEUE_DCU_SEQNUM(i)); | ||
1129 | } else { | ||
1130 | ath5k_hw_reg_write(ah, s_seq[0], | ||
1131 | AR5K_QUEUE_DCU_SEQNUM(0)); | ||
1132 | } | ||
1133 | |||
1134 | |||
1135 | if (ah->ah_version == AR5K_AR5211) { | ||
1136 | ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); | ||
1137 | ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); | ||
1138 | } | ||
1139 | } | 1241 | } |
1140 | } | 1242 | } |
1141 | 1243 | ||
@@ -1146,203 +1248,34 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1146 | ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); | 1248 | ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); |
1147 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); | 1249 | ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); |
1148 | 1250 | ||
1149 | /* Restore sta_id flags and preserve our mac address*/ | ||
1150 | ath5k_hw_reg_write(ah, | ||
1151 | get_unaligned_le32(common->macaddr), | ||
1152 | AR5K_STA_ID0); | ||
1153 | ath5k_hw_reg_write(ah, | ||
1154 | staid1_flags | get_unaligned_le16(common->macaddr + 4), | ||
1155 | AR5K_STA_ID1); | ||
1156 | |||
1157 | |||
1158 | /* | 1251 | /* |
1159 | * Configure PCU | 1252 | * Initialize PCU |
1160 | */ | 1253 | */ |
1161 | 1254 | ath5k_hw_pcu_init(ah, op_mode, mode); | |
1162 | /* Restore bssid and bssid mask */ | ||
1163 | ath5k_hw_set_associd(ah); | ||
1164 | |||
1165 | /* Set PCU config */ | ||
1166 | ath5k_hw_set_opmode(ah, op_mode); | ||
1167 | |||
1168 | /* Clear any pending interrupts | ||
1169 | * PISR/SISR Not available on 5210 */ | ||
1170 | if (ah->ah_version != AR5K_AR5210) | ||
1171 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); | ||
1172 | |||
1173 | /* Set RSSI/BRSSI thresholds | ||
1174 | * | ||
1175 | * Note: If we decide to set this value | ||
1176 | * dynamicaly, have in mind that when AR5K_RSSI_THR | ||
1177 | * register is read it might return 0x40 if we haven't | ||
1178 | * wrote anything to it plus BMISS RSSI threshold is zeroed. | ||
1179 | * So doing a save/restore procedure here isn't the right | ||
1180 | * choice. Instead store it on ath5k_hw */ | ||
1181 | ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | | ||
1182 | AR5K_TUNE_BMISS_THRES << | ||
1183 | AR5K_RSSI_THR_BMISS_S), | ||
1184 | AR5K_RSSI_THR); | ||
1185 | |||
1186 | /* MIC QoS support */ | ||
1187 | if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { | ||
1188 | ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); | ||
1189 | ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); | ||
1190 | } | ||
1191 | |||
1192 | /* QoS NOACK Policy */ | ||
1193 | if (ah->ah_version == AR5K_AR5212) { | ||
1194 | ath5k_hw_reg_write(ah, | ||
1195 | AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | | ||
1196 | AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | | ||
1197 | AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), | ||
1198 | AR5K_QOS_NOACK); | ||
1199 | } | ||
1200 | |||
1201 | 1255 | ||
1202 | /* | 1256 | /* |
1203 | * Configure PHY | 1257 | * Initialize PHY |
1204 | */ | 1258 | */ |
1205 | 1259 | ret = ath5k_hw_phy_init(ah, channel, mode, false); | |
1206 | /* Set channel on PHY */ | 1260 | if (ret) { |
1207 | ret = ath5k_hw_channel(ah, channel); | 1261 | ATH5K_ERR(ah->ah_sc, |
1208 | if (ret) | 1262 | "failed to initialize PHY (%i) !\n", ret); |
1209 | return ret; | 1263 | return ret; |
1210 | |||
1211 | /* | ||
1212 | * Enable the PHY and wait until completion | ||
1213 | * This includes BaseBand and Synthesizer | ||
1214 | * activation. | ||
1215 | */ | ||
1216 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
1217 | |||
1218 | /* | ||
1219 | * On 5211+ read activation -> rx delay | ||
1220 | * and use it. | ||
1221 | * | ||
1222 | * TODO: Half/quarter rate support | ||
1223 | */ | ||
1224 | if (ah->ah_version != AR5K_AR5210) { | ||
1225 | u32 delay; | ||
1226 | delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
1227 | AR5K_PHY_RX_DELAY_M; | ||
1228 | delay = (channel->hw_value & CHANNEL_CCK) ? | ||
1229 | ((delay << 2) / 22) : (delay / 10); | ||
1230 | |||
1231 | udelay(100 + (2 * delay)); | ||
1232 | } else { | ||
1233 | mdelay(1); | ||
1234 | } | ||
1235 | |||
1236 | /* | ||
1237 | * Perform ADC test to see if baseband is ready | ||
1238 | * Set tx hold and check adc test register | ||
1239 | */ | ||
1240 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | ||
1241 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | ||
1242 | for (i = 0; i <= 20; i++) { | ||
1243 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | ||
1244 | break; | ||
1245 | udelay(200); | ||
1246 | } | ||
1247 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); | ||
1248 | |||
1249 | /* | ||
1250 | * Start automatic gain control calibration | ||
1251 | * | ||
1252 | * During AGC calibration RX path is re-routed to | ||
1253 | * a power detector so we don't receive anything. | ||
1254 | * | ||
1255 | * This method is used to calibrate some static offsets | ||
1256 | * used together with on-the fly I/Q calibration (the | ||
1257 | * one performed via ath5k_hw_phy_calibrate), that doesn't | ||
1258 | * interrupt rx path. | ||
1259 | * | ||
1260 | * While rx path is re-routed to the power detector we also | ||
1261 | * start a noise floor calibration, to measure the | ||
1262 | * card's noise floor (the noise we measure when we are not | ||
1263 | * transmiting or receiving anything). | ||
1264 | * | ||
1265 | * If we are in a noisy environment AGC calibration may time | ||
1266 | * out and/or noise floor calibration might timeout. | ||
1267 | */ | ||
1268 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1269 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); | ||
1270 | |||
1271 | /* At the same time start I/Q calibration for QAM constellation | ||
1272 | * -no need for CCK- */ | ||
1273 | ah->ah_calibration = false; | ||
1274 | if (!(mode == AR5K_MODE_11B)) { | ||
1275 | ah->ah_calibration = true; | ||
1276 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
1277 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
1278 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
1279 | AR5K_PHY_IQ_RUN); | ||
1280 | } | 1264 | } |
1281 | 1265 | ||
1282 | /* Wait for gain calibration to finish (we check for I/Q calibration | ||
1283 | * during ath5k_phy_calibrate) */ | ||
1284 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
1285 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | ||
1286 | ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", | ||
1287 | channel->center_freq); | ||
1288 | } | ||
1289 | |||
1290 | /* Restore antenna mode */ | ||
1291 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | ||
1292 | |||
1293 | /* Restore slot time and ACK timeouts */ | ||
1294 | if (ah->ah_coverage_class > 0) | ||
1295 | ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); | ||
1296 | |||
1297 | /* | 1266 | /* |
1298 | * Configure QCUs/DCUs | 1267 | * Configure QCUs/DCUs |
1299 | */ | 1268 | */ |
1300 | 1269 | ret = ath5k_hw_init_queues(ah); | |
1301 | /* TODO: HW Compression support for data queues */ | 1270 | if (ret) |
1302 | /* TODO: Burst prefetch for data queues */ | 1271 | return ret; |
1303 | |||
1304 | /* | ||
1305 | * Reset queues and start beacon timers at the end of the reset routine | ||
1306 | * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping | ||
1307 | * Note: If we want we can assign multiple qcus on one dcu. | ||
1308 | */ | ||
1309 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { | ||
1310 | ret = ath5k_hw_reset_tx_queue(ah, i); | ||
1311 | if (ret) { | ||
1312 | ATH5K_ERR(ah->ah_sc, | ||
1313 | "failed to reset TX queue #%d\n", i); | ||
1314 | return ret; | ||
1315 | } | ||
1316 | } | ||
1317 | 1272 | ||
1318 | 1273 | ||
1319 | /* | 1274 | /* |
1320 | * Configure DMA/Interrupts | 1275 | * Initialize DMA/Interrupts |
1321 | */ | 1276 | */ |
1277 | ath5k_hw_dma_init(ah); | ||
1322 | 1278 | ||
1323 | /* | ||
1324 | * Set Rx/Tx DMA Configuration | ||
1325 | * | ||
1326 | * Set standard DMA size (128). Note that | ||
1327 | * a DMA size of 512 causes rx overruns and tx errors | ||
1328 | * on pci-e cards (tested on 5424 but since rx overruns | ||
1329 | * also occur on 5416/5418 with madwifi we set 128 | ||
1330 | * for all PCI-E cards to be safe). | ||
1331 | * | ||
1332 | * XXX: need to check 5210 for this | ||
1333 | * TODO: Check out tx triger level, it's always 64 on dumps but I | ||
1334 | * guess we can tweak it and see how it goes ;-) | ||
1335 | */ | ||
1336 | if (ah->ah_version != AR5K_AR5210) { | ||
1337 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | ||
1338 | AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); | ||
1339 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, | ||
1340 | AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); | ||
1341 | } | ||
1342 | |||
1343 | /* Pre-enable interrupts on 5211/5212*/ | ||
1344 | if (ah->ah_version != AR5K_AR5210) | ||
1345 | ath5k_hw_set_imr(ah, ah->ah_imr); | ||
1346 | 1279 | ||
1347 | /* Enable 32KHz clock function for AR5212+ chips | 1280 | /* Enable 32KHz clock function for AR5212+ chips |
1348 | * Set clocks to 32KHz operation and use an | 1281 | * Set clocks to 32KHz operation and use an |
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h index e50baff66175..16b67e84906d 100644 --- a/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h | |||
@@ -25,10 +25,10 @@ | |||
25 | * | 25 | * |
26 | * We don't write on those registers directly but | 26 | * We don't write on those registers directly but |
27 | * we send a data packet on the chip, using a special register, | 27 | * we send a data packet on the chip, using a special register, |
28 | * that holds all the settings we need. After we 've sent the | 28 | * that holds all the settings we need. After we've sent the |
29 | * data packet, we write on another special register to notify hw | 29 | * data packet, we write on another special register to notify hw |
30 | * to apply the settings. This is done so that control registers | 30 | * to apply the settings. This is done so that control registers |
31 | * can be dynamicaly programmed during operation and the settings | 31 | * can be dynamically programmed during operation and the settings |
32 | * are applied faster on the hw. | 32 | * are applied faster on the hw. |
33 | * | 33 | * |
34 | * We call each data packet an "RF Bank" and all the data we write | 34 | * We call each data packet an "RF Bank" and all the data we write |
@@ -51,7 +51,7 @@ | |||
51 | struct ath5k_ini_rfbuffer { | 51 | struct ath5k_ini_rfbuffer { |
52 | u8 rfb_bank; /* RF Bank number */ | 52 | u8 rfb_bank; /* RF Bank number */ |
53 | u16 rfb_ctrl_register; /* RF Buffer control register */ | 53 | u16 rfb_ctrl_register; /* RF Buffer control register */ |
54 | u32 rfb_mode_data[5]; /* RF Buffer data for each mode */ | 54 | u32 rfb_mode_data[3]; /* RF Buffer data for each mode */ |
55 | }; | 55 | }; |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -79,8 +79,10 @@ struct ath5k_rf_reg { | |||
79 | * life easier by using an index for each register | 79 | * life easier by using an index for each register |
80 | * instead of a full rfb_field */ | 80 | * instead of a full rfb_field */ |
81 | enum ath5k_rf_regs_idx { | 81 | enum ath5k_rf_regs_idx { |
82 | /* BANK 2 */ | ||
83 | AR5K_RF_TURBO = 0, | ||
82 | /* BANK 6 */ | 84 | /* BANK 6 */ |
83 | AR5K_RF_OB_2GHZ = 0, | 85 | AR5K_RF_OB_2GHZ, |
84 | AR5K_RF_OB_5GHZ, | 86 | AR5K_RF_OB_5GHZ, |
85 | AR5K_RF_DB_2GHZ, | 87 | AR5K_RF_DB_2GHZ, |
86 | AR5K_RF_DB_5GHZ, | 88 | AR5K_RF_DB_5GHZ, |
@@ -134,6 +136,9 @@ enum ath5k_rf_regs_idx { | |||
134 | * RF5111 (Sombrero) * | 136 | * RF5111 (Sombrero) * |
135 | \*******************/ | 137 | \*******************/ |
136 | 138 | ||
139 | /* BANK 2 len pos col */ | ||
140 | #define AR5K_RF5111_RF_TURBO { 1, 3, 0 } | ||
141 | |||
137 | /* BANK 6 len pos col */ | 142 | /* BANK 6 len pos col */ |
138 | #define AR5K_RF5111_OB_2GHZ { 3, 119, 0 } | 143 | #define AR5K_RF5111_OB_2GHZ { 3, 119, 0 } |
139 | #define AR5K_RF5111_DB_2GHZ { 3, 122, 0 } | 144 | #define AR5K_RF5111_DB_2GHZ { 3, 122, 0 } |
@@ -158,6 +163,7 @@ enum ath5k_rf_regs_idx { | |||
158 | #define AR5K_RF5111_MAX_TIME { 2, 49, 0 } | 163 | #define AR5K_RF5111_MAX_TIME { 2, 49, 0 } |
159 | 164 | ||
160 | static const struct ath5k_rf_reg rf_regs_5111[] = { | 165 | static const struct ath5k_rf_reg rf_regs_5111[] = { |
166 | {2, AR5K_RF_TURBO, AR5K_RF5111_RF_TURBO}, | ||
161 | {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ}, | 167 | {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ}, |
162 | {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ}, | 168 | {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ}, |
163 | {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ}, | 169 | {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ}, |
@@ -177,97 +183,52 @@ static const struct ath5k_rf_reg rf_regs_5111[] = { | |||
177 | 183 | ||
178 | /* Default mode specific settings */ | 184 | /* Default mode specific settings */ |
179 | static const struct ath5k_ini_rfbuffer rfb_5111[] = { | 185 | static const struct ath5k_ini_rfbuffer rfb_5111[] = { |
180 | { 0, 0x989c, | 186 | /* BANK / C.R. A/XR B G */ |
181 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | 187 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
182 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 188 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
183 | { 0, 0x989c, | 189 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
184 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 190 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
185 | { 0, 0x989c, | 191 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
186 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 192 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
187 | { 0, 0x989c, | 193 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
188 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 194 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
189 | { 0, 0x989c, | 195 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
190 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 196 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
191 | { 0, 0x989c, | 197 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
192 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 198 | { 0, 0x989c, { 0x00380000, 0x00380000, 0x00380000 } }, |
193 | { 0, 0x989c, | 199 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
194 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 200 | { 0, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
195 | { 0, 0x989c, | 201 | { 0, 0x989c, { 0x00000000, 0x000000c0, 0x00000080 } }, |
196 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 202 | { 0, 0x989c, { 0x000400f9, 0x000400ff, 0x000400fd } }, |
197 | { 0, 0x989c, | 203 | { 0, 0x98d4, { 0x00000000, 0x00000004, 0x00000004 } }, |
198 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 204 | { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, |
199 | { 0, 0x989c, | 205 | { 2, 0x98d4, { 0x00000010, 0x00000010, 0x00000010 } }, |
200 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 206 | { 3, 0x98d8, { 0x00601068, 0x00601068, 0x00601068 } }, |
201 | { 0, 0x989c, | 207 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
202 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 208 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
203 | { 0, 0x989c, | 209 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
204 | { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } }, | 210 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
205 | { 0, 0x989c, | 211 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
206 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 212 | { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, |
207 | { 0, 0x989c, | 213 | { 6, 0x989c, { 0x04000000, 0x04000000, 0x04000000 } }, |
208 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 214 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
209 | { 0, 0x989c, | 215 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
210 | { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } }, | 216 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
211 | { 0, 0x989c, | 217 | { 6, 0x989c, { 0x00000000, 0x0a000000, 0x00000000 } }, |
212 | { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } }, | 218 | { 6, 0x989c, { 0x003800c0, 0x023800c0, 0x003800c0 } }, |
213 | { 0, 0x98d4, | 219 | { 6, 0x989c, { 0x00020006, 0x00000006, 0x00020006 } }, |
214 | { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } }, | 220 | { 6, 0x989c, { 0x00000089, 0x00000089, 0x00000089 } }, |
215 | { 1, 0x98d4, | 221 | { 6, 0x989c, { 0x000000a0, 0x000000a0, 0x000000a0 } }, |
216 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | 222 | { 6, 0x989c, { 0x00040007, 0x00040007, 0x00040007 } }, |
217 | { 2, 0x98d4, | 223 | { 6, 0x98d4, { 0x0000001a, 0x0000001a, 0x0000001a } }, |
218 | { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } }, | 224 | { 7, 0x989c, { 0x00000040, 0x00000040, 0x00000040 } }, |
219 | { 3, 0x98d8, | 225 | { 7, 0x989c, { 0x00000010, 0x00000010, 0x00000010 } }, |
220 | { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } }, | 226 | { 7, 0x989c, { 0x00000008, 0x00000008, 0x00000008 } }, |
221 | { 6, 0x989c, | 227 | { 7, 0x989c, { 0x0000004f, 0x0000004f, 0x0000004f } }, |
222 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 228 | { 7, 0x989c, { 0x000000f1, 0x00000061, 0x000000f1 } }, |
223 | { 6, 0x989c, | 229 | { 7, 0x989c, { 0x0000904f, 0x0000904c, 0x0000904f } }, |
224 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 230 | { 7, 0x989c, { 0x0000125a, 0x0000129a, 0x0000125a } }, |
225 | { 6, 0x989c, | 231 | { 7, 0x98cc, { 0x0000000e, 0x0000000f, 0x0000000e } }, |
226 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
227 | { 6, 0x989c, | ||
228 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
229 | { 6, 0x989c, | ||
230 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
231 | { 6, 0x989c, | ||
232 | { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, | ||
233 | { 6, 0x989c, | ||
234 | { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } }, | ||
235 | { 6, 0x989c, | ||
236 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
237 | { 6, 0x989c, | ||
238 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
239 | { 6, 0x989c, | ||
240 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
241 | { 6, 0x989c, | ||
242 | { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } }, | ||
243 | { 6, 0x989c, | ||
244 | { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } }, | ||
245 | { 6, 0x989c, | ||
246 | { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } }, | ||
247 | { 6, 0x989c, | ||
248 | { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } }, | ||
249 | { 6, 0x989c, | ||
250 | { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } }, | ||
251 | { 6, 0x989c, | ||
252 | { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } }, | ||
253 | { 6, 0x98d4, | ||
254 | { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } }, | ||
255 | { 7, 0x989c, | ||
256 | { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } }, | ||
257 | { 7, 0x989c, | ||
258 | { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } }, | ||
259 | { 7, 0x989c, | ||
260 | { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, | ||
261 | { 7, 0x989c, | ||
262 | { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } }, | ||
263 | { 7, 0x989c, | ||
264 | { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } }, | ||
265 | { 7, 0x989c, | ||
266 | { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } }, | ||
267 | { 7, 0x989c, | ||
268 | { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } }, | ||
269 | { 7, 0x98cc, | ||
270 | { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } }, | ||
271 | }; | 232 | }; |
272 | 233 | ||
273 | 234 | ||
@@ -276,6 +237,9 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = { | |||
276 | * RF5112/RF2112 (Derby) * | 237 | * RF5112/RF2112 (Derby) * |
277 | \***********************/ | 238 | \***********************/ |
278 | 239 | ||
240 | /* BANK 2 (Common) len pos col */ | ||
241 | #define AR5K_RF5112X_RF_TURBO { 1, 1, 2 } | ||
242 | |||
279 | /* BANK 7 (Common) len pos col */ | 243 | /* BANK 7 (Common) len pos col */ |
280 | #define AR5K_RF5112X_GAIN_I { 6, 14, 0 } | 244 | #define AR5K_RF5112X_GAIN_I { 6, 14, 0 } |
281 | #define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 } | 245 | #define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 } |
@@ -307,6 +271,7 @@ static const struct ath5k_ini_rfbuffer rfb_5111[] = { | |||
307 | #define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 } | 271 | #define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 } |
308 | 272 | ||
309 | static const struct ath5k_rf_reg rf_regs_5112[] = { | 273 | static const struct ath5k_rf_reg rf_regs_5112[] = { |
274 | {2, AR5K_RF_TURBO, AR5K_RF5112X_RF_TURBO}, | ||
310 | {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ}, | 275 | {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ}, |
311 | {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ}, | 276 | {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ}, |
312 | {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ}, | 277 | {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ}, |
@@ -335,115 +300,61 @@ static const struct ath5k_rf_reg rf_regs_5112[] = { | |||
335 | 300 | ||
336 | /* Default mode specific settings */ | 301 | /* Default mode specific settings */ |
337 | static const struct ath5k_ini_rfbuffer rfb_5112[] = { | 302 | static const struct ath5k_ini_rfbuffer rfb_5112[] = { |
338 | { 1, 0x98d4, | 303 | /* BANK / C.R. A/XR B G */ |
339 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | 304 | { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, |
340 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | 305 | { 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } }, |
341 | { 2, 0x98d0, | 306 | { 3, 0x98dc, { 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, |
342 | { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, | 307 | { 6, 0x989c, { 0x00a00000, 0x00a00000, 0x00a00000 } }, |
343 | { 3, 0x98dc, | 308 | { 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } }, |
344 | { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, | 309 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
345 | { 6, 0x989c, | 310 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
346 | { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } }, | 311 | { 6, 0x989c, { 0x00660000, 0x00660000, 0x00660000 } }, |
347 | { 6, 0x989c, | 312 | { 6, 0x989c, { 0x00db0000, 0x00db0000, 0x00db0000 } }, |
348 | { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, | 313 | { 6, 0x989c, { 0x00f10000, 0x00f10000, 0x00f10000 } }, |
349 | { 6, 0x989c, | 314 | { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } }, |
350 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 315 | { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } }, |
351 | { 6, 0x989c, | 316 | { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, |
352 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 317 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
353 | { 6, 0x989c, | 318 | { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } }, |
354 | { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } }, | 319 | { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, |
355 | { 6, 0x989c, | 320 | { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, |
356 | { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } }, | 321 | { 6, 0x989c, { 0x008b0000, 0x008b0000, 0x008b0000 } }, |
357 | { 6, 0x989c, | 322 | { 6, 0x989c, { 0x00600000, 0x00600000, 0x00600000 } }, |
358 | { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } }, | 323 | { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } }, |
359 | { 6, 0x989c, | 324 | { 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } }, |
360 | { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, | 325 | { 6, 0x989c, { 0x00640000, 0x00640000, 0x00640000 } }, |
361 | { 6, 0x989c, | 326 | { 6, 0x989c, { 0x00200000, 0x00200000, 0x00200000 } }, |
362 | { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, | 327 | { 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } }, |
363 | { 6, 0x989c, | 328 | { 6, 0x989c, { 0x00250000, 0x00250000, 0x00250000 } }, |
364 | { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, | 329 | { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } }, |
365 | { 6, 0x989c, | 330 | { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } }, |
366 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 331 | { 6, 0x989c, { 0x00510000, 0x00510000, 0x00510000 } }, |
367 | { 6, 0x989c, | 332 | { 6, 0x989c, { 0x1c040000, 0x1c040000, 0x1c040000 } }, |
368 | { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, | 333 | { 6, 0x989c, { 0x000a0000, 0x000a0000, 0x000a0000 } }, |
369 | { 6, 0x989c, | 334 | { 6, 0x989c, { 0x00a10000, 0x00a10000, 0x00a10000 } }, |
370 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | 335 | { 6, 0x989c, { 0x00400000, 0x00400000, 0x00400000 } }, |
371 | { 6, 0x989c, | 336 | { 6, 0x989c, { 0x03090000, 0x03090000, 0x03090000 } }, |
372 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | 337 | { 6, 0x989c, { 0x06000000, 0x06000000, 0x06000000 } }, |
373 | { 6, 0x989c, | 338 | { 6, 0x989c, { 0x000000b0, 0x000000a8, 0x000000a8 } }, |
374 | { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } }, | 339 | { 6, 0x989c, { 0x0000002e, 0x0000002e, 0x0000002e } }, |
375 | { 6, 0x989c, | 340 | { 6, 0x989c, { 0x006c4a41, 0x006c4af1, 0x006c4a61 } }, |
376 | { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } }, | 341 | { 6, 0x989c, { 0x0050892a, 0x0050892b, 0x0050892b } }, |
377 | { 6, 0x989c, | 342 | { 6, 0x989c, { 0x00842400, 0x00842400, 0x00842400 } }, |
378 | { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, | 343 | { 6, 0x989c, { 0x00c69200, 0x00c69200, 0x00c69200 } }, |
379 | { 6, 0x989c, | 344 | { 6, 0x98d0, { 0x0002000c, 0x0002000c, 0x0002000c } }, |
380 | { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, | 345 | { 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } }, |
381 | { 6, 0x989c, | 346 | { 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } }, |
382 | { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } }, | 347 | { 7, 0x989c, { 0x0000000a, 0x00000012, 0x00000012 } }, |
383 | { 6, 0x989c, | 348 | { 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } }, |
384 | { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } }, | 349 | { 7, 0x989c, { 0x000000c1, 0x000000c1, 0x000000c1 } }, |
385 | { 6, 0x989c, | 350 | { 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } }, |
386 | { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, | 351 | { 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } }, |
387 | { 6, 0x989c, | 352 | { 7, 0x989c, { 0x00000022, 0x00000022, 0x00000022 } }, |
388 | { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } }, | 353 | { 7, 0x989c, { 0x00000092, 0x00000092, 0x00000092 } }, |
389 | { 6, 0x989c, | 354 | { 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } }, |
390 | { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, | 355 | { 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } }, |
391 | { 6, 0x989c, | 356 | { 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } }, |
392 | { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, | 357 | { 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } }, |
393 | { 6, 0x989c, | ||
394 | { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } }, | ||
395 | { 6, 0x989c, | ||
396 | { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } }, | ||
397 | { 6, 0x989c, | ||
398 | { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, | ||
399 | { 6, 0x989c, | ||
400 | { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } }, | ||
401 | { 6, 0x989c, | ||
402 | { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } }, | ||
403 | { 6, 0x989c, | ||
404 | { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } }, | ||
405 | { 6, 0x989c, | ||
406 | { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } }, | ||
407 | { 6, 0x989c, | ||
408 | { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } }, | ||
409 | { 6, 0x989c, | ||
410 | { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } }, | ||
411 | { 6, 0x989c, | ||
412 | { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } }, | ||
413 | { 6, 0x989c, | ||
414 | { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } }, | ||
415 | { 6, 0x989c, | ||
416 | { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } }, | ||
417 | { 6, 0x989c, | ||
418 | { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } }, | ||
419 | { 6, 0x98d0, | ||
420 | { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } }, | ||
421 | { 7, 0x989c, | ||
422 | { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, | ||
423 | { 7, 0x989c, | ||
424 | { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, | ||
425 | { 7, 0x989c, | ||
426 | { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } }, | ||
427 | { 7, 0x989c, | ||
428 | { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, | ||
429 | { 7, 0x989c, | ||
430 | { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } }, | ||
431 | { 7, 0x989c, | ||
432 | { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, | ||
433 | { 7, 0x989c, | ||
434 | { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, | ||
435 | { 7, 0x989c, | ||
436 | { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } }, | ||
437 | { 7, 0x989c, | ||
438 | { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } }, | ||
439 | { 7, 0x989c, | ||
440 | { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, | ||
441 | { 7, 0x989c, | ||
442 | { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, | ||
443 | { 7, 0x989c, | ||
444 | { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, | ||
445 | { 7, 0x98c4, | ||
446 | { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, | ||
447 | }; | 358 | }; |
448 | 359 | ||
449 | /* RFX112A (Derby 2) */ | 360 | /* RFX112A (Derby 2) */ |
@@ -477,6 +388,7 @@ static const struct ath5k_ini_rfbuffer rfb_5112[] = { | |||
477 | #define AR5K_RF5112A_XB5_LVL { 2, 3, 3 } | 388 | #define AR5K_RF5112A_XB5_LVL { 2, 3, 3 } |
478 | 389 | ||
479 | static const struct ath5k_rf_reg rf_regs_5112a[] = { | 390 | static const struct ath5k_rf_reg rf_regs_5112a[] = { |
391 | {2, AR5K_RF_TURBO, AR5K_RF5112X_RF_TURBO}, | ||
480 | {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ}, | 392 | {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ}, |
481 | {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ}, | 393 | {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ}, |
482 | {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ}, | 394 | {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ}, |
@@ -515,119 +427,63 @@ static const struct ath5k_rf_reg rf_regs_5112a[] = { | |||
515 | 427 | ||
516 | /* Default mode specific settings */ | 428 | /* Default mode specific settings */ |
517 | static const struct ath5k_ini_rfbuffer rfb_5112a[] = { | 429 | static const struct ath5k_ini_rfbuffer rfb_5112a[] = { |
518 | { 1, 0x98d4, | 430 | /* BANK / C.R. A/XR B G */ |
519 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | 431 | { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, |
520 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | 432 | { 2, 0x98d0, { 0x03060408, 0x03060408, 0x03060408 } }, |
521 | { 2, 0x98d0, | 433 | { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, |
522 | { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, | 434 | { 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } }, |
523 | { 3, 0x98dc, | 435 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
524 | { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, | 436 | { 6, 0x989c, { 0x00800000, 0x00800000, 0x00800000 } }, |
525 | { 6, 0x989c, | 437 | { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, |
526 | { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, | 438 | { 6, 0x989c, { 0x00010000, 0x00010000, 0x00010000 } }, |
527 | { 6, 0x989c, | 439 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
528 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 440 | { 6, 0x989c, { 0x00180000, 0x00180000, 0x00180000 } }, |
529 | { 6, 0x989c, | 441 | { 6, 0x989c, { 0x00600000, 0x006e0000, 0x006e0000 } }, |
530 | { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } }, | 442 | { 6, 0x989c, { 0x00c70000, 0x00c70000, 0x00c70000 } }, |
531 | { 6, 0x989c, | 443 | { 6, 0x989c, { 0x004b0000, 0x004b0000, 0x004b0000 } }, |
532 | { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, | 444 | { 6, 0x989c, { 0x04480000, 0x04480000, 0x04480000 } }, |
533 | { 6, 0x989c, | 445 | { 6, 0x989c, { 0x004c0000, 0x004c0000, 0x004c0000 } }, |
534 | { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, | 446 | { 6, 0x989c, { 0x00e40000, 0x00e40000, 0x00e40000 } }, |
535 | { 6, 0x989c, | 447 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
536 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 448 | { 6, 0x989c, { 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, |
537 | { 6, 0x989c, | 449 | { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, |
538 | { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } }, | 450 | { 6, 0x989c, { 0x043f0000, 0x043f0000, 0x043f0000 } }, |
539 | { 6, 0x989c, | 451 | { 6, 0x989c, { 0x000c0000, 0x000c0000, 0x000c0000 } }, |
540 | { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } }, | 452 | { 6, 0x989c, { 0x02190000, 0x02190000, 0x02190000 } }, |
541 | { 6, 0x989c, | 453 | { 6, 0x989c, { 0x00240000, 0x00240000, 0x00240000 } }, |
542 | { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } }, | 454 | { 6, 0x989c, { 0x00b40000, 0x00b40000, 0x00b40000 } }, |
543 | { 6, 0x989c, | 455 | { 6, 0x989c, { 0x00990000, 0x00990000, 0x00990000 } }, |
544 | { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } }, | 456 | { 6, 0x989c, { 0x00500000, 0x00500000, 0x00500000 } }, |
545 | { 6, 0x989c, | 457 | { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, |
546 | { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } }, | 458 | { 6, 0x989c, { 0x00120000, 0x00120000, 0x00120000 } }, |
547 | { 6, 0x989c, | 459 | { 6, 0x989c, { 0xc0320000, 0xc0320000, 0xc0320000 } }, |
548 | { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } }, | 460 | { 6, 0x989c, { 0x01740000, 0x01740000, 0x01740000 } }, |
549 | { 6, 0x989c, | 461 | { 6, 0x989c, { 0x00110000, 0x00110000, 0x00110000 } }, |
550 | { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } }, | 462 | { 6, 0x989c, { 0x86280000, 0x86280000, 0x86280000 } }, |
551 | { 6, 0x989c, | 463 | { 6, 0x989c, { 0x31840000, 0x31840000, 0x31840000 } }, |
552 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 464 | { 6, 0x989c, { 0x00f20080, 0x00f20080, 0x00f20080 } }, |
553 | { 6, 0x989c, | 465 | { 6, 0x989c, { 0x00270019, 0x00270019, 0x00270019 } }, |
554 | { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, | 466 | { 6, 0x989c, { 0x00000003, 0x00000003, 0x00000003 } }, |
555 | { 6, 0x989c, | 467 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
556 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | 468 | { 6, 0x989c, { 0x000000b2, 0x000000b2, 0x000000b2 } }, |
557 | { 6, 0x989c, | 469 | { 6, 0x989c, { 0x00b02084, 0x00b02084, 0x00b02084 } }, |
558 | { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } }, | 470 | { 6, 0x989c, { 0x004125a4, 0x004125a4, 0x004125a4 } }, |
559 | { 6, 0x989c, | 471 | { 6, 0x989c, { 0x00119220, 0x00119220, 0x00119220 } }, |
560 | { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, | 472 | { 6, 0x989c, { 0x001a4800, 0x001a4800, 0x001a4800 } }, |
561 | { 6, 0x989c, | 473 | { 6, 0x98d8, { 0x000b0230, 0x000b0230, 0x000b0230 } }, |
562 | { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } }, | 474 | { 7, 0x989c, { 0x00000094, 0x00000094, 0x00000094 } }, |
563 | { 6, 0x989c, | 475 | { 7, 0x989c, { 0x00000091, 0x00000091, 0x00000091 } }, |
564 | { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, | 476 | { 7, 0x989c, { 0x00000012, 0x00000012, 0x00000012 } }, |
565 | { 6, 0x989c, | 477 | { 7, 0x989c, { 0x00000080, 0x00000080, 0x00000080 } }, |
566 | { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } }, | 478 | { 7, 0x989c, { 0x000000d9, 0x000000d9, 0x000000d9 } }, |
567 | { 6, 0x989c, | 479 | { 7, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } }, |
568 | { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } }, | 480 | { 7, 0x989c, { 0x000000f0, 0x000000f0, 0x000000f0 } }, |
569 | { 6, 0x989c, | 481 | { 7, 0x989c, { 0x000000a2, 0x000000a2, 0x000000a2 } }, |
570 | { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } }, | 482 | { 7, 0x989c, { 0x00000052, 0x00000052, 0x00000052 } }, |
571 | { 6, 0x989c, | 483 | { 7, 0x989c, { 0x000000d4, 0x000000d4, 0x000000d4 } }, |
572 | { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, | 484 | { 7, 0x989c, { 0x000014cc, 0x000014cc, 0x000014cc } }, |
573 | { 6, 0x989c, | 485 | { 7, 0x989c, { 0x0000048c, 0x0000048c, 0x0000048c } }, |
574 | { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, | 486 | { 7, 0x98c4, { 0x00000003, 0x00000003, 0x00000003 } }, |
575 | { 6, 0x989c, | ||
576 | { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } }, | ||
577 | { 6, 0x989c, | ||
578 | { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } }, | ||
579 | { 6, 0x989c, | ||
580 | { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, | ||
581 | { 6, 0x989c, | ||
582 | { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } }, | ||
583 | { 6, 0x989c, | ||
584 | { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } }, | ||
585 | { 6, 0x989c, | ||
586 | { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } }, | ||
587 | { 6, 0x989c, | ||
588 | { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } }, | ||
589 | { 6, 0x989c, | ||
590 | { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, | ||
591 | { 6, 0x989c, | ||
592 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
593 | { 6, 0x989c, | ||
594 | { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } }, | ||
595 | { 6, 0x989c, | ||
596 | { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } }, | ||
597 | { 6, 0x989c, | ||
598 | { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } }, | ||
599 | { 6, 0x989c, | ||
600 | { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } }, | ||
601 | { 6, 0x989c, | ||
602 | { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } }, | ||
603 | { 6, 0x98d8, | ||
604 | { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } }, | ||
605 | { 7, 0x989c, | ||
606 | { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, | ||
607 | { 7, 0x989c, | ||
608 | { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, | ||
609 | { 7, 0x989c, | ||
610 | { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } }, | ||
611 | { 7, 0x989c, | ||
612 | { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, | ||
613 | { 7, 0x989c, | ||
614 | { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } }, | ||
615 | { 7, 0x989c, | ||
616 | { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, | ||
617 | { 7, 0x989c, | ||
618 | { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, | ||
619 | { 7, 0x989c, | ||
620 | { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } }, | ||
621 | { 7, 0x989c, | ||
622 | { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } }, | ||
623 | { 7, 0x989c, | ||
624 | { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, | ||
625 | { 7, 0x989c, | ||
626 | { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, | ||
627 | { 7, 0x989c, | ||
628 | { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, | ||
629 | { 7, 0x98c4, | ||
630 | { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, | ||
631 | }; | 487 | }; |
632 | 488 | ||
633 | 489 | ||
@@ -636,11 +492,15 @@ static const struct ath5k_ini_rfbuffer rfb_5112a[] = { | |||
636 | * RF2413 (Griffin) * | 492 | * RF2413 (Griffin) * |
637 | \******************/ | 493 | \******************/ |
638 | 494 | ||
495 | /* BANK 2 len pos col */ | ||
496 | #define AR5K_RF2413_RF_TURBO { 1, 1, 2 } | ||
497 | |||
639 | /* BANK 6 len pos col */ | 498 | /* BANK 6 len pos col */ |
640 | #define AR5K_RF2413_OB_2GHZ { 3, 168, 0 } | 499 | #define AR5K_RF2413_OB_2GHZ { 3, 168, 0 } |
641 | #define AR5K_RF2413_DB_2GHZ { 3, 165, 0 } | 500 | #define AR5K_RF2413_DB_2GHZ { 3, 165, 0 } |
642 | 501 | ||
643 | static const struct ath5k_rf_reg rf_regs_2413[] = { | 502 | static const struct ath5k_rf_reg rf_regs_2413[] = { |
503 | {2, AR5K_RF_TURBO, AR5K_RF2413_RF_TURBO}, | ||
644 | {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ}, | 504 | {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ}, |
645 | {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ}, | 505 | {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ}, |
646 | }; | 506 | }; |
@@ -649,73 +509,40 @@ static const struct ath5k_rf_reg rf_regs_2413[] = { | |||
649 | * XXX: a/aTurbo ??? | 509 | * XXX: a/aTurbo ??? |
650 | */ | 510 | */ |
651 | static const struct ath5k_ini_rfbuffer rfb_2413[] = { | 511 | static const struct ath5k_ini_rfbuffer rfb_2413[] = { |
652 | { 1, 0x98d4, | 512 | /* BANK / C.R. A/XR B G */ |
653 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | 513 | { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, |
654 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | 514 | { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, |
655 | { 2, 0x98d0, | 515 | { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, |
656 | { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, | 516 | { 6, 0x989c, { 0xf0000000, 0xf0000000, 0xf0000000 } }, |
657 | { 3, 0x98dc, | 517 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
658 | { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, | 518 | { 6, 0x989c, { 0x03000000, 0x03000000, 0x03000000 } }, |
659 | { 6, 0x989c, | 519 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
660 | { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } }, | 520 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
661 | { 6, 0x989c, | 521 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
662 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 522 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
663 | { 6, 0x989c, | 523 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
664 | { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } }, | 524 | { 6, 0x989c, { 0x40400000, 0x40400000, 0x40400000 } }, |
665 | { 6, 0x989c, | 525 | { 6, 0x989c, { 0x65050000, 0x65050000, 0x65050000 } }, |
666 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 526 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
667 | { 6, 0x989c, | 527 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
668 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 528 | { 6, 0x989c, { 0x00420000, 0x00420000, 0x00420000 } }, |
669 | { 6, 0x989c, | 529 | { 6, 0x989c, { 0x00b50000, 0x00b50000, 0x00b50000 } }, |
670 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 530 | { 6, 0x989c, { 0x00030000, 0x00030000, 0x00030000 } }, |
671 | { 6, 0x989c, | 531 | { 6, 0x989c, { 0x00f70000, 0x00f70000, 0x00f70000 } }, |
672 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 532 | { 6, 0x989c, { 0x009d0000, 0x009d0000, 0x009d0000 } }, |
673 | { 6, 0x989c, | 533 | { 6, 0x989c, { 0x00220000, 0x00220000, 0x00220000 } }, |
674 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 534 | { 6, 0x989c, { 0x04220000, 0x04220000, 0x04220000 } }, |
675 | { 6, 0x989c, | 535 | { 6, 0x989c, { 0x00230018, 0x00230018, 0x00230018 } }, |
676 | { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } }, | 536 | { 6, 0x989c, { 0x00280000, 0x00280060, 0x00280060 } }, |
677 | { 6, 0x989c, | 537 | { 6, 0x989c, { 0x005000c0, 0x005000c3, 0x005000c3 } }, |
678 | { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } }, | 538 | { 6, 0x989c, { 0x0004007f, 0x0004007f, 0x0004007f } }, |
679 | { 6, 0x989c, | 539 | { 6, 0x989c, { 0x00000458, 0x00000458, 0x00000458 } }, |
680 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 540 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
681 | { 6, 0x989c, | 541 | { 6, 0x989c, { 0x0000c000, 0x0000c000, 0x0000c000 } }, |
682 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 542 | { 6, 0x98d8, { 0x00400230, 0x00400230, 0x00400230 } }, |
683 | { 6, 0x989c, | 543 | { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, |
684 | { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } }, | 544 | { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, |
685 | { 6, 0x989c, | 545 | { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, |
686 | { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } }, | ||
687 | { 6, 0x989c, | ||
688 | { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } }, | ||
689 | { 6, 0x989c, | ||
690 | { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } }, | ||
691 | { 6, 0x989c, | ||
692 | { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } }, | ||
693 | { 6, 0x989c, | ||
694 | { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } }, | ||
695 | { 6, 0x989c, | ||
696 | { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } }, | ||
697 | { 6, 0x989c, | ||
698 | { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } }, | ||
699 | { 6, 0x989c, | ||
700 | { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } }, | ||
701 | { 6, 0x989c, | ||
702 | { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } }, | ||
703 | { 6, 0x989c, | ||
704 | { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } }, | ||
705 | { 6, 0x989c, | ||
706 | { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } }, | ||
707 | { 6, 0x989c, | ||
708 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
709 | { 6, 0x989c, | ||
710 | { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } }, | ||
711 | { 6, 0x98d8, | ||
712 | { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } }, | ||
713 | { 7, 0x989c, | ||
714 | { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, | ||
715 | { 7, 0x989c, | ||
716 | { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, | ||
717 | { 7, 0x98cc, | ||
718 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
719 | }; | 546 | }; |
720 | 547 | ||
721 | 548 | ||
@@ -724,88 +551,57 @@ static const struct ath5k_ini_rfbuffer rfb_2413[] = { | |||
724 | * RF2315/RF2316 (Cobra SoC) * | 551 | * RF2315/RF2316 (Cobra SoC) * |
725 | \***************************/ | 552 | \***************************/ |
726 | 553 | ||
554 | /* BANK 2 len pos col */ | ||
555 | #define AR5K_RF2316_RF_TURBO { 1, 1, 2 } | ||
556 | |||
727 | /* BANK 6 len pos col */ | 557 | /* BANK 6 len pos col */ |
728 | #define AR5K_RF2316_OB_2GHZ { 3, 178, 0 } | 558 | #define AR5K_RF2316_OB_2GHZ { 3, 178, 0 } |
729 | #define AR5K_RF2316_DB_2GHZ { 3, 175, 0 } | 559 | #define AR5K_RF2316_DB_2GHZ { 3, 175, 0 } |
730 | 560 | ||
731 | static const struct ath5k_rf_reg rf_regs_2316[] = { | 561 | static const struct ath5k_rf_reg rf_regs_2316[] = { |
562 | {2, AR5K_RF_TURBO, AR5K_RF2316_RF_TURBO}, | ||
732 | {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ}, | 563 | {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ}, |
733 | {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ}, | 564 | {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ}, |
734 | }; | 565 | }; |
735 | 566 | ||
736 | /* Default mode specific settings */ | 567 | /* Default mode specific settings */ |
737 | static const struct ath5k_ini_rfbuffer rfb_2316[] = { | 568 | static const struct ath5k_ini_rfbuffer rfb_2316[] = { |
738 | { 1, 0x98d4, | 569 | /* BANK / C.R. A/XR B G */ |
739 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | 570 | { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, |
740 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | 571 | { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, |
741 | { 2, 0x98d0, | 572 | { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, |
742 | { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, | 573 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
743 | { 3, 0x98dc, | 574 | { 6, 0x989c, { 0xc0000000, 0xc0000000, 0xc0000000 } }, |
744 | { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, | 575 | { 6, 0x989c, { 0x0f000000, 0x0f000000, 0x0f000000 } }, |
745 | { 6, 0x989c, | 576 | { 6, 0x989c, { 0x02000000, 0x02000000, 0x02000000 } }, |
746 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 577 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
747 | { 6, 0x989c, | 578 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
748 | { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } }, | 579 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
749 | { 6, 0x989c, | 580 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
750 | { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, | 581 | { 6, 0x989c, { 0xf8000000, 0xf8000000, 0xf8000000 } }, |
751 | { 6, 0x989c, | 582 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
752 | { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } }, | 583 | { 6, 0x989c, { 0x95150000, 0x95150000, 0x95150000 } }, |
753 | { 6, 0x989c, | 584 | { 6, 0x989c, { 0xc1000000, 0xc1000000, 0xc1000000 } }, |
754 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 585 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
755 | { 6, 0x989c, | 586 | { 6, 0x989c, { 0x00080000, 0x00080000, 0x00080000 } }, |
756 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 587 | { 6, 0x989c, { 0x00d50000, 0x00d50000, 0x00d50000 } }, |
757 | { 6, 0x989c, | 588 | { 6, 0x989c, { 0x000e0000, 0x000e0000, 0x000e0000 } }, |
758 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 589 | { 6, 0x989c, { 0x00dc0000, 0x00dc0000, 0x00dc0000 } }, |
759 | { 6, 0x989c, | 590 | { 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } }, |
760 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 591 | { 6, 0x989c, { 0x008a0000, 0x008a0000, 0x008a0000 } }, |
761 | { 6, 0x989c, | 592 | { 6, 0x989c, { 0x10880000, 0x10880000, 0x10880000 } }, |
762 | { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } }, | 593 | { 6, 0x989c, { 0x008c0060, 0x008c0060, 0x008c0060 } }, |
763 | { 6, 0x989c, | 594 | { 6, 0x989c, { 0x00a00000, 0x00a00080, 0x00a00080 } }, |
764 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 595 | { 6, 0x989c, { 0x00400000, 0x0040000d, 0x0040000d } }, |
765 | { 6, 0x989c, | 596 | { 6, 0x989c, { 0x00110400, 0x00110400, 0x00110400 } }, |
766 | { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } }, | 597 | { 6, 0x989c, { 0x00000060, 0x00000060, 0x00000060 } }, |
767 | { 6, 0x989c, | 598 | { 6, 0x989c, { 0x00000001, 0x00000001, 0x00000001 } }, |
768 | { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } }, | 599 | { 6, 0x989c, { 0x00000b00, 0x00000b00, 0x00000b00 } }, |
769 | { 6, 0x989c, | 600 | { 6, 0x989c, { 0x00000be8, 0x00000be8, 0x00000be8 } }, |
770 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 601 | { 6, 0x98c0, { 0x00010000, 0x00010000, 0x00010000 } }, |
771 | { 6, 0x989c, | 602 | { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, |
772 | { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } }, | 603 | { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, |
773 | { 6, 0x989c, | 604 | { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, |
774 | { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } }, | ||
775 | { 6, 0x989c, | ||
776 | { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } }, | ||
777 | { 6, 0x989c, | ||
778 | { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } }, | ||
779 | { 6, 0x989c, | ||
780 | { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, | ||
781 | { 6, 0x989c, | ||
782 | { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } }, | ||
783 | { 6, 0x989c, | ||
784 | { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } }, | ||
785 | { 6, 0x989c, | ||
786 | { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } }, | ||
787 | { 6, 0x989c, | ||
788 | { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } }, | ||
789 | { 6, 0x989c, | ||
790 | { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } }, | ||
791 | { 6, 0x989c, | ||
792 | { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } }, | ||
793 | { 6, 0x989c, | ||
794 | { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, | ||
795 | { 6, 0x989c, | ||
796 | { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, | ||
797 | { 6, 0x989c, | ||
798 | { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } }, | ||
799 | { 6, 0x989c, | ||
800 | { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } }, | ||
801 | { 6, 0x98c0, | ||
802 | { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, | ||
803 | { 7, 0x989c, | ||
804 | { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, | ||
805 | { 7, 0x989c, | ||
806 | { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, | ||
807 | { 7, 0x98cc, | ||
808 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
809 | }; | 605 | }; |
810 | 606 | ||
811 | 607 | ||
@@ -835,93 +631,50 @@ static const struct ath5k_rf_reg rf_regs_5413[] = { | |||
835 | 631 | ||
836 | /* Default mode specific settings */ | 632 | /* Default mode specific settings */ |
837 | static const struct ath5k_ini_rfbuffer rfb_5413[] = { | 633 | static const struct ath5k_ini_rfbuffer rfb_5413[] = { |
838 | { 1, 0x98d4, | 634 | /* BANK / C.R. A/XR B G */ |
839 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | 635 | { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, |
840 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | 636 | { 2, 0x98d0, { 0x00000008, 0x00000008, 0x00000008 } }, |
841 | { 2, 0x98d0, | 637 | { 3, 0x98dc, { 0x00a000c0, 0x00e000c0, 0x00e000c0 } }, |
842 | { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, | 638 | { 6, 0x989c, { 0x33000000, 0x33000000, 0x33000000 } }, |
843 | { 3, 0x98dc, | 639 | { 6, 0x989c, { 0x01000000, 0x01000000, 0x01000000 } }, |
844 | { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } }, | 640 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
845 | { 6, 0x989c, | 641 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
846 | { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } }, | 642 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
847 | { 6, 0x989c, | 643 | { 6, 0x989c, { 0x1f000000, 0x1f000000, 0x1f000000 } }, |
848 | { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } }, | 644 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
849 | { 6, 0x989c, | 645 | { 6, 0x989c, { 0x00b80000, 0x00b80000, 0x00b80000 } }, |
850 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 646 | { 6, 0x989c, { 0x00b70000, 0x00b70000, 0x00b70000 } }, |
851 | { 6, 0x989c, | 647 | { 6, 0x989c, { 0x00840000, 0x00840000, 0x00840000 } }, |
852 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 648 | { 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } }, |
853 | { 6, 0x989c, | 649 | { 6, 0x989c, { 0x00c00000, 0x00c00000, 0x00c00000 } }, |
854 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 650 | { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, |
855 | { 6, 0x989c, | 651 | { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, |
856 | { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } }, | 652 | { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, |
857 | { 6, 0x989c, | 653 | { 6, 0x989c, { 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, |
858 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 654 | { 6, 0x989c, { 0x00d70000, 0x00d70000, 0x00d70000 } }, |
859 | { 6, 0x989c, | 655 | { 6, 0x989c, { 0x00610000, 0x00610000, 0x00610000 } }, |
860 | { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } }, | 656 | { 6, 0x989c, { 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, |
861 | { 6, 0x989c, | 657 | { 6, 0x989c, { 0x00de0000, 0x00de0000, 0x00de0000 } }, |
862 | { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } }, | 658 | { 6, 0x989c, { 0x007f0000, 0x007f0000, 0x007f0000 } }, |
863 | { 6, 0x989c, | 659 | { 6, 0x989c, { 0x043d0000, 0x043d0000, 0x043d0000 } }, |
864 | { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, | 660 | { 6, 0x989c, { 0x00770000, 0x00770000, 0x00770000 } }, |
865 | { 6, 0x989c, | 661 | { 6, 0x989c, { 0x00440000, 0x00440000, 0x00440000 } }, |
866 | { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, | 662 | { 6, 0x989c, { 0x00980000, 0x00980000, 0x00980000 } }, |
867 | { 6, 0x989c, | 663 | { 6, 0x989c, { 0x00100080, 0x00100080, 0x00100080 } }, |
868 | { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } }, | 664 | { 6, 0x989c, { 0x0005c034, 0x0005c034, 0x0005c034 } }, |
869 | { 6, 0x989c, | 665 | { 6, 0x989c, { 0x003100f0, 0x003100f0, 0x003100f0 } }, |
870 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | 666 | { 6, 0x989c, { 0x000c011f, 0x000c011f, 0x000c011f } }, |
871 | { 6, 0x989c, | 667 | { 6, 0x989c, { 0x00510040, 0x00510040, 0x00510040 } }, |
872 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | 668 | { 6, 0x989c, { 0x005000da, 0x005000da, 0x005000da } }, |
873 | { 6, 0x989c, | 669 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
874 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | 670 | { 6, 0x989c, { 0x00004044, 0x00004044, 0x00004044 } }, |
875 | { 6, 0x989c, | 671 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
876 | { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, | 672 | { 6, 0x989c, { 0x000060c0, 0x000060c0, 0x000060c0 } }, |
877 | { 6, 0x989c, | 673 | { 6, 0x989c, { 0x00002c00, 0x00003600, 0x00003600 } }, |
878 | { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } }, | 674 | { 6, 0x98c8, { 0x00000403, 0x00040403, 0x00040403 } }, |
879 | { 6, 0x989c, | 675 | { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, |
880 | { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } }, | 676 | { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, |
881 | { 6, 0x989c, | 677 | { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, |
882 | { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, | ||
883 | { 6, 0x989c, | ||
884 | { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } }, | ||
885 | { 6, 0x989c, | ||
886 | { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } }, | ||
887 | { 6, 0x989c, | ||
888 | { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } }, | ||
889 | { 6, 0x989c, | ||
890 | { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, | ||
891 | { 6, 0x989c, | ||
892 | { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } }, | ||
893 | { 6, 0x989c, | ||
894 | { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, | ||
895 | { 6, 0x989c, | ||
896 | { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } }, | ||
897 | { 6, 0x989c, | ||
898 | { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } }, | ||
899 | { 6, 0x989c, | ||
900 | { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } }, | ||
901 | { 6, 0x989c, | ||
902 | { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } }, | ||
903 | { 6, 0x989c, | ||
904 | { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } }, | ||
905 | { 6, 0x989c, | ||
906 | { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } }, | ||
907 | { 6, 0x989c, | ||
908 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
909 | { 6, 0x989c, | ||
910 | { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } }, | ||
911 | { 6, 0x989c, | ||
912 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
913 | { 6, 0x989c, | ||
914 | { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } }, | ||
915 | { 6, 0x989c, | ||
916 | { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } }, | ||
917 | { 6, 0x98c8, | ||
918 | { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } }, | ||
919 | { 7, 0x989c, | ||
920 | { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, | ||
921 | { 7, 0x989c, | ||
922 | { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, | ||
923 | { 7, 0x98cc, | ||
924 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
925 | }; | 678 | }; |
926 | 679 | ||
927 | 680 | ||
@@ -931,92 +684,59 @@ static const struct ath5k_ini_rfbuffer rfb_5413[] = { | |||
931 | * AR2317 (Spider SoC) * | 684 | * AR2317 (Spider SoC) * |
932 | \***************************/ | 685 | \***************************/ |
933 | 686 | ||
687 | /* BANK 2 len pos col */ | ||
688 | #define AR5K_RF2425_RF_TURBO { 1, 1, 2 } | ||
689 | |||
934 | /* BANK 6 len pos col */ | 690 | /* BANK 6 len pos col */ |
935 | #define AR5K_RF2425_OB_2GHZ { 3, 193, 0 } | 691 | #define AR5K_RF2425_OB_2GHZ { 3, 193, 0 } |
936 | #define AR5K_RF2425_DB_2GHZ { 3, 190, 0 } | 692 | #define AR5K_RF2425_DB_2GHZ { 3, 190, 0 } |
937 | 693 | ||
938 | static const struct ath5k_rf_reg rf_regs_2425[] = { | 694 | static const struct ath5k_rf_reg rf_regs_2425[] = { |
695 | {2, AR5K_RF_TURBO, AR5K_RF2425_RF_TURBO}, | ||
939 | {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ}, | 696 | {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ}, |
940 | {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ}, | 697 | {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ}, |
941 | }; | 698 | }; |
942 | 699 | ||
943 | /* Default mode specific settings | 700 | /* Default mode specific settings |
944 | * XXX: a/aTurbo ? | ||
945 | */ | 701 | */ |
946 | static const struct ath5k_ini_rfbuffer rfb_2425[] = { | 702 | static const struct ath5k_ini_rfbuffer rfb_2425[] = { |
947 | { 1, 0x98d4, | 703 | /* BANK / C.R. A/XR B G */ |
948 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | 704 | { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, |
949 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | 705 | { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, |
950 | { 2, 0x98d0, | 706 | { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, |
951 | { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, | 707 | { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, |
952 | { 3, 0x98dc, | 708 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
953 | { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, | 709 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
954 | { 6, 0x989c, | 710 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
955 | { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, | 711 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
956 | { 6, 0x989c, | 712 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
957 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 713 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
958 | { 6, 0x989c, | 714 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
959 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 715 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
960 | { 6, 0x989c, | 716 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
961 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 717 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
962 | { 6, 0x989c, | 718 | { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, |
963 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 719 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
964 | { 6, 0x989c, | 720 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
965 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 721 | { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } }, |
966 | { 6, 0x989c, | 722 | { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } }, |
967 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 723 | { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, |
968 | { 6, 0x989c, | 724 | { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } }, |
969 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 725 | { 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } }, |
970 | { 6, 0x989c, | 726 | { 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } }, |
971 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 727 | { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } }, |
972 | { 6, 0x989c, | 728 | { 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } }, |
973 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 729 | { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } }, |
974 | { 6, 0x989c, | 730 | { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } }, |
975 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 731 | { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } }, |
976 | { 6, 0x989c, | 732 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
977 | { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, | 733 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
978 | { 6, 0x989c, | 734 | { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } }, |
979 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 735 | { 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } }, |
980 | { 6, 0x989c, | 736 | { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } }, |
981 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 737 | { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, |
982 | { 6, 0x989c, | 738 | { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, |
983 | { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, | 739 | { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, |
984 | { 6, 0x989c, | ||
985 | { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, | ||
986 | { 6, 0x989c, | ||
987 | { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, | ||
988 | { 6, 0x989c, | ||
989 | { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, | ||
990 | { 6, 0x989c, | ||
991 | { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, | ||
992 | { 6, 0x989c, | ||
993 | { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, | ||
994 | { 6, 0x989c, | ||
995 | { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, | ||
996 | { 6, 0x989c, | ||
997 | { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, | ||
998 | { 6, 0x989c, | ||
999 | { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, | ||
1000 | { 6, 0x989c, | ||
1001 | { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, | ||
1002 | { 6, 0x989c, | ||
1003 | { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, | ||
1004 | { 6, 0x989c, | ||
1005 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1006 | { 6, 0x989c, | ||
1007 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1008 | { 6, 0x989c, | ||
1009 | { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, | ||
1010 | { 6, 0x989c, | ||
1011 | { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, | ||
1012 | { 6, 0x98c4, | ||
1013 | { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, | ||
1014 | { 7, 0x989c, | ||
1015 | { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, | ||
1016 | { 7, 0x989c, | ||
1017 | { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, | ||
1018 | { 7, 0x98cc, | ||
1019 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
1020 | }; | 740 | }; |
1021 | 741 | ||
1022 | /* | 742 | /* |
@@ -1024,158 +744,85 @@ static const struct ath5k_ini_rfbuffer rfb_2425[] = { | |||
1024 | * bank modification and get rid of this | 744 | * bank modification and get rid of this |
1025 | */ | 745 | */ |
1026 | static const struct ath5k_ini_rfbuffer rfb_2317[] = { | 746 | static const struct ath5k_ini_rfbuffer rfb_2317[] = { |
1027 | { 1, 0x98d4, | 747 | /* BANK / C.R. A/XR B G */ |
1028 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | 748 | { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, |
1029 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | 749 | { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, |
1030 | { 2, 0x98d0, | 750 | { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, |
1031 | { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, | 751 | { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, |
1032 | { 3, 0x98dc, | 752 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1033 | { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, | 753 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1034 | { 6, 0x989c, | 754 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1035 | { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, | 755 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1036 | { 6, 0x989c, | 756 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1037 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 757 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1038 | { 6, 0x989c, | 758 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1039 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 759 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1040 | { 6, 0x989c, | 760 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1041 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 761 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1042 | { 6, 0x989c, | 762 | { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, |
1043 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 763 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1044 | { 6, 0x989c, | 764 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1045 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 765 | { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } }, |
1046 | { 6, 0x989c, | 766 | { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } }, |
1047 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 767 | { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, |
1048 | { 6, 0x989c, | 768 | { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } }, |
1049 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 769 | { 6, 0x989c, { 0x00e70000, 0x00e70000, 0x00e70000 } }, |
1050 | { 6, 0x989c, | 770 | { 6, 0x989c, { 0x00140100, 0x00140100, 0x00140100 } }, |
1051 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 771 | { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } }, |
1052 | { 6, 0x989c, | 772 | { 6, 0x989c, { 0x0007001a, 0x0007001a, 0x0007001a } }, |
1053 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 773 | { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } }, |
1054 | { 6, 0x989c, | 774 | { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } }, |
1055 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 775 | { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } }, |
1056 | { 6, 0x989c, | 776 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1057 | { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, | 777 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1058 | { 6, 0x989c, | 778 | { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } }, |
1059 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 779 | { 6, 0x989c, { 0x00009688, 0x00009688, 0x00009688 } }, |
1060 | { 6, 0x989c, | 780 | { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } }, |
1061 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 781 | { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, |
1062 | { 6, 0x989c, | 782 | { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, |
1063 | { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, | 783 | { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, |
1064 | { 6, 0x989c, | ||
1065 | { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, | ||
1066 | { 6, 0x989c, | ||
1067 | { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, | ||
1068 | { 6, 0x989c, | ||
1069 | { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, | ||
1070 | { 6, 0x989c, | ||
1071 | { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, | ||
1072 | { 6, 0x989c, | ||
1073 | { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } }, | ||
1074 | { 6, 0x989c, | ||
1075 | { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, | ||
1076 | { 6, 0x989c, | ||
1077 | { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, | ||
1078 | { 6, 0x989c, | ||
1079 | { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, | ||
1080 | { 6, 0x989c, | ||
1081 | { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, | ||
1082 | { 6, 0x989c, | ||
1083 | { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, | ||
1084 | { 6, 0x989c, | ||
1085 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1086 | { 6, 0x989c, | ||
1087 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1088 | { 6, 0x989c, | ||
1089 | { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, | ||
1090 | { 6, 0x989c, | ||
1091 | { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } }, | ||
1092 | { 6, 0x98c4, | ||
1093 | { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, | ||
1094 | { 7, 0x989c, | ||
1095 | { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, | ||
1096 | { 7, 0x989c, | ||
1097 | { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, | ||
1098 | { 7, 0x98cc, | ||
1099 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
1100 | }; | 784 | }; |
1101 | 785 | ||
1102 | /* | 786 | /* |
1103 | * TODO: Handle the few differences with swan during | 787 | * TODO: Handle the few differences with swan during |
1104 | * bank modification and get rid of this | 788 | * bank modification and get rid of this |
1105 | * XXX: a/aTurbo ? | ||
1106 | */ | 789 | */ |
1107 | static const struct ath5k_ini_rfbuffer rfb_2417[] = { | 790 | static const struct ath5k_ini_rfbuffer rfb_2417[] = { |
1108 | { 1, 0x98d4, | 791 | /* BANK / C.R. A/XR B G */ |
1109 | /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ | 792 | { 1, 0x98d4, { 0x00000020, 0x00000020, 0x00000020 } }, |
1110 | { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, | 793 | { 2, 0x98d0, { 0x02001408, 0x02001408, 0x02001408 } }, |
1111 | { 2, 0x98d0, | 794 | { 3, 0x98dc, { 0x00a020c0, 0x00e020c0, 0x00e020c0 } }, |
1112 | { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, | 795 | { 6, 0x989c, { 0x10000000, 0x10000000, 0x10000000 } }, |
1113 | { 3, 0x98dc, | 796 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1114 | { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, | 797 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1115 | { 6, 0x989c, | 798 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1116 | { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, | 799 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1117 | { 6, 0x989c, | 800 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1118 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 801 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1119 | { 6, 0x989c, | 802 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1120 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 803 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1121 | { 6, 0x989c, | 804 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1122 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 805 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1123 | { 6, 0x989c, | 806 | { 6, 0x989c, { 0x002a0000, 0x002a0000, 0x002a0000 } }, |
1124 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 807 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1125 | { 6, 0x989c, | 808 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1126 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 809 | { 6, 0x989c, { 0x00100000, 0x00100000, 0x00100000 } }, |
1127 | { 6, 0x989c, | 810 | { 6, 0x989c, { 0x00020000, 0x00020000, 0x00020000 } }, |
1128 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 811 | { 6, 0x989c, { 0x00730000, 0x00730000, 0x00730000 } }, |
1129 | { 6, 0x989c, | 812 | { 6, 0x989c, { 0x00f80000, 0x00f80000, 0x00f80000 } }, |
1130 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 813 | { 6, 0x989c, { 0x00e70000, 0x80e70000, 0x80e70000 } }, |
1131 | { 6, 0x989c, | 814 | { 6, 0x989c, { 0x00140000, 0x00140000, 0x00140000 } }, |
1132 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 815 | { 6, 0x989c, { 0x00910040, 0x00910040, 0x00910040 } }, |
1133 | { 6, 0x989c, | 816 | { 6, 0x989c, { 0x0007001a, 0x0207001a, 0x0207001a } }, |
1134 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 817 | { 6, 0x989c, { 0x00410000, 0x00410000, 0x00410000 } }, |
1135 | { 6, 0x989c, | 818 | { 6, 0x989c, { 0x00810000, 0x00810060, 0x00810060 } }, |
1136 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 819 | { 6, 0x989c, { 0x00020800, 0x00020803, 0x00020803 } }, |
1137 | { 6, 0x989c, | 820 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1138 | { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, | 821 | { 6, 0x989c, { 0x00000000, 0x00000000, 0x00000000 } }, |
1139 | { 6, 0x989c, | 822 | { 6, 0x989c, { 0x00001660, 0x00001660, 0x00001660 } }, |
1140 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 823 | { 6, 0x989c, { 0x00001688, 0x00001688, 0x00001688 } }, |
1141 | { 6, 0x989c, | 824 | { 6, 0x98c4, { 0x00000001, 0x00000001, 0x00000001 } }, |
1142 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | 825 | { 7, 0x989c, { 0x00006400, 0x00006400, 0x00006400 } }, |
1143 | { 6, 0x989c, | 826 | { 7, 0x989c, { 0x00000800, 0x00000800, 0x00000800 } }, |
1144 | { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, | 827 | { 7, 0x98cc, { 0x0000000e, 0x0000000e, 0x0000000e } }, |
1145 | { 6, 0x989c, | ||
1146 | { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, | ||
1147 | { 6, 0x989c, | ||
1148 | { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, | ||
1149 | { 6, 0x989c, | ||
1150 | { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, | ||
1151 | { 6, 0x989c, | ||
1152 | { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } }, | ||
1153 | { 6, 0x989c, | ||
1154 | { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, | ||
1155 | { 6, 0x989c, | ||
1156 | { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, | ||
1157 | { 6, 0x989c, | ||
1158 | { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } }, | ||
1159 | { 6, 0x989c, | ||
1160 | { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, | ||
1161 | { 6, 0x989c, | ||
1162 | { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, | ||
1163 | { 6, 0x989c, | ||
1164 | { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, | ||
1165 | { 6, 0x989c, | ||
1166 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1167 | { 6, 0x989c, | ||
1168 | { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, | ||
1169 | { 6, 0x989c, | ||
1170 | { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, | ||
1171 | { 6, 0x989c, | ||
1172 | { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, | ||
1173 | { 6, 0x98c4, | ||
1174 | { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, | ||
1175 | { 7, 0x989c, | ||
1176 | { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, | ||
1177 | { 7, 0x989c, | ||
1178 | { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, | ||
1179 | { 7, 0x98cc, | ||
1180 | { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, | ||
1181 | }; | 828 | }; |
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c index 90757de7bf59..a073cdce1f15 100644 --- a/drivers/net/wireless/ath/ath5k/sysfs.c +++ b/drivers/net/wireless/ath/ath5k/sysfs.c | |||
@@ -10,7 +10,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \ | |||
10 | struct device_attribute *attr, \ | 10 | struct device_attribute *attr, \ |
11 | char *buf) \ | 11 | char *buf) \ |
12 | { \ | 12 | { \ |
13 | struct ath5k_softc *sc = dev_get_drvdata(dev); \ | 13 | struct ieee80211_hw *hw = dev_get_drvdata(dev); \ |
14 | struct ath5k_softc *sc = hw->priv; \ | ||
14 | return snprintf(buf, PAGE_SIZE, "%d\n", get); \ | 15 | return snprintf(buf, PAGE_SIZE, "%d\n", get); \ |
15 | } \ | 16 | } \ |
16 | \ | 17 | \ |
@@ -18,7 +19,8 @@ static ssize_t ath5k_attr_store_##name(struct device *dev, \ | |||
18 | struct device_attribute *attr, \ | 19 | struct device_attribute *attr, \ |
19 | const char *buf, size_t count) \ | 20 | const char *buf, size_t count) \ |
20 | { \ | 21 | { \ |
21 | struct ath5k_softc *sc = dev_get_drvdata(dev); \ | 22 | struct ieee80211_hw *hw = dev_get_drvdata(dev); \ |
23 | struct ath5k_softc *sc = hw->priv; \ | ||
22 | int val; \ | 24 | int val; \ |
23 | \ | 25 | \ |
24 | val = (int)simple_strtoul(buf, NULL, 10); \ | 26 | val = (int)simple_strtoul(buf, NULL, 10); \ |
@@ -33,7 +35,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \ | |||
33 | struct device_attribute *attr, \ | 35 | struct device_attribute *attr, \ |
34 | char *buf) \ | 36 | char *buf) \ |
35 | { \ | 37 | { \ |
36 | struct ath5k_softc *sc = dev_get_drvdata(dev); \ | 38 | struct ieee80211_hw *hw = dev_get_drvdata(dev); \ |
39 | struct ath5k_softc *sc = hw->priv; \ | ||
37 | return snprintf(buf, PAGE_SIZE, "%d\n", get); \ | 40 | return snprintf(buf, PAGE_SIZE, "%d\n", get); \ |
38 | } \ | 41 | } \ |
39 | static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL) | 42 | static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL) |
@@ -95,7 +98,7 @@ static struct attribute_group ath5k_attribute_group_ani = { | |||
95 | int | 98 | int |
96 | ath5k_sysfs_register(struct ath5k_softc *sc) | 99 | ath5k_sysfs_register(struct ath5k_softc *sc) |
97 | { | 100 | { |
98 | struct device *dev = &sc->pdev->dev; | 101 | struct device *dev = sc->dev; |
99 | int err; | 102 | int err; |
100 | 103 | ||
101 | err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani); | 104 | err = sysfs_create_group(&dev->kobj, &ath5k_attribute_group_ani); |
@@ -110,7 +113,7 @@ ath5k_sysfs_register(struct ath5k_softc *sc) | |||
110 | void | 113 | void |
111 | ath5k_sysfs_unregister(struct ath5k_softc *sc) | 114 | ath5k_sysfs_unregister(struct ath5k_softc *sc) |
112 | { | 115 | { |
113 | struct device *dev = &sc->pdev->dev; | 116 | struct device *dev = sc->dev; |
114 | 117 | ||
115 | sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani); | 118 | sysfs_remove_group(&dev->kobj, &ath5k_attribute_group_ani); |
116 | } | 119 | } |
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h new file mode 100644 index 000000000000..2de68adb6240 --- /dev/null +++ b/drivers/net/wireless/ath/ath5k/trace.h | |||
@@ -0,0 +1,107 @@ | |||
1 | #if !defined(__TRACE_ATH5K_H) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | #define __TRACE_ATH5K_H | ||
3 | |||
4 | #include <linux/tracepoint.h> | ||
5 | #include "base.h" | ||
6 | |||
7 | #ifndef CONFIG_ATH5K_TRACER | ||
8 | #undef TRACE_EVENT | ||
9 | #define TRACE_EVENT(name, proto, ...) \ | ||
10 | static inline void trace_ ## name(proto) {} | ||
11 | #endif | ||
12 | |||
13 | struct sk_buff; | ||
14 | |||
15 | #define PRIV_ENTRY __field(struct ath5k_softc *, priv) | ||
16 | #define PRIV_ASSIGN __entry->priv = priv | ||
17 | |||
18 | #undef TRACE_SYSTEM | ||
19 | #define TRACE_SYSTEM ath5k | ||
20 | |||
21 | TRACE_EVENT(ath5k_rx, | ||
22 | TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb), | ||
23 | TP_ARGS(priv, skb), | ||
24 | TP_STRUCT__entry( | ||
25 | PRIV_ENTRY | ||
26 | __field(unsigned long, skbaddr) | ||
27 | __dynamic_array(u8, frame, skb->len) | ||
28 | ), | ||
29 | TP_fast_assign( | ||
30 | PRIV_ASSIGN; | ||
31 | __entry->skbaddr = (unsigned long) skb; | ||
32 | memcpy(__get_dynamic_array(frame), skb->data, skb->len); | ||
33 | ), | ||
34 | TP_printk( | ||
35 | "[%p] RX skb=%lx", __entry->priv, __entry->skbaddr | ||
36 | ) | ||
37 | ); | ||
38 | |||
39 | TRACE_EVENT(ath5k_tx, | ||
40 | TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb, | ||
41 | struct ath5k_txq *q), | ||
42 | |||
43 | TP_ARGS(priv, skb, q), | ||
44 | |||
45 | TP_STRUCT__entry( | ||
46 | PRIV_ENTRY | ||
47 | __field(unsigned long, skbaddr) | ||
48 | __field(u8, qnum) | ||
49 | __dynamic_array(u8, frame, skb->len) | ||
50 | ), | ||
51 | |||
52 | TP_fast_assign( | ||
53 | PRIV_ASSIGN; | ||
54 | __entry->skbaddr = (unsigned long) skb; | ||
55 | __entry->qnum = (u8) q->qnum; | ||
56 | memcpy(__get_dynamic_array(frame), skb->data, skb->len); | ||
57 | ), | ||
58 | |||
59 | TP_printk( | ||
60 | "[%p] TX skb=%lx q=%d", __entry->priv, __entry->skbaddr, | ||
61 | __entry->qnum | ||
62 | ) | ||
63 | ); | ||
64 | |||
65 | TRACE_EVENT(ath5k_tx_complete, | ||
66 | TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb, | ||
67 | struct ath5k_txq *q, struct ath5k_tx_status *ts), | ||
68 | |||
69 | TP_ARGS(priv, skb, q, ts), | ||
70 | |||
71 | TP_STRUCT__entry( | ||
72 | PRIV_ENTRY | ||
73 | __field(unsigned long, skbaddr) | ||
74 | __field(u8, qnum) | ||
75 | __field(u8, ts_status) | ||
76 | __field(s8, ts_rssi) | ||
77 | __field(u8, ts_antenna) | ||
78 | ), | ||
79 | |||
80 | TP_fast_assign( | ||
81 | PRIV_ASSIGN; | ||
82 | __entry->skbaddr = (unsigned long) skb; | ||
83 | __entry->qnum = (u8) q->qnum; | ||
84 | __entry->ts_status = ts->ts_status; | ||
85 | __entry->ts_rssi = ts->ts_rssi; | ||
86 | __entry->ts_antenna = ts->ts_antenna; | ||
87 | ), | ||
88 | |||
89 | TP_printk( | ||
90 | "[%p] TX end skb=%lx q=%d stat=%x rssi=%d ant=%x", | ||
91 | __entry->priv, __entry->skbaddr, __entry->qnum, | ||
92 | __entry->ts_status, __entry->ts_rssi, __entry->ts_antenna | ||
93 | ) | ||
94 | ); | ||
95 | |||
96 | #endif /* __TRACE_ATH5K_H */ | ||
97 | |||
98 | #ifdef CONFIG_ATH5K_TRACER | ||
99 | |||
100 | #undef TRACE_INCLUDE_PATH | ||
101 | #define TRACE_INCLUDE_PATH ../../drivers/net/wireless/ath/ath5k | ||
102 | #undef TRACE_INCLUDE_FILE | ||
103 | #define TRACE_INCLUDE_FILE trace | ||
104 | |||
105 | #include <trace/define_trace.h> | ||
106 | |||
107 | #endif | ||