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 | ||
