diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
70 files changed, 17203 insertions, 10553 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 35f23bdc442f..d9c08c619a3a 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -5,7 +5,7 @@ config ATH9K_COMMON | |||
5 | 5 | ||
6 | config ATH9K | 6 | config ATH9K |
7 | tristate "Atheros 802.11n wireless cards support" | 7 | tristate "Atheros 802.11n wireless cards support" |
8 | depends on PCI && MAC80211 | 8 | depends on MAC80211 |
9 | select ATH9K_HW | 9 | select ATH9K_HW |
10 | select MAC80211_LEDS | 10 | select MAC80211_LEDS |
11 | select LEDS_CLASS | 11 | select LEDS_CLASS |
@@ -23,6 +23,24 @@ config ATH9K | |||
23 | 23 | ||
24 | If you choose to build a module, it'll be called ath9k. | 24 | If you choose to build a module, it'll be called ath9k. |
25 | 25 | ||
26 | config ATH9K_PCI | ||
27 | bool "Atheros ath9k PCI/PCIe bus support" | ||
28 | depends on ATH9K && PCI | ||
29 | ---help--- | ||
30 | This option enables the PCI bus support in ath9k. | ||
31 | |||
32 | Say Y, if you have a compatible PCI/PCIe wireless card. | ||
33 | |||
34 | config ATH9K_AHB | ||
35 | bool "Atheros ath9k AHB bus support" | ||
36 | depends on ATH9K | ||
37 | default n | ||
38 | ---help--- | ||
39 | This option enables the AHB bus support in ath9k. | ||
40 | |||
41 | Say Y, if you have a SoC with a compatible built-in | ||
42 | wireless MAC. Say N if unsure. | ||
43 | |||
26 | config ATH9K_DEBUGFS | 44 | config ATH9K_DEBUGFS |
27 | bool "Atheros ath9k debugging" | 45 | bool "Atheros ath9k debugging" |
28 | depends on ATH9K && DEBUG_FS | 46 | depends on ATH9K && DEBUG_FS |
@@ -32,6 +50,14 @@ config ATH9K_DEBUGFS | |||
32 | 50 | ||
33 | Also required for changing debug message flags at run time. | 51 | Also required for changing debug message flags at run time. |
34 | 52 | ||
53 | config ATH9K_RATE_CONTROL | ||
54 | bool "Atheros ath9k rate control" | ||
55 | depends on ATH9K | ||
56 | default y | ||
57 | ---help--- | ||
58 | Say Y, if you want to use the ath9k specific rate control | ||
59 | module instead of minstrel_ht. | ||
60 | |||
35 | config ATH9K_HTC | 61 | config ATH9K_HTC |
36 | tristate "Atheros HTC based wireless cards support" | 62 | tristate "Atheros HTC based wireless cards support" |
37 | depends on USB && MAC80211 | 63 | depends on USB && MAC80211 |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 973ae4f49f35..05a6fade7b1c 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -4,11 +4,10 @@ ath9k-y += beacon.o \ | |||
4 | main.o \ | 4 | main.o \ |
5 | recv.o \ | 5 | recv.o \ |
6 | xmit.o \ | 6 | xmit.o \ |
7 | virtual.o \ | ||
8 | rc.o | ||
9 | 7 | ||
10 | ath9k-$(CONFIG_PCI) += pci.o | 8 | ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o |
11 | ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o | 9 | ath9k-$(CONFIG_ATH9K_PCI) += pci.o |
10 | ath9k-$(CONFIG_ATH9K_AHB) += ahb.o | ||
12 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 11 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
13 | 12 | ||
14 | obj-$(CONFIG_ATH9K) += ath9k.o | 13 | obj-$(CONFIG_ATH9K) += ath9k.o |
@@ -46,6 +45,9 @@ ath9k_htc-y += htc_hst.o \ | |||
46 | htc_drv_txrx.o \ | 45 | htc_drv_txrx.o \ |
47 | htc_drv_main.o \ | 46 | htc_drv_main.o \ |
48 | htc_drv_beacon.o \ | 47 | htc_drv_beacon.o \ |
49 | htc_drv_init.o | 48 | htc_drv_init.o \ |
49 | htc_drv_gpio.o | ||
50 | |||
51 | ath9k_htc-$(CONFIG_ATH9K_HTC_DEBUGFS) += htc_drv_debug.o | ||
50 | 52 | ||
51 | obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o | 53 | obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o |
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index 1a984b02e9e5..5b49cd03bfdf 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> | 3 | * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> |
4 | * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> | 4 | * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> |
5 | * | 5 | * |
@@ -21,6 +21,18 @@ | |||
21 | #include <linux/ath9k_platform.h> | 21 | #include <linux/ath9k_platform.h> |
22 | #include "ath9k.h" | 22 | #include "ath9k.h" |
23 | 23 | ||
24 | static const struct platform_device_id ath9k_platform_id_table[] = { | ||
25 | { | ||
26 | .name = "ath9k", | ||
27 | .driver_data = AR5416_AR9100_DEVID, | ||
28 | }, | ||
29 | { | ||
30 | .name = "ar934x_wmac", | ||
31 | .driver_data = AR9300_DEVID_AR9340, | ||
32 | }, | ||
33 | {}, | ||
34 | }; | ||
35 | |||
24 | /* return bus cachesize in 4B word units */ | 36 | /* return bus cachesize in 4B word units */ |
25 | static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) | 37 | static void ath_ahb_read_cachesize(struct ath_common *common, int *csz) |
26 | { | 38 | { |
@@ -35,10 +47,9 @@ static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data) | |||
35 | 47 | ||
36 | pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; | 48 | pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; |
37 | if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { | 49 | if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { |
38 | ath_print(common, ATH_DBG_FATAL, | 50 | ath_err(common, |
39 | "%s: flash read failed, offset %08x " | 51 | "%s: flash read failed, offset %08x is out of range\n", |
40 | "is out of range\n", | 52 | __func__, off); |
41 | __func__, off); | ||
42 | return false; | 53 | return false; |
43 | } | 54 | } |
44 | 55 | ||
@@ -55,10 +66,10 @@ static struct ath_bus_ops ath_ahb_bus_ops = { | |||
55 | static int ath_ahb_probe(struct platform_device *pdev) | 66 | static int ath_ahb_probe(struct platform_device *pdev) |
56 | { | 67 | { |
57 | void __iomem *mem; | 68 | void __iomem *mem; |
58 | struct ath_wiphy *aphy; | ||
59 | struct ath_softc *sc; | 69 | struct ath_softc *sc; |
60 | struct ieee80211_hw *hw; | 70 | struct ieee80211_hw *hw; |
61 | struct resource *res; | 71 | struct resource *res; |
72 | const struct platform_device_id *id = platform_get_device_id(pdev); | ||
62 | int irq; | 73 | int irq; |
63 | int ret = 0; | 74 | int ret = 0; |
64 | struct ath_hw *ah; | 75 | struct ath_hw *ah; |
@@ -77,7 +88,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
77 | goto err_out; | 88 | goto err_out; |
78 | } | 89 | } |
79 | 90 | ||
80 | mem = ioremap_nocache(res->start, res->end - res->start + 1); | 91 | mem = ioremap_nocache(res->start, resource_size(res)); |
81 | if (mem == NULL) { | 92 | if (mem == NULL) { |
82 | dev_err(&pdev->dev, "ioremap failed\n"); | 93 | dev_err(&pdev->dev, "ioremap failed\n"); |
83 | ret = -ENOMEM; | 94 | ret = -ENOMEM; |
@@ -93,8 +104,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
93 | 104 | ||
94 | irq = res->start; | 105 | irq = res->start; |
95 | 106 | ||
96 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + | 107 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); |
97 | sizeof(struct ath_softc), &ath9k_ops); | ||
98 | if (hw == NULL) { | 108 | if (hw == NULL) { |
99 | dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); | 109 | dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); |
100 | ret = -ENOMEM; | 110 | ret = -ENOMEM; |
@@ -104,11 +114,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
104 | SET_IEEE80211_DEV(hw, &pdev->dev); | 114 | SET_IEEE80211_DEV(hw, &pdev->dev); |
105 | platform_set_drvdata(pdev, hw); | 115 | platform_set_drvdata(pdev, hw); |
106 | 116 | ||
107 | aphy = hw->priv; | 117 | sc = hw->priv; |
108 | sc = (struct ath_softc *) (aphy + 1); | ||
109 | aphy->sc = sc; | ||
110 | aphy->hw = hw; | ||
111 | sc->pri_wiphy = aphy; | ||
112 | sc->hw = hw; | 118 | sc->hw = hw; |
113 | sc->dev = &pdev->dev; | 119 | sc->dev = &pdev->dev; |
114 | sc->mem = mem; | 120 | sc->mem = mem; |
@@ -123,7 +129,7 @@ static int ath_ahb_probe(struct platform_device *pdev) | |||
123 | goto err_free_hw; | 129 | goto err_free_hw; |
124 | } | 130 | } |
125 | 131 | ||
126 | ret = ath9k_init_device(AR5416_AR9100_DEVID, sc, 0x0, &ath_ahb_bus_ops); | 132 | ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops); |
127 | if (ret) { | 133 | if (ret) { |
128 | dev_err(&pdev->dev, "failed to initialize device\n"); | 134 | dev_err(&pdev->dev, "failed to initialize device\n"); |
129 | goto err_irq; | 135 | goto err_irq; |
@@ -152,8 +158,7 @@ static int ath_ahb_remove(struct platform_device *pdev) | |||
152 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); | 158 | struct ieee80211_hw *hw = platform_get_drvdata(pdev); |
153 | 159 | ||
154 | if (hw) { | 160 | if (hw) { |
155 | struct ath_wiphy *aphy = hw->priv; | 161 | struct ath_softc *sc = hw->priv; |
156 | struct ath_softc *sc = aphy->sc; | ||
157 | void __iomem *mem = sc->mem; | 162 | void __iomem *mem = sc->mem; |
158 | 163 | ||
159 | ath9k_deinit_device(sc); | 164 | ath9k_deinit_device(sc); |
@@ -173,8 +178,11 @@ static struct platform_driver ath_ahb_driver = { | |||
173 | .name = "ath9k", | 178 | .name = "ath9k", |
174 | .owner = THIS_MODULE, | 179 | .owner = THIS_MODULE, |
175 | }, | 180 | }, |
181 | .id_table = ath9k_platform_id_table, | ||
176 | }; | 182 | }; |
177 | 183 | ||
184 | MODULE_DEVICE_TABLE(platform, ath9k_platform_id_table); | ||
185 | |||
178 | int ath_ahb_init(void) | 186 | int ath_ahb_init(void) |
179 | { | 187 | { |
180 | return platform_driver_register(&ath_ahb_driver); | 188 | return platform_driver_register(&ath_ahb_driver); |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index a3d95cca8f0c..bfb6481f01f9 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -14,6 +14,7 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | ||
17 | #include "hw.h" | 18 | #include "hw.h" |
18 | #include "hw-ops.h" | 19 | #include "hw-ops.h" |
19 | 20 | ||
@@ -48,7 +49,7 @@ static const struct ani_ofdm_level_entry ofdm_level_table[] = { | |||
48 | { 7, 8, 0 } /* lvl 9 */ | 49 | { 7, 8, 0 } /* lvl 9 */ |
49 | }; | 50 | }; |
50 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ | 51 | #define ATH9K_ANI_OFDM_NUM_LEVEL \ |
51 | (sizeof(ofdm_level_table)/sizeof(ofdm_level_table[0])) | 52 | ARRAY_SIZE(ofdm_level_table) |
52 | #define ATH9K_ANI_OFDM_MAX_LEVEL \ | 53 | #define ATH9K_ANI_OFDM_MAX_LEVEL \ |
53 | (ATH9K_ANI_OFDM_NUM_LEVEL-1) | 54 | (ATH9K_ANI_OFDM_NUM_LEVEL-1) |
54 | #define ATH9K_ANI_OFDM_DEF_LEVEL \ | 55 | #define ATH9K_ANI_OFDM_DEF_LEVEL \ |
@@ -94,7 +95,7 @@ static const struct ani_cck_level_entry cck_level_table[] = { | |||
94 | }; | 95 | }; |
95 | 96 | ||
96 | #define ATH9K_ANI_CCK_NUM_LEVEL \ | 97 | #define ATH9K_ANI_CCK_NUM_LEVEL \ |
97 | (sizeof(cck_level_table)/sizeof(cck_level_table[0])) | 98 | ARRAY_SIZE(cck_level_table) |
98 | #define ATH9K_ANI_CCK_MAX_LEVEL \ | 99 | #define ATH9K_ANI_CCK_MAX_LEVEL \ |
99 | (ATH9K_ANI_CCK_NUM_LEVEL-1) | 100 | (ATH9K_ANI_CCK_NUM_LEVEL-1) |
100 | #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ | 101 | #define ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI \ |
@@ -102,31 +103,9 @@ static const struct ani_cck_level_entry cck_level_table[] = { | |||
102 | #define ATH9K_ANI_CCK_DEF_LEVEL \ | 103 | #define ATH9K_ANI_CCK_DEF_LEVEL \ |
103 | 2 /* default level - matches the INI settings */ | 104 | 2 /* default level - matches the INI settings */ |
104 | 105 | ||
105 | /* Private to ani.c */ | 106 | static bool use_new_ani(struct ath_hw *ah) |
106 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) | ||
107 | { | 107 | { |
108 | ath9k_hw_private_ops(ah)->ani_lower_immunity(ah); | 108 | return AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani; |
109 | } | ||
110 | |||
111 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | ||
112 | struct ath9k_channel *chan) | ||
113 | { | ||
114 | int i; | ||
115 | |||
116 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | ||
117 | if (ah->ani[i].c && | ||
118 | ah->ani[i].c->channel == chan->channel) | ||
119 | return i; | ||
120 | if (ah->ani[i].c == NULL) { | ||
121 | ah->ani[i].c = chan; | ||
122 | return i; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, | ||
127 | "No more channel states left. Using channel 0\n"); | ||
128 | |||
129 | return 0; | ||
130 | } | 109 | } |
131 | 110 | ||
132 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, | 111 | static void ath9k_hw_update_mibstats(struct ath_hw *ah, |
@@ -139,82 +118,34 @@ static void ath9k_hw_update_mibstats(struct ath_hw *ah, | |||
139 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); | 118 | stats->beacons += REG_READ(ah, AR_BEACON_CNT); |
140 | } | 119 | } |
141 | 120 | ||
142 | static void ath9k_ani_restart_old(struct ath_hw *ah) | 121 | static void ath9k_ani_restart(struct ath_hw *ah) |
143 | { | 122 | { |
144 | struct ar5416AniState *aniState; | 123 | struct ar5416AniState *aniState; |
145 | struct ath_common *common = ath9k_hw_common(ah); | 124 | struct ath_common *common = ath9k_hw_common(ah); |
125 | u32 ofdm_base = 0, cck_base = 0; | ||
146 | 126 | ||
147 | if (!DO_ANI(ah)) | 127 | if (!DO_ANI(ah)) |
148 | return; | 128 | return; |
149 | 129 | ||
150 | aniState = ah->curani; | 130 | aniState = &ah->curchan->ani; |
151 | aniState->listenTime = 0; | 131 | aniState->listenTime = 0; |
152 | 132 | ||
153 | if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { | 133 | if (!use_new_ani(ah)) { |
154 | aniState->ofdmPhyErrBase = 0; | 134 | ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high; |
155 | ath_print(common, ATH_DBG_ANI, | 135 | cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high; |
156 | "OFDM Trigger is too high for hw counters\n"); | ||
157 | } else { | ||
158 | aniState->ofdmPhyErrBase = | ||
159 | AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; | ||
160 | } | ||
161 | if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { | ||
162 | aniState->cckPhyErrBase = 0; | ||
163 | ath_print(common, ATH_DBG_ANI, | ||
164 | "CCK Trigger is too high for hw counters\n"); | ||
165 | } else { | ||
166 | aniState->cckPhyErrBase = | ||
167 | AR_PHY_COUNTMAX - aniState->cckTrigHigh; | ||
168 | } | 136 | } |
169 | ath_print(common, ATH_DBG_ANI, | ||
170 | "Writing ofdmbase=%u cckbase=%u\n", | ||
171 | aniState->ofdmPhyErrBase, | ||
172 | aniState->cckPhyErrBase); | ||
173 | |||
174 | ENABLE_REGWRITE_BUFFER(ah); | ||
175 | |||
176 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | ||
177 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | ||
178 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | ||
179 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | ||
180 | |||
181 | REGWRITE_BUFFER_FLUSH(ah); | ||
182 | DISABLE_REGWRITE_BUFFER(ah); | ||
183 | |||
184 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
185 | |||
186 | aniState->ofdmPhyErrCount = 0; | ||
187 | aniState->cckPhyErrCount = 0; | ||
188 | } | ||
189 | 137 | ||
190 | static void ath9k_ani_restart_new(struct ath_hw *ah) | 138 | ath_dbg(common, ATH_DBG_ANI, |
191 | { | 139 | "Writing ofdmbase=%u cckbase=%u\n", ofdm_base, cck_base); |
192 | struct ar5416AniState *aniState; | ||
193 | struct ath_common *common = ath9k_hw_common(ah); | ||
194 | |||
195 | if (!DO_ANI(ah)) | ||
196 | return; | ||
197 | |||
198 | aniState = ah->curani; | ||
199 | aniState->listenTime = 0; | ||
200 | |||
201 | aniState->ofdmPhyErrBase = 0; | ||
202 | aniState->cckPhyErrBase = 0; | ||
203 | |||
204 | ath_print(common, ATH_DBG_ANI, | ||
205 | "Writing ofdmbase=%08x cckbase=%08x\n", | ||
206 | aniState->ofdmPhyErrBase, | ||
207 | aniState->cckPhyErrBase); | ||
208 | 140 | ||
209 | ENABLE_REGWRITE_BUFFER(ah); | 141 | ENABLE_REGWRITE_BUFFER(ah); |
210 | 142 | ||
211 | REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); | 143 | REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base); |
212 | REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); | 144 | REG_WRITE(ah, AR_PHY_ERR_2, cck_base); |
213 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); | 145 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); |
214 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 146 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
215 | 147 | ||
216 | REGWRITE_BUFFER_FLUSH(ah); | 148 | REGWRITE_BUFFER_FLUSH(ah); |
217 | DISABLE_REGWRITE_BUFFER(ah); | ||
218 | 149 | ||
219 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 150 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
220 | 151 | ||
@@ -228,10 +159,7 @@ static void ath9k_hw_ani_ofdm_err_trigger_old(struct ath_hw *ah) | |||
228 | struct ar5416AniState *aniState; | 159 | struct ar5416AniState *aniState; |
229 | int32_t rssi; | 160 | int32_t rssi; |
230 | 161 | ||
231 | if (!DO_ANI(ah)) | 162 | aniState = &ah->curchan->ani; |
232 | return; | ||
233 | |||
234 | aniState = ah->curani; | ||
235 | 163 | ||
236 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | 164 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { |
237 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | 165 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, |
@@ -300,10 +228,7 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) | |||
300 | struct ar5416AniState *aniState; | 228 | struct ar5416AniState *aniState; |
301 | int32_t rssi; | 229 | int32_t rssi; |
302 | 230 | ||
303 | if (!DO_ANI(ah)) | 231 | aniState = &ah->curchan->ani; |
304 | return; | ||
305 | |||
306 | aniState = ah->curani; | ||
307 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { | 232 | if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { |
308 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, | 233 | if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, |
309 | aniState->noiseImmunityLevel + 1)) { | 234 | aniState->noiseImmunityLevel + 1)) { |
@@ -335,18 +260,18 @@ static void ath9k_hw_ani_cck_err_trigger_old(struct ath_hw *ah) | |||
335 | /* Adjust the OFDM Noise Immunity Level */ | 260 | /* Adjust the OFDM Noise Immunity Level */ |
336 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | 261 | static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) |
337 | { | 262 | { |
338 | struct ar5416AniState *aniState = ah->curani; | 263 | struct ar5416AniState *aniState = &ah->curchan->ani; |
339 | struct ath_common *common = ath9k_hw_common(ah); | 264 | struct ath_common *common = ath9k_hw_common(ah); |
340 | const struct ani_ofdm_level_entry *entry_ofdm; | 265 | const struct ani_ofdm_level_entry *entry_ofdm; |
341 | const struct ani_cck_level_entry *entry_cck; | 266 | const struct ani_cck_level_entry *entry_cck; |
342 | 267 | ||
343 | aniState->noiseFloor = BEACON_RSSI(ah); | 268 | aniState->noiseFloor = BEACON_RSSI(ah); |
344 | 269 | ||
345 | ath_print(common, ATH_DBG_ANI, | 270 | ath_dbg(common, ATH_DBG_ANI, |
346 | "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | 271 | "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", |
347 | aniState->ofdmNoiseImmunityLevel, | 272 | aniState->ofdmNoiseImmunityLevel, |
348 | immunityLevel, aniState->noiseFloor, | 273 | immunityLevel, aniState->noiseFloor, |
349 | aniState->rssiThrLow, aniState->rssiThrHigh); | 274 | aniState->rssiThrLow, aniState->rssiThrHigh); |
350 | 275 | ||
351 | aniState->ofdmNoiseImmunityLevel = immunityLevel; | 276 | aniState->ofdmNoiseImmunityLevel = immunityLevel; |
352 | 277 | ||
@@ -380,14 +305,19 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel) | |||
380 | } | 305 | } |
381 | } | 306 | } |
382 | 307 | ||
383 | static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) | 308 | static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) |
384 | { | 309 | { |
385 | struct ar5416AniState *aniState; | 310 | struct ar5416AniState *aniState; |
386 | 311 | ||
387 | if (!DO_ANI(ah)) | 312 | if (!DO_ANI(ah)) |
388 | return; | 313 | return; |
389 | 314 | ||
390 | aniState = ah->curani; | 315 | if (!use_new_ani(ah)) { |
316 | ath9k_hw_ani_ofdm_err_trigger_old(ah); | ||
317 | return; | ||
318 | } | ||
319 | |||
320 | aniState = &ah->curchan->ani; | ||
391 | 321 | ||
392 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) | 322 | if (aniState->ofdmNoiseImmunityLevel < ATH9K_ANI_OFDM_MAX_LEVEL) |
393 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); | 323 | ath9k_hw_set_ofdm_nil(ah, aniState->ofdmNoiseImmunityLevel + 1); |
@@ -398,17 +328,17 @@ static void ath9k_hw_ani_ofdm_err_trigger_new(struct ath_hw *ah) | |||
398 | */ | 328 | */ |
399 | static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | 329 | static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) |
400 | { | 330 | { |
401 | struct ar5416AniState *aniState = ah->curani; | 331 | struct ar5416AniState *aniState = &ah->curchan->ani; |
402 | struct ath_common *common = ath9k_hw_common(ah); | 332 | struct ath_common *common = ath9k_hw_common(ah); |
403 | const struct ani_ofdm_level_entry *entry_ofdm; | 333 | const struct ani_ofdm_level_entry *entry_ofdm; |
404 | const struct ani_cck_level_entry *entry_cck; | 334 | const struct ani_cck_level_entry *entry_cck; |
405 | 335 | ||
406 | aniState->noiseFloor = BEACON_RSSI(ah); | 336 | aniState->noiseFloor = BEACON_RSSI(ah); |
407 | ath_print(common, ATH_DBG_ANI, | 337 | ath_dbg(common, ATH_DBG_ANI, |
408 | "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", | 338 | "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", |
409 | aniState->cckNoiseImmunityLevel, immunityLevel, | 339 | aniState->cckNoiseImmunityLevel, immunityLevel, |
410 | aniState->noiseFloor, aniState->rssiThrLow, | 340 | aniState->noiseFloor, aniState->rssiThrLow, |
411 | aniState->rssiThrHigh); | 341 | aniState->rssiThrHigh); |
412 | 342 | ||
413 | if ((ah->opmode == NL80211_IFTYPE_STATION || | 343 | if ((ah->opmode == NL80211_IFTYPE_STATION || |
414 | ah->opmode == NL80211_IFTYPE_ADHOC) && | 344 | ah->opmode == NL80211_IFTYPE_ADHOC) && |
@@ -428,7 +358,7 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | |||
428 | entry_cck->fir_step_level); | 358 | entry_cck->fir_step_level); |
429 | 359 | ||
430 | /* Skip MRC CCK for pre AR9003 families */ | 360 | /* Skip MRC CCK for pre AR9003 families */ |
431 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 361 | if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah)) |
432 | return; | 362 | return; |
433 | 363 | ||
434 | if (aniState->mrcCCKOff == entry_cck->mrc_cck_on) | 364 | if (aniState->mrcCCKOff == entry_cck->mrc_cck_on) |
@@ -437,14 +367,19 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) | |||
437 | entry_cck->mrc_cck_on); | 367 | entry_cck->mrc_cck_on); |
438 | } | 368 | } |
439 | 369 | ||
440 | static void ath9k_hw_ani_cck_err_trigger_new(struct ath_hw *ah) | 370 | static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) |
441 | { | 371 | { |
442 | struct ar5416AniState *aniState; | 372 | struct ar5416AniState *aniState; |
443 | 373 | ||
444 | if (!DO_ANI(ah)) | 374 | if (!DO_ANI(ah)) |
445 | return; | 375 | return; |
446 | 376 | ||
447 | aniState = ah->curani; | 377 | if (!use_new_ani(ah)) { |
378 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | aniState = &ah->curchan->ani; | ||
448 | 383 | ||
449 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) | 384 | if (aniState->cckNoiseImmunityLevel < ATH9K_ANI_CCK_MAX_LEVEL) |
450 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); | 385 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel + 1); |
@@ -455,7 +390,7 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | |||
455 | struct ar5416AniState *aniState; | 390 | struct ar5416AniState *aniState; |
456 | int32_t rssi; | 391 | int32_t rssi; |
457 | 392 | ||
458 | aniState = ah->curani; | 393 | aniState = &ah->curchan->ani; |
459 | 394 | ||
460 | if (ah->opmode == NL80211_IFTYPE_AP) { | 395 | if (ah->opmode == NL80211_IFTYPE_AP) { |
461 | if (aniState->firstepLevel > 0) { | 396 | if (aniState->firstepLevel > 0) { |
@@ -507,11 +442,16 @@ static void ath9k_hw_ani_lower_immunity_old(struct ath_hw *ah) | |||
507 | * only lower either OFDM or CCK errors per turn | 442 | * only lower either OFDM or CCK errors per turn |
508 | * we lower the other one next time | 443 | * we lower the other one next time |
509 | */ | 444 | */ |
510 | static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah) | 445 | static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) |
511 | { | 446 | { |
512 | struct ar5416AniState *aniState; | 447 | struct ar5416AniState *aniState; |
513 | 448 | ||
514 | aniState = ah->curani; | 449 | aniState = &ah->curchan->ani; |
450 | |||
451 | if (!use_new_ani(ah)) { | ||
452 | ath9k_hw_ani_lower_immunity_old(ah); | ||
453 | return; | ||
454 | } | ||
515 | 455 | ||
516 | /* lower OFDM noise immunity */ | 456 | /* lower OFDM noise immunity */ |
517 | if (aniState->ofdmNoiseImmunityLevel > 0 && | 457 | if (aniState->ofdmNoiseImmunityLevel > 0 && |
@@ -525,90 +465,21 @@ static void ath9k_hw_ani_lower_immunity_new(struct ath_hw *ah) | |||
525 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); | 465 | ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); |
526 | } | 466 | } |
527 | 467 | ||
528 | static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) | ||
529 | { | ||
530 | struct ath9k_channel *chan = ah->curchan; | ||
531 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
532 | u8 clockrate; /* in MHz */ | ||
533 | |||
534 | if (!ah->curchan) /* should really check for CCK instead */ | ||
535 | clockrate = ATH9K_CLOCK_RATE_CCK; | ||
536 | else if (conf->channel->band == IEEE80211_BAND_2GHZ) | ||
537 | clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; | ||
538 | else if (IS_CHAN_A_FAST_CLOCK(ah, chan)) | ||
539 | clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; | ||
540 | else | ||
541 | clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; | ||
542 | |||
543 | if (conf_is_ht40(conf)) | ||
544 | return clockrate * 2; | ||
545 | |||
546 | return clockrate; | ||
547 | } | ||
548 | |||
549 | static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) | ||
550 | { | ||
551 | struct ar5416AniState *aniState; | ||
552 | struct ath_common *common = ath9k_hw_common(ah); | ||
553 | u32 txFrameCount, rxFrameCount, cycleCount; | ||
554 | int32_t listenTime; | ||
555 | |||
556 | txFrameCount = REG_READ(ah, AR_TFCNT); | ||
557 | rxFrameCount = REG_READ(ah, AR_RFCNT); | ||
558 | cycleCount = REG_READ(ah, AR_CCCNT); | ||
559 | |||
560 | aniState = ah->curani; | ||
561 | if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { | ||
562 | listenTime = 0; | ||
563 | ah->stats.ast_ani_lzero++; | ||
564 | ath_print(common, ATH_DBG_ANI, | ||
565 | "1st call: aniState->cycleCount=%d\n", | ||
566 | aniState->cycleCount); | ||
567 | } else { | ||
568 | int32_t ccdelta = cycleCount - aniState->cycleCount; | ||
569 | int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; | ||
570 | int32_t tfdelta = txFrameCount - aniState->txFrameCount; | ||
571 | int32_t clock_rate; | ||
572 | |||
573 | /* | ||
574 | * convert HW counter values to ms using mode | ||
575 | * specifix clock rate | ||
576 | */ | ||
577 | clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000;; | ||
578 | |||
579 | listenTime = (ccdelta - rfdelta - tfdelta) / clock_rate; | ||
580 | |||
581 | ath_print(common, ATH_DBG_ANI, | ||
582 | "cyclecount=%d, rfcount=%d, " | ||
583 | "tfcount=%d, listenTime=%d CLOCK_RATE=%d\n", | ||
584 | ccdelta, rfdelta, tfdelta, listenTime, clock_rate); | ||
585 | } | ||
586 | |||
587 | aniState->cycleCount = cycleCount; | ||
588 | aniState->txFrameCount = txFrameCount; | ||
589 | aniState->rxFrameCount = rxFrameCount; | ||
590 | |||
591 | return listenTime; | ||
592 | } | ||
593 | |||
594 | static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | 468 | static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) |
595 | { | 469 | { |
596 | struct ar5416AniState *aniState; | 470 | struct ar5416AniState *aniState; |
597 | struct ath9k_channel *chan = ah->curchan; | 471 | struct ath9k_channel *chan = ah->curchan; |
598 | struct ath_common *common = ath9k_hw_common(ah); | 472 | struct ath_common *common = ath9k_hw_common(ah); |
599 | int index; | ||
600 | 473 | ||
601 | if (!DO_ANI(ah)) | 474 | if (!DO_ANI(ah)) |
602 | return; | 475 | return; |
603 | 476 | ||
604 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | 477 | aniState = &ah->curchan->ani; |
605 | aniState = &ah->ani[index]; | ||
606 | ah->curani = aniState; | ||
607 | 478 | ||
608 | if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION | 479 | if (ah->opmode != NL80211_IFTYPE_STATION |
609 | && ah->opmode != NL80211_IFTYPE_ADHOC) { | 480 | && ah->opmode != NL80211_IFTYPE_ADHOC) { |
610 | ath_print(common, ATH_DBG_ANI, | 481 | ath_dbg(common, ATH_DBG_ANI, |
611 | "Reset ANI state opmode %u\n", ah->opmode); | 482 | "Reset ANI state opmode %u\n", ah->opmode); |
612 | ah->stats.ast_ani_reset++; | 483 | ah->stats.ast_ani_reset++; |
613 | 484 | ||
614 | if (ah->opmode == NL80211_IFTYPE_AP) { | 485 | if (ah->opmode == NL80211_IFTYPE_AP) { |
@@ -634,17 +505,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
634 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | | 505 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | |
635 | ATH9K_RX_FILTER_PHYERR); | 506 | ATH9K_RX_FILTER_PHYERR); |
636 | 507 | ||
637 | if (ah->opmode == NL80211_IFTYPE_AP) { | 508 | ath9k_ani_restart(ah); |
638 | ah->curani->ofdmTrigHigh = | ||
639 | ah->config.ofdm_trig_high; | ||
640 | ah->curani->ofdmTrigLow = | ||
641 | ah->config.ofdm_trig_low; | ||
642 | ah->curani->cckTrigHigh = | ||
643 | ah->config.cck_trig_high; | ||
644 | ah->curani->cckTrigLow = | ||
645 | ah->config.cck_trig_low; | ||
646 | } | ||
647 | ath9k_ani_restart_old(ah); | ||
648 | return; | 509 | return; |
649 | } | 510 | } |
650 | 511 | ||
@@ -666,7 +527,7 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
666 | 527 | ||
667 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & | 528 | ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & |
668 | ~ATH9K_RX_FILTER_PHYERR); | 529 | ~ATH9K_RX_FILTER_PHYERR); |
669 | ath9k_ani_restart_old(ah); | 530 | ath9k_ani_restart(ah); |
670 | 531 | ||
671 | ENABLE_REGWRITE_BUFFER(ah); | 532 | ENABLE_REGWRITE_BUFFER(ah); |
672 | 533 | ||
@@ -674,7 +535,6 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
674 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 535 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
675 | 536 | ||
676 | REGWRITE_BUFFER_FLUSH(ah); | 537 | REGWRITE_BUFFER_FLUSH(ah); |
677 | DISABLE_REGWRITE_BUFFER(ah); | ||
678 | } | 538 | } |
679 | 539 | ||
680 | /* | 540 | /* |
@@ -682,15 +542,18 @@ static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) | |||
682 | * This routine should be called for every hardware reset and for | 542 | * This routine should be called for every hardware reset and for |
683 | * every channel change. | 543 | * every channel change. |
684 | */ | 544 | */ |
685 | static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | 545 | void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) |
686 | { | 546 | { |
687 | struct ar5416AniState *aniState = ah->curani; | 547 | struct ar5416AniState *aniState = &ah->curchan->ani; |
688 | struct ath9k_channel *chan = ah->curchan; | 548 | struct ath9k_channel *chan = ah->curchan; |
689 | struct ath_common *common = ath9k_hw_common(ah); | 549 | struct ath_common *common = ath9k_hw_common(ah); |
690 | 550 | ||
691 | if (!DO_ANI(ah)) | 551 | if (!DO_ANI(ah)) |
692 | return; | 552 | return; |
693 | 553 | ||
554 | if (!use_new_ani(ah)) | ||
555 | return ath9k_ani_reset_old(ah, is_scanning); | ||
556 | |||
694 | BUG_ON(aniState == NULL); | 557 | BUG_ON(aniState == NULL); |
695 | ah->stats.ast_ani_reset++; | 558 | ah->stats.ast_ani_reset++; |
696 | 559 | ||
@@ -721,16 +584,14 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | |||
721 | ATH9K_ANI_OFDM_DEF_LEVEL || | 584 | ATH9K_ANI_OFDM_DEF_LEVEL || |
722 | aniState->cckNoiseImmunityLevel != | 585 | aniState->cckNoiseImmunityLevel != |
723 | ATH9K_ANI_CCK_DEF_LEVEL) { | 586 | ATH9K_ANI_CCK_DEF_LEVEL) { |
724 | ath_print(common, ATH_DBG_ANI, | 587 | ath_dbg(common, ATH_DBG_ANI, |
725 | "Restore defaults: opmode %u " | 588 | "Restore defaults: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", |
726 | "chan %d Mhz/0x%x is_scanning=%d " | 589 | ah->opmode, |
727 | "ofdm:%d cck:%d\n", | 590 | chan->channel, |
728 | ah->opmode, | 591 | chan->channelFlags, |
729 | chan->channel, | 592 | is_scanning, |
730 | chan->channelFlags, | 593 | aniState->ofdmNoiseImmunityLevel, |
731 | is_scanning, | 594 | aniState->cckNoiseImmunityLevel); |
732 | aniState->ofdmNoiseImmunityLevel, | ||
733 | aniState->cckNoiseImmunityLevel); | ||
734 | 595 | ||
735 | ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); | 596 | ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL); |
736 | ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); | 597 | ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL); |
@@ -739,16 +600,14 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | |||
739 | /* | 600 | /* |
740 | * restore historical levels for this channel | 601 | * restore historical levels for this channel |
741 | */ | 602 | */ |
742 | ath_print(common, ATH_DBG_ANI, | 603 | ath_dbg(common, ATH_DBG_ANI, |
743 | "Restore history: opmode %u " | 604 | "Restore history: opmode %u chan %d Mhz/0x%x is_scanning=%d ofdm:%d cck:%d\n", |
744 | "chan %d Mhz/0x%x is_scanning=%d " | 605 | ah->opmode, |
745 | "ofdm:%d cck:%d\n", | 606 | chan->channel, |
746 | ah->opmode, | 607 | chan->channelFlags, |
747 | chan->channel, | 608 | is_scanning, |
748 | chan->channelFlags, | 609 | aniState->ofdmNoiseImmunityLevel, |
749 | is_scanning, | 610 | aniState->cckNoiseImmunityLevel); |
750 | aniState->ofdmNoiseImmunityLevel, | ||
751 | aniState->cckNoiseImmunityLevel); | ||
752 | 611 | ||
753 | ath9k_hw_set_ofdm_nil(ah, | 612 | ath9k_hw_set_ofdm_nil(ah, |
754 | aniState->ofdmNoiseImmunityLevel); | 613 | aniState->ofdmNoiseImmunityLevel); |
@@ -760,7 +619,7 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | |||
760 | * enable phy counters if hw supports or if not, enable phy | 619 | * enable phy counters if hw supports or if not, enable phy |
761 | * interrupts (so we can count each one) | 620 | * interrupts (so we can count each one) |
762 | */ | 621 | */ |
763 | ath9k_ani_restart_new(ah); | 622 | ath9k_ani_restart(ah); |
764 | 623 | ||
765 | ENABLE_REGWRITE_BUFFER(ah); | 624 | ENABLE_REGWRITE_BUFFER(ah); |
766 | 625 | ||
@@ -768,28 +627,30 @@ static void ath9k_ani_reset_new(struct ath_hw *ah, bool is_scanning) | |||
768 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 627 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
769 | 628 | ||
770 | REGWRITE_BUFFER_FLUSH(ah); | 629 | REGWRITE_BUFFER_FLUSH(ah); |
771 | DISABLE_REGWRITE_BUFFER(ah); | ||
772 | } | 630 | } |
773 | 631 | ||
774 | static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, | 632 | static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) |
775 | struct ath9k_channel *chan) | ||
776 | { | 633 | { |
777 | struct ar5416AniState *aniState; | ||
778 | struct ath_common *common = ath9k_hw_common(ah); | 634 | struct ath_common *common = ath9k_hw_common(ah); |
779 | int32_t listenTime; | 635 | struct ar5416AniState *aniState = &ah->curchan->ani; |
780 | u32 phyCnt1, phyCnt2; | 636 | u32 ofdm_base = 0; |
637 | u32 cck_base = 0; | ||
781 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | 638 | u32 ofdmPhyErrCnt, cckPhyErrCnt; |
639 | u32 phyCnt1, phyCnt2; | ||
640 | int32_t listenTime; | ||
782 | 641 | ||
783 | if (!DO_ANI(ah)) | 642 | ath_hw_cycle_counters_update(common); |
784 | return; | 643 | listenTime = ath_hw_get_listen_time(common); |
785 | |||
786 | aniState = ah->curani; | ||
787 | 644 | ||
788 | listenTime = ath9k_hw_ani_get_listen_time(ah); | 645 | if (listenTime <= 0) { |
789 | if (listenTime < 0) { | ||
790 | ah->stats.ast_ani_lneg++; | 646 | ah->stats.ast_ani_lneg++; |
791 | ath9k_ani_restart_old(ah); | 647 | ath9k_ani_restart(ah); |
792 | return; | 648 | return false; |
649 | } | ||
650 | |||
651 | if (!use_new_ani(ah)) { | ||
652 | ofdm_base = AR_PHY_COUNTMAX - ah->config.ofdm_trig_high; | ||
653 | cck_base = AR_PHY_COUNTMAX - ah->config.cck_trig_high; | ||
793 | } | 654 | } |
794 | 655 | ||
795 | aniState->listenTime += listenTime; | 656 | aniState->listenTime += listenTime; |
@@ -799,215 +660,95 @@ static void ath9k_hw_ani_monitor_old(struct ath_hw *ah, | |||
799 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | 660 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); |
800 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | 661 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); |
801 | 662 | ||
802 | if (phyCnt1 < aniState->ofdmPhyErrBase || | 663 | if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) { |
803 | phyCnt2 < aniState->cckPhyErrBase) { | 664 | if (phyCnt1 < ofdm_base) { |
804 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | 665 | ath_dbg(common, ATH_DBG_ANI, |
805 | ath_print(common, ATH_DBG_ANI, | 666 | "phyCnt1 0x%x, resetting counter value to 0x%x\n", |
806 | "phyCnt1 0x%x, resetting " | 667 | phyCnt1, ofdm_base); |
807 | "counter value to 0x%x\n", | 668 | REG_WRITE(ah, AR_PHY_ERR_1, ofdm_base); |
808 | phyCnt1, | ||
809 | aniState->ofdmPhyErrBase); | ||
810 | REG_WRITE(ah, AR_PHY_ERR_1, | ||
811 | aniState->ofdmPhyErrBase); | ||
812 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | 669 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, |
813 | AR_PHY_ERR_OFDM_TIMING); | 670 | AR_PHY_ERR_OFDM_TIMING); |
814 | } | 671 | } |
815 | if (phyCnt2 < aniState->cckPhyErrBase) { | 672 | if (phyCnt2 < cck_base) { |
816 | ath_print(common, ATH_DBG_ANI, | 673 | ath_dbg(common, ATH_DBG_ANI, |
817 | "phyCnt2 0x%x, resetting " | 674 | "phyCnt2 0x%x, resetting counter value to 0x%x\n", |
818 | "counter value to 0x%x\n", | 675 | phyCnt2, cck_base); |
819 | phyCnt2, | 676 | REG_WRITE(ah, AR_PHY_ERR_2, cck_base); |
820 | aniState->cckPhyErrBase); | ||
821 | REG_WRITE(ah, AR_PHY_ERR_2, | ||
822 | aniState->cckPhyErrBase); | ||
823 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | 677 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, |
824 | AR_PHY_ERR_CCK_TIMING); | 678 | AR_PHY_ERR_CCK_TIMING); |
825 | } | 679 | } |
826 | return; | 680 | return false; |
827 | } | 681 | } |
828 | 682 | ||
829 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | 683 | ofdmPhyErrCnt = phyCnt1 - ofdm_base; |
830 | ah->stats.ast_ani_ofdmerrs += | 684 | ah->stats.ast_ani_ofdmerrs += |
831 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | 685 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; |
832 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | 686 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; |
833 | 687 | ||
834 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | 688 | cckPhyErrCnt = phyCnt2 - cck_base; |
835 | ah->stats.ast_ani_cckerrs += | 689 | ah->stats.ast_ani_cckerrs += |
836 | cckPhyErrCnt - aniState->cckPhyErrCount; | 690 | cckPhyErrCnt - aniState->cckPhyErrCount; |
837 | aniState->cckPhyErrCount = cckPhyErrCnt; | 691 | aniState->cckPhyErrCount = cckPhyErrCnt; |
838 | 692 | return true; | |
839 | if (aniState->listenTime > 5 * ah->aniperiod) { | ||
840 | if (aniState->ofdmPhyErrCount <= aniState->listenTime * | ||
841 | aniState->ofdmTrigLow / 1000 && | ||
842 | aniState->cckPhyErrCount <= aniState->listenTime * | ||
843 | aniState->cckTrigLow / 1000) | ||
844 | ath9k_hw_ani_lower_immunity(ah); | ||
845 | ath9k_ani_restart_old(ah); | ||
846 | } else if (aniState->listenTime > ah->aniperiod) { | ||
847 | if (aniState->ofdmPhyErrCount > aniState->listenTime * | ||
848 | aniState->ofdmTrigHigh / 1000) { | ||
849 | ath9k_hw_ani_ofdm_err_trigger_old(ah); | ||
850 | ath9k_ani_restart_old(ah); | ||
851 | } else if (aniState->cckPhyErrCount > | ||
852 | aniState->listenTime * aniState->cckTrigHigh / | ||
853 | 1000) { | ||
854 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
855 | ath9k_ani_restart_old(ah); | ||
856 | } | ||
857 | } | ||
858 | } | 693 | } |
859 | 694 | ||
860 | static void ath9k_hw_ani_monitor_new(struct ath_hw *ah, | 695 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) |
861 | struct ath9k_channel *chan) | ||
862 | { | 696 | { |
863 | struct ar5416AniState *aniState; | 697 | struct ar5416AniState *aniState; |
864 | struct ath_common *common = ath9k_hw_common(ah); | 698 | struct ath_common *common = ath9k_hw_common(ah); |
865 | int32_t listenTime; | ||
866 | u32 phyCnt1, phyCnt2; | ||
867 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
868 | u32 ofdmPhyErrRate, cckPhyErrRate; | 699 | u32 ofdmPhyErrRate, cckPhyErrRate; |
869 | 700 | ||
870 | if (!DO_ANI(ah)) | 701 | if (!DO_ANI(ah)) |
871 | return; | 702 | return; |
872 | 703 | ||
873 | aniState = ah->curani; | 704 | aniState = &ah->curchan->ani; |
874 | if (WARN_ON(!aniState)) | 705 | if (WARN_ON(!aniState)) |
875 | return; | 706 | return; |
876 | 707 | ||
877 | listenTime = ath9k_hw_ani_get_listen_time(ah); | 708 | if (!ath9k_hw_ani_read_counters(ah)) |
878 | if (listenTime <= 0) { | ||
879 | ah->stats.ast_ani_lneg++; | ||
880 | /* restart ANI period if listenTime is invalid */ | ||
881 | ath_print(common, ATH_DBG_ANI, | ||
882 | "listenTime=%d - on new ani monitor\n", | ||
883 | listenTime); | ||
884 | ath9k_ani_restart_new(ah); | ||
885 | return; | 709 | return; |
886 | } | ||
887 | |||
888 | aniState->listenTime += listenTime; | ||
889 | |||
890 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
891 | |||
892 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
893 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
894 | |||
895 | if (phyCnt1 < aniState->ofdmPhyErrBase || | ||
896 | phyCnt2 < aniState->cckPhyErrBase) { | ||
897 | if (phyCnt1 < aniState->ofdmPhyErrBase) { | ||
898 | ath_print(common, ATH_DBG_ANI, | ||
899 | "phyCnt1 0x%x, resetting " | ||
900 | "counter value to 0x%x\n", | ||
901 | phyCnt1, | ||
902 | aniState->ofdmPhyErrBase); | ||
903 | REG_WRITE(ah, AR_PHY_ERR_1, | ||
904 | aniState->ofdmPhyErrBase); | ||
905 | REG_WRITE(ah, AR_PHY_ERR_MASK_1, | ||
906 | AR_PHY_ERR_OFDM_TIMING); | ||
907 | } | ||
908 | if (phyCnt2 < aniState->cckPhyErrBase) { | ||
909 | ath_print(common, ATH_DBG_ANI, | ||
910 | "phyCnt2 0x%x, resetting " | ||
911 | "counter value to 0x%x\n", | ||
912 | phyCnt2, | ||
913 | aniState->cckPhyErrBase); | ||
914 | REG_WRITE(ah, AR_PHY_ERR_2, | ||
915 | aniState->cckPhyErrBase); | ||
916 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, | ||
917 | AR_PHY_ERR_CCK_TIMING); | ||
918 | } | ||
919 | return; | ||
920 | } | ||
921 | |||
922 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | ||
923 | ah->stats.ast_ani_ofdmerrs += | ||
924 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
925 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
926 | |||
927 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
928 | ah->stats.ast_ani_cckerrs += | ||
929 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
930 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
931 | |||
932 | ath_print(common, ATH_DBG_ANI, | ||
933 | "Errors: OFDM=0x%08x-0x%08x=%d " | ||
934 | "CCK=0x%08x-0x%08x=%d\n", | ||
935 | phyCnt1, | ||
936 | aniState->ofdmPhyErrBase, | ||
937 | ofdmPhyErrCnt, | ||
938 | phyCnt2, | ||
939 | aniState->cckPhyErrBase, | ||
940 | cckPhyErrCnt); | ||
941 | 710 | ||
942 | ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / | 711 | ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / |
943 | aniState->listenTime; | 712 | aniState->listenTime; |
944 | cckPhyErrRate = aniState->cckPhyErrCount * 1000 / | 713 | cckPhyErrRate = aniState->cckPhyErrCount * 1000 / |
945 | aniState->listenTime; | 714 | aniState->listenTime; |
946 | 715 | ||
947 | ath_print(common, ATH_DBG_ANI, | 716 | ath_dbg(common, ATH_DBG_ANI, |
948 | "listenTime=%d OFDM:%d errs=%d/s CCK:%d " | 717 | "listenTime=%d OFDM:%d errs=%d/s CCK:%d errs=%d/s ofdm_turn=%d\n", |
949 | "errs=%d/s ofdm_turn=%d\n", | 718 | aniState->listenTime, |
950 | listenTime, aniState->ofdmNoiseImmunityLevel, | 719 | aniState->ofdmNoiseImmunityLevel, |
951 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, | 720 | ofdmPhyErrRate, aniState->cckNoiseImmunityLevel, |
952 | cckPhyErrRate, aniState->ofdmsTurn); | 721 | cckPhyErrRate, aniState->ofdmsTurn); |
953 | 722 | ||
954 | if (aniState->listenTime > 5 * ah->aniperiod) { | 723 | if (aniState->listenTime > 5 * ah->aniperiod) { |
955 | if (ofdmPhyErrRate <= aniState->ofdmTrigLow && | 724 | if (ofdmPhyErrRate <= ah->config.ofdm_trig_low && |
956 | cckPhyErrRate <= aniState->cckTrigLow) { | 725 | cckPhyErrRate <= ah->config.cck_trig_low) { |
957 | ath_print(common, ATH_DBG_ANI, | ||
958 | "1. listenTime=%d OFDM:%d errs=%d/s(<%d) " | ||
959 | "CCK:%d errs=%d/s(<%d) -> " | ||
960 | "ath9k_hw_ani_lower_immunity()\n", | ||
961 | aniState->listenTime, | ||
962 | aniState->ofdmNoiseImmunityLevel, | ||
963 | ofdmPhyErrRate, | ||
964 | aniState->ofdmTrigLow, | ||
965 | aniState->cckNoiseImmunityLevel, | ||
966 | cckPhyErrRate, | ||
967 | aniState->cckTrigLow); | ||
968 | ath9k_hw_ani_lower_immunity(ah); | 726 | ath9k_hw_ani_lower_immunity(ah); |
969 | aniState->ofdmsTurn = !aniState->ofdmsTurn; | 727 | aniState->ofdmsTurn = !aniState->ofdmsTurn; |
970 | } | 728 | } |
971 | ath_print(common, ATH_DBG_ANI, | 729 | ath9k_ani_restart(ah); |
972 | "1 listenTime=%d ofdm=%d/s cck=%d/s - " | ||
973 | "calling ath9k_ani_restart_new()\n", | ||
974 | aniState->listenTime, ofdmPhyErrRate, cckPhyErrRate); | ||
975 | ath9k_ani_restart_new(ah); | ||
976 | } else if (aniState->listenTime > ah->aniperiod) { | 730 | } else if (aniState->listenTime > ah->aniperiod) { |
977 | /* check to see if need to raise immunity */ | 731 | /* check to see if need to raise immunity */ |
978 | if (ofdmPhyErrRate > aniState->ofdmTrigHigh && | 732 | if (ofdmPhyErrRate > ah->config.ofdm_trig_high && |
979 | (cckPhyErrRate <= aniState->cckTrigHigh || | 733 | (cckPhyErrRate <= ah->config.cck_trig_high || |
980 | aniState->ofdmsTurn)) { | 734 | aniState->ofdmsTurn)) { |
981 | ath_print(common, ATH_DBG_ANI, | 735 | ath9k_hw_ani_ofdm_err_trigger(ah); |
982 | "2 listenTime=%d OFDM:%d errs=%d/s(>%d) -> " | 736 | ath9k_ani_restart(ah); |
983 | "ath9k_hw_ani_ofdm_err_trigger_new()\n", | ||
984 | aniState->listenTime, | ||
985 | aniState->ofdmNoiseImmunityLevel, | ||
986 | ofdmPhyErrRate, | ||
987 | aniState->ofdmTrigHigh); | ||
988 | ath9k_hw_ani_ofdm_err_trigger_new(ah); | ||
989 | ath9k_ani_restart_new(ah); | ||
990 | aniState->ofdmsTurn = false; | 737 | aniState->ofdmsTurn = false; |
991 | } else if (cckPhyErrRate > aniState->cckTrigHigh) { | 738 | } else if (cckPhyErrRate > ah->config.cck_trig_high) { |
992 | ath_print(common, ATH_DBG_ANI, | 739 | ath9k_hw_ani_cck_err_trigger(ah); |
993 | "3 listenTime=%d CCK:%d errs=%d/s(>%d) -> " | 740 | ath9k_ani_restart(ah); |
994 | "ath9k_hw_ani_cck_err_trigger_new()\n", | ||
995 | aniState->listenTime, | ||
996 | aniState->cckNoiseImmunityLevel, | ||
997 | cckPhyErrRate, | ||
998 | aniState->cckTrigHigh); | ||
999 | ath9k_hw_ani_cck_err_trigger_new(ah); | ||
1000 | ath9k_ani_restart_new(ah); | ||
1001 | aniState->ofdmsTurn = true; | 741 | aniState->ofdmsTurn = true; |
1002 | } | 742 | } |
1003 | } | 743 | } |
1004 | } | 744 | } |
745 | EXPORT_SYMBOL(ath9k_hw_ani_monitor); | ||
1005 | 746 | ||
1006 | void ath9k_enable_mib_counters(struct ath_hw *ah) | 747 | void ath9k_enable_mib_counters(struct ath_hw *ah) |
1007 | { | 748 | { |
1008 | struct ath_common *common = ath9k_hw_common(ah); | 749 | struct ath_common *common = ath9k_hw_common(ah); |
1009 | 750 | ||
1010 | ath_print(common, ATH_DBG_ANI, "Enable MIB counters\n"); | 751 | ath_dbg(common, ATH_DBG_ANI, "Enable MIB counters\n"); |
1011 | 752 | ||
1012 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 753 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
1013 | 754 | ||
@@ -1022,7 +763,6 @@ void ath9k_enable_mib_counters(struct ath_hw *ah) | |||
1022 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); | 763 | REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); |
1023 | 764 | ||
1024 | REGWRITE_BUFFER_FLUSH(ah); | 765 | REGWRITE_BUFFER_FLUSH(ah); |
1025 | DISABLE_REGWRITE_BUFFER(ah); | ||
1026 | } | 766 | } |
1027 | 767 | ||
1028 | /* Freeze the MIB counters, get the stats and then clear them */ | 768 | /* Freeze the MIB counters, get the stats and then clear them */ |
@@ -1030,7 +770,7 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) | |||
1030 | { | 770 | { |
1031 | struct ath_common *common = ath9k_hw_common(ah); | 771 | struct ath_common *common = ath9k_hw_common(ah); |
1032 | 772 | ||
1033 | ath_print(common, ATH_DBG_ANI, "Disable MIB counters\n"); | 773 | ath_dbg(common, ATH_DBG_ANI, "Disable MIB counters\n"); |
1034 | 774 | ||
1035 | REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); | 775 | REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); |
1036 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 776 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
@@ -1040,53 +780,12 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) | |||
1040 | } | 780 | } |
1041 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); | 781 | EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); |
1042 | 782 | ||
1043 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, | ||
1044 | u32 *rxc_pcnt, | ||
1045 | u32 *rxf_pcnt, | ||
1046 | u32 *txf_pcnt) | ||
1047 | { | ||
1048 | struct ath_common *common = ath9k_hw_common(ah); | ||
1049 | static u32 cycles, rx_clear, rx_frame, tx_frame; | ||
1050 | u32 good = 1; | ||
1051 | |||
1052 | u32 rc = REG_READ(ah, AR_RCCNT); | ||
1053 | u32 rf = REG_READ(ah, AR_RFCNT); | ||
1054 | u32 tf = REG_READ(ah, AR_TFCNT); | ||
1055 | u32 cc = REG_READ(ah, AR_CCCNT); | ||
1056 | |||
1057 | if (cycles == 0 || cycles > cc) { | ||
1058 | ath_print(common, ATH_DBG_ANI, | ||
1059 | "cycle counter wrap. ExtBusy = 0\n"); | ||
1060 | good = 0; | ||
1061 | } else { | ||
1062 | u32 cc_d = cc - cycles; | ||
1063 | u32 rc_d = rc - rx_clear; | ||
1064 | u32 rf_d = rf - rx_frame; | ||
1065 | u32 tf_d = tf - tx_frame; | ||
1066 | |||
1067 | if (cc_d != 0) { | ||
1068 | *rxc_pcnt = rc_d * 100 / cc_d; | ||
1069 | *rxf_pcnt = rf_d * 100 / cc_d; | ||
1070 | *txf_pcnt = tf_d * 100 / cc_d; | ||
1071 | } else { | ||
1072 | good = 0; | ||
1073 | } | ||
1074 | } | ||
1075 | |||
1076 | cycles = cc; | ||
1077 | rx_frame = rf; | ||
1078 | rx_clear = rc; | ||
1079 | tx_frame = tf; | ||
1080 | |||
1081 | return good; | ||
1082 | } | ||
1083 | |||
1084 | /* | 783 | /* |
1085 | * Process a MIB interrupt. We may potentially be invoked because | 784 | * Process a MIB interrupt. We may potentially be invoked because |
1086 | * any of the MIB counters overflow/trigger so don't assume we're | 785 | * any of the MIB counters overflow/trigger so don't assume we're |
1087 | * here because a PHY error counter triggered. | 786 | * here because a PHY error counter triggered. |
1088 | */ | 787 | */ |
1089 | static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) | 788 | void ath9k_hw_proc_mib_event(struct ath_hw *ah) |
1090 | { | 789 | { |
1091 | u32 phyCnt1, phyCnt2; | 790 | u32 phyCnt1, phyCnt2; |
1092 | 791 | ||
@@ -1114,81 +813,24 @@ static void ath9k_hw_proc_mib_event_old(struct ath_hw *ah) | |||
1114 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | 813 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); |
1115 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | 814 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || |
1116 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { | 815 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { |
1117 | struct ar5416AniState *aniState = ah->curani; | ||
1118 | u32 ofdmPhyErrCnt, cckPhyErrCnt; | ||
1119 | 816 | ||
1120 | /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ | 817 | if (!use_new_ani(ah)) |
1121 | ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; | 818 | ath9k_hw_ani_read_counters(ah); |
1122 | ah->stats.ast_ani_ofdmerrs += | ||
1123 | ofdmPhyErrCnt - aniState->ofdmPhyErrCount; | ||
1124 | aniState->ofdmPhyErrCount = ofdmPhyErrCnt; | ||
1125 | 819 | ||
1126 | cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; | ||
1127 | ah->stats.ast_ani_cckerrs += | ||
1128 | cckPhyErrCnt - aniState->cckPhyErrCount; | ||
1129 | aniState->cckPhyErrCount = cckPhyErrCnt; | ||
1130 | |||
1131 | /* | ||
1132 | * NB: figure out which counter triggered. If both | ||
1133 | * trigger we'll only deal with one as the processing | ||
1134 | * clobbers the error counter so the trigger threshold | ||
1135 | * check will never be true. | ||
1136 | */ | ||
1137 | if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) | ||
1138 | ath9k_hw_ani_ofdm_err_trigger_new(ah); | ||
1139 | if (aniState->cckPhyErrCount > aniState->cckTrigHigh) | ||
1140 | ath9k_hw_ani_cck_err_trigger_old(ah); | ||
1141 | /* NB: always restart to insure the h/w counters are reset */ | 820 | /* NB: always restart to insure the h/w counters are reset */ |
1142 | ath9k_ani_restart_old(ah); | 821 | ath9k_ani_restart(ah); |
1143 | } | ||
1144 | } | ||
1145 | |||
1146 | /* | ||
1147 | * Process a MIB interrupt. We may potentially be invoked because | ||
1148 | * any of the MIB counters overflow/trigger so don't assume we're | ||
1149 | * here because a PHY error counter triggered. | ||
1150 | */ | ||
1151 | static void ath9k_hw_proc_mib_event_new(struct ath_hw *ah) | ||
1152 | { | ||
1153 | u32 phyCnt1, phyCnt2; | ||
1154 | |||
1155 | /* Reset these counters regardless */ | ||
1156 | REG_WRITE(ah, AR_FILT_OFDM, 0); | ||
1157 | REG_WRITE(ah, AR_FILT_CCK, 0); | ||
1158 | if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) | ||
1159 | REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); | ||
1160 | |||
1161 | /* Clear the mib counters and save them in the stats */ | ||
1162 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | ||
1163 | |||
1164 | if (!DO_ANI(ah)) { | ||
1165 | /* | ||
1166 | * We must always clear the interrupt cause by | ||
1167 | * resetting the phy error regs. | ||
1168 | */ | ||
1169 | REG_WRITE(ah, AR_PHY_ERR_1, 0); | ||
1170 | REG_WRITE(ah, AR_PHY_ERR_2, 0); | ||
1171 | return; | ||
1172 | } | 822 | } |
1173 | |||
1174 | /* NB: these are not reset-on-read */ | ||
1175 | phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); | ||
1176 | phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); | ||
1177 | |||
1178 | /* NB: always restart to insure the h/w counters are reset */ | ||
1179 | if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || | ||
1180 | ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) | ||
1181 | ath9k_ani_restart_new(ah); | ||
1182 | } | 823 | } |
824 | EXPORT_SYMBOL(ath9k_hw_proc_mib_event); | ||
1183 | 825 | ||
1184 | void ath9k_hw_ani_setup(struct ath_hw *ah) | 826 | void ath9k_hw_ani_setup(struct ath_hw *ah) |
1185 | { | 827 | { |
1186 | int i; | 828 | int i; |
1187 | 829 | ||
1188 | const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; | 830 | static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; |
1189 | const int coarseHigh[] = { -14, -14, -14, -14, -12 }; | 831 | static const int coarseHigh[] = { -14, -14, -14, -14, -12 }; |
1190 | const int coarseLow[] = { -64, -64, -64, -64, -70 }; | 832 | static const int coarseLow[] = { -64, -64, -64, -64, -70 }; |
1191 | const int firpwr[] = { -78, -78, -78, -78, -80 }; | 833 | static const int firpwr[] = { -78, -78, -78, -78, -80 }; |
1192 | 834 | ||
1193 | for (i = 0; i < 5; i++) { | 835 | for (i = 0; i < 5; i++) { |
1194 | ah->totalSizeDesired[i] = totalSizeDesired[i]; | 836 | ah->totalSizeDesired[i] = totalSizeDesired[i]; |
@@ -1203,69 +845,60 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
1203 | struct ath_common *common = ath9k_hw_common(ah); | 845 | struct ath_common *common = ath9k_hw_common(ah); |
1204 | int i; | 846 | int i; |
1205 | 847 | ||
1206 | ath_print(common, ATH_DBG_ANI, "Initialize ANI\n"); | 848 | ath_dbg(common, ATH_DBG_ANI, "Initialize ANI\n"); |
1207 | 849 | ||
1208 | memset(ah->ani, 0, sizeof(ah->ani)); | 850 | if (use_new_ani(ah)) { |
1209 | for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { | 851 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; |
1210 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { | 852 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_NEW; |
1211 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_NEW; | ||
1212 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_NEW; | ||
1213 | 853 | ||
1214 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_NEW; | 854 | ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_NEW; |
1215 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_NEW; | 855 | ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_NEW; |
856 | } else { | ||
857 | ah->config.ofdm_trig_high = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
858 | ah->config.ofdm_trig_low = ATH9K_ANI_OFDM_TRIG_LOW_OLD; | ||
1216 | 859 | ||
1217 | ah->ani[i].spurImmunityLevel = | 860 | ah->config.cck_trig_high = ATH9K_ANI_CCK_TRIG_HIGH_OLD; |
1218 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | 861 | ah->config.cck_trig_low = ATH9K_ANI_CCK_TRIG_LOW_OLD; |
862 | } | ||
1219 | 863 | ||
1220 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 864 | for (i = 0; i < ARRAY_SIZE(ah->channels); i++) { |
865 | struct ath9k_channel *chan = &ah->channels[i]; | ||
866 | struct ar5416AniState *ani = &chan->ani; | ||
1221 | 867 | ||
1222 | ah->ani[i].ofdmPhyErrBase = 0; | 868 | if (use_new_ani(ah)) { |
1223 | ah->ani[i].cckPhyErrBase = 0; | 869 | ani->spurImmunityLevel = |
870 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW; | ||
871 | |||
872 | ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | ||
1224 | 873 | ||
1225 | if (AR_SREV_9300_20_OR_LATER(ah)) | 874 | if (AR_SREV_9300_20_OR_LATER(ah)) |
1226 | ah->ani[i].mrcCCKOff = | 875 | ani->mrcCCKOff = |
1227 | !ATH9K_ANI_ENABLE_MRC_CCK; | 876 | !ATH9K_ANI_ENABLE_MRC_CCK; |
1228 | else | 877 | else |
1229 | ah->ani[i].mrcCCKOff = true; | 878 | ani->mrcCCKOff = true; |
1230 | 879 | ||
1231 | ah->ani[i].ofdmsTurn = true; | 880 | ani->ofdmsTurn = true; |
1232 | } else { | 881 | } else { |
1233 | ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | 882 | ani->spurImmunityLevel = |
1234 | ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW_OLD; | ||
1235 | |||
1236 | ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1237 | ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW_OLD; | ||
1238 | |||
1239 | ah->ani[i].spurImmunityLevel = | ||
1240 | ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; | 883 | ATH9K_ANI_SPUR_IMMUNE_LVL_OLD; |
1241 | ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; | 884 | ani->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_OLD; |
1242 | 885 | ||
1243 | ah->ani[i].ofdmPhyErrBase = | 886 | ani->cckWeakSigThreshold = |
1244 | AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH_OLD; | ||
1245 | ah->ani[i].cckPhyErrBase = | ||
1246 | AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH_OLD; | ||
1247 | ah->ani[i].cckWeakSigThreshold = | ||
1248 | ATH9K_ANI_CCK_WEAK_SIG_THR; | 887 | ATH9K_ANI_CCK_WEAK_SIG_THR; |
1249 | } | 888 | } |
1250 | 889 | ||
1251 | ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; | 890 | ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; |
1252 | ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; | 891 | ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; |
1253 | ah->ani[i].ofdmWeakSigDetectOff = | 892 | ani->ofdmWeakSigDetectOff = |
1254 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 893 | !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
1255 | ah->ani[i].cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; | 894 | ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; |
1256 | } | 895 | } |
1257 | 896 | ||
1258 | /* | 897 | /* |
1259 | * since we expect some ongoing maintenance on the tables, let's sanity | 898 | * since we expect some ongoing maintenance on the tables, let's sanity |
1260 | * check here default level should not modify INI setting. | 899 | * check here default level should not modify INI setting. |
1261 | */ | 900 | */ |
1262 | if (AR_SREV_9300_20_OR_LATER(ah) || modparam_force_new_ani) { | 901 | if (use_new_ani(ah)) { |
1263 | const struct ani_ofdm_level_entry *entry_ofdm; | ||
1264 | const struct ani_cck_level_entry *entry_cck; | ||
1265 | |||
1266 | entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; | ||
1267 | entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; | ||
1268 | |||
1269 | ah->aniperiod = ATH9K_ANI_PERIOD_NEW; | 902 | ah->aniperiod = ATH9K_ANI_PERIOD_NEW; |
1270 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; | 903 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; |
1271 | } else { | 904 | } else { |
@@ -1273,50 +906,9 @@ void ath9k_hw_ani_init(struct ath_hw *ah) | |||
1273 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; | 906 | ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_OLD; |
1274 | } | 907 | } |
1275 | 908 | ||
1276 | ath_print(common, ATH_DBG_ANI, | ||
1277 | "Setting OfdmErrBase = 0x%08x\n", | ||
1278 | ah->ani[0].ofdmPhyErrBase); | ||
1279 | ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", | ||
1280 | ah->ani[0].cckPhyErrBase); | ||
1281 | |||
1282 | ENABLE_REGWRITE_BUFFER(ah); | ||
1283 | |||
1284 | REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); | ||
1285 | REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); | ||
1286 | |||
1287 | REGWRITE_BUFFER_FLUSH(ah); | ||
1288 | DISABLE_REGWRITE_BUFFER(ah); | ||
1289 | |||
1290 | ath9k_enable_mib_counters(ah); | ||
1291 | |||
1292 | if (ah->config.enable_ani) | 909 | if (ah->config.enable_ani) |
1293 | ah->proc_phyerr |= HAL_PROCESS_ANI; | 910 | ah->proc_phyerr |= HAL_PROCESS_ANI; |
1294 | } | ||
1295 | |||
1296 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah) | ||
1297 | { | ||
1298 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1299 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1300 | |||
1301 | priv_ops->ani_reset = ath9k_ani_reset_old; | ||
1302 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_old; | ||
1303 | |||
1304 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_old; | ||
1305 | ops->ani_monitor = ath9k_hw_ani_monitor_old; | ||
1306 | |||
1307 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v1\n"); | ||
1308 | } | ||
1309 | |||
1310 | void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah) | ||
1311 | { | ||
1312 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
1313 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1314 | 911 | ||
1315 | priv_ops->ani_reset = ath9k_ani_reset_new; | 912 | ath9k_ani_restart(ah); |
1316 | priv_ops->ani_lower_immunity = ath9k_hw_ani_lower_immunity_new; | 913 | ath9k_enable_mib_counters(ah); |
1317 | |||
1318 | ops->ani_proc_mib_event = ath9k_hw_proc_mib_event_new; | ||
1319 | ops->ani_monitor = ath9k_hw_ani_monitor_new; | ||
1320 | |||
1321 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, "Using ANI v2\n"); | ||
1322 | } | 914 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index f4d0a4d48b37..dbab5b9ce494 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | #define HAL_PROCESS_ANI 0x00000001 | 20 | #define HAL_PROCESS_ANI 0x00000001 |
21 | 21 | ||
22 | #define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) | 22 | #define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI) && ah->curchan) |
23 | 23 | ||
24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) | 24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) |
25 | 25 | ||
@@ -123,20 +123,11 @@ struct ar5416AniState { | |||
123 | u8 ofdmWeakSigDetectOff; | 123 | u8 ofdmWeakSigDetectOff; |
124 | u8 cckWeakSigThreshold; | 124 | u8 cckWeakSigThreshold; |
125 | u32 listenTime; | 125 | u32 listenTime; |
126 | u32 ofdmTrigHigh; | ||
127 | u32 ofdmTrigLow; | ||
128 | int32_t cckTrigHigh; | ||
129 | int32_t cckTrigLow; | ||
130 | int32_t rssiThrLow; | 126 | int32_t rssiThrLow; |
131 | int32_t rssiThrHigh; | 127 | int32_t rssiThrHigh; |
132 | u32 noiseFloor; | 128 | u32 noiseFloor; |
133 | u32 txFrameCount; | ||
134 | u32 rxFrameCount; | ||
135 | u32 cycleCount; | ||
136 | u32 ofdmPhyErrCount; | 129 | u32 ofdmPhyErrCount; |
137 | u32 cckPhyErrCount; | 130 | u32 cckPhyErrCount; |
138 | u32 ofdmPhyErrBase; | ||
139 | u32 cckPhyErrBase; | ||
140 | int16_t pktRssi[2]; | 131 | int16_t pktRssi[2]; |
141 | int16_t ofdmErrRssi[2]; | 132 | int16_t ofdmErrRssi[2]; |
142 | int16_t cckErrRssi[2]; | 133 | int16_t cckErrRssi[2]; |
@@ -166,8 +157,6 @@ struct ar5416Stats { | |||
166 | 157 | ||
167 | void ath9k_enable_mib_counters(struct ath_hw *ah); | 158 | void ath9k_enable_mib_counters(struct ath_hw *ah); |
168 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); | 159 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); |
169 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, | ||
170 | u32 *rxf_pcnt, u32 *txf_pcnt); | ||
171 | void ath9k_hw_ani_setup(struct ath_hw *ah); | 160 | void ath9k_hw_ani_setup(struct ath_hw *ah); |
172 | void ath9k_hw_ani_init(struct ath_hw *ah); | 161 | void ath9k_hw_ani_init(struct ath_hw *ah); |
173 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, | 162 | int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h index 36f7d0639db3..234617c948a1 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar5008_initvals.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 3d2c8679bc85..441bb33f17ad 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -44,6 +44,34 @@ static const int m1ThreshExt_off = 127; | |||
44 | static const int m2ThreshExt_off = 127; | 44 | static const int m2ThreshExt_off = 127; |
45 | 45 | ||
46 | 46 | ||
47 | static void ar5008_rf_bank_setup(u32 *bank, struct ar5416IniArray *array, | ||
48 | int col) | ||
49 | { | ||
50 | int i; | ||
51 | |||
52 | for (i = 0; i < array->ia_rows; i++) | ||
53 | bank[i] = INI_RA(array, i, col); | ||
54 | } | ||
55 | |||
56 | |||
57 | #define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) \ | ||
58 | ar5008_write_rf_array(ah, iniarray, regData, &(regWr)) | ||
59 | |||
60 | static void ar5008_write_rf_array(struct ath_hw *ah, struct ar5416IniArray *array, | ||
61 | u32 *data, unsigned int *writecnt) | ||
62 | { | ||
63 | int r; | ||
64 | |||
65 | ENABLE_REGWRITE_BUFFER(ah); | ||
66 | |||
67 | for (r = 0; r < array->ia_rows; r++) { | ||
68 | REG_WRITE(ah, INI_RA(array, r, 0), data[r]); | ||
69 | DO_DELAY(*writecnt); | ||
70 | } | ||
71 | |||
72 | REGWRITE_BUFFER_FLUSH(ah); | ||
73 | } | ||
74 | |||
47 | /** | 75 | /** |
48 | * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters | 76 | * ar5008_hw_phy_modify_rx_buffer() - perform analog swizzling of parameters |
49 | * @rfbuf: | 77 | * @rfbuf: |
@@ -118,7 +146,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq) | |||
118 | if (!AR_SREV_5416(ah) || synth_freq >= 3000) | 146 | if (!AR_SREV_5416(ah) || synth_freq >= 3000) |
119 | return; | 147 | return; |
120 | 148 | ||
121 | BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); | 149 | BUG_ON(AR_SREV_9280_20_OR_LATER(ah)); |
122 | 150 | ||
123 | if (synth_freq < 2412) | 151 | if (synth_freq < 2412) |
124 | new_bias = 0; | 152 | new_bias = 0; |
@@ -130,9 +158,8 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq) | |||
130 | /* pre-reverse this field */ | 158 | /* pre-reverse this field */ |
131 | tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); | 159 | tmp_reg = ath9k_hw_reverse_bits(new_bias, 3); |
132 | 160 | ||
133 | ath_print(common, ATH_DBG_CONFIG, | 161 | ath_dbg(common, ATH_DBG_CONFIG, "Force rf_pwd_icsyndiv to %1d on %4d\n", |
134 | "Force rf_pwd_icsyndiv to %1d on %4d\n", | 162 | new_bias, synth_freq); |
135 | new_bias, synth_freq); | ||
136 | 163 | ||
137 | /* swizzle rf_pwd_icsyndiv */ | 164 | /* swizzle rf_pwd_icsyndiv */ |
138 | ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); | 165 | ar5008_hw_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3); |
@@ -143,7 +170,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq) | |||
143 | 170 | ||
144 | /** | 171 | /** |
145 | * ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios | 172 | * ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios |
146 | * @ah: atheros hardware stucture | 173 | * @ah: atheros hardware structure |
147 | * @chan: | 174 | * @chan: |
148 | * | 175 | * |
149 | * For the external AR2133/AR5133 radios, takes the MHz channel value and set | 176 | * For the external AR2133/AR5133 radios, takes the MHz channel value and set |
@@ -173,8 +200,7 @@ static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
173 | channelSel = ((freq - 704) * 2 - 3040) / 10; | 200 | channelSel = ((freq - 704) * 2 - 3040) / 10; |
174 | bModeSynth = 1; | 201 | bModeSynth = 1; |
175 | } else { | 202 | } else { |
176 | ath_print(common, ATH_DBG_FATAL, | 203 | ath_err(common, "Invalid channel %u MHz\n", freq); |
177 | "Invalid channel %u MHz\n", freq); | ||
178 | return -EINVAL; | 204 | return -EINVAL; |
179 | } | 205 | } |
180 | 206 | ||
@@ -206,8 +232,7 @@ static int ar5008_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
206 | channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); | 232 | channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); |
207 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); | 233 | aModeRefSel = ath9k_hw_reverse_bits(1, 2); |
208 | } else { | 234 | } else { |
209 | ath_print(common, ATH_DBG_FATAL, | 235 | ath_err(common, "Invalid channel %u MHz\n", freq); |
210 | "Invalid channel %u MHz\n", freq); | ||
211 | return -EINVAL; | 236 | return -EINVAL; |
212 | } | 237 | } |
213 | 238 | ||
@@ -244,13 +269,15 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah, | |||
244 | int upper, lower, cur_vit_mask; | 269 | int upper, lower, cur_vit_mask; |
245 | int tmp, new; | 270 | int tmp, new; |
246 | int i; | 271 | int i; |
247 | int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, | 272 | static int pilot_mask_reg[4] = { |
248 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | 273 | AR_PHY_TIMING7, AR_PHY_TIMING8, |
274 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | ||
249 | }; | 275 | }; |
250 | int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, | 276 | static int chan_mask_reg[4] = { |
251 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | 277 | AR_PHY_TIMING9, AR_PHY_TIMING10, |
278 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | ||
252 | }; | 279 | }; |
253 | int inc[4] = { 0, 100, 0, 0 }; | 280 | static int inc[4] = { 0, 100, 0, 0 }; |
254 | 281 | ||
255 | int8_t mask_m[123]; | 282 | int8_t mask_m[123]; |
256 | int8_t mask_p[123]; | 283 | int8_t mask_p[123]; |
@@ -446,15 +473,14 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) | |||
446 | #define ATH_ALLOC_BANK(bank, size) do { \ | 473 | #define ATH_ALLOC_BANK(bank, size) do { \ |
447 | bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ | 474 | bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \ |
448 | if (!bank) { \ | 475 | if (!bank) { \ |
449 | ath_print(common, ATH_DBG_FATAL, \ | 476 | ath_err(common, "Cannot allocate RF banks\n"); \ |
450 | "Cannot allocate RF banks\n"); \ | ||
451 | return -ENOMEM; \ | 477 | return -ENOMEM; \ |
452 | } \ | 478 | } \ |
453 | } while (0); | 479 | } while (0); |
454 | 480 | ||
455 | struct ath_common *common = ath9k_hw_common(ah); | 481 | struct ath_common *common = ath9k_hw_common(ah); |
456 | 482 | ||
457 | BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); | 483 | BUG_ON(AR_SREV_9280_20_OR_LATER(ah)); |
458 | 484 | ||
459 | ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); | 485 | ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); |
460 | ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); | 486 | ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); |
@@ -484,7 +510,7 @@ static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah) | |||
484 | bank = NULL; \ | 510 | bank = NULL; \ |
485 | } while (0); | 511 | } while (0); |
486 | 512 | ||
487 | BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); | 513 | BUG_ON(AR_SREV_9280_20_OR_LATER(ah)); |
488 | 514 | ||
489 | ATH_FREE_BANK(ah->analogBank0Data); | 515 | ATH_FREE_BANK(ah->analogBank0Data); |
490 | ATH_FREE_BANK(ah->analogBank1Data); | 516 | ATH_FREE_BANK(ah->analogBank1Data); |
@@ -525,23 +551,23 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, | |||
525 | * for single chip devices, that is AR9280 or anything | 551 | * for single chip devices, that is AR9280 or anything |
526 | * after that. | 552 | * after that. |
527 | */ | 553 | */ |
528 | if (AR_SREV_9280_10_OR_LATER(ah)) | 554 | if (AR_SREV_9280_20_OR_LATER(ah)) |
529 | return true; | 555 | return true; |
530 | 556 | ||
531 | /* Setup rf parameters */ | 557 | /* Setup rf parameters */ |
532 | eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); | 558 | eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); |
533 | 559 | ||
534 | /* Setup Bank 0 Write */ | 560 | /* Setup Bank 0 Write */ |
535 | RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); | 561 | ar5008_rf_bank_setup(ah->analogBank0Data, &ah->iniBank0, 1); |
536 | 562 | ||
537 | /* Setup Bank 1 Write */ | 563 | /* Setup Bank 1 Write */ |
538 | RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); | 564 | ar5008_rf_bank_setup(ah->analogBank1Data, &ah->iniBank1, 1); |
539 | 565 | ||
540 | /* Setup Bank 2 Write */ | 566 | /* Setup Bank 2 Write */ |
541 | RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); | 567 | ar5008_rf_bank_setup(ah->analogBank2Data, &ah->iniBank2, 1); |
542 | 568 | ||
543 | /* Setup Bank 6 Write */ | 569 | /* Setup Bank 6 Write */ |
544 | RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, | 570 | ar5008_rf_bank_setup(ah->analogBank3Data, &ah->iniBank3, |
545 | modesIndex); | 571 | modesIndex); |
546 | { | 572 | { |
547 | int i; | 573 | int i; |
@@ -571,7 +597,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, | |||
571 | } | 597 | } |
572 | 598 | ||
573 | /* Setup Bank 7 Setup */ | 599 | /* Setup Bank 7 Setup */ |
574 | RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); | 600 | ar5008_rf_bank_setup(ah->analogBank7Data, &ah->iniBank7, 1); |
575 | 601 | ||
576 | /* Write Analog registers */ | 602 | /* Write Analog registers */ |
577 | REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, | 603 | REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, |
@@ -613,14 +639,11 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah) | |||
613 | rx_chainmask = ah->rxchainmask; | 639 | rx_chainmask = ah->rxchainmask; |
614 | tx_chainmask = ah->txchainmask; | 640 | tx_chainmask = ah->txchainmask; |
615 | 641 | ||
616 | ENABLE_REGWRITE_BUFFER(ah); | ||
617 | 642 | ||
618 | switch (rx_chainmask) { | 643 | switch (rx_chainmask) { |
619 | case 0x5: | 644 | case 0x5: |
620 | DISABLE_REGWRITE_BUFFER(ah); | ||
621 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 645 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
622 | AR_PHY_SWAP_ALT_CHAIN); | 646 | AR_PHY_SWAP_ALT_CHAIN); |
623 | ENABLE_REGWRITE_BUFFER(ah); | ||
624 | case 0x3: | 647 | case 0x3: |
625 | if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { | 648 | if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { |
626 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); | 649 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); |
@@ -630,17 +653,18 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah) | |||
630 | case 0x1: | 653 | case 0x1: |
631 | case 0x2: | 654 | case 0x2: |
632 | case 0x7: | 655 | case 0x7: |
656 | ENABLE_REGWRITE_BUFFER(ah); | ||
633 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); | 657 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); |
634 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); | 658 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); |
635 | break; | 659 | break; |
636 | default: | 660 | default: |
661 | ENABLE_REGWRITE_BUFFER(ah); | ||
637 | break; | 662 | break; |
638 | } | 663 | } |
639 | 664 | ||
640 | REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); | 665 | REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); |
641 | 666 | ||
642 | REGWRITE_BUFFER_FLUSH(ah); | 667 | REGWRITE_BUFFER_FLUSH(ah); |
643 | DISABLE_REGWRITE_BUFFER(ah); | ||
644 | 668 | ||
645 | if (tx_chainmask == 0x5) { | 669 | if (tx_chainmask == 0x5) { |
646 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 670 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
@@ -663,20 +687,20 @@ static void ar5008_hw_override_ini(struct ath_hw *ah, | |||
663 | */ | 687 | */ |
664 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); | 688 | REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); |
665 | 689 | ||
666 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 690 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
667 | val = REG_READ(ah, AR_PCU_MISC_MODE2); | 691 | val = REG_READ(ah, AR_PCU_MISC_MODE2); |
668 | 692 | ||
669 | if (!AR_SREV_9271(ah)) | 693 | if (!AR_SREV_9271(ah)) |
670 | val &= ~AR_PCU_MISC_MODE2_HWWAR1; | 694 | val &= ~AR_PCU_MISC_MODE2_HWWAR1; |
671 | 695 | ||
672 | if (AR_SREV_9287_10_OR_LATER(ah)) | 696 | if (AR_SREV_9287_11_OR_LATER(ah)) |
673 | val = val & (~AR_PCU_MISC_MODE2_HWWAR2); | 697 | val = val & (~AR_PCU_MISC_MODE2_HWWAR2); |
674 | 698 | ||
675 | REG_WRITE(ah, AR_PCU_MISC_MODE2, val); | 699 | REG_WRITE(ah, AR_PCU_MISC_MODE2, val); |
676 | } | 700 | } |
677 | 701 | ||
678 | if (!AR_SREV_5416_20_OR_LATER(ah) || | 702 | if (!AR_SREV_5416_20_OR_LATER(ah) || |
679 | AR_SREV_9280_10_OR_LATER(ah)) | 703 | AR_SREV_9280_20_OR_LATER(ah)) |
680 | return; | 704 | return; |
681 | /* | 705 | /* |
682 | * Disable BB clock gating | 706 | * Disable BB clock gating |
@@ -701,7 +725,7 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah, | |||
701 | u32 phymode; | 725 | u32 phymode; |
702 | u32 enableDacFifo = 0; | 726 | u32 enableDacFifo = 0; |
703 | 727 | ||
704 | if (AR_SREV_9285_10_OR_LATER(ah)) | 728 | if (AR_SREV_9285_12_OR_LATER(ah)) |
705 | enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & | 729 | enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & |
706 | AR_PHY_FC_ENABLE_DAC_FIFO); | 730 | AR_PHY_FC_ENABLE_DAC_FIFO); |
707 | 731 | ||
@@ -726,7 +750,6 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah, | |||
726 | REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); | 750 | REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); |
727 | 751 | ||
728 | REGWRITE_BUFFER_FLUSH(ah); | 752 | REGWRITE_BUFFER_FLUSH(ah); |
729 | DISABLE_REGWRITE_BUFFER(ah); | ||
730 | } | 753 | } |
731 | 754 | ||
732 | 755 | ||
@@ -734,6 +757,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
734 | struct ath9k_channel *chan) | 757 | struct ath9k_channel *chan) |
735 | { | 758 | { |
736 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 759 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
760 | struct ath_common *common = ath9k_hw_common(ah); | ||
737 | int i, regWrites = 0; | 761 | int i, regWrites = 0; |
738 | struct ieee80211_channel *channel = chan->chan; | 762 | struct ieee80211_channel *channel = chan->chan; |
739 | u32 modesIndex, freqIndex; | 763 | u32 modesIndex, freqIndex; |
@@ -810,7 +834,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
810 | REG_WRITE(ah, reg, val); | 834 | REG_WRITE(ah, reg, val); |
811 | 835 | ||
812 | if (reg >= 0x7800 && reg < 0x78a0 | 836 | if (reg >= 0x7800 && reg < 0x78a0 |
813 | && ah->config.analog_shiftreg) { | 837 | && ah->config.analog_shiftreg |
838 | && (common->bus_ops->ath_bus_type != ATH_USB)) { | ||
814 | udelay(100); | 839 | udelay(100); |
815 | } | 840 | } |
816 | 841 | ||
@@ -818,13 +843,12 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
818 | } | 843 | } |
819 | 844 | ||
820 | REGWRITE_BUFFER_FLUSH(ah); | 845 | REGWRITE_BUFFER_FLUSH(ah); |
821 | DISABLE_REGWRITE_BUFFER(ah); | ||
822 | 846 | ||
823 | if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah)) | 847 | if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah)) |
824 | REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); | 848 | REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); |
825 | 849 | ||
826 | if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || | 850 | if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || |
827 | AR_SREV_9287_10_OR_LATER(ah)) | 851 | AR_SREV_9287_11_OR_LATER(ah)) |
828 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); | 852 | REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); |
829 | 853 | ||
830 | if (AR_SREV_9271_10(ah)) | 854 | if (AR_SREV_9271_10(ah)) |
@@ -841,7 +865,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
841 | REG_WRITE(ah, reg, val); | 865 | REG_WRITE(ah, reg, val); |
842 | 866 | ||
843 | if (reg >= 0x7800 && reg < 0x78a0 | 867 | if (reg >= 0x7800 && reg < 0x78a0 |
844 | && ah->config.analog_shiftreg) { | 868 | && ah->config.analog_shiftreg |
869 | && (common->bus_ops->ath_bus_type != ATH_USB)) { | ||
845 | udelay(100); | 870 | udelay(100); |
846 | } | 871 | } |
847 | 872 | ||
@@ -849,7 +874,6 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
849 | } | 874 | } |
850 | 875 | ||
851 | REGWRITE_BUFFER_FLUSH(ah); | 876 | REGWRITE_BUFFER_FLUSH(ah); |
852 | DISABLE_REGWRITE_BUFFER(ah); | ||
853 | 877 | ||
854 | if (AR_SREV_9271(ah)) { | 878 | if (AR_SREV_9271(ah)) { |
855 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) | 879 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1) |
@@ -878,12 +902,11 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, | |||
878 | channel->max_antenna_gain * 2, | 902 | channel->max_antenna_gain * 2, |
879 | channel->max_power * 2, | 903 | channel->max_power * 2, |
880 | min((u32) MAX_RATE_POWER, | 904 | min((u32) MAX_RATE_POWER, |
881 | (u32) regulatory->power_limit)); | 905 | (u32) regulatory->power_limit), false); |
882 | 906 | ||
883 | /* Write analog registers */ | 907 | /* Write analog registers */ |
884 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { | 908 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { |
885 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 909 | ath_err(ath9k_hw_common(ah), "ar5416SetRfRegs failed\n"); |
886 | "ar5416SetRfRegs failed\n"); | ||
887 | return -EIO; | 910 | return -EIO; |
888 | } | 911 | } |
889 | 912 | ||
@@ -900,7 +923,7 @@ static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) | |||
900 | rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) | 923 | rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) |
901 | ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; | 924 | ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; |
902 | 925 | ||
903 | if (!AR_SREV_9280_10_OR_LATER(ah)) | 926 | if (!AR_SREV_9280_20_OR_LATER(ah)) |
904 | rfMode |= (IS_CHAN_5GHZ(chan)) ? | 927 | rfMode |= (IS_CHAN_5GHZ(chan)) ? |
905 | AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; | 928 | AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; |
906 | 929 | ||
@@ -969,18 +992,6 @@ static void ar5008_hw_rfbus_done(struct ath_hw *ah) | |||
969 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); | 992 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); |
970 | } | 993 | } |
971 | 994 | ||
972 | static void ar5008_hw_enable_rfkill(struct ath_hw *ah) | ||
973 | { | ||
974 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
975 | AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); | ||
976 | |||
977 | REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, | ||
978 | AR_GPIO_INPUT_MUX2_RFSILENT); | ||
979 | |||
980 | ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); | ||
981 | REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); | ||
982 | } | ||
983 | |||
984 | static void ar5008_restore_chainmask(struct ath_hw *ah) | 995 | static void ar5008_restore_chainmask(struct ath_hw *ah) |
985 | { | 996 | { |
986 | int rx_chainmask = ah->rxchainmask; | 997 | int rx_chainmask = ah->rxchainmask; |
@@ -1053,7 +1064,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1053 | enum ath9k_ani_cmd cmd, | 1064 | enum ath9k_ani_cmd cmd, |
1054 | int param) | 1065 | int param) |
1055 | { | 1066 | { |
1056 | struct ar5416AniState *aniState = ah->curani; | 1067 | struct ar5416AniState *aniState = &ah->curchan->ani; |
1057 | struct ath_common *common = ath9k_hw_common(ah); | 1068 | struct ath_common *common = ath9k_hw_common(ah); |
1058 | 1069 | ||
1059 | switch (cmd & ah->ani_function) { | 1070 | switch (cmd & ah->ani_function) { |
@@ -1061,10 +1072,9 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1061 | u32 level = param; | 1072 | u32 level = param; |
1062 | 1073 | ||
1063 | if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { | 1074 | if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { |
1064 | ath_print(common, ATH_DBG_ANI, | 1075 | ath_dbg(common, ATH_DBG_ANI, |
1065 | "level out of range (%u > %u)\n", | 1076 | "level out of range (%u > %zu)\n", |
1066 | level, | 1077 | level, ARRAY_SIZE(ah->totalSizeDesired)); |
1067 | (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); | ||
1068 | return false; | 1078 | return false; |
1069 | } | 1079 | } |
1070 | 1080 | ||
@@ -1089,12 +1099,12 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1089 | break; | 1099 | break; |
1090 | } | 1100 | } |
1091 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | 1101 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ |
1092 | const int m1ThreshLow[] = { 127, 50 }; | 1102 | static const int m1ThreshLow[] = { 127, 50 }; |
1093 | const int m2ThreshLow[] = { 127, 40 }; | 1103 | static const int m2ThreshLow[] = { 127, 40 }; |
1094 | const int m1Thresh[] = { 127, 0x4d }; | 1104 | static const int m1Thresh[] = { 127, 0x4d }; |
1095 | const int m2Thresh[] = { 127, 0x40 }; | 1105 | static const int m2Thresh[] = { 127, 0x40 }; |
1096 | const int m2CountThr[] = { 31, 16 }; | 1106 | static const int m2CountThr[] = { 31, 16 }; |
1097 | const int m2CountThrLow[] = { 63, 48 }; | 1107 | static const int m2CountThrLow[] = { 63, 48 }; |
1098 | u32 on = param ? 1 : 0; | 1108 | u32 on = param ? 1 : 0; |
1099 | 1109 | ||
1100 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | 1110 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, |
@@ -1146,7 +1156,7 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1146 | break; | 1156 | break; |
1147 | } | 1157 | } |
1148 | case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ | 1158 | case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ |
1149 | const int weakSigThrCck[] = { 8, 6 }; | 1159 | static const int weakSigThrCck[] = { 8, 6 }; |
1150 | u32 high = param ? 1 : 0; | 1160 | u32 high = param ? 1 : 0; |
1151 | 1161 | ||
1152 | REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, | 1162 | REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, |
@@ -1162,14 +1172,13 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1162 | break; | 1172 | break; |
1163 | } | 1173 | } |
1164 | case ATH9K_ANI_FIRSTEP_LEVEL:{ | 1174 | case ATH9K_ANI_FIRSTEP_LEVEL:{ |
1165 | const int firstep[] = { 0, 4, 8 }; | 1175 | static const int firstep[] = { 0, 4, 8 }; |
1166 | u32 level = param; | 1176 | u32 level = param; |
1167 | 1177 | ||
1168 | if (level >= ARRAY_SIZE(firstep)) { | 1178 | if (level >= ARRAY_SIZE(firstep)) { |
1169 | ath_print(common, ATH_DBG_ANI, | 1179 | ath_dbg(common, ATH_DBG_ANI, |
1170 | "level out of range (%u > %u)\n", | 1180 | "level out of range (%u > %zu)\n", |
1171 | level, | 1181 | level, ARRAY_SIZE(firstep)); |
1172 | (unsigned) ARRAY_SIZE(firstep)); | ||
1173 | return false; | 1182 | return false; |
1174 | } | 1183 | } |
1175 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | 1184 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, |
@@ -1183,14 +1192,13 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1183 | break; | 1192 | break; |
1184 | } | 1193 | } |
1185 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ | 1194 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ |
1186 | const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; | 1195 | static const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; |
1187 | u32 level = param; | 1196 | u32 level = param; |
1188 | 1197 | ||
1189 | if (level >= ARRAY_SIZE(cycpwrThr1)) { | 1198 | if (level >= ARRAY_SIZE(cycpwrThr1)) { |
1190 | ath_print(common, ATH_DBG_ANI, | 1199 | ath_dbg(common, ATH_DBG_ANI, |
1191 | "level out of range (%u > %u)\n", | 1200 | "level out of range (%u > %zu)\n", |
1192 | level, | 1201 | level, ARRAY_SIZE(cycpwrThr1)); |
1193 | (unsigned) ARRAY_SIZE(cycpwrThr1)); | ||
1194 | return false; | 1202 | return false; |
1195 | } | 1203 | } |
1196 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | 1204 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, |
@@ -1206,27 +1214,23 @@ static bool ar5008_hw_ani_control_old(struct ath_hw *ah, | |||
1206 | case ATH9K_ANI_PRESENT: | 1214 | case ATH9K_ANI_PRESENT: |
1207 | break; | 1215 | break; |
1208 | default: | 1216 | default: |
1209 | ath_print(common, ATH_DBG_ANI, | 1217 | ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd); |
1210 | "invalid cmd %u\n", cmd); | ||
1211 | return false; | 1218 | return false; |
1212 | } | 1219 | } |
1213 | 1220 | ||
1214 | ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); | 1221 | ath_dbg(common, ATH_DBG_ANI, "ANI parameters:\n"); |
1215 | ath_print(common, ATH_DBG_ANI, | 1222 | ath_dbg(common, ATH_DBG_ANI, |
1216 | "noiseImmunityLevel=%d, spurImmunityLevel=%d, " | 1223 | "noiseImmunityLevel=%d, spurImmunityLevel=%d, ofdmWeakSigDetectOff=%d\n", |
1217 | "ofdmWeakSigDetectOff=%d\n", | 1224 | aniState->noiseImmunityLevel, |
1218 | aniState->noiseImmunityLevel, | 1225 | aniState->spurImmunityLevel, |
1219 | aniState->spurImmunityLevel, | 1226 | !aniState->ofdmWeakSigDetectOff); |
1220 | !aniState->ofdmWeakSigDetectOff); | 1227 | ath_dbg(common, ATH_DBG_ANI, |
1221 | ath_print(common, ATH_DBG_ANI, | 1228 | "cckWeakSigThreshold=%d, firstepLevel=%d, listenTime=%d\n", |
1222 | "cckWeakSigThreshold=%d, " | 1229 | aniState->cckWeakSigThreshold, |
1223 | "firstepLevel=%d, listenTime=%d\n", | 1230 | aniState->firstepLevel, |
1224 | aniState->cckWeakSigThreshold, | 1231 | aniState->listenTime); |
1225 | aniState->firstepLevel, | 1232 | ath_dbg(common, ATH_DBG_ANI, |
1226 | aniState->listenTime); | 1233 | "ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", |
1227 | ath_print(common, ATH_DBG_ANI, | ||
1228 | "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", | ||
1229 | aniState->cycleCount, | ||
1230 | aniState->ofdmPhyErrCount, | 1234 | aniState->ofdmPhyErrCount, |
1231 | aniState->cckPhyErrCount); | 1235 | aniState->cckPhyErrCount); |
1232 | 1236 | ||
@@ -1237,9 +1241,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1237 | enum ath9k_ani_cmd cmd, | 1241 | enum ath9k_ani_cmd cmd, |
1238 | int param) | 1242 | int param) |
1239 | { | 1243 | { |
1240 | struct ar5416AniState *aniState = ah->curani; | ||
1241 | struct ath_common *common = ath9k_hw_common(ah); | 1244 | struct ath_common *common = ath9k_hw_common(ah); |
1242 | struct ath9k_channel *chan = ah->curchan; | 1245 | struct ath9k_channel *chan = ah->curchan; |
1246 | struct ar5416AniState *aniState = &chan->ani; | ||
1243 | s32 value, value2; | 1247 | s32 value, value2; |
1244 | 1248 | ||
1245 | switch (cmd & ah->ani_function) { | 1249 | switch (cmd & ah->ani_function) { |
@@ -1310,12 +1314,12 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1310 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | 1314 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); |
1311 | 1315 | ||
1312 | if (!on != aniState->ofdmWeakSigDetectOff) { | 1316 | if (!on != aniState->ofdmWeakSigDetectOff) { |
1313 | ath_print(common, ATH_DBG_ANI, | 1317 | ath_dbg(common, ATH_DBG_ANI, |
1314 | "** ch %d: ofdm weak signal: %s=>%s\n", | 1318 | "** ch %d: ofdm weak signal: %s=>%s\n", |
1315 | chan->channel, | 1319 | chan->channel, |
1316 | !aniState->ofdmWeakSigDetectOff ? | 1320 | !aniState->ofdmWeakSigDetectOff ? |
1317 | "on" : "off", | 1321 | "on" : "off", |
1318 | on ? "on" : "off"); | 1322 | on ? "on" : "off"); |
1319 | if (on) | 1323 | if (on) |
1320 | ah->stats.ast_ani_ofdmon++; | 1324 | ah->stats.ast_ani_ofdmon++; |
1321 | else | 1325 | else |
@@ -1328,11 +1332,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1328 | u32 level = param; | 1332 | u32 level = param; |
1329 | 1333 | ||
1330 | if (level >= ARRAY_SIZE(firstep_table)) { | 1334 | if (level >= ARRAY_SIZE(firstep_table)) { |
1331 | ath_print(common, ATH_DBG_ANI, | 1335 | ath_dbg(common, ATH_DBG_ANI, |
1332 | "ATH9K_ANI_FIRSTEP_LEVEL: level " | 1336 | "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n", |
1333 | "out of range (%u > %u)\n", | 1337 | level, ARRAY_SIZE(firstep_table)); |
1334 | level, | ||
1335 | (unsigned) ARRAY_SIZE(firstep_table)); | ||
1336 | return false; | 1338 | return false; |
1337 | } | 1339 | } |
1338 | 1340 | ||
@@ -1367,24 +1369,22 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1367 | AR_PHY_FIND_SIG_FIRSTEP_LOW, value2); | 1369 | AR_PHY_FIND_SIG_FIRSTEP_LOW, value2); |
1368 | 1370 | ||
1369 | if (level != aniState->firstepLevel) { | 1371 | if (level != aniState->firstepLevel) { |
1370 | ath_print(common, ATH_DBG_ANI, | 1372 | ath_dbg(common, ATH_DBG_ANI, |
1371 | "** ch %d: level %d=>%d[def:%d] " | 1373 | "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n", |
1372 | "firstep[level]=%d ini=%d\n", | 1374 | chan->channel, |
1373 | chan->channel, | 1375 | aniState->firstepLevel, |
1374 | aniState->firstepLevel, | 1376 | level, |
1375 | level, | 1377 | ATH9K_ANI_FIRSTEP_LVL_NEW, |
1376 | ATH9K_ANI_FIRSTEP_LVL_NEW, | 1378 | value, |
1377 | value, | 1379 | aniState->iniDef.firstep); |
1378 | aniState->iniDef.firstep); | 1380 | ath_dbg(common, ATH_DBG_ANI, |
1379 | ath_print(common, ATH_DBG_ANI, | 1381 | "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n", |
1380 | "** ch %d: level %d=>%d[def:%d] " | 1382 | chan->channel, |
1381 | "firstep_low[level]=%d ini=%d\n", | 1383 | aniState->firstepLevel, |
1382 | chan->channel, | 1384 | level, |
1383 | aniState->firstepLevel, | 1385 | ATH9K_ANI_FIRSTEP_LVL_NEW, |
1384 | level, | 1386 | value2, |
1385 | ATH9K_ANI_FIRSTEP_LVL_NEW, | 1387 | aniState->iniDef.firstepLow); |
1386 | value2, | ||
1387 | aniState->iniDef.firstepLow); | ||
1388 | if (level > aniState->firstepLevel) | 1388 | if (level > aniState->firstepLevel) |
1389 | ah->stats.ast_ani_stepup++; | 1389 | ah->stats.ast_ani_stepup++; |
1390 | else if (level < aniState->firstepLevel) | 1390 | else if (level < aniState->firstepLevel) |
@@ -1397,11 +1397,9 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1397 | u32 level = param; | 1397 | u32 level = param; |
1398 | 1398 | ||
1399 | if (level >= ARRAY_SIZE(cycpwrThr1_table)) { | 1399 | if (level >= ARRAY_SIZE(cycpwrThr1_table)) { |
1400 | ath_print(common, ATH_DBG_ANI, | 1400 | ath_dbg(common, ATH_DBG_ANI, |
1401 | "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " | 1401 | "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n", |
1402 | "out of range (%u > %u)\n", | 1402 | level, ARRAY_SIZE(cycpwrThr1_table)); |
1403 | level, | ||
1404 | (unsigned) ARRAY_SIZE(cycpwrThr1_table)); | ||
1405 | return false; | 1403 | return false; |
1406 | } | 1404 | } |
1407 | /* | 1405 | /* |
@@ -1435,24 +1433,22 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1435 | AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2); | 1433 | AR_PHY_EXT_TIMING5_CYCPWR_THR1, value2); |
1436 | 1434 | ||
1437 | if (level != aniState->spurImmunityLevel) { | 1435 | if (level != aniState->spurImmunityLevel) { |
1438 | ath_print(common, ATH_DBG_ANI, | 1436 | ath_dbg(common, ATH_DBG_ANI, |
1439 | "** ch %d: level %d=>%d[def:%d] " | 1437 | "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n", |
1440 | "cycpwrThr1[level]=%d ini=%d\n", | 1438 | chan->channel, |
1441 | chan->channel, | 1439 | aniState->spurImmunityLevel, |
1442 | aniState->spurImmunityLevel, | 1440 | level, |
1443 | level, | 1441 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, |
1444 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | 1442 | value, |
1445 | value, | 1443 | aniState->iniDef.cycpwrThr1); |
1446 | aniState->iniDef.cycpwrThr1); | 1444 | ath_dbg(common, ATH_DBG_ANI, |
1447 | ath_print(common, ATH_DBG_ANI, | 1445 | "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n", |
1448 | "** ch %d: level %d=>%d[def:%d] " | 1446 | chan->channel, |
1449 | "cycpwrThr1Ext[level]=%d ini=%d\n", | 1447 | aniState->spurImmunityLevel, |
1450 | chan->channel, | 1448 | level, |
1451 | aniState->spurImmunityLevel, | 1449 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, |
1452 | level, | 1450 | value2, |
1453 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | 1451 | aniState->iniDef.cycpwrThr1Ext); |
1454 | value2, | ||
1455 | aniState->iniDef.cycpwrThr1Ext); | ||
1456 | if (level > aniState->spurImmunityLevel) | 1452 | if (level > aniState->spurImmunityLevel) |
1457 | ah->stats.ast_ani_spurup++; | 1453 | ah->stats.ast_ani_spurup++; |
1458 | else if (level < aniState->spurImmunityLevel) | 1454 | else if (level < aniState->spurImmunityLevel) |
@@ -1471,24 +1467,19 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, | |||
1471 | case ATH9K_ANI_PRESENT: | 1467 | case ATH9K_ANI_PRESENT: |
1472 | break; | 1468 | break; |
1473 | default: | 1469 | default: |
1474 | ath_print(common, ATH_DBG_ANI, | 1470 | ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd); |
1475 | "invalid cmd %u\n", cmd); | ||
1476 | return false; | 1471 | return false; |
1477 | } | 1472 | } |
1478 | 1473 | ||
1479 | ath_print(common, ATH_DBG_ANI, | 1474 | ath_dbg(common, ATH_DBG_ANI, |
1480 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " | 1475 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", |
1481 | "MRCcck=%s listenTime=%d CC=%d listen=%d " | 1476 | aniState->spurImmunityLevel, |
1482 | "ofdmErrs=%d cckErrs=%d\n", | 1477 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", |
1483 | aniState->spurImmunityLevel, | 1478 | aniState->firstepLevel, |
1484 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", | 1479 | !aniState->mrcCCKOff ? "on" : "off", |
1485 | aniState->firstepLevel, | 1480 | aniState->listenTime, |
1486 | !aniState->mrcCCKOff ? "on" : "off", | 1481 | aniState->ofdmPhyErrCount, |
1487 | aniState->listenTime, | 1482 | aniState->cckPhyErrCount); |
1488 | aniState->cycleCount, | ||
1489 | aniState->listenTime, | ||
1490 | aniState->ofdmPhyErrCount, | ||
1491 | aniState->cckPhyErrCount); | ||
1492 | return true; | 1483 | return true; |
1493 | } | 1484 | } |
1494 | 1485 | ||
@@ -1498,25 +1489,25 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah, | |||
1498 | int16_t nf; | 1489 | int16_t nf; |
1499 | 1490 | ||
1500 | nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); | 1491 | nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); |
1501 | nfarray[0] = sign_extend(nf, 9); | 1492 | nfarray[0] = sign_extend32(nf, 8); |
1502 | 1493 | ||
1503 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); | 1494 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR); |
1504 | nfarray[1] = sign_extend(nf, 9); | 1495 | nfarray[1] = sign_extend32(nf, 8); |
1505 | 1496 | ||
1506 | nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); | 1497 | nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR); |
1507 | nfarray[2] = sign_extend(nf, 9); | 1498 | nfarray[2] = sign_extend32(nf, 8); |
1508 | 1499 | ||
1509 | if (!IS_CHAN_HT40(ah->curchan)) | 1500 | if (!IS_CHAN_HT40(ah->curchan)) |
1510 | return; | 1501 | return; |
1511 | 1502 | ||
1512 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); | 1503 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); |
1513 | nfarray[3] = sign_extend(nf, 9); | 1504 | nfarray[3] = sign_extend32(nf, 8); |
1514 | 1505 | ||
1515 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); | 1506 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR); |
1516 | nfarray[4] = sign_extend(nf, 9); | 1507 | nfarray[4] = sign_extend32(nf, 8); |
1517 | 1508 | ||
1518 | nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); | 1509 | nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR); |
1519 | nfarray[5] = sign_extend(nf, 9); | 1510 | nfarray[5] = sign_extend32(nf, 8); |
1520 | } | 1511 | } |
1521 | 1512 | ||
1522 | /* | 1513 | /* |
@@ -1526,25 +1517,20 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah, | |||
1526 | */ | 1517 | */ |
1527 | static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) | 1518 | static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) |
1528 | { | 1519 | { |
1529 | struct ar5416AniState *aniState; | ||
1530 | struct ath_common *common = ath9k_hw_common(ah); | 1520 | struct ath_common *common = ath9k_hw_common(ah); |
1531 | struct ath9k_channel *chan = ah->curchan; | 1521 | struct ath9k_channel *chan = ah->curchan; |
1522 | struct ar5416AniState *aniState = &chan->ani; | ||
1532 | struct ath9k_ani_default *iniDef; | 1523 | struct ath9k_ani_default *iniDef; |
1533 | int index; | ||
1534 | u32 val; | 1524 | u32 val; |
1535 | 1525 | ||
1536 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | ||
1537 | aniState = &ah->ani[index]; | ||
1538 | ah->curani = aniState; | ||
1539 | iniDef = &aniState->iniDef; | 1526 | iniDef = &aniState->iniDef; |
1540 | 1527 | ||
1541 | ath_print(common, ATH_DBG_ANI, | 1528 | ath_dbg(common, ATH_DBG_ANI, "ver %d.%d opmode %u chan %d Mhz/0x%x\n", |
1542 | "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | 1529 | ah->hw_version.macVersion, |
1543 | ah->hw_version.macVersion, | 1530 | ah->hw_version.macRev, |
1544 | ah->hw_version.macRev, | 1531 | ah->opmode, |
1545 | ah->opmode, | 1532 | chan->channel, |
1546 | chan->channel, | 1533 | chan->channelFlags); |
1547 | chan->channelFlags); | ||
1548 | 1534 | ||
1549 | val = REG_READ(ah, AR_PHY_SFCORR); | 1535 | val = REG_READ(ah, AR_PHY_SFCORR); |
1550 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | 1536 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); |
@@ -1579,8 +1565,6 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1579 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 1565 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; |
1580 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 1566 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
1581 | aniState->mrcCCKOff = true; /* not available on pre AR9003 */ | 1567 | aniState->mrcCCKOff = true; /* not available on pre AR9003 */ |
1582 | |||
1583 | aniState->cycleCount = 0; | ||
1584 | } | 1568 | } |
1585 | 1569 | ||
1586 | static void ar5008_hw_set_nf_limits(struct ath_hw *ah) | 1570 | static void ar5008_hw_set_nf_limits(struct ath_hw *ah) |
@@ -1593,10 +1577,55 @@ static void ar5008_hw_set_nf_limits(struct ath_hw *ah) | |||
1593 | ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; | 1577 | ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ; |
1594 | } | 1578 | } |
1595 | 1579 | ||
1580 | static void ar5008_hw_set_radar_params(struct ath_hw *ah, | ||
1581 | struct ath_hw_radar_conf *conf) | ||
1582 | { | ||
1583 | u32 radar_0 = 0, radar_1 = 0; | ||
1584 | |||
1585 | if (!conf) { | ||
1586 | REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); | ||
1587 | return; | ||
1588 | } | ||
1589 | |||
1590 | radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA; | ||
1591 | radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR); | ||
1592 | radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI); | ||
1593 | radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT); | ||
1594 | radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); | ||
1595 | radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); | ||
1596 | |||
1597 | radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; | ||
1598 | radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; | ||
1599 | radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); | ||
1600 | radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH); | ||
1601 | radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH); | ||
1602 | |||
1603 | REG_WRITE(ah, AR_PHY_RADAR_0, radar_0); | ||
1604 | REG_WRITE(ah, AR_PHY_RADAR_1, radar_1); | ||
1605 | if (conf->ext_channel) | ||
1606 | REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); | ||
1607 | else | ||
1608 | REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); | ||
1609 | } | ||
1610 | |||
1611 | static void ar5008_hw_set_radar_conf(struct ath_hw *ah) | ||
1612 | { | ||
1613 | struct ath_hw_radar_conf *conf = &ah->radar_conf; | ||
1614 | |||
1615 | conf->fir_power = -33; | ||
1616 | conf->radar_rssi = 20; | ||
1617 | conf->pulse_height = 10; | ||
1618 | conf->pulse_rssi = 24; | ||
1619 | conf->pulse_inband = 15; | ||
1620 | conf->pulse_maxlen = 255; | ||
1621 | conf->pulse_inband_step = 12; | ||
1622 | conf->radar_inband = 8; | ||
1623 | } | ||
1624 | |||
1596 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | 1625 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah) |
1597 | { | 1626 | { |
1598 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1627 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
1599 | const u32 ar5416_cca_regs[6] = { | 1628 | static const u32 ar5416_cca_regs[6] = { |
1600 | AR_PHY_CCA, | 1629 | AR_PHY_CCA, |
1601 | AR_PHY_CH1_CCA, | 1630 | AR_PHY_CH1_CCA, |
1602 | AR_PHY_CH2_CCA, | 1631 | AR_PHY_CH2_CCA, |
@@ -1619,10 +1648,10 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | |||
1619 | priv_ops->set_delta_slope = ar5008_hw_set_delta_slope; | 1648 | priv_ops->set_delta_slope = ar5008_hw_set_delta_slope; |
1620 | priv_ops->rfbus_req = ar5008_hw_rfbus_req; | 1649 | priv_ops->rfbus_req = ar5008_hw_rfbus_req; |
1621 | priv_ops->rfbus_done = ar5008_hw_rfbus_done; | 1650 | priv_ops->rfbus_done = ar5008_hw_rfbus_done; |
1622 | priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; | ||
1623 | priv_ops->restore_chainmask = ar5008_restore_chainmask; | 1651 | priv_ops->restore_chainmask = ar5008_restore_chainmask; |
1624 | priv_ops->set_diversity = ar5008_set_diversity; | 1652 | priv_ops->set_diversity = ar5008_set_diversity; |
1625 | priv_ops->do_getnf = ar5008_hw_do_getnf; | 1653 | priv_ops->do_getnf = ar5008_hw_do_getnf; |
1654 | priv_ops->set_radar_params = ar5008_hw_set_radar_params; | ||
1626 | 1655 | ||
1627 | if (modparam_force_new_ani) { | 1656 | if (modparam_force_new_ani) { |
1628 | priv_ops->ani_control = ar5008_hw_ani_control_new; | 1657 | priv_ops->ani_control = ar5008_hw_ani_control_new; |
@@ -1638,5 +1667,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) | |||
1638 | priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; | 1667 | priv_ops->compute_pll_control = ar5008_hw_compute_pll_control; |
1639 | 1668 | ||
1640 | ar5008_hw_set_nf_limits(ah); | 1669 | ar5008_hw_set_nf_limits(ah); |
1670 | ar5008_hw_set_radar_conf(ah); | ||
1641 | memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs)); | 1671 | memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs)); |
1642 | } | 1672 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h index 69a94c7e45cb..6d2e2f3303f9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9001_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9001_initvals.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index fe7418aefc4a..2d4c0910295b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -20,6 +20,34 @@ | |||
20 | 20 | ||
21 | #define AR9285_CLCAL_REDO_THRESH 1 | 21 | #define AR9285_CLCAL_REDO_THRESH 1 |
22 | 22 | ||
23 | enum ar9002_cal_types { | ||
24 | ADC_GAIN_CAL = BIT(0), | ||
25 | ADC_DC_CAL = BIT(1), | ||
26 | IQ_MISMATCH_CAL = BIT(2), | ||
27 | }; | ||
28 | |||
29 | static bool ar9002_hw_is_cal_supported(struct ath_hw *ah, | ||
30 | struct ath9k_channel *chan, | ||
31 | enum ar9002_cal_types cal_type) | ||
32 | { | ||
33 | bool supported = false; | ||
34 | switch (ah->supp_cals & cal_type) { | ||
35 | case IQ_MISMATCH_CAL: | ||
36 | /* Run IQ Mismatch for non-CCK only */ | ||
37 | if (!IS_CHAN_B(chan)) | ||
38 | supported = true; | ||
39 | break; | ||
40 | case ADC_GAIN_CAL: | ||
41 | case ADC_DC_CAL: | ||
42 | /* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */ | ||
43 | if (!IS_CHAN_B(chan) && | ||
44 | !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) | ||
45 | supported = true; | ||
46 | break; | ||
47 | } | ||
48 | return supported; | ||
49 | } | ||
50 | |||
23 | static void ar9002_hw_setup_calibration(struct ath_hw *ah, | 51 | static void ar9002_hw_setup_calibration(struct ath_hw *ah, |
24 | struct ath9k_cal_list *currCal) | 52 | struct ath9k_cal_list *currCal) |
25 | { | 53 | { |
@@ -32,26 +60,19 @@ static void ar9002_hw_setup_calibration(struct ath_hw *ah, | |||
32 | switch (currCal->calData->calType) { | 60 | switch (currCal->calData->calType) { |
33 | case IQ_MISMATCH_CAL: | 61 | case IQ_MISMATCH_CAL: |
34 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); | 62 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); |
35 | ath_print(common, ATH_DBG_CALIBRATE, | 63 | ath_dbg(common, ATH_DBG_CALIBRATE, |
36 | "starting IQ Mismatch Calibration\n"); | 64 | "starting IQ Mismatch Calibration\n"); |
37 | break; | 65 | break; |
38 | case ADC_GAIN_CAL: | 66 | case ADC_GAIN_CAL: |
39 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); | 67 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); |
40 | ath_print(common, ATH_DBG_CALIBRATE, | 68 | ath_dbg(common, ATH_DBG_CALIBRATE, |
41 | "starting ADC Gain Calibration\n"); | 69 | "starting ADC Gain Calibration\n"); |
42 | break; | 70 | break; |
43 | case ADC_DC_CAL: | 71 | case ADC_DC_CAL: |
44 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); | 72 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); |
45 | ath_print(common, ATH_DBG_CALIBRATE, | 73 | ath_dbg(common, ATH_DBG_CALIBRATE, |
46 | "starting ADC DC Calibration\n"); | 74 | "starting ADC DC Calibration\n"); |
47 | break; | ||
48 | case ADC_DC_INIT_CAL: | ||
49 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); | ||
50 | ath_print(common, ATH_DBG_CALIBRATE, | ||
51 | "starting Init ADC DC Calibration\n"); | ||
52 | break; | 75 | break; |
53 | case TEMP_COMP_CAL: | ||
54 | break; /* Not supported */ | ||
55 | } | 76 | } |
56 | 77 | ||
57 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), | 78 | REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), |
@@ -96,25 +117,6 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah, | |||
96 | return iscaldone; | 117 | return iscaldone; |
97 | } | 118 | } |
98 | 119 | ||
99 | /* Assumes you are talking about the currently configured channel */ | ||
100 | static bool ar9002_hw_iscal_supported(struct ath_hw *ah, | ||
101 | enum ath9k_cal_types calType) | ||
102 | { | ||
103 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | ||
104 | |||
105 | switch (calType & ah->supp_cals) { | ||
106 | case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ | ||
107 | return true; | ||
108 | case ADC_GAIN_CAL: | ||
109 | case ADC_DC_CAL: | ||
110 | if (!(conf->channel->band == IEEE80211_BAND_2GHZ && | ||
111 | conf_is_ht20(conf))) | ||
112 | return true; | ||
113 | break; | ||
114 | } | ||
115 | return false; | ||
116 | } | ||
117 | |||
118 | static void ar9002_hw_iqcal_collect(struct ath_hw *ah) | 120 | static void ar9002_hw_iqcal_collect(struct ath_hw *ah) |
119 | { | 121 | { |
120 | int i; | 122 | int i; |
@@ -126,11 +128,11 @@ static void ar9002_hw_iqcal_collect(struct ath_hw *ah) | |||
126 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | 128 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); |
127 | ah->totalIqCorrMeas[i] += | 129 | ah->totalIqCorrMeas[i] += |
128 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | 130 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); |
129 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | 131 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
130 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", | 132 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", |
131 | ah->cal_samples, i, ah->totalPowerMeasI[i], | 133 | ah->cal_samples, i, ah->totalPowerMeasI[i], |
132 | ah->totalPowerMeasQ[i], | 134 | ah->totalPowerMeasQ[i], |
133 | ah->totalIqCorrMeas[i]); | 135 | ah->totalIqCorrMeas[i]); |
134 | } | 136 | } |
135 | } | 137 | } |
136 | 138 | ||
@@ -148,14 +150,13 @@ static void ar9002_hw_adc_gaincal_collect(struct ath_hw *ah) | |||
148 | ah->totalAdcQEvenPhase[i] += | 150 | ah->totalAdcQEvenPhase[i] += |
149 | REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | 151 | REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); |
150 | 152 | ||
151 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | 153 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
152 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | 154 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", |
153 | "oddq=0x%08x; evenq=0x%08x;\n", | 155 | ah->cal_samples, i, |
154 | ah->cal_samples, i, | 156 | ah->totalAdcIOddPhase[i], |
155 | ah->totalAdcIOddPhase[i], | 157 | ah->totalAdcIEvenPhase[i], |
156 | ah->totalAdcIEvenPhase[i], | 158 | ah->totalAdcQOddPhase[i], |
157 | ah->totalAdcQOddPhase[i], | 159 | ah->totalAdcQEvenPhase[i]); |
158 | ah->totalAdcQEvenPhase[i]); | ||
159 | } | 160 | } |
160 | } | 161 | } |
161 | 162 | ||
@@ -173,14 +174,13 @@ static void ar9002_hw_adc_dccal_collect(struct ath_hw *ah) | |||
173 | ah->totalAdcDcOffsetQEvenPhase[i] += | 174 | ah->totalAdcDcOffsetQEvenPhase[i] += |
174 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); | 175 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); |
175 | 176 | ||
176 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | 177 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
177 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " | 178 | "%d: Chn %d oddi=0x%08x; eveni=0x%08x; oddq=0x%08x; evenq=0x%08x;\n", |
178 | "oddq=0x%08x; evenq=0x%08x;\n", | 179 | ah->cal_samples, i, |
179 | ah->cal_samples, i, | 180 | ah->totalAdcDcOffsetIOddPhase[i], |
180 | ah->totalAdcDcOffsetIOddPhase[i], | 181 | ah->totalAdcDcOffsetIEvenPhase[i], |
181 | ah->totalAdcDcOffsetIEvenPhase[i], | 182 | ah->totalAdcDcOffsetQOddPhase[i], |
182 | ah->totalAdcDcOffsetQOddPhase[i], | 183 | ah->totalAdcDcOffsetQEvenPhase[i]); |
183 | ah->totalAdcDcOffsetQEvenPhase[i]); | ||
184 | } | 184 | } |
185 | } | 185 | } |
186 | 186 | ||
@@ -197,13 +197,13 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
197 | powerMeasQ = ah->totalPowerMeasQ[i]; | 197 | powerMeasQ = ah->totalPowerMeasQ[i]; |
198 | iqCorrMeas = ah->totalIqCorrMeas[i]; | 198 | iqCorrMeas = ah->totalIqCorrMeas[i]; |
199 | 199 | ||
200 | ath_print(common, ATH_DBG_CALIBRATE, | 200 | ath_dbg(common, ATH_DBG_CALIBRATE, |
201 | "Starting IQ Cal and Correction for Chain %d\n", | 201 | "Starting IQ Cal and Correction for Chain %d\n", |
202 | i); | 202 | i); |
203 | 203 | ||
204 | ath_print(common, ATH_DBG_CALIBRATE, | 204 | ath_dbg(common, ATH_DBG_CALIBRATE, |
205 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", | 205 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", |
206 | i, ah->totalIqCorrMeas[i]); | 206 | i, ah->totalIqCorrMeas[i]); |
207 | 207 | ||
208 | iqCorrNeg = 0; | 208 | iqCorrNeg = 0; |
209 | 209 | ||
@@ -212,12 +212,12 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
212 | iqCorrNeg = 1; | 212 | iqCorrNeg = 1; |
213 | } | 213 | } |
214 | 214 | ||
215 | ath_print(common, ATH_DBG_CALIBRATE, | 215 | ath_dbg(common, ATH_DBG_CALIBRATE, |
216 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); | 216 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); |
217 | ath_print(common, ATH_DBG_CALIBRATE, | 217 | ath_dbg(common, ATH_DBG_CALIBRATE, |
218 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); | 218 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); |
219 | ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", | 219 | ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", |
220 | iqCorrNeg); | 220 | iqCorrNeg); |
221 | 221 | ||
222 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; | 222 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; |
223 | qCoffDenom = powerMeasQ / 64; | 223 | qCoffDenom = powerMeasQ / 64; |
@@ -226,14 +226,14 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
226 | (qCoffDenom != 0)) { | 226 | (qCoffDenom != 0)) { |
227 | iCoff = iqCorrMeas / iCoffDenom; | 227 | iCoff = iqCorrMeas / iCoffDenom; |
228 | qCoff = powerMeasI / qCoffDenom - 64; | 228 | qCoff = powerMeasI / qCoffDenom - 64; |
229 | ath_print(common, ATH_DBG_CALIBRATE, | 229 | ath_dbg(common, ATH_DBG_CALIBRATE, |
230 | "Chn %d iCoff = 0x%08x\n", i, iCoff); | 230 | "Chn %d iCoff = 0x%08x\n", i, iCoff); |
231 | ath_print(common, ATH_DBG_CALIBRATE, | 231 | ath_dbg(common, ATH_DBG_CALIBRATE, |
232 | "Chn %d qCoff = 0x%08x\n", i, qCoff); | 232 | "Chn %d qCoff = 0x%08x\n", i, qCoff); |
233 | 233 | ||
234 | iCoff = iCoff & 0x3f; | 234 | iCoff = iCoff & 0x3f; |
235 | ath_print(common, ATH_DBG_CALIBRATE, | 235 | ath_dbg(common, ATH_DBG_CALIBRATE, |
236 | "New: Chn %d iCoff = 0x%08x\n", i, iCoff); | 236 | "New: Chn %d iCoff = 0x%08x\n", i, iCoff); |
237 | if (iqCorrNeg == 0x0) | 237 | if (iqCorrNeg == 0x0) |
238 | iCoff = 0x40 - iCoff; | 238 | iCoff = 0x40 - iCoff; |
239 | 239 | ||
@@ -242,9 +242,9 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
242 | else if (qCoff <= -16) | 242 | else if (qCoff <= -16) |
243 | qCoff = -16; | 243 | qCoff = -16; |
244 | 244 | ||
245 | ath_print(common, ATH_DBG_CALIBRATE, | 245 | ath_dbg(common, ATH_DBG_CALIBRATE, |
246 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", | 246 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", |
247 | i, iCoff, qCoff); | 247 | i, iCoff, qCoff); |
248 | 248 | ||
249 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | 249 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), |
250 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, | 250 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, |
@@ -252,9 +252,9 @@ static void ar9002_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
252 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), | 252 | REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), |
253 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, | 253 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, |
254 | qCoff); | 254 | qCoff); |
255 | ath_print(common, ATH_DBG_CALIBRATE, | 255 | ath_dbg(common, ATH_DBG_CALIBRATE, |
256 | "IQ Cal and Correction done for Chain %d\n", | 256 | "IQ Cal and Correction done for Chain %d\n", |
257 | i); | 257 | i); |
258 | } | 258 | } |
259 | } | 259 | } |
260 | 260 | ||
@@ -274,21 +274,21 @@ static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) | |||
274 | qOddMeasOffset = ah->totalAdcQOddPhase[i]; | 274 | qOddMeasOffset = ah->totalAdcQOddPhase[i]; |
275 | qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; | 275 | qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; |
276 | 276 | ||
277 | ath_print(common, ATH_DBG_CALIBRATE, | 277 | ath_dbg(common, ATH_DBG_CALIBRATE, |
278 | "Starting ADC Gain Cal for Chain %d\n", i); | 278 | "Starting ADC Gain Cal for Chain %d\n", i); |
279 | 279 | ||
280 | ath_print(common, ATH_DBG_CALIBRATE, | 280 | ath_dbg(common, ATH_DBG_CALIBRATE, |
281 | "Chn %d pwr_meas_odd_i = 0x%08x\n", i, | 281 | "Chn %d pwr_meas_odd_i = 0x%08x\n", i, |
282 | iOddMeasOffset); | 282 | iOddMeasOffset); |
283 | ath_print(common, ATH_DBG_CALIBRATE, | 283 | ath_dbg(common, ATH_DBG_CALIBRATE, |
284 | "Chn %d pwr_meas_even_i = 0x%08x\n", i, | 284 | "Chn %d pwr_meas_even_i = 0x%08x\n", i, |
285 | iEvenMeasOffset); | 285 | iEvenMeasOffset); |
286 | ath_print(common, ATH_DBG_CALIBRATE, | 286 | ath_dbg(common, ATH_DBG_CALIBRATE, |
287 | "Chn %d pwr_meas_odd_q = 0x%08x\n", i, | 287 | "Chn %d pwr_meas_odd_q = 0x%08x\n", i, |
288 | qOddMeasOffset); | 288 | qOddMeasOffset); |
289 | ath_print(common, ATH_DBG_CALIBRATE, | 289 | ath_dbg(common, ATH_DBG_CALIBRATE, |
290 | "Chn %d pwr_meas_even_q = 0x%08x\n", i, | 290 | "Chn %d pwr_meas_even_q = 0x%08x\n", i, |
291 | qEvenMeasOffset); | 291 | qEvenMeasOffset); |
292 | 292 | ||
293 | if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { | 293 | if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { |
294 | iGainMismatch = | 294 | iGainMismatch = |
@@ -298,20 +298,20 @@ static void ar9002_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) | |||
298 | ((qOddMeasOffset * 32) / | 298 | ((qOddMeasOffset * 32) / |
299 | qEvenMeasOffset) & 0x3f; | 299 | qEvenMeasOffset) & 0x3f; |
300 | 300 | ||
301 | ath_print(common, ATH_DBG_CALIBRATE, | 301 | ath_dbg(common, ATH_DBG_CALIBRATE, |
302 | "Chn %d gain_mismatch_i = 0x%08x\n", i, | 302 | "Chn %d gain_mismatch_i = 0x%08x\n", i, |
303 | iGainMismatch); | 303 | iGainMismatch); |
304 | ath_print(common, ATH_DBG_CALIBRATE, | 304 | ath_dbg(common, ATH_DBG_CALIBRATE, |
305 | "Chn %d gain_mismatch_q = 0x%08x\n", i, | 305 | "Chn %d gain_mismatch_q = 0x%08x\n", i, |
306 | qGainMismatch); | 306 | qGainMismatch); |
307 | 307 | ||
308 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | 308 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); |
309 | val &= 0xfffff000; | 309 | val &= 0xfffff000; |
310 | val |= (qGainMismatch) | (iGainMismatch << 6); | 310 | val |= (qGainMismatch) | (iGainMismatch << 6); |
311 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | 311 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); |
312 | 312 | ||
313 | ath_print(common, ATH_DBG_CALIBRATE, | 313 | ath_dbg(common, ATH_DBG_CALIBRATE, |
314 | "ADC Gain Cal done for Chain %d\n", i); | 314 | "ADC Gain Cal done for Chain %d\n", i); |
315 | } | 315 | } |
316 | } | 316 | } |
317 | 317 | ||
@@ -336,41 +336,41 @@ static void ar9002_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) | |||
336 | qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; | 336 | qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; |
337 | qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; | 337 | qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; |
338 | 338 | ||
339 | ath_print(common, ATH_DBG_CALIBRATE, | 339 | ath_dbg(common, ATH_DBG_CALIBRATE, |
340 | "Starting ADC DC Offset Cal for Chain %d\n", i); | 340 | "Starting ADC DC Offset Cal for Chain %d\n", i); |
341 | 341 | ||
342 | ath_print(common, ATH_DBG_CALIBRATE, | 342 | ath_dbg(common, ATH_DBG_CALIBRATE, |
343 | "Chn %d pwr_meas_odd_i = %d\n", i, | 343 | "Chn %d pwr_meas_odd_i = %d\n", i, |
344 | iOddMeasOffset); | 344 | iOddMeasOffset); |
345 | ath_print(common, ATH_DBG_CALIBRATE, | 345 | ath_dbg(common, ATH_DBG_CALIBRATE, |
346 | "Chn %d pwr_meas_even_i = %d\n", i, | 346 | "Chn %d pwr_meas_even_i = %d\n", i, |
347 | iEvenMeasOffset); | 347 | iEvenMeasOffset); |
348 | ath_print(common, ATH_DBG_CALIBRATE, | 348 | ath_dbg(common, ATH_DBG_CALIBRATE, |
349 | "Chn %d pwr_meas_odd_q = %d\n", i, | 349 | "Chn %d pwr_meas_odd_q = %d\n", i, |
350 | qOddMeasOffset); | 350 | qOddMeasOffset); |
351 | ath_print(common, ATH_DBG_CALIBRATE, | 351 | ath_dbg(common, ATH_DBG_CALIBRATE, |
352 | "Chn %d pwr_meas_even_q = %d\n", i, | 352 | "Chn %d pwr_meas_even_q = %d\n", i, |
353 | qEvenMeasOffset); | 353 | qEvenMeasOffset); |
354 | 354 | ||
355 | iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / | 355 | iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / |
356 | numSamples) & 0x1ff; | 356 | numSamples) & 0x1ff; |
357 | qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / | 357 | qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / |
358 | numSamples) & 0x1ff; | 358 | numSamples) & 0x1ff; |
359 | 359 | ||
360 | ath_print(common, ATH_DBG_CALIBRATE, | 360 | ath_dbg(common, ATH_DBG_CALIBRATE, |
361 | "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, | 361 | "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, |
362 | iDcMismatch); | 362 | iDcMismatch); |
363 | ath_print(common, ATH_DBG_CALIBRATE, | 363 | ath_dbg(common, ATH_DBG_CALIBRATE, |
364 | "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, | 364 | "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, |
365 | qDcMismatch); | 365 | qDcMismatch); |
366 | 366 | ||
367 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); | 367 | val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); |
368 | val &= 0xc0000fff; | 368 | val &= 0xc0000fff; |
369 | val |= (qDcMismatch << 12) | (iDcMismatch << 21); | 369 | val |= (qDcMismatch << 12) | (iDcMismatch << 21); |
370 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); | 370 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); |
371 | 371 | ||
372 | ath_print(common, ATH_DBG_CALIBRATE, | 372 | ath_dbg(common, ATH_DBG_CALIBRATE, |
373 | "ADC DC Offset Cal done for Chain %d\n", i); | 373 | "ADC DC Offset Cal done for Chain %d\n", i); |
374 | } | 374 | } |
375 | 375 | ||
376 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), | 376 | REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), |
@@ -541,7 +541,6 @@ static void ar9271_hw_pa_cal(struct ath_hw *ah, bool is_reset) | |||
541 | REG_WRITE(ah, regList[i][0], regList[i][1]); | 541 | REG_WRITE(ah, regList[i][0], regList[i][1]); |
542 | 542 | ||
543 | REGWRITE_BUFFER_FLUSH(ah); | 543 | REGWRITE_BUFFER_FLUSH(ah); |
544 | DISABLE_REGWRITE_BUFFER(ah); | ||
545 | } | 544 | } |
546 | 545 | ||
547 | static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) | 546 | static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) |
@@ -560,18 +559,13 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) | |||
560 | { 0x7838, 0 }, | 559 | { 0x7838, 0 }, |
561 | }; | 560 | }; |
562 | 561 | ||
563 | ath_print(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); | 562 | ath_dbg(common, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); |
564 | 563 | ||
565 | /* PA CAL is not needed for high power solution */ | 564 | /* PA CAL is not needed for high power solution */ |
566 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == | 565 | if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == |
567 | AR5416_EEP_TXGAIN_HIGH_POWER) | 566 | AR5416_EEP_TXGAIN_HIGH_POWER) |
568 | return; | 567 | return; |
569 | 568 | ||
570 | if (AR_SREV_9285_11(ah)) { | ||
571 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | ||
572 | udelay(10); | ||
573 | } | ||
574 | |||
575 | for (i = 0; i < ARRAY_SIZE(regList); i++) | 569 | for (i = 0; i < ARRAY_SIZE(regList); i++) |
576 | regList[i][1] = REG_READ(ah, regList[i][0]); | 570 | regList[i][1] = REG_READ(ah, regList[i][0]); |
577 | 571 | ||
@@ -651,10 +645,6 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) | |||
651 | REG_WRITE(ah, regList[i][0], regList[i][1]); | 645 | REG_WRITE(ah, regList[i][0], regList[i][1]); |
652 | 646 | ||
653 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); | 647 | REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); |
654 | |||
655 | if (AR_SREV_9285_11(ah)) | ||
656 | REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); | ||
657 | |||
658 | } | 648 | } |
659 | 649 | ||
660 | static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) | 650 | static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) |
@@ -664,7 +654,7 @@ static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) | |||
664 | ar9271_hw_pa_cal(ah, is_reset); | 654 | ar9271_hw_pa_cal(ah, is_reset); |
665 | else | 655 | else |
666 | ah->pacal_info.skipcount--; | 656 | ah->pacal_info.skipcount--; |
667 | } else if (AR_SREV_9285_11_OR_LATER(ah)) { | 657 | } else if (AR_SREV_9285_12_OR_LATER(ah)) { |
668 | if (is_reset || !ah->pacal_info.skipcount) | 658 | if (is_reset || !ah->pacal_info.skipcount) |
669 | ar9285_hw_pa_cal(ah, is_reset); | 659 | ar9285_hw_pa_cal(ah, is_reset); |
670 | else | 660 | else |
@@ -710,10 +700,6 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
710 | 700 | ||
711 | /* Do NF cal only at longer intervals */ | 701 | /* Do NF cal only at longer intervals */ |
712 | if (longcal || nfcal_pending) { | 702 | if (longcal || nfcal_pending) { |
713 | /* Do periodic PAOffset Cal */ | ||
714 | ar9002_hw_pa_cal(ah, false); | ||
715 | ar9002_hw_olc_temp_compensation(ah); | ||
716 | |||
717 | /* | 703 | /* |
718 | * Get the value from the previous NF cal and update | 704 | * Get the value from the previous NF cal and update |
719 | * history buffer. | 705 | * history buffer. |
@@ -728,8 +714,12 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
728 | ath9k_hw_loadnf(ah, ah->curchan); | 714 | ath9k_hw_loadnf(ah, ah->curchan); |
729 | } | 715 | } |
730 | 716 | ||
731 | if (longcal) | 717 | if (longcal) { |
732 | ath9k_hw_start_nfcal(ah, false); | 718 | ath9k_hw_start_nfcal(ah, false); |
719 | /* Do periodic PAOffset Cal */ | ||
720 | ar9002_hw_pa_cal(ah, false); | ||
721 | ar9002_hw_olc_temp_compensation(ah); | ||
722 | } | ||
733 | } | 723 | } |
734 | 724 | ||
735 | return iscaldone; | 725 | return iscaldone; |
@@ -750,9 +740,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
750 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | 740 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); |
751 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | 741 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, |
752 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { | 742 | AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { |
753 | ath_print(common, ATH_DBG_CALIBRATE, "offset " | 743 | ath_dbg(common, ATH_DBG_CALIBRATE, |
754 | "calibration failed to complete in " | 744 | "offset calibration failed to complete in 1ms; noisy environment?\n"); |
755 | "1ms; noisy ??\n"); | ||
756 | return false; | 745 | return false; |
757 | } | 746 | } |
758 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); | 747 | REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); |
@@ -765,8 +754,8 @@ static bool ar9285_hw_cl_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
765 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); | 754 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); |
766 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | 755 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, |
767 | 0, AH_WAIT_TIMEOUT)) { | 756 | 0, AH_WAIT_TIMEOUT)) { |
768 | ath_print(common, ATH_DBG_CALIBRATE, "offset calibration " | 757 | ath_dbg(common, ATH_DBG_CALIBRATE, |
769 | "failed to complete in 1ms; noisy ??\n"); | 758 | "offset calibration failed to complete in 1ms; noisy environment?\n"); |
770 | return false; | 759 | return false; |
771 | } | 760 | } |
772 | 761 | ||
@@ -837,12 +826,15 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
837 | { | 826 | { |
838 | struct ath_common *common = ath9k_hw_common(ah); | 827 | struct ath_common *common = ath9k_hw_common(ah); |
839 | 828 | ||
840 | if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) { | 829 | if (AR_SREV_9271(ah)) { |
830 | if (!ar9285_hw_cl_cal(ah, chan)) | ||
831 | return false; | ||
832 | } else if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) { | ||
841 | if (!ar9285_hw_clc(ah, chan)) | 833 | if (!ar9285_hw_clc(ah, chan)) |
842 | return false; | 834 | return false; |
843 | } else { | 835 | } else { |
844 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 836 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
845 | if (!AR_SREV_9287_10_OR_LATER(ah)) | 837 | if (!AR_SREV_9287_11_OR_LATER(ah)) |
846 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, | 838 | REG_CLR_BIT(ah, AR_PHY_ADC_CTL, |
847 | AR_PHY_ADC_CTL_OFF_PWDADC); | 839 | AR_PHY_ADC_CTL_OFF_PWDADC); |
848 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, | 840 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, |
@@ -858,14 +850,13 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
858 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | 850 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, |
859 | AR_PHY_AGC_CONTROL_CAL, | 851 | AR_PHY_AGC_CONTROL_CAL, |
860 | 0, AH_WAIT_TIMEOUT)) { | 852 | 0, AH_WAIT_TIMEOUT)) { |
861 | ath_print(common, ATH_DBG_CALIBRATE, | 853 | ath_dbg(common, ATH_DBG_CALIBRATE, |
862 | "offset calibration failed to " | 854 | "offset calibration failed to complete in 1ms; noisy environment?\n"); |
863 | "complete in 1ms; noisy environment?\n"); | ||
864 | return false; | 855 | return false; |
865 | } | 856 | } |
866 | 857 | ||
867 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 858 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
868 | if (!AR_SREV_9287_10_OR_LATER(ah)) | 859 | if (!AR_SREV_9287_11_OR_LATER(ah)) |
869 | REG_SET_BIT(ah, AR_PHY_ADC_CTL, | 860 | REG_SET_BIT(ah, AR_PHY_ADC_CTL, |
870 | AR_PHY_ADC_CTL_OFF_PWDADC); | 861 | AR_PHY_ADC_CTL_OFF_PWDADC); |
871 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | 862 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, |
@@ -886,23 +877,33 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
886 | 877 | ||
887 | /* Enable IQ, ADC Gain and ADC DC offset CALs */ | 878 | /* Enable IQ, ADC Gain and ADC DC offset CALs */ |
888 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { | 879 | if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { |
889 | if (ar9002_hw_iscal_supported(ah, ADC_GAIN_CAL)) { | 880 | ah->supp_cals = IQ_MISMATCH_CAL; |
881 | |||
882 | if (AR_SREV_9160_10_OR_LATER(ah)) | ||
883 | ah->supp_cals |= ADC_GAIN_CAL | ADC_DC_CAL; | ||
884 | |||
885 | if (AR_SREV_9287(ah)) | ||
886 | ah->supp_cals &= ~ADC_GAIN_CAL; | ||
887 | |||
888 | if (ar9002_hw_is_cal_supported(ah, chan, ADC_GAIN_CAL)) { | ||
890 | INIT_CAL(&ah->adcgain_caldata); | 889 | INIT_CAL(&ah->adcgain_caldata); |
891 | INSERT_CAL(ah, &ah->adcgain_caldata); | 890 | INSERT_CAL(ah, &ah->adcgain_caldata); |
892 | ath_print(common, ATH_DBG_CALIBRATE, | 891 | ath_dbg(common, ATH_DBG_CALIBRATE, |
893 | "enabling ADC Gain Calibration.\n"); | 892 | "enabling ADC Gain Calibration.\n"); |
894 | } | 893 | } |
895 | if (ar9002_hw_iscal_supported(ah, ADC_DC_CAL)) { | 894 | |
895 | if (ar9002_hw_is_cal_supported(ah, chan, ADC_DC_CAL)) { | ||
896 | INIT_CAL(&ah->adcdc_caldata); | 896 | INIT_CAL(&ah->adcdc_caldata); |
897 | INSERT_CAL(ah, &ah->adcdc_caldata); | 897 | INSERT_CAL(ah, &ah->adcdc_caldata); |
898 | ath_print(common, ATH_DBG_CALIBRATE, | 898 | ath_dbg(common, ATH_DBG_CALIBRATE, |
899 | "enabling ADC DC Calibration.\n"); | 899 | "enabling ADC DC Calibration.\n"); |
900 | } | 900 | } |
901 | if (ar9002_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { | 901 | |
902 | if (ar9002_hw_is_cal_supported(ah, chan, IQ_MISMATCH_CAL)) { | ||
902 | INIT_CAL(&ah->iq_caldata); | 903 | INIT_CAL(&ah->iq_caldata); |
903 | INSERT_CAL(ah, &ah->iq_caldata); | 904 | INSERT_CAL(ah, &ah->iq_caldata); |
904 | ath_print(common, ATH_DBG_CALIBRATE, | 905 | ath_dbg(common, ATH_DBG_CALIBRATE, |
905 | "enabling IQ Calibration.\n"); | 906 | "enabling IQ Calibration.\n"); |
906 | } | 907 | } |
907 | 908 | ||
908 | ah->cal_list_curr = ah->cal_list; | 909 | ah->cal_list_curr = ah->cal_list; |
@@ -959,13 +960,6 @@ static const struct ath9k_percal_data adc_dc_cal_single_sample = { | |||
959 | ar9002_hw_adc_dccal_collect, | 960 | ar9002_hw_adc_dccal_collect, |
960 | ar9002_hw_adc_dccal_calibrate | 961 | ar9002_hw_adc_dccal_calibrate |
961 | }; | 962 | }; |
962 | static const struct ath9k_percal_data adc_init_dc_cal = { | ||
963 | ADC_DC_INIT_CAL, | ||
964 | MIN_CAL_SAMPLES, | ||
965 | INIT_LOG_COUNT, | ||
966 | ar9002_hw_adc_dccal_collect, | ||
967 | ar9002_hw_adc_dccal_calibrate | ||
968 | }; | ||
969 | 963 | ||
970 | static void ar9002_hw_init_cal_settings(struct ath_hw *ah) | 964 | static void ar9002_hw_init_cal_settings(struct ath_hw *ah) |
971 | { | 965 | { |
@@ -976,24 +970,23 @@ static void ar9002_hw_init_cal_settings(struct ath_hw *ah) | |||
976 | } | 970 | } |
977 | 971 | ||
978 | if (AR_SREV_9160_10_OR_LATER(ah)) { | 972 | if (AR_SREV_9160_10_OR_LATER(ah)) { |
979 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 973 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
980 | ah->iq_caldata.calData = &iq_cal_single_sample; | 974 | ah->iq_caldata.calData = &iq_cal_single_sample; |
981 | ah->adcgain_caldata.calData = | 975 | ah->adcgain_caldata.calData = |
982 | &adc_gain_cal_single_sample; | 976 | &adc_gain_cal_single_sample; |
983 | ah->adcdc_caldata.calData = | 977 | ah->adcdc_caldata.calData = |
984 | &adc_dc_cal_single_sample; | 978 | &adc_dc_cal_single_sample; |
985 | ah->adcdc_calinitdata.calData = | ||
986 | &adc_init_dc_cal; | ||
987 | } else { | 979 | } else { |
988 | ah->iq_caldata.calData = &iq_cal_multi_sample; | 980 | ah->iq_caldata.calData = &iq_cal_multi_sample; |
989 | ah->adcgain_caldata.calData = | 981 | ah->adcgain_caldata.calData = |
990 | &adc_gain_cal_multi_sample; | 982 | &adc_gain_cal_multi_sample; |
991 | ah->adcdc_caldata.calData = | 983 | ah->adcdc_caldata.calData = |
992 | &adc_dc_cal_multi_sample; | 984 | &adc_dc_cal_multi_sample; |
993 | ah->adcdc_calinitdata.calData = | ||
994 | &adc_init_dc_cal; | ||
995 | } | 985 | } |
996 | ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; | 986 | ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; |
987 | |||
988 | if (AR_SREV_9287(ah)) | ||
989 | ah->supp_cals &= ~ADC_GAIN_CAL; | ||
997 | } | 990 | } |
998 | } | 991 | } |
999 | 992 | ||
@@ -1005,7 +998,6 @@ void ar9002_hw_attach_calib_ops(struct ath_hw *ah) | |||
1005 | priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; | 998 | priv_ops->init_cal_settings = ar9002_hw_init_cal_settings; |
1006 | priv_ops->init_cal = ar9002_hw_init_cal; | 999 | priv_ops->init_cal = ar9002_hw_init_cal; |
1007 | priv_ops->setup_calibration = ar9002_hw_setup_calibration; | 1000 | priv_ops->setup_calibration = ar9002_hw_setup_calibration; |
1008 | priv_ops->iscal_supported = ar9002_hw_iscal_supported; | ||
1009 | 1001 | ||
1010 | ops->calibrate = ar9002_hw_calibrate; | 1002 | ops->calibrate = ar9002_hw_calibrate; |
1011 | } | 1003 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 303c63da5ea3..f344cc2b3d59 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -22,28 +22,10 @@ | |||
22 | 22 | ||
23 | int modparam_force_new_ani; | 23 | int modparam_force_new_ani; |
24 | module_param_named(force_new_ani, modparam_force_new_ani, int, 0444); | 24 | module_param_named(force_new_ani, modparam_force_new_ani, int, 0444); |
25 | MODULE_PARM_DESC(nohwcrypt, "Force new ANI for AR5008, AR9001, AR9002"); | 25 | MODULE_PARM_DESC(force_new_ani, "Force new ANI for AR5008, AR9001, AR9002"); |
26 | 26 | ||
27 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ | 27 | /* General hardware code for the A5008/AR9001/AR9002 hadware families */ |
28 | 28 | ||
29 | static bool ar9002_hw_macversion_supported(u32 macversion) | ||
30 | { | ||
31 | switch (macversion) { | ||
32 | case AR_SREV_VERSION_5416_PCI: | ||
33 | case AR_SREV_VERSION_5416_PCIE: | ||
34 | case AR_SREV_VERSION_9160: | ||
35 | case AR_SREV_VERSION_9100: | ||
36 | case AR_SREV_VERSION_9280: | ||
37 | case AR_SREV_VERSION_9285: | ||
38 | case AR_SREV_VERSION_9287: | ||
39 | case AR_SREV_VERSION_9271: | ||
40 | return true; | ||
41 | default: | ||
42 | break; | ||
43 | } | ||
44 | return false; | ||
45 | } | ||
46 | |||
47 | static void ar9002_hw_init_mode_regs(struct ath_hw *ah) | 29 | static void ar9002_hw_init_mode_regs(struct ath_hw *ah) |
48 | { | 30 | { |
49 | if (AR_SREV_9271(ah)) { | 31 | if (AR_SREV_9271(ah)) { |
@@ -371,7 +353,6 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |||
371 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | 353 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); |
372 | 354 | ||
373 | REGWRITE_BUFFER_FLUSH(ah); | 355 | REGWRITE_BUFFER_FLUSH(ah); |
374 | DISABLE_REGWRITE_BUFFER(ah); | ||
375 | } | 356 | } |
376 | 357 | ||
377 | udelay(1000); | 358 | udelay(1000); |
@@ -411,6 +392,9 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |||
411 | val &= ~(AR_WA_BIT6 | AR_WA_BIT7); | 392 | val &= ~(AR_WA_BIT6 | AR_WA_BIT7); |
412 | } | 393 | } |
413 | 394 | ||
395 | if (AR_SREV_9280(ah)) | ||
396 | val |= AR_WA_BIT22; | ||
397 | |||
414 | if (AR_SREV_9285E_20(ah)) | 398 | if (AR_SREV_9285E_20(ah)) |
415 | val |= AR_WA_BIT23; | 399 | val |= AR_WA_BIT23; |
416 | 400 | ||
@@ -442,9 +426,8 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah, | |||
442 | } | 426 | } |
443 | 427 | ||
444 | /* WAR for ASPM system hang */ | 428 | /* WAR for ASPM system hang */ |
445 | if (AR_SREV_9280(ah) || AR_SREV_9285(ah) || AR_SREV_9287(ah)) { | 429 | if (AR_SREV_9285(ah) || AR_SREV_9287(ah)) |
446 | val |= (AR_WA_BIT6 | AR_WA_BIT7); | 430 | val |= (AR_WA_BIT6 | AR_WA_BIT7); |
447 | } | ||
448 | 431 | ||
449 | if (AR_SREV_9285E_20(ah)) | 432 | if (AR_SREV_9285E_20(ah)) |
450 | val |= AR_WA_BIT23; | 433 | val |= AR_WA_BIT23; |
@@ -468,7 +451,6 @@ static int ar9002_hw_get_radiorev(struct ath_hw *ah) | |||
468 | REG_WRITE(ah, AR_PHY(0x20), 0x00010000); | 451 | REG_WRITE(ah, AR_PHY(0x20), 0x00010000); |
469 | 452 | ||
470 | REGWRITE_BUFFER_FLUSH(ah); | 453 | REGWRITE_BUFFER_FLUSH(ah); |
471 | DISABLE_REGWRITE_BUFFER(ah); | ||
472 | 454 | ||
473 | val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; | 455 | val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; |
474 | val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); | 456 | val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); |
@@ -493,9 +475,9 @@ int ar9002_hw_rf_claim(struct ath_hw *ah) | |||
493 | case AR_RAD2122_SREV_MAJOR: | 475 | case AR_RAD2122_SREV_MAJOR: |
494 | break; | 476 | break; |
495 | default: | 477 | default: |
496 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 478 | ath_err(ath9k_hw_common(ah), |
497 | "Radio Chip Rev 0x%02X not supported\n", | 479 | "Radio Chip Rev 0x%02X not supported\n", |
498 | val & AR_RADIO_SREV_MAJOR); | 480 | val & AR_RADIO_SREV_MAJOR); |
499 | return -EOPNOTSUPP; | 481 | return -EOPNOTSUPP; |
500 | } | 482 | } |
501 | 483 | ||
@@ -564,19 +546,61 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) | |||
564 | 546 | ||
565 | priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; | 547 | priv_ops->init_mode_regs = ar9002_hw_init_mode_regs; |
566 | priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; | 548 | priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs; |
567 | priv_ops->macversion_supported = ar9002_hw_macversion_supported; | ||
568 | 549 | ||
569 | ops->config_pci_powersave = ar9002_hw_configpcipowersave; | 550 | ops->config_pci_powersave = ar9002_hw_configpcipowersave; |
570 | 551 | ||
571 | ar5008_hw_attach_phy_ops(ah); | 552 | ar5008_hw_attach_phy_ops(ah); |
572 | if (AR_SREV_9280_10_OR_LATER(ah)) | 553 | if (AR_SREV_9280_20_OR_LATER(ah)) |
573 | ar9002_hw_attach_phy_ops(ah); | 554 | ar9002_hw_attach_phy_ops(ah); |
574 | 555 | ||
575 | ar9002_hw_attach_calib_ops(ah); | 556 | ar9002_hw_attach_calib_ops(ah); |
576 | ar9002_hw_attach_mac_ops(ah); | 557 | ar9002_hw_attach_mac_ops(ah); |
558 | } | ||
577 | 559 | ||
578 | if (modparam_force_new_ani) | 560 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan) |
579 | ath9k_hw_attach_ani_ops_new(ah); | 561 | { |
580 | else | 562 | u32 modesIndex; |
581 | ath9k_hw_attach_ani_ops_old(ah); | 563 | int i; |
564 | |||
565 | switch (chan->chanmode) { | ||
566 | case CHANNEL_A: | ||
567 | case CHANNEL_A_HT20: | ||
568 | modesIndex = 1; | ||
569 | break; | ||
570 | case CHANNEL_A_HT40PLUS: | ||
571 | case CHANNEL_A_HT40MINUS: | ||
572 | modesIndex = 2; | ||
573 | break; | ||
574 | case CHANNEL_G: | ||
575 | case CHANNEL_G_HT20: | ||
576 | case CHANNEL_B: | ||
577 | modesIndex = 4; | ||
578 | break; | ||
579 | case CHANNEL_G_HT40PLUS: | ||
580 | case CHANNEL_G_HT40MINUS: | ||
581 | modesIndex = 3; | ||
582 | break; | ||
583 | |||
584 | default: | ||
585 | return; | ||
586 | } | ||
587 | |||
588 | ENABLE_REGWRITE_BUFFER(ah); | ||
589 | |||
590 | for (i = 0; i < ah->iniModes_9271_ANI_reg.ia_rows; i++) { | ||
591 | u32 reg = INI_RA(&ah->iniModes_9271_ANI_reg, i, 0); | ||
592 | u32 val = INI_RA(&ah->iniModes_9271_ANI_reg, i, modesIndex); | ||
593 | u32 val_orig; | ||
594 | |||
595 | if (reg == AR_PHY_CCK_DETECT) { | ||
596 | val_orig = REG_READ(ah, reg); | ||
597 | val &= AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | ||
598 | val_orig &= ~AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK; | ||
599 | |||
600 | REG_WRITE(ah, reg, val|val_orig); | ||
601 | } else | ||
602 | REG_WRITE(ah, reg, val); | ||
603 | } | ||
604 | |||
605 | REGWRITE_BUFFER_FLUSH(ah); | ||
582 | } | 606 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h index 6203eed860dd..7573257731b6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_initvals.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index 50dda394f8be..077e8a6983fa 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -90,13 +90,10 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
90 | 90 | ||
91 | *masked = isr & ATH9K_INT_COMMON; | 91 | *masked = isr & ATH9K_INT_COMMON; |
92 | 92 | ||
93 | if (ah->config.rx_intr_mitigation) { | 93 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM | |
94 | if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) | 94 | AR_ISR_RXOK | AR_ISR_RXERR)) |
95 | *masked |= ATH9K_INT_RX; | ||
96 | } | ||
97 | |||
98 | if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) | ||
99 | *masked |= ATH9K_INT_RX; | 95 | *masked |= ATH9K_INT_RX; |
96 | |||
100 | if (isr & | 97 | if (isr & |
101 | (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | | 98 | (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | |
102 | AR_ISR_TXEOL)) { | 99 | AR_ISR_TXEOL)) { |
@@ -114,16 +111,8 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
114 | } | 111 | } |
115 | 112 | ||
116 | if (isr & AR_ISR_RXORN) { | 113 | if (isr & AR_ISR_RXORN) { |
117 | ath_print(common, ATH_DBG_INTERRUPT, | 114 | ath_dbg(common, ATH_DBG_INTERRUPT, |
118 | "receive FIFO overrun interrupt\n"); | 115 | "receive FIFO overrun interrupt\n"); |
119 | } | ||
120 | |||
121 | if (!AR_SREV_9100(ah)) { | ||
122 | if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
123 | u32 isr5 = REG_READ(ah, AR_ISR_S5_S); | ||
124 | if (isr5 & AR_ISR_S5_TIM_TIMER) | ||
125 | *masked |= ATH9K_INT_TIM_TIMER; | ||
126 | } | ||
127 | } | 116 | } |
128 | 117 | ||
129 | *masked |= mask2; | 118 | *masked |= mask2; |
@@ -136,17 +125,18 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
136 | u32 s5_s; | 125 | u32 s5_s; |
137 | 126 | ||
138 | s5_s = REG_READ(ah, AR_ISR_S5_S); | 127 | s5_s = REG_READ(ah, AR_ISR_S5_S); |
139 | if (isr & AR_ISR_GENTMR) { | 128 | ah->intr_gen_timer_trigger = |
140 | ah->intr_gen_timer_trigger = | ||
141 | MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); | 129 | MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); |
142 | 130 | ||
143 | ah->intr_gen_timer_thresh = | 131 | ah->intr_gen_timer_thresh = |
144 | MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); | 132 | MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); |
145 | 133 | ||
146 | if (ah->intr_gen_timer_trigger) | 134 | if (ah->intr_gen_timer_trigger) |
147 | *masked |= ATH9K_INT_GENTIMER; | 135 | *masked |= ATH9K_INT_GENTIMER; |
148 | 136 | ||
149 | } | 137 | if ((s5_s & AR_ISR_S5_TIM_TIMER) && |
138 | !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | ||
139 | *masked |= ATH9K_INT_TIM_TIMER; | ||
150 | } | 140 | } |
151 | 141 | ||
152 | if (sync_cause) { | 142 | if (sync_cause) { |
@@ -157,25 +147,25 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
157 | 147 | ||
158 | if (fatal_int) { | 148 | if (fatal_int) { |
159 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { | 149 | if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { |
160 | ath_print(common, ATH_DBG_ANY, | 150 | ath_dbg(common, ATH_DBG_ANY, |
161 | "received PCI FATAL interrupt\n"); | 151 | "received PCI FATAL interrupt\n"); |
162 | } | 152 | } |
163 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { | 153 | if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { |
164 | ath_print(common, ATH_DBG_ANY, | 154 | ath_dbg(common, ATH_DBG_ANY, |
165 | "received PCI PERR interrupt\n"); | 155 | "received PCI PERR interrupt\n"); |
166 | } | 156 | } |
167 | *masked |= ATH9K_INT_FATAL; | 157 | *masked |= ATH9K_INT_FATAL; |
168 | } | 158 | } |
169 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { | 159 | if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { |
170 | ath_print(common, ATH_DBG_INTERRUPT, | 160 | ath_dbg(common, ATH_DBG_INTERRUPT, |
171 | "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); | 161 | "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); |
172 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); | 162 | REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); |
173 | REG_WRITE(ah, AR_RC, 0); | 163 | REG_WRITE(ah, AR_RC, 0); |
174 | *masked |= ATH9K_INT_FATAL; | 164 | *masked |= ATH9K_INT_FATAL; |
175 | } | 165 | } |
176 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { | 166 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { |
177 | ath_print(common, ATH_DBG_INTERRUPT, | 167 | ath_dbg(common, ATH_DBG_INTERRUPT, |
178 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); | 168 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); |
179 | } | 169 | } |
180 | 170 | ||
181 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); | 171 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); |
@@ -218,77 +208,70 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, | |||
218 | struct ath_tx_status *ts) | 208 | struct ath_tx_status *ts) |
219 | { | 209 | { |
220 | struct ar5416_desc *ads = AR5416DESC(ds); | 210 | struct ar5416_desc *ads = AR5416DESC(ds); |
211 | u32 status; | ||
221 | 212 | ||
222 | if ((ads->ds_txstatus9 & AR_TxDone) == 0) | 213 | status = ACCESS_ONCE(ads->ds_txstatus9); |
214 | if ((status & AR_TxDone) == 0) | ||
223 | return -EINPROGRESS; | 215 | return -EINPROGRESS; |
224 | 216 | ||
225 | ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); | ||
226 | ts->ts_tstamp = ads->AR_SendTimestamp; | 217 | ts->ts_tstamp = ads->AR_SendTimestamp; |
227 | ts->ts_status = 0; | 218 | ts->ts_status = 0; |
228 | ts->ts_flags = 0; | 219 | ts->ts_flags = 0; |
229 | 220 | ||
230 | if (ads->ds_txstatus1 & AR_FrmXmitOK) | 221 | if (status & AR_TxOpExceeded) |
222 | ts->ts_status |= ATH9K_TXERR_XTXOP; | ||
223 | ts->tid = MS(status, AR_TxTid); | ||
224 | ts->ts_rateindex = MS(status, AR_FinalTxIdx); | ||
225 | ts->ts_seqnum = MS(status, AR_SeqNum); | ||
226 | |||
227 | status = ACCESS_ONCE(ads->ds_txstatus0); | ||
228 | ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); | ||
229 | ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); | ||
230 | ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); | ||
231 | if (status & AR_TxBaStatus) { | ||
232 | ts->ts_flags |= ATH9K_TX_BA; | ||
233 | ts->ba_low = ads->AR_BaBitmapLow; | ||
234 | ts->ba_high = ads->AR_BaBitmapHigh; | ||
235 | } | ||
236 | |||
237 | status = ACCESS_ONCE(ads->ds_txstatus1); | ||
238 | if (status & AR_FrmXmitOK) | ||
231 | ts->ts_status |= ATH9K_TX_ACKED; | 239 | ts->ts_status |= ATH9K_TX_ACKED; |
232 | if (ads->ds_txstatus1 & AR_ExcessiveRetries) | 240 | else { |
233 | ts->ts_status |= ATH9K_TXERR_XRETRY; | 241 | if (status & AR_ExcessiveRetries) |
234 | if (ads->ds_txstatus1 & AR_Filtered) | 242 | ts->ts_status |= ATH9K_TXERR_XRETRY; |
235 | ts->ts_status |= ATH9K_TXERR_FILT; | 243 | if (status & AR_Filtered) |
236 | if (ads->ds_txstatus1 & AR_FIFOUnderrun) { | 244 | ts->ts_status |= ATH9K_TXERR_FILT; |
237 | ts->ts_status |= ATH9K_TXERR_FIFO; | 245 | if (status & AR_FIFOUnderrun) { |
238 | ath9k_hw_updatetxtriglevel(ah, true); | 246 | ts->ts_status |= ATH9K_TXERR_FIFO; |
247 | ath9k_hw_updatetxtriglevel(ah, true); | ||
248 | } | ||
239 | } | 249 | } |
240 | if (ads->ds_txstatus9 & AR_TxOpExceeded) | 250 | if (status & AR_TxTimerExpired) |
241 | ts->ts_status |= ATH9K_TXERR_XTXOP; | ||
242 | if (ads->ds_txstatus1 & AR_TxTimerExpired) | ||
243 | ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; | 251 | ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; |
244 | 252 | if (status & AR_DescCfgErr) | |
245 | if (ads->ds_txstatus1 & AR_DescCfgErr) | ||
246 | ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; | 253 | ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; |
247 | if (ads->ds_txstatus1 & AR_TxDataUnderrun) { | 254 | if (status & AR_TxDataUnderrun) { |
248 | ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; | 255 | ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; |
249 | ath9k_hw_updatetxtriglevel(ah, true); | 256 | ath9k_hw_updatetxtriglevel(ah, true); |
250 | } | 257 | } |
251 | if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { | 258 | if (status & AR_TxDelimUnderrun) { |
252 | ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; | 259 | ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; |
253 | ath9k_hw_updatetxtriglevel(ah, true); | 260 | ath9k_hw_updatetxtriglevel(ah, true); |
254 | } | 261 | } |
255 | if (ads->ds_txstatus0 & AR_TxBaStatus) { | 262 | ts->ts_shortretry = MS(status, AR_RTSFailCnt); |
256 | ts->ts_flags |= ATH9K_TX_BA; | 263 | ts->ts_longretry = MS(status, AR_DataFailCnt); |
257 | ts->ba_low = ads->AR_BaBitmapLow; | 264 | ts->ts_virtcol = MS(status, AR_VirtRetryCnt); |
258 | ts->ba_high = ads->AR_BaBitmapHigh; | ||
259 | } | ||
260 | 265 | ||
261 | ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); | 266 | status = ACCESS_ONCE(ads->ds_txstatus5); |
262 | switch (ts->ts_rateindex) { | 267 | ts->ts_rssi = MS(status, AR_TxRSSICombined); |
263 | case 0: | 268 | ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); |
264 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); | 269 | ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); |
265 | break; | 270 | ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); |
266 | case 1: | ||
267 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); | ||
268 | break; | ||
269 | case 2: | ||
270 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); | ||
271 | break; | ||
272 | case 3: | ||
273 | ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); | ||
274 | break; | ||
275 | } | ||
276 | 271 | ||
277 | ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); | ||
278 | ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); | ||
279 | ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); | ||
280 | ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); | ||
281 | ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); | ||
282 | ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); | ||
283 | ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); | ||
284 | ts->evm0 = ads->AR_TxEVM0; | 272 | ts->evm0 = ads->AR_TxEVM0; |
285 | ts->evm1 = ads->AR_TxEVM1; | 273 | ts->evm1 = ads->AR_TxEVM1; |
286 | ts->evm2 = ads->AR_TxEVM2; | 274 | ts->evm2 = ads->AR_TxEVM2; |
287 | ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); | ||
288 | ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); | ||
289 | ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); | ||
290 | ts->tid = MS(ads->ds_txstatus9, AR_TxTid); | ||
291 | ts->ts_antenna = 0; | ||
292 | 275 | ||
293 | return 0; | 276 | return 0; |
294 | } | 277 | } |
@@ -300,7 +283,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
300 | { | 283 | { |
301 | struct ar5416_desc *ads = AR5416DESC(ds); | 284 | struct ar5416_desc *ads = AR5416DESC(ds); |
302 | 285 | ||
303 | txPower += ah->txpower_indexoffset; | ||
304 | if (txPower > 63) | 286 | if (txPower > 63) |
305 | txPower = 63; | 287 | txPower = 63; |
306 | 288 | ||
@@ -308,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
308 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | 290 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
309 | | SM(txPower, AR_XmitPower) | 291 | | SM(txPower, AR_XmitPower) |
310 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | 292 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
311 | | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | ||
312 | | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) | 293 | | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) |
313 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); | 294 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); |
314 | 295 | ||
@@ -329,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
329 | } | 310 | } |
330 | } | 311 | } |
331 | 312 | ||
313 | static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) | ||
314 | { | ||
315 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
316 | |||
317 | if (val) | ||
318 | ads->ds_ctl0 |= AR_ClrDestMask; | ||
319 | else | ||
320 | ads->ds_ctl0 &= ~AR_ClrDestMask; | ||
321 | } | ||
322 | |||
332 | static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, | 323 | static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, |
333 | void *lastds, | 324 | void *lastds, |
334 | u32 durUpdateEn, u32 rtsctsRate, | 325 | u32 durUpdateEn, u32 rtsctsRate, |
@@ -424,26 +415,6 @@ static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds) | |||
424 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); | 415 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); |
425 | } | 416 | } |
426 | 417 | ||
427 | static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, | ||
428 | u32 burstDuration) | ||
429 | { | ||
430 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
431 | |||
432 | ads->ds_ctl2 &= ~AR_BurstDur; | ||
433 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); | ||
434 | } | ||
435 | |||
436 | static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | ||
437 | u32 vmf) | ||
438 | { | ||
439 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
440 | |||
441 | if (vmf) | ||
442 | ads->ds_ctl0 |= AR_VirtMoreFrag; | ||
443 | else | ||
444 | ads->ds_ctl0 &= ~AR_VirtMoreFrag; | ||
445 | } | ||
446 | |||
447 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | 418 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, |
448 | u32 size, u32 flags) | 419 | u32 size, u32 flags) |
449 | { | 420 | { |
@@ -476,6 +447,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) | |||
476 | ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; | 447 | ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; |
477 | ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; | 448 | ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; |
478 | ops->clr11n_aggr = ar9002_hw_clr11n_aggr; | 449 | ops->clr11n_aggr = ar9002_hw_clr11n_aggr; |
479 | ops->set11n_burstduration = ar9002_hw_set11n_burstduration; | 450 | ops->set_clrdmask = ar9002_hw_set_clrdmask; |
480 | ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag; | ||
481 | } | 451 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index adbf031fbc5a..2fe0a34cbabc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -175,13 +175,15 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, | |||
175 | int upper, lower, cur_vit_mask; | 175 | int upper, lower, cur_vit_mask; |
176 | int tmp, newVal; | 176 | int tmp, newVal; |
177 | int i; | 177 | int i; |
178 | int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, | 178 | static const int pilot_mask_reg[4] = { |
179 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | 179 | AR_PHY_TIMING7, AR_PHY_TIMING8, |
180 | AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 | ||
180 | }; | 181 | }; |
181 | int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, | 182 | static const int chan_mask_reg[4] = { |
182 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | 183 | AR_PHY_TIMING9, AR_PHY_TIMING10, |
184 | AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 | ||
183 | }; | 185 | }; |
184 | int inc[4] = { 0, 100, 0, 0 }; | 186 | static const int inc[4] = { 0, 100, 0, 0 }; |
185 | struct chan_centers centers; | 187 | struct chan_centers centers; |
186 | 188 | ||
187 | int8_t mask_m[123]; | 189 | int8_t mask_m[123]; |
@@ -201,13 +203,14 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, | |||
201 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | 203 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
202 | cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); | 204 | cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); |
203 | 205 | ||
206 | if (AR_NO_SPUR == cur_bb_spur) | ||
207 | break; | ||
208 | |||
204 | if (is2GHz) | 209 | if (is2GHz) |
205 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; | 210 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; |
206 | else | 211 | else |
207 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; | 212 | cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; |
208 | 213 | ||
209 | if (AR_NO_SPUR == cur_bb_spur) | ||
210 | break; | ||
211 | cur_bb_spur = cur_bb_spur - freq; | 214 | cur_bb_spur = cur_bb_spur - freq; |
212 | 215 | ||
213 | if (IS_CHAN_HT40(chan)) { | 216 | if (IS_CHAN_HT40(chan)) { |
@@ -415,7 +418,6 @@ static void ar9002_hw_spur_mitigate(struct ath_hw *ah, | |||
415 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); | 418 | REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); |
416 | 419 | ||
417 | REGWRITE_BUFFER_FLUSH(ah); | 420 | REGWRITE_BUFFER_FLUSH(ah); |
418 | DISABLE_REGWRITE_BUFFER(ah); | ||
419 | } | 421 | } |
420 | 422 | ||
421 | static void ar9002_olc_init(struct ath_hw *ah) | 423 | static void ar9002_olc_init(struct ath_hw *ah) |
@@ -474,21 +476,21 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah, | |||
474 | int16_t nf; | 476 | int16_t nf; |
475 | 477 | ||
476 | nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); | 478 | nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); |
477 | nfarray[0] = sign_extend(nf, 9); | 479 | nfarray[0] = sign_extend32(nf, 8); |
478 | 480 | ||
479 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); | 481 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR); |
480 | if (IS_CHAN_HT40(ah->curchan)) | 482 | if (IS_CHAN_HT40(ah->curchan)) |
481 | nfarray[3] = sign_extend(nf, 9); | 483 | nfarray[3] = sign_extend32(nf, 8); |
482 | 484 | ||
483 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | 485 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
484 | return; | 486 | return; |
485 | 487 | ||
486 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); | 488 | nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR); |
487 | nfarray[1] = sign_extend(nf, 9); | 489 | nfarray[1] = sign_extend32(nf, 8); |
488 | 490 | ||
489 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR); | 491 | nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR); |
490 | if (IS_CHAN_HT40(ah->curchan)) | 492 | if (IS_CHAN_HT40(ah->curchan)) |
491 | nfarray[4] = sign_extend(nf, 9); | 493 | nfarray[4] = sign_extend32(nf, 8); |
492 | } | 494 | } |
493 | 495 | ||
494 | static void ar9002_hw_set_nf_limits(struct ath_hw *ah) | 496 | static void ar9002_hw_set_nf_limits(struct ath_hw *ah) |
@@ -515,9 +517,45 @@ static void ar9002_hw_set_nf_limits(struct ath_hw *ah) | |||
515 | } | 517 | } |
516 | } | 518 | } |
517 | 519 | ||
520 | static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah, | ||
521 | struct ath_hw_antcomb_conf *antconf) | ||
522 | { | ||
523 | u32 regval; | ||
524 | |||
525 | regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
526 | antconf->main_lna_conf = (regval & AR_PHY_9285_ANT_DIV_MAIN_LNACONF) >> | ||
527 | AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S; | ||
528 | antconf->alt_lna_conf = (regval & AR_PHY_9285_ANT_DIV_ALT_LNACONF) >> | ||
529 | AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; | ||
530 | antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> | ||
531 | AR_PHY_9285_FAST_DIV_BIAS_S; | ||
532 | antconf->lna1_lna2_delta = -3; | ||
533 | antconf->div_group = 0; | ||
534 | } | ||
535 | |||
536 | static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah, | ||
537 | struct ath_hw_antcomb_conf *antconf) | ||
538 | { | ||
539 | u32 regval; | ||
540 | |||
541 | regval = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); | ||
542 | regval &= ~(AR_PHY_9285_ANT_DIV_MAIN_LNACONF | | ||
543 | AR_PHY_9285_ANT_DIV_ALT_LNACONF | | ||
544 | AR_PHY_9285_FAST_DIV_BIAS); | ||
545 | regval |= ((antconf->main_lna_conf << AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S) | ||
546 | & AR_PHY_9285_ANT_DIV_MAIN_LNACONF); | ||
547 | regval |= ((antconf->alt_lna_conf << AR_PHY_9285_ANT_DIV_ALT_LNACONF_S) | ||
548 | & AR_PHY_9285_ANT_DIV_ALT_LNACONF); | ||
549 | regval |= ((antconf->fast_div_bias << AR_PHY_9285_FAST_DIV_BIAS_S) | ||
550 | & AR_PHY_9285_FAST_DIV_BIAS); | ||
551 | |||
552 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); | ||
553 | } | ||
554 | |||
518 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | 555 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) |
519 | { | 556 | { |
520 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 557 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
558 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
521 | 559 | ||
522 | priv_ops->set_rf_regs = NULL; | 560 | priv_ops->set_rf_regs = NULL; |
523 | priv_ops->rf_alloc_ext_banks = NULL; | 561 | priv_ops->rf_alloc_ext_banks = NULL; |
@@ -528,5 +566,8 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | |||
528 | priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; | 566 | priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; |
529 | priv_ops->do_getnf = ar9002_hw_do_getnf; | 567 | priv_ops->do_getnf = ar9002_hw_do_getnf; |
530 | 568 | ||
569 | ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get; | ||
570 | ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set; | ||
571 | |||
531 | ar9002_hw_set_nf_limits(ah); | 572 | ar9002_hw_set_nf_limits(ah); |
532 | } | 573 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.h b/drivers/net/wireless/ath/ath9k/ar9002_phy.h index c5151a4dd10b..453af6dc514b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -302,6 +302,8 @@ | |||
302 | #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 | 302 | #define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 |
303 | 303 | ||
304 | #define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac | 304 | #define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac |
305 | #define AR_PHY_9285_FAST_DIV_BIAS 0x00007E00 | ||
306 | #define AR_PHY_9285_FAST_DIV_BIAS_S 9 | ||
305 | #define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 | 307 | #define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 |
306 | #define AR_PHY_9285_ANT_DIV_CTL 0x01000000 | 308 | #define AR_PHY_9285_ANT_DIV_CTL 0x01000000 |
307 | #define AR_PHY_9285_ANT_DIV_CTL_S 24 | 309 | #define AR_PHY_9285_ANT_DIV_CTL_S 24 |
@@ -481,7 +483,11 @@ | |||
481 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 | 483 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 |
482 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 | 484 | #define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 |
483 | 485 | ||
486 | #define AR_PHY_TX_PWRCTRL8 0xa278 | ||
487 | |||
484 | #define AR_PHY_TX_PWRCTRL9 0xa27C | 488 | #define AR_PHY_TX_PWRCTRL9 0xa27C |
489 | |||
490 | #define AR_PHY_TX_PWRCTRL10 0xa394 | ||
485 | #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 | 491 | #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 |
486 | #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 | 492 | #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 |
487 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 | 493 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 |
@@ -493,6 +499,8 @@ | |||
493 | 499 | ||
494 | #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 | 500 | #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 |
495 | #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 | 501 | #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 |
502 | #define AR_PHY_CH0_TX_PWRCTRL12 0xa3dc | ||
503 | #define AR_PHY_CH0_TX_PWRCTRL13 0xa3e0 | ||
496 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 | 504 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 |
497 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 | 505 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 |
498 | 506 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index ec98ab50748a..e8ac70da5ac7 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -34,6 +34,10 @@ static const u32 ar9300_2p2_radio_postamble[][5] = { | |||
34 | 34 | ||
35 | static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { | 35 | static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { |
36 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 36 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
37 | {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, | ||
38 | {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, | ||
39 | {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, | ||
40 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
37 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 41 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, |
38 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 42 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
39 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | 43 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, |
@@ -52,21 +56,21 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { | |||
52 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, | 56 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, |
53 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, | 57 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, |
54 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, | 58 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, |
55 | {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, | 59 | {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, |
56 | {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, | 60 | {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, |
57 | {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, | 61 | {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, |
58 | {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, | 62 | {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, |
59 | {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, | 63 | {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, |
60 | {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, | 64 | {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, |
61 | {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, | 65 | {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, |
62 | {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, | 66 | {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, |
63 | {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 67 | {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
64 | {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 68 | {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
65 | {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 69 | {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
66 | {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 70 | {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
67 | {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 71 | {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
68 | {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 72 | {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
69 | {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 73 | {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
70 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | 74 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, |
71 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | 75 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, |
72 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | 76 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, |
@@ -84,21 +88,45 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = { | |||
84 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, | 88 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, |
85 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, | 89 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, |
86 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, | 90 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, |
87 | {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, | 91 | {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, |
88 | {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, | 92 | {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, |
89 | {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, | 93 | {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, |
90 | {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, | 94 | {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, |
91 | {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, | 95 | {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, |
92 | {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, | 96 | {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, |
93 | {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, | 97 | {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, |
94 | {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, | 98 | {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, |
95 | {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 99 | {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
96 | {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 100 | {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
97 | {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 101 | {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
98 | {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 102 | {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
99 | {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 103 | {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
100 | {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 104 | {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
101 | {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 105 | {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
106 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
107 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
108 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
109 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
110 | {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
111 | {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, | ||
112 | {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, | ||
113 | {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, | ||
114 | {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, | ||
115 | {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, | ||
116 | {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, | ||
117 | {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
118 | {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
119 | {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
120 | {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
121 | {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
122 | {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, | ||
123 | {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, | ||
124 | {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, | ||
125 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
126 | {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, | ||
127 | {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, | ||
128 | {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, | ||
129 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
102 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 130 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, |
103 | {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, | 131 | {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, |
104 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 132 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
@@ -118,7 +146,7 @@ static const u32 ar9300Modes_fast_clock_2p2[][3] = { | |||
118 | {0x00008014, 0x044c044c, 0x08980898}, | 146 | {0x00008014, 0x044c044c, 0x08980898}, |
119 | {0x0000801c, 0x148ec02b, 0x148ec057}, | 147 | {0x0000801c, 0x148ec02b, 0x148ec057}, |
120 | {0x00008318, 0x000044c0, 0x00008980}, | 148 | {0x00008318, 0x000044c0, 0x00008980}, |
121 | {0x00009e00, 0x03721821, 0x03721821}, | 149 | {0x00009e00, 0x0372131c, 0x0372131c}, |
122 | {0x0000a230, 0x0000000b, 0x00000016}, | 150 | {0x0000a230, 0x0000000b, 0x00000016}, |
123 | {0x0000a254, 0x00000898, 0x00001130}, | 151 | {0x0000a254, 0x00000898, 0x00001130}, |
124 | }; | 152 | }; |
@@ -595,20 +623,22 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { | |||
595 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | 623 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, |
596 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, | 624 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, |
597 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, | 625 | {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, |
598 | {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, | 626 | {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, |
599 | {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, | 627 | {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, |
600 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, | 628 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, |
601 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, | 629 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, |
602 | {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, | 630 | {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, |
603 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 631 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
604 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 632 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
605 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | 633 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, |
606 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | 634 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, |
635 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, | ||
607 | {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, | 636 | {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, |
608 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 637 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
609 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 638 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
610 | {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, | 639 | {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, |
611 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, | 640 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, |
641 | {0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f}, | ||
612 | {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, | 642 | {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, |
613 | {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, | 643 | {0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, |
614 | {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, | 644 | {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, |
@@ -624,16 +654,16 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { | |||
624 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | 654 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, |
625 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 655 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, |
626 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, | 656 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, |
627 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, | 657 | {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, |
628 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 658 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
629 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | 659 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, |
630 | {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | 660 | {0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, |
631 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 661 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
632 | {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | 662 | {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, |
633 | {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, | 663 | {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, |
634 | {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, | 664 | {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, |
635 | {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | 665 | {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, |
636 | {0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | 666 | {0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, |
637 | {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 667 | {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
638 | {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | 668 | {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, |
639 | {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, | 669 | {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, |
@@ -649,13 +679,13 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
649 | {0x00009814, 0x9280c00a}, | 679 | {0x00009814, 0x9280c00a}, |
650 | {0x00009818, 0x00000000}, | 680 | {0x00009818, 0x00000000}, |
651 | {0x0000981c, 0x00020028}, | 681 | {0x0000981c, 0x00020028}, |
652 | {0x00009834, 0x5f3ca3de}, | 682 | {0x00009834, 0x6400a290}, |
653 | {0x00009838, 0x0108ecff}, | 683 | {0x00009838, 0x0108ecff}, |
654 | {0x0000983c, 0x14750600}, | 684 | {0x0000983c, 0x0d000600}, |
655 | {0x00009880, 0x201fff00}, | 685 | {0x00009880, 0x201fff00}, |
656 | {0x00009884, 0x00001042}, | 686 | {0x00009884, 0x00001042}, |
657 | {0x000098a4, 0x00200400}, | 687 | {0x000098a4, 0x00200400}, |
658 | {0x000098b0, 0x52440bbe}, | 688 | {0x000098b0, 0x32840bbe}, |
659 | {0x000098d0, 0x004b6a8e}, | 689 | {0x000098d0, 0x004b6a8e}, |
660 | {0x000098d4, 0x00000820}, | 690 | {0x000098d4, 0x00000820}, |
661 | {0x000098dc, 0x00000000}, | 691 | {0x000098dc, 0x00000000}, |
@@ -681,7 +711,6 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
681 | {0x00009e30, 0x06336f77}, | 711 | {0x00009e30, 0x06336f77}, |
682 | {0x00009e34, 0x6af6532f}, | 712 | {0x00009e34, 0x6af6532f}, |
683 | {0x00009e38, 0x0cc80c00}, | 713 | {0x00009e38, 0x0cc80c00}, |
684 | {0x00009e3c, 0xcf946222}, | ||
685 | {0x00009e40, 0x0d261820}, | 714 | {0x00009e40, 0x0d261820}, |
686 | {0x00009e4c, 0x00001004}, | 715 | {0x00009e4c, 0x00001004}, |
687 | {0x00009e50, 0x00ff03f1}, | 716 | {0x00009e50, 0x00ff03f1}, |
@@ -694,7 +723,6 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
694 | {0x0000a220, 0x00000000}, | 723 | {0x0000a220, 0x00000000}, |
695 | {0x0000a224, 0x00000000}, | 724 | {0x0000a224, 0x00000000}, |
696 | {0x0000a228, 0x10002310}, | 725 | {0x0000a228, 0x10002310}, |
697 | {0x0000a22c, 0x01036a1e}, | ||
698 | {0x0000a23c, 0x00000000}, | 726 | {0x0000a23c, 0x00000000}, |
699 | {0x0000a244, 0x0c000000}, | 727 | {0x0000a244, 0x0c000000}, |
700 | {0x0000a2a0, 0x00000001}, | 728 | {0x0000a2a0, 0x00000001}, |
@@ -702,10 +730,6 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
702 | {0x0000a2c8, 0x00000000}, | 730 | {0x0000a2c8, 0x00000000}, |
703 | {0x0000a2cc, 0x18c43433}, | 731 | {0x0000a2cc, 0x18c43433}, |
704 | {0x0000a2d4, 0x00000000}, | 732 | {0x0000a2d4, 0x00000000}, |
705 | {0x0000a2dc, 0x00000000}, | ||
706 | {0x0000a2e0, 0x00000000}, | ||
707 | {0x0000a2e4, 0x00000000}, | ||
708 | {0x0000a2e8, 0x00000000}, | ||
709 | {0x0000a2ec, 0x00000000}, | 733 | {0x0000a2ec, 0x00000000}, |
710 | {0x0000a2f0, 0x00000000}, | 734 | {0x0000a2f0, 0x00000000}, |
711 | {0x0000a2f4, 0x00000000}, | 735 | {0x0000a2f4, 0x00000000}, |
@@ -753,33 +777,17 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
753 | {0x0000a430, 0x1ce739ce}, | 777 | {0x0000a430, 0x1ce739ce}, |
754 | {0x0000a434, 0x00000000}, | 778 | {0x0000a434, 0x00000000}, |
755 | {0x0000a438, 0x00001801}, | 779 | {0x0000a438, 0x00001801}, |
756 | {0x0000a43c, 0x00000000}, | 780 | {0x0000a43c, 0x00100000}, |
757 | {0x0000a440, 0x00000000}, | 781 | {0x0000a440, 0x00000000}, |
758 | {0x0000a444, 0x00000000}, | 782 | {0x0000a444, 0x00000000}, |
759 | {0x0000a448, 0x06000080}, | 783 | {0x0000a448, 0x06000080}, |
760 | {0x0000a44c, 0x00000001}, | 784 | {0x0000a44c, 0x00000001}, |
761 | {0x0000a450, 0x00010000}, | 785 | {0x0000a450, 0x00010000}, |
762 | {0x0000a458, 0x00000000}, | 786 | {0x0000a458, 0x00000000}, |
763 | {0x0000a600, 0x00000000}, | ||
764 | {0x0000a604, 0x00000000}, | ||
765 | {0x0000a608, 0x00000000}, | ||
766 | {0x0000a60c, 0x00000000}, | ||
767 | {0x0000a610, 0x00000000}, | ||
768 | {0x0000a614, 0x00000000}, | ||
769 | {0x0000a618, 0x00000000}, | ||
770 | {0x0000a61c, 0x00000000}, | ||
771 | {0x0000a620, 0x00000000}, | ||
772 | {0x0000a624, 0x00000000}, | ||
773 | {0x0000a628, 0x00000000}, | ||
774 | {0x0000a62c, 0x00000000}, | ||
775 | {0x0000a630, 0x00000000}, | ||
776 | {0x0000a634, 0x00000000}, | ||
777 | {0x0000a638, 0x00000000}, | ||
778 | {0x0000a63c, 0x00000000}, | ||
779 | {0x0000a640, 0x00000000}, | 787 | {0x0000a640, 0x00000000}, |
780 | {0x0000a644, 0x3fad9d74}, | 788 | {0x0000a644, 0x3fad9d74}, |
781 | {0x0000a648, 0x0048060a}, | 789 | {0x0000a648, 0x0048060a}, |
782 | {0x0000a64c, 0x00000637}, | 790 | {0x0000a64c, 0x00003c37}, |
783 | {0x0000a670, 0x03020100}, | 791 | {0x0000a670, 0x03020100}, |
784 | {0x0000a674, 0x09080504}, | 792 | {0x0000a674, 0x09080504}, |
785 | {0x0000a678, 0x0d0c0b0a}, | 793 | {0x0000a678, 0x0d0c0b0a}, |
@@ -802,10 +810,6 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
802 | {0x0000a8f4, 0x00000000}, | 810 | {0x0000a8f4, 0x00000000}, |
803 | {0x0000b2d0, 0x00000080}, | 811 | {0x0000b2d0, 0x00000080}, |
804 | {0x0000b2d4, 0x00000000}, | 812 | {0x0000b2d4, 0x00000000}, |
805 | {0x0000b2dc, 0x00000000}, | ||
806 | {0x0000b2e0, 0x00000000}, | ||
807 | {0x0000b2e4, 0x00000000}, | ||
808 | {0x0000b2e8, 0x00000000}, | ||
809 | {0x0000b2ec, 0x00000000}, | 813 | {0x0000b2ec, 0x00000000}, |
810 | {0x0000b2f0, 0x00000000}, | 814 | {0x0000b2f0, 0x00000000}, |
811 | {0x0000b2f4, 0x00000000}, | 815 | {0x0000b2f4, 0x00000000}, |
@@ -820,10 +824,6 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
820 | {0x0000b8f4, 0x00000000}, | 824 | {0x0000b8f4, 0x00000000}, |
821 | {0x0000c2d0, 0x00000080}, | 825 | {0x0000c2d0, 0x00000080}, |
822 | {0x0000c2d4, 0x00000000}, | 826 | {0x0000c2d4, 0x00000000}, |
823 | {0x0000c2dc, 0x00000000}, | ||
824 | {0x0000c2e0, 0x00000000}, | ||
825 | {0x0000c2e4, 0x00000000}, | ||
826 | {0x0000c2e8, 0x00000000}, | ||
827 | {0x0000c2ec, 0x00000000}, | 827 | {0x0000c2ec, 0x00000000}, |
828 | {0x0000c2f0, 0x00000000}, | 828 | {0x0000c2f0, 0x00000000}, |
829 | {0x0000c2f4, 0x00000000}, | 829 | {0x0000c2f4, 0x00000000}, |
@@ -835,6 +835,10 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
835 | 835 | ||
836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | 836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { |
837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
838 | {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | ||
839 | {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, | ||
840 | {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, | ||
841 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
838 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, | 842 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
839 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 843 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
840 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | 844 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
@@ -855,7 +859,7 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | |||
855 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, | 859 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, |
856 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, | 860 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, |
857 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, | 861 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, |
858 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | 862 | {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, |
859 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, | 863 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, |
860 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, | 864 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, |
861 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, | 865 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, |
@@ -900,6 +904,30 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | |||
900 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 904 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
901 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 905 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
902 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 906 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
907 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
908 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
909 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
910 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
911 | {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, | ||
912 | {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, | ||
913 | {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, | ||
914 | {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, | ||
915 | {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, | ||
916 | {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, | ||
917 | {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, | ||
918 | {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
919 | {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
920 | {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
921 | {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
922 | {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
923 | {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | ||
924 | {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, | ||
925 | {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, | ||
926 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
927 | {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, | ||
928 | {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, | ||
929 | {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, | ||
930 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
903 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | 931 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, |
904 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | 932 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, |
905 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | 933 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, |
@@ -913,6 +941,10 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | |||
913 | 941 | ||
914 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { | 942 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { |
915 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 943 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
944 | {0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, | ||
945 | {0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | ||
946 | {0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | ||
947 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
916 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, | 948 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
917 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 949 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
918 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | 950 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
@@ -933,7 +965,7 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { | |||
933 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, | 965 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, |
934 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, | 966 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, |
935 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, | 967 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, |
936 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | 968 | {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, |
937 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, | 969 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, |
938 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, | 970 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, |
939 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, | 971 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, |
@@ -978,6 +1010,30 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { | |||
978 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 1010 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
979 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 1011 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
980 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 1012 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
1013 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1014 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1015 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1016 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1017 | {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, | ||
1018 | {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, | ||
1019 | {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, | ||
1020 | {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, | ||
1021 | {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, | ||
1022 | {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, | ||
1023 | {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, | ||
1024 | {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1025 | {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1026 | {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1027 | {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1028 | {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, | ||
1029 | {0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, | ||
1030 | {0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | ||
1031 | {0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | ||
1032 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1033 | {0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, | ||
1034 | {0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, | ||
1035 | {0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, | ||
1036 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
981 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | 1037 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, |
982 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | 1038 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, |
983 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 1039 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
@@ -1151,14 +1207,14 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = { | |||
1151 | {0x0000b074, 0x00000000}, | 1207 | {0x0000b074, 0x00000000}, |
1152 | {0x0000b078, 0x00000000}, | 1208 | {0x0000b078, 0x00000000}, |
1153 | {0x0000b07c, 0x00000000}, | 1209 | {0x0000b07c, 0x00000000}, |
1154 | {0x0000b080, 0x32323232}, | 1210 | {0x0000b080, 0x2a2d2f32}, |
1155 | {0x0000b084, 0x2f2f3232}, | 1211 | {0x0000b084, 0x21232328}, |
1156 | {0x0000b088, 0x23282a2d}, | 1212 | {0x0000b088, 0x19191c1e}, |
1157 | {0x0000b08c, 0x1c1e2123}, | 1213 | {0x0000b08c, 0x12141417}, |
1158 | {0x0000b090, 0x14171919}, | 1214 | {0x0000b090, 0x07070e0e}, |
1159 | {0x0000b094, 0x0e0e1214}, | 1215 | {0x0000b094, 0x03030305}, |
1160 | {0x0000b098, 0x03050707}, | 1216 | {0x0000b098, 0x00000003}, |
1161 | {0x0000b09c, 0x00030303}, | 1217 | {0x0000b09c, 0x00000000}, |
1162 | {0x0000b0a0, 0x00000000}, | 1218 | {0x0000b0a0, 0x00000000}, |
1163 | {0x0000b0a4, 0x00000000}, | 1219 | {0x0000b0a4, 0x00000000}, |
1164 | {0x0000b0a8, 0x00000000}, | 1220 | {0x0000b0a8, 0x00000000}, |
@@ -1251,6 +1307,10 @@ static const u32 ar9300Common_rx_gain_table_2p2[][2] = { | |||
1251 | 1307 | ||
1252 | static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { | 1308 | static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { |
1253 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 1309 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
1310 | {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, | ||
1311 | {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, | ||
1312 | {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, | ||
1313 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1254 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 1314 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, |
1255 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 1315 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1256 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | 1316 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, |
@@ -1269,21 +1329,21 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { | |||
1269 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, | 1329 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, |
1270 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, | 1330 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, |
1271 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, | 1331 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, |
1272 | {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, | 1332 | {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, |
1273 | {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, | 1333 | {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, |
1274 | {0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, | 1334 | {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, |
1275 | {0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, | 1335 | {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, |
1276 | {0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, | 1336 | {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, |
1277 | {0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, | 1337 | {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, |
1278 | {0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, | 1338 | {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, |
1279 | {0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, | 1339 | {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, |
1280 | {0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1340 | {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1281 | {0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1341 | {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1282 | {0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1342 | {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1283 | {0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1343 | {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1284 | {0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1344 | {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1285 | {0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1345 | {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1286 | {0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, | 1346 | {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
1287 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | 1347 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, |
1288 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | 1348 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, |
1289 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | 1349 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, |
@@ -1301,21 +1361,45 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p2[][5] = { | |||
1301 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, | 1361 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, |
1302 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, | 1362 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, |
1303 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, | 1363 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, |
1304 | {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, | 1364 | {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, |
1305 | {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, | 1365 | {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, |
1306 | {0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, | 1366 | {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, |
1307 | {0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, | 1367 | {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, |
1308 | {0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, | 1368 | {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, |
1309 | {0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, | 1369 | {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, |
1310 | {0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, | 1370 | {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, |
1311 | {0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, | 1371 | {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, |
1312 | {0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1372 | {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1313 | {0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1373 | {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1314 | {0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1374 | {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1315 | {0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1375 | {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1316 | {0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1376 | {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1317 | {0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1377 | {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1318 | {0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, | 1378 | {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
1379 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1380 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1381 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1382 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1383 | {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1384 | {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, | ||
1385 | {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, | ||
1386 | {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, | ||
1387 | {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, | ||
1388 | {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, | ||
1389 | {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, | ||
1390 | {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
1391 | {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
1392 | {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
1393 | {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
1394 | {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, | ||
1395 | {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, | ||
1396 | {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, | ||
1397 | {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, | ||
1398 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1399 | {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, | ||
1400 | {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, | ||
1401 | {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, | ||
1402 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | ||
1319 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 1403 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, |
1320 | {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, | 1404 | {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, |
1321 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 1405 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
@@ -1414,15 +1498,10 @@ static const u32 ar9300_2p2_mac_core[][2] = { | |||
1414 | {0x00008144, 0xffffffff}, | 1498 | {0x00008144, 0xffffffff}, |
1415 | {0x00008168, 0x00000000}, | 1499 | {0x00008168, 0x00000000}, |
1416 | {0x0000816c, 0x00000000}, | 1500 | {0x0000816c, 0x00000000}, |
1417 | {0x00008170, 0x18486200}, | ||
1418 | {0x00008174, 0x33332210}, | ||
1419 | {0x00008178, 0x00000000}, | ||
1420 | {0x0000817c, 0x00020000}, | ||
1421 | {0x000081c0, 0x00000000}, | 1501 | {0x000081c0, 0x00000000}, |
1422 | {0x000081c4, 0x33332210}, | 1502 | {0x000081c4, 0x33332210}, |
1423 | {0x000081c8, 0x00000000}, | 1503 | {0x000081c8, 0x00000000}, |
1424 | {0x000081cc, 0x00000000}, | 1504 | {0x000081cc, 0x00000000}, |
1425 | {0x000081d4, 0x00000000}, | ||
1426 | {0x000081ec, 0x00000000}, | 1505 | {0x000081ec, 0x00000000}, |
1427 | {0x000081f0, 0x00000000}, | 1506 | {0x000081f0, 0x00000000}, |
1428 | {0x000081f4, 0x00000000}, | 1507 | {0x000081f4, 0x00000000}, |
@@ -1763,7 +1842,7 @@ static const u32 ar9300_2p2_soc_preamble[][2] = { | |||
1763 | 1842 | ||
1764 | static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = { | 1843 | static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2[][2] = { |
1765 | /* Addr allmodes */ | 1844 | /* Addr allmodes */ |
1766 | {0x00004040, 0x08212e5e}, | 1845 | {0x00004040, 0x0821265e}, |
1767 | {0x00004040, 0x0008003b}, | 1846 | {0x00004040, 0x0008003b}, |
1768 | {0x00004044, 0x00000000}, | 1847 | {0x00004044, 0x00000000}, |
1769 | }; | 1848 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 4674ea8c9c99..f48051c50092 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -18,6 +18,21 @@ | |||
18 | #include "hw-ops.h" | 18 | #include "hw-ops.h" |
19 | #include "ar9003_phy.h" | 19 | #include "ar9003_phy.h" |
20 | 20 | ||
21 | #define MAX_MEASUREMENT 8 | ||
22 | #define MAX_MAG_DELTA 11 | ||
23 | #define MAX_PHS_DELTA 10 | ||
24 | |||
25 | struct coeff { | ||
26 | int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; | ||
27 | int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; | ||
28 | int iqc_coeff[2]; | ||
29 | }; | ||
30 | |||
31 | enum ar9003_cal_types { | ||
32 | IQ_MISMATCH_CAL = BIT(0), | ||
33 | TEMP_COMP_CAL = BIT(1), | ||
34 | }; | ||
35 | |||
21 | static void ar9003_hw_setup_calibration(struct ath_hw *ah, | 36 | static void ar9003_hw_setup_calibration(struct ath_hw *ah, |
22 | struct ath9k_cal_list *currCal) | 37 | struct ath9k_cal_list *currCal) |
23 | { | 38 | { |
@@ -35,8 +50,8 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah, | |||
35 | currCal->calData->calCountMax); | 50 | currCal->calData->calCountMax); |
36 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); | 51 | REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); |
37 | 52 | ||
38 | ath_print(common, ATH_DBG_CALIBRATE, | 53 | ath_dbg(common, ATH_DBG_CALIBRATE, |
39 | "starting IQ Mismatch Calibration\n"); | 54 | "starting IQ Mismatch Calibration\n"); |
40 | 55 | ||
41 | /* Kick-off cal */ | 56 | /* Kick-off cal */ |
42 | REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); | 57 | REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL); |
@@ -47,13 +62,8 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah, | |||
47 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, | 62 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM, |
48 | AR_PHY_65NM_CH0_THERM_START, 1); | 63 | AR_PHY_65NM_CH0_THERM_START, 1); |
49 | 64 | ||
50 | ath_print(common, ATH_DBG_CALIBRATE, | 65 | ath_dbg(common, ATH_DBG_CALIBRATE, |
51 | "starting Temperature Compensation Calibration\n"); | 66 | "starting Temperature Compensation Calibration\n"); |
52 | break; | ||
53 | case ADC_DC_INIT_CAL: | ||
54 | case ADC_GAIN_CAL: | ||
55 | case ADC_DC_CAL: | ||
56 | /* Not yet */ | ||
57 | break; | 67 | break; |
58 | } | 68 | } |
59 | } | 69 | } |
@@ -175,17 +185,19 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah) | |||
175 | 185 | ||
176 | /* Accumulate IQ cal measures for active chains */ | 186 | /* Accumulate IQ cal measures for active chains */ |
177 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | 187 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { |
178 | ah->totalPowerMeasI[i] += | 188 | if (ah->txchainmask & BIT(i)) { |
179 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); | 189 | ah->totalPowerMeasI[i] += |
180 | ah->totalPowerMeasQ[i] += | 190 | REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); |
181 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); | 191 | ah->totalPowerMeasQ[i] += |
182 | ah->totalIqCorrMeas[i] += | 192 | REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); |
183 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); | 193 | ah->totalIqCorrMeas[i] += |
184 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | 194 | (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); |
185 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", | 195 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
186 | ah->cal_samples, i, ah->totalPowerMeasI[i], | 196 | "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", |
187 | ah->totalPowerMeasQ[i], | 197 | ah->cal_samples, i, ah->totalPowerMeasI[i], |
188 | ah->totalIqCorrMeas[i]); | 198 | ah->totalPowerMeasQ[i], |
199 | ah->totalIqCorrMeas[i]); | ||
200 | } | ||
189 | } | 201 | } |
190 | } | 202 | } |
191 | 203 | ||
@@ -196,7 +208,7 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
196 | u32 qCoffDenom, iCoffDenom; | 208 | u32 qCoffDenom, iCoffDenom; |
197 | int32_t qCoff, iCoff; | 209 | int32_t qCoff, iCoff; |
198 | int iqCorrNeg, i; | 210 | int iqCorrNeg, i; |
199 | const u_int32_t offset_array[3] = { | 211 | static const u_int32_t offset_array[3] = { |
200 | AR_PHY_RX_IQCAL_CORR_B0, | 212 | AR_PHY_RX_IQCAL_CORR_B0, |
201 | AR_PHY_RX_IQCAL_CORR_B1, | 213 | AR_PHY_RX_IQCAL_CORR_B1, |
202 | AR_PHY_RX_IQCAL_CORR_B2, | 214 | AR_PHY_RX_IQCAL_CORR_B2, |
@@ -207,13 +219,13 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
207 | powerMeasQ = ah->totalPowerMeasQ[i]; | 219 | powerMeasQ = ah->totalPowerMeasQ[i]; |
208 | iqCorrMeas = ah->totalIqCorrMeas[i]; | 220 | iqCorrMeas = ah->totalIqCorrMeas[i]; |
209 | 221 | ||
210 | ath_print(common, ATH_DBG_CALIBRATE, | 222 | ath_dbg(common, ATH_DBG_CALIBRATE, |
211 | "Starting IQ Cal and Correction for Chain %d\n", | 223 | "Starting IQ Cal and Correction for Chain %d\n", |
212 | i); | 224 | i); |
213 | 225 | ||
214 | ath_print(common, ATH_DBG_CALIBRATE, | 226 | ath_dbg(common, ATH_DBG_CALIBRATE, |
215 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", | 227 | "Orignal: Chn %diq_corr_meas = 0x%08x\n", |
216 | i, ah->totalIqCorrMeas[i]); | 228 | i, ah->totalIqCorrMeas[i]); |
217 | 229 | ||
218 | iqCorrNeg = 0; | 230 | iqCorrNeg = 0; |
219 | 231 | ||
@@ -222,12 +234,12 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
222 | iqCorrNeg = 1; | 234 | iqCorrNeg = 1; |
223 | } | 235 | } |
224 | 236 | ||
225 | ath_print(common, ATH_DBG_CALIBRATE, | 237 | ath_dbg(common, ATH_DBG_CALIBRATE, |
226 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); | 238 | "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); |
227 | ath_print(common, ATH_DBG_CALIBRATE, | 239 | ath_dbg(common, ATH_DBG_CALIBRATE, |
228 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); | 240 | "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); |
229 | ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", | 241 | ath_dbg(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", |
230 | iqCorrNeg); | 242 | iqCorrNeg); |
231 | 243 | ||
232 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256; | 244 | iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256; |
233 | qCoffDenom = powerMeasQ / 64; | 245 | qCoffDenom = powerMeasQ / 64; |
@@ -235,10 +247,10 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
235 | if ((iCoffDenom != 0) && (qCoffDenom != 0)) { | 247 | if ((iCoffDenom != 0) && (qCoffDenom != 0)) { |
236 | iCoff = iqCorrMeas / iCoffDenom; | 248 | iCoff = iqCorrMeas / iCoffDenom; |
237 | qCoff = powerMeasI / qCoffDenom - 64; | 249 | qCoff = powerMeasI / qCoffDenom - 64; |
238 | ath_print(common, ATH_DBG_CALIBRATE, | 250 | ath_dbg(common, ATH_DBG_CALIBRATE, |
239 | "Chn %d iCoff = 0x%08x\n", i, iCoff); | 251 | "Chn %d iCoff = 0x%08x\n", i, iCoff); |
240 | ath_print(common, ATH_DBG_CALIBRATE, | 252 | ath_dbg(common, ATH_DBG_CALIBRATE, |
241 | "Chn %d qCoff = 0x%08x\n", i, qCoff); | 253 | "Chn %d qCoff = 0x%08x\n", i, qCoff); |
242 | 254 | ||
243 | /* Force bounds on iCoff */ | 255 | /* Force bounds on iCoff */ |
244 | if (iCoff >= 63) | 256 | if (iCoff >= 63) |
@@ -259,14 +271,13 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
259 | iCoff = iCoff & 0x7f; | 271 | iCoff = iCoff & 0x7f; |
260 | qCoff = qCoff & 0x7f; | 272 | qCoff = qCoff & 0x7f; |
261 | 273 | ||
262 | ath_print(common, ATH_DBG_CALIBRATE, | 274 | ath_dbg(common, ATH_DBG_CALIBRATE, |
263 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", | 275 | "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", |
264 | i, iCoff, qCoff); | 276 | i, iCoff, qCoff); |
265 | ath_print(common, ATH_DBG_CALIBRATE, | 277 | ath_dbg(common, ATH_DBG_CALIBRATE, |
266 | "Register offset (0x%04x) " | 278 | "Register offset (0x%04x) before update = 0x%x\n", |
267 | "before update = 0x%x\n", | 279 | offset_array[i], |
268 | offset_array[i], | 280 | REG_READ(ah, offset_array[i])); |
269 | REG_READ(ah, offset_array[i])); | ||
270 | 281 | ||
271 | REG_RMW_FIELD(ah, offset_array[i], | 282 | REG_RMW_FIELD(ah, offset_array[i], |
272 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, | 283 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, |
@@ -274,33 +285,29 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
274 | REG_RMW_FIELD(ah, offset_array[i], | 285 | REG_RMW_FIELD(ah, offset_array[i], |
275 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, | 286 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, |
276 | qCoff); | 287 | qCoff); |
277 | ath_print(common, ATH_DBG_CALIBRATE, | 288 | ath_dbg(common, ATH_DBG_CALIBRATE, |
278 | "Register offset (0x%04x) QI COFF " | 289 | "Register offset (0x%04x) QI COFF (bitfields 0x%08x) after update = 0x%x\n", |
279 | "(bitfields 0x%08x) after update = 0x%x\n", | 290 | offset_array[i], |
280 | offset_array[i], | 291 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, |
281 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, | 292 | REG_READ(ah, offset_array[i])); |
282 | REG_READ(ah, offset_array[i])); | 293 | ath_dbg(common, ATH_DBG_CALIBRATE, |
283 | ath_print(common, ATH_DBG_CALIBRATE, | 294 | "Register offset (0x%04x) QQ COFF (bitfields 0x%08x) after update = 0x%x\n", |
284 | "Register offset (0x%04x) QQ COFF " | 295 | offset_array[i], |
285 | "(bitfields 0x%08x) after update = 0x%x\n", | 296 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, |
286 | offset_array[i], | 297 | REG_READ(ah, offset_array[i])); |
287 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF, | 298 | |
288 | REG_READ(ah, offset_array[i])); | 299 | ath_dbg(common, ATH_DBG_CALIBRATE, |
289 | 300 | "IQ Cal and Correction done for Chain %d\n", i); | |
290 | ath_print(common, ATH_DBG_CALIBRATE, | ||
291 | "IQ Cal and Correction done for Chain %d\n", | ||
292 | i); | ||
293 | } | 301 | } |
294 | } | 302 | } |
295 | 303 | ||
296 | REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0, | 304 | REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0, |
297 | AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE); | 305 | AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE); |
298 | ath_print(common, ATH_DBG_CALIBRATE, | 306 | ath_dbg(common, ATH_DBG_CALIBRATE, |
299 | "IQ Cal and Correction (offset 0x%04x) enabled " | 307 | "IQ Cal and Correction (offset 0x%04x) enabled (bit position 0x%08x). New Value 0x%08x\n", |
300 | "(bit position 0x%08x). New Value 0x%08x\n", | 308 | (unsigned) (AR_PHY_RX_IQCAL_CORR_B0), |
301 | (unsigned) (AR_PHY_RX_IQCAL_CORR_B0), | 309 | AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE, |
302 | AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE, | 310 | REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0)); |
303 | REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0)); | ||
304 | } | 311 | } |
305 | 312 | ||
306 | static const struct ath9k_percal_data iq_cal_single_sample = { | 313 | static const struct ath9k_percal_data iq_cal_single_sample = { |
@@ -314,27 +321,6 @@ static const struct ath9k_percal_data iq_cal_single_sample = { | |||
314 | static void ar9003_hw_init_cal_settings(struct ath_hw *ah) | 321 | static void ar9003_hw_init_cal_settings(struct ath_hw *ah) |
315 | { | 322 | { |
316 | ah->iq_caldata.calData = &iq_cal_single_sample; | 323 | ah->iq_caldata.calData = &iq_cal_single_sample; |
317 | ah->supp_cals = IQ_MISMATCH_CAL; | ||
318 | } | ||
319 | |||
320 | static bool ar9003_hw_iscal_supported(struct ath_hw *ah, | ||
321 | enum ath9k_cal_types calType) | ||
322 | { | ||
323 | switch (calType & ah->supp_cals) { | ||
324 | case IQ_MISMATCH_CAL: | ||
325 | /* | ||
326 | * XXX: Run IQ Mismatch for non-CCK only | ||
327 | * Note that CHANNEL_B is never set though. | ||
328 | */ | ||
329 | return true; | ||
330 | case ADC_GAIN_CAL: | ||
331 | case ADC_DC_CAL: | ||
332 | return false; | ||
333 | case TEMP_COMP_CAL: | ||
334 | return true; | ||
335 | } | ||
336 | |||
337 | return false; | ||
338 | } | 324 | } |
339 | 325 | ||
340 | /* | 326 | /* |
@@ -361,7 +347,7 @@ static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah, | |||
361 | f2 = (f1 * f1 + f3 * f3) / result_shift; | 347 | f2 = (f1 * f1 + f3 * f3) / result_shift; |
362 | 348 | ||
363 | if (!f2) { | 349 | if (!f2) { |
364 | ath_print(common, ATH_DBG_CALIBRATE, "Divide by 0\n"); | 350 | ath_dbg(common, ATH_DBG_CALIBRATE, "Divide by 0\n"); |
365 | return false; | 351 | return false; |
366 | } | 352 | } |
367 | 353 | ||
@@ -482,11 +468,14 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
482 | 468 | ||
483 | if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) || | 469 | if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) || |
484 | (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) { | 470 | (i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) { |
485 | ath_print(common, ATH_DBG_CALIBRATE, | 471 | ath_dbg(common, ATH_DBG_CALIBRATE, |
486 | "Divide by 0:\na0_d0=%d\n" | 472 | "Divide by 0:\n" |
487 | "a0_d1=%d\na2_d0=%d\na1_d1=%d\n", | 473 | "a0_d0=%d\n" |
488 | i2_p_q2_a0_d0, i2_p_q2_a0_d1, | 474 | "a0_d1=%d\n" |
489 | i2_p_q2_a1_d0, i2_p_q2_a1_d1); | 475 | "a2_d0=%d\n" |
476 | "a1_d1=%d\n", | ||
477 | i2_p_q2_a0_d0, i2_p_q2_a0_d1, | ||
478 | i2_p_q2_a1_d0, i2_p_q2_a1_d1); | ||
490 | return false; | 479 | return false; |
491 | } | 480 | } |
492 | 481 | ||
@@ -519,9 +508,9 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
519 | mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2); | 508 | mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2); |
520 | 509 | ||
521 | if ((mag1 == 0) || (mag2 == 0)) { | 510 | if ((mag1 == 0) || (mag2 == 0)) { |
522 | ath_print(common, ATH_DBG_CALIBRATE, | 511 | ath_dbg(common, ATH_DBG_CALIBRATE, |
523 | "Divide by 0: mag1=%d, mag2=%d\n", | 512 | "Divide by 0: mag1=%d, mag2=%d\n", |
524 | mag1, mag2); | 513 | mag1, mag2); |
525 | return false; | 514 | return false; |
526 | } | 515 | } |
527 | 516 | ||
@@ -538,8 +527,8 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
538 | mag_a0_d0, phs_a0_d0, | 527 | mag_a0_d0, phs_a0_d0, |
539 | mag_a1_d0, | 528 | mag_a1_d0, |
540 | phs_a1_d0, solved_eq)) { | 529 | phs_a1_d0, solved_eq)) { |
541 | ath_print(common, ATH_DBG_CALIBRATE, | 530 | ath_dbg(common, ATH_DBG_CALIBRATE, |
542 | "Call to ar9003_hw_solve_iq_cal() failed.\n"); | 531 | "Call to ar9003_hw_solve_iq_cal() failed.\n"); |
543 | return false; | 532 | return false; |
544 | } | 533 | } |
545 | 534 | ||
@@ -548,14 +537,14 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
548 | mag_rx = solved_eq[2]; | 537 | mag_rx = solved_eq[2]; |
549 | phs_rx = solved_eq[3]; | 538 | phs_rx = solved_eq[3]; |
550 | 539 | ||
551 | ath_print(common, ATH_DBG_CALIBRATE, | 540 | ath_dbg(common, ATH_DBG_CALIBRATE, |
552 | "chain %d: mag mismatch=%d phase mismatch=%d\n", | 541 | "chain %d: mag mismatch=%d phase mismatch=%d\n", |
553 | chain_idx, mag_tx/res_scale, phs_tx/res_scale); | 542 | chain_idx, mag_tx/res_scale, phs_tx/res_scale); |
554 | 543 | ||
555 | if (res_scale == mag_tx) { | 544 | if (res_scale == mag_tx) { |
556 | ath_print(common, ATH_DBG_CALIBRATE, | 545 | ath_dbg(common, ATH_DBG_CALIBRATE, |
557 | "Divide by 0: mag_tx=%d, res_scale=%d\n", | 546 | "Divide by 0: mag_tx=%d, res_scale=%d\n", |
558 | mag_tx, res_scale); | 547 | mag_tx, res_scale); |
559 | return false; | 548 | return false; |
560 | } | 549 | } |
561 | 550 | ||
@@ -566,9 +555,9 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
566 | q_q_coff = (mag_corr_tx * 128 / res_scale); | 555 | q_q_coff = (mag_corr_tx * 128 / res_scale); |
567 | q_i_coff = (phs_corr_tx * 256 / res_scale); | 556 | q_i_coff = (phs_corr_tx * 256 / res_scale); |
568 | 557 | ||
569 | ath_print(common, ATH_DBG_CALIBRATE, | 558 | ath_dbg(common, ATH_DBG_CALIBRATE, |
570 | "tx chain %d: mag corr=%d phase corr=%d\n", | 559 | "tx chain %d: mag corr=%d phase corr=%d\n", |
571 | chain_idx, q_q_coff, q_i_coff); | 560 | chain_idx, q_q_coff, q_i_coff); |
572 | 561 | ||
573 | if (q_i_coff < -63) | 562 | if (q_i_coff < -63) |
574 | q_i_coff = -63; | 563 | q_i_coff = -63; |
@@ -581,14 +570,14 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
581 | 570 | ||
582 | iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; | 571 | iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; |
583 | 572 | ||
584 | ath_print(common, ATH_DBG_CALIBRATE, | 573 | ath_dbg(common, ATH_DBG_CALIBRATE, |
585 | "tx chain %d: iq corr coeff=%x\n", | 574 | "tx chain %d: iq corr coeff=%x\n", |
586 | chain_idx, iqc_coeff[0]); | 575 | chain_idx, iqc_coeff[0]); |
587 | 576 | ||
588 | if (-mag_rx == res_scale) { | 577 | if (-mag_rx == res_scale) { |
589 | ath_print(common, ATH_DBG_CALIBRATE, | 578 | ath_dbg(common, ATH_DBG_CALIBRATE, |
590 | "Divide by 0: mag_rx=%d, res_scale=%d\n", | 579 | "Divide by 0: mag_rx=%d, res_scale=%d\n", |
591 | mag_rx, res_scale); | 580 | mag_rx, res_scale); |
592 | return false; | 581 | return false; |
593 | } | 582 | } |
594 | 583 | ||
@@ -599,9 +588,9 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
599 | q_q_coff = (mag_corr_rx * 128 / res_scale); | 588 | q_q_coff = (mag_corr_rx * 128 / res_scale); |
600 | q_i_coff = (phs_corr_rx * 256 / res_scale); | 589 | q_i_coff = (phs_corr_rx * 256 / res_scale); |
601 | 590 | ||
602 | ath_print(common, ATH_DBG_CALIBRATE, | 591 | ath_dbg(common, ATH_DBG_CALIBRATE, |
603 | "rx chain %d: mag corr=%d phase corr=%d\n", | 592 | "rx chain %d: mag corr=%d phase corr=%d\n", |
604 | chain_idx, q_q_coff, q_i_coff); | 593 | chain_idx, q_q_coff, q_i_coff); |
605 | 594 | ||
606 | if (q_i_coff < -63) | 595 | if (q_i_coff < -63) |
607 | q_i_coff = -63; | 596 | q_i_coff = -63; |
@@ -614,14 +603,142 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, | |||
614 | 603 | ||
615 | iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; | 604 | iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; |
616 | 605 | ||
617 | ath_print(common, ATH_DBG_CALIBRATE, | 606 | ath_dbg(common, ATH_DBG_CALIBRATE, |
618 | "rx chain %d: iq corr coeff=%x\n", | 607 | "rx chain %d: iq corr coeff=%x\n", |
619 | chain_idx, iqc_coeff[1]); | 608 | chain_idx, iqc_coeff[1]); |
620 | 609 | ||
621 | return true; | 610 | return true; |
622 | } | 611 | } |
623 | 612 | ||
624 | static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) | 613 | static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, |
614 | int max_delta) | ||
615 | { | ||
616 | int mp_max = -64, max_idx = 0; | ||
617 | int mp_min = 63, min_idx = 0; | ||
618 | int mp_avg = 0, i, outlier_idx = 0; | ||
619 | |||
620 | /* find min/max mismatch across all calibrated gains */ | ||
621 | for (i = 0; i < nmeasurement; i++) { | ||
622 | mp_avg += mp_coeff[i]; | ||
623 | if (mp_coeff[i] > mp_max) { | ||
624 | mp_max = mp_coeff[i]; | ||
625 | max_idx = i; | ||
626 | } else if (mp_coeff[i] < mp_min) { | ||
627 | mp_min = mp_coeff[i]; | ||
628 | min_idx = i; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | /* find average (exclude max abs value) */ | ||
633 | for (i = 0; i < nmeasurement; i++) { | ||
634 | if ((abs(mp_coeff[i]) < abs(mp_max)) || | ||
635 | (abs(mp_coeff[i]) < abs(mp_min))) | ||
636 | mp_avg += mp_coeff[i]; | ||
637 | } | ||
638 | mp_avg /= (nmeasurement - 1); | ||
639 | |||
640 | /* detect outlier */ | ||
641 | if (abs(mp_max - mp_min) > max_delta) { | ||
642 | if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg)) | ||
643 | outlier_idx = max_idx; | ||
644 | else | ||
645 | outlier_idx = min_idx; | ||
646 | } | ||
647 | mp_coeff[outlier_idx] = mp_avg; | ||
648 | } | ||
649 | |||
650 | static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, | ||
651 | u8 num_chains, | ||
652 | struct coeff *coeff) | ||
653 | { | ||
654 | int i, im, nmeasurement; | ||
655 | u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; | ||
656 | |||
657 | memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); | ||
658 | for (i = 0; i < MAX_MEASUREMENT / 2; i++) { | ||
659 | tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] = | ||
660 | AR_PHY_TX_IQCAL_CORR_COEFF_B0(i); | ||
661 | if (!AR_SREV_9485(ah)) { | ||
662 | tx_corr_coeff[i * 2][1] = | ||
663 | tx_corr_coeff[(i * 2) + 1][1] = | ||
664 | AR_PHY_TX_IQCAL_CORR_COEFF_B1(i); | ||
665 | |||
666 | tx_corr_coeff[i * 2][2] = | ||
667 | tx_corr_coeff[(i * 2) + 1][2] = | ||
668 | AR_PHY_TX_IQCAL_CORR_COEFF_B2(i); | ||
669 | } | ||
670 | } | ||
671 | |||
672 | /* Load the average of 2 passes */ | ||
673 | for (i = 0; i < num_chains; i++) { | ||
674 | nmeasurement = REG_READ_FIELD(ah, | ||
675 | AR_PHY_TX_IQCAL_STATUS_B0, | ||
676 | AR_PHY_CALIBRATED_GAINS_0); | ||
677 | |||
678 | if (nmeasurement > MAX_MEASUREMENT) | ||
679 | nmeasurement = MAX_MEASUREMENT; | ||
680 | |||
681 | /* detect outlier only if nmeasurement > 1 */ | ||
682 | if (nmeasurement > 1) { | ||
683 | /* Detect magnitude outlier */ | ||
684 | ar9003_hw_detect_outlier(coeff->mag_coeff[i], | ||
685 | nmeasurement, MAX_MAG_DELTA); | ||
686 | |||
687 | /* Detect phase outlier */ | ||
688 | ar9003_hw_detect_outlier(coeff->phs_coeff[i], | ||
689 | nmeasurement, MAX_PHS_DELTA); | ||
690 | } | ||
691 | |||
692 | for (im = 0; im < nmeasurement; im++) { | ||
693 | |||
694 | coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | | ||
695 | ((coeff->phs_coeff[i][im] & 0x7f) << 7); | ||
696 | |||
697 | if ((im % 2) == 0) | ||
698 | REG_RMW_FIELD(ah, tx_corr_coeff[im][i], | ||
699 | AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE, | ||
700 | coeff->iqc_coeff[0]); | ||
701 | else | ||
702 | REG_RMW_FIELD(ah, tx_corr_coeff[im][i], | ||
703 | AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, | ||
704 | coeff->iqc_coeff[0]); | ||
705 | } | ||
706 | } | ||
707 | |||
708 | REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, | ||
709 | AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1); | ||
710 | REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, | ||
711 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); | ||
712 | |||
713 | return; | ||
714 | |||
715 | } | ||
716 | |||
717 | static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) | ||
718 | { | ||
719 | struct ath_common *common = ath9k_hw_common(ah); | ||
720 | u8 tx_gain_forced; | ||
721 | |||
722 | tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
723 | AR_PHY_TXGAIN_FORCE); | ||
724 | if (tx_gain_forced) | ||
725 | REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, | ||
726 | AR_PHY_TXGAIN_FORCE, 0); | ||
727 | |||
728 | REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, | ||
729 | AR_PHY_TX_IQCAL_START_DO_CAL, 1); | ||
730 | |||
731 | if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, | ||
732 | AR_PHY_TX_IQCAL_START_DO_CAL, 0, | ||
733 | AH_WAIT_TIMEOUT)) { | ||
734 | ath_dbg(common, ATH_DBG_CALIBRATE, | ||
735 | "Tx IQ Cal is not completed.\n"); | ||
736 | return false; | ||
737 | } | ||
738 | return true; | ||
739 | } | ||
740 | |||
741 | static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) | ||
625 | { | 742 | { |
626 | struct ath_common *common = ath9k_hw_common(ah); | 743 | struct ath_common *common = ath9k_hw_common(ah); |
627 | const u32 txiqcal_status[AR9300_MAX_CHAINS] = { | 744 | const u32 txiqcal_status[AR9300_MAX_CHAINS] = { |
@@ -629,128 +746,130 @@ static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) | |||
629 | AR_PHY_TX_IQCAL_STATUS_B1, | 746 | AR_PHY_TX_IQCAL_STATUS_B1, |
630 | AR_PHY_TX_IQCAL_STATUS_B2, | 747 | AR_PHY_TX_IQCAL_STATUS_B2, |
631 | }; | 748 | }; |
632 | const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = { | ||
633 | AR_PHY_TX_IQCAL_CORR_COEFF_01_B0, | ||
634 | AR_PHY_TX_IQCAL_CORR_COEFF_01_B1, | ||
635 | AR_PHY_TX_IQCAL_CORR_COEFF_01_B2, | ||
636 | }; | ||
637 | const u32 rx_corr[AR9300_MAX_CHAINS] = { | ||
638 | AR_PHY_RX_IQCAL_CORR_B0, | ||
639 | AR_PHY_RX_IQCAL_CORR_B1, | ||
640 | AR_PHY_RX_IQCAL_CORR_B2, | ||
641 | }; | ||
642 | const u_int32_t chan_info_tab[] = { | 749 | const u_int32_t chan_info_tab[] = { |
643 | AR_PHY_CHAN_INFO_TAB_0, | 750 | AR_PHY_CHAN_INFO_TAB_0, |
644 | AR_PHY_CHAN_INFO_TAB_1, | 751 | AR_PHY_CHAN_INFO_TAB_1, |
645 | AR_PHY_CHAN_INFO_TAB_2, | 752 | AR_PHY_CHAN_INFO_TAB_2, |
646 | }; | 753 | }; |
754 | struct coeff coeff; | ||
647 | s32 iq_res[6]; | 755 | s32 iq_res[6]; |
648 | s32 iqc_coeff[2]; | 756 | u8 num_chains = 0; |
649 | s32 i, j; | 757 | int i, im, j; |
650 | u32 num_chains = 0; | 758 | int nmeasurement; |
651 | 759 | ||
652 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | 760 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { |
653 | if (ah->txchainmask & (1 << i)) | 761 | if (ah->txchainmask & (1 << i)) |
654 | num_chains++; | 762 | num_chains++; |
655 | } | 763 | } |
656 | 764 | ||
657 | REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, | ||
658 | AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, | ||
659 | DELPT); | ||
660 | REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, | ||
661 | AR_PHY_TX_IQCAL_START_DO_CAL, | ||
662 | AR_PHY_TX_IQCAL_START_DO_CAL); | ||
663 | |||
664 | if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, | ||
665 | AR_PHY_TX_IQCAL_START_DO_CAL, | ||
666 | 0, AH_WAIT_TIMEOUT)) { | ||
667 | ath_print(common, ATH_DBG_CALIBRATE, | ||
668 | "Tx IQ Cal not complete.\n"); | ||
669 | goto TX_IQ_CAL_FAILED; | ||
670 | } | ||
671 | |||
672 | for (i = 0; i < num_chains; i++) { | 765 | for (i = 0; i < num_chains; i++) { |
673 | ath_print(common, ATH_DBG_CALIBRATE, | 766 | nmeasurement = REG_READ_FIELD(ah, |
674 | "Doing Tx IQ Cal for chain %d.\n", i); | 767 | AR_PHY_TX_IQCAL_STATUS_B0, |
675 | 768 | AR_PHY_CALIBRATED_GAINS_0); | |
676 | if (REG_READ(ah, txiqcal_status[i]) & | 769 | if (nmeasurement > MAX_MEASUREMENT) |
677 | AR_PHY_TX_IQCAL_STATUS_FAILED) { | 770 | nmeasurement = MAX_MEASUREMENT; |
678 | ath_print(common, ATH_DBG_CALIBRATE, | 771 | |
679 | "Tx IQ Cal failed for chain %d.\n", i); | 772 | for (im = 0; im < nmeasurement; im++) { |
680 | goto TX_IQ_CAL_FAILED; | 773 | ath_dbg(common, ATH_DBG_CALIBRATE, |
681 | } | 774 | "Doing Tx IQ Cal for chain %d.\n", i); |
682 | 775 | ||
683 | for (j = 0; j < 3; j++) { | 776 | if (REG_READ(ah, txiqcal_status[i]) & |
684 | u_int8_t idx = 2 * j, | 777 | AR_PHY_TX_IQCAL_STATUS_FAILED) { |
685 | offset = 4 * j; | 778 | ath_dbg(common, ATH_DBG_CALIBRATE, |
686 | 779 | "Tx IQ Cal failed for chain %d.\n", i); | |
687 | REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, | 780 | goto tx_iqcal_fail; |
688 | AR_PHY_CHAN_INFO_TAB_S2_READ, 0); | 781 | } |
689 | |||
690 | /* 32 bits */ | ||
691 | iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset); | ||
692 | 782 | ||
693 | REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, | 783 | for (j = 0; j < 3; j++) { |
694 | AR_PHY_CHAN_INFO_TAB_S2_READ, 1); | 784 | u32 idx = 2 * j, offset = 4 * (3 * im + j); |
785 | |||
786 | REG_RMW_FIELD(ah, | ||
787 | AR_PHY_CHAN_INFO_MEMORY, | ||
788 | AR_PHY_CHAN_INFO_TAB_S2_READ, | ||
789 | 0); | ||
790 | |||
791 | /* 32 bits */ | ||
792 | iq_res[idx] = REG_READ(ah, | ||
793 | chan_info_tab[i] + | ||
794 | offset); | ||
795 | |||
796 | REG_RMW_FIELD(ah, | ||
797 | AR_PHY_CHAN_INFO_MEMORY, | ||
798 | AR_PHY_CHAN_INFO_TAB_S2_READ, | ||
799 | 1); | ||
800 | |||
801 | /* 16 bits */ | ||
802 | iq_res[idx + 1] = 0xffff & REG_READ(ah, | ||
803 | chan_info_tab[i] + offset); | ||
804 | |||
805 | ath_dbg(common, ATH_DBG_CALIBRATE, | ||
806 | "IQ RES[%d]=0x%x" | ||
807 | "IQ_RES[%d]=0x%x\n", | ||
808 | idx, iq_res[idx], idx + 1, | ||
809 | iq_res[idx + 1]); | ||
810 | } | ||
695 | 811 | ||
696 | /* 16 bits */ | 812 | if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, |
697 | iq_res[idx+1] = 0xffff & REG_READ(ah, | 813 | coeff.iqc_coeff)) { |
698 | chan_info_tab[i] + | 814 | ath_dbg(common, ATH_DBG_CALIBRATE, |
699 | offset); | 815 | "Failed in calculation of \ |
816 | IQ correction.\n"); | ||
817 | goto tx_iqcal_fail; | ||
818 | } | ||
700 | 819 | ||
701 | ath_print(common, ATH_DBG_CALIBRATE, | 820 | coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; |
702 | "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", | 821 | coeff.phs_coeff[i][im] = |
703 | idx, iq_res[idx], idx+1, iq_res[idx+1]); | 822 | (coeff.iqc_coeff[0] >> 7) & 0x7f; |
704 | } | ||
705 | 823 | ||
706 | if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, iqc_coeff)) { | 824 | if (coeff.mag_coeff[i][im] > 63) |
707 | ath_print(common, ATH_DBG_CALIBRATE, | 825 | coeff.mag_coeff[i][im] -= 128; |
708 | "Failed in calculation of IQ correction.\n"); | 826 | if (coeff.phs_coeff[i][im] > 63) |
709 | goto TX_IQ_CAL_FAILED; | 827 | coeff.phs_coeff[i][im] -= 128; |
710 | } | 828 | } |
711 | |||
712 | ath_print(common, ATH_DBG_CALIBRATE, | ||
713 | "IQ_COEFF[0] = 0x%x IQ_COEFF[1] = 0x%x\n", | ||
714 | iqc_coeff[0], iqc_coeff[1]); | ||
715 | |||
716 | REG_RMW_FIELD(ah, tx_corr_coeff[i], | ||
717 | AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE, | ||
718 | iqc_coeff[0]); | ||
719 | REG_RMW_FIELD(ah, rx_corr[i], | ||
720 | AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF, | ||
721 | iqc_coeff[1] >> 7); | ||
722 | REG_RMW_FIELD(ah, rx_corr[i], | ||
723 | AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF, | ||
724 | iqc_coeff[1]); | ||
725 | } | 829 | } |
726 | 830 | ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); | |
727 | REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, | ||
728 | AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1); | ||
729 | REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, | ||
730 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); | ||
731 | 831 | ||
732 | return; | 832 | return; |
733 | 833 | ||
734 | TX_IQ_CAL_FAILED: | 834 | tx_iqcal_fail: |
735 | ath_print(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); | 835 | ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); |
836 | return; | ||
736 | } | 837 | } |
737 | |||
738 | static bool ar9003_hw_init_cal(struct ath_hw *ah, | 838 | static bool ar9003_hw_init_cal(struct ath_hw *ah, |
739 | struct ath9k_channel *chan) | 839 | struct ath9k_channel *chan) |
740 | { | 840 | { |
741 | struct ath_common *common = ath9k_hw_common(ah); | 841 | struct ath_common *common = ath9k_hw_common(ah); |
842 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
843 | int val; | ||
844 | bool txiqcal_done = false; | ||
742 | 845 | ||
743 | /* | 846 | val = REG_READ(ah, AR_ENT_OTP); |
744 | * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before | 847 | ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); |
745 | * running AGC/TxIQ cals | 848 | |
746 | */ | 849 | /* Configure rx/tx chains before running AGC/TxiQ cals */ |
747 | ar9003_hw_set_chain_masks(ah, 0x7, 0x7); | 850 | if (val & AR_ENT_OTP_CHAIN2_DISABLE) |
851 | ar9003_hw_set_chain_masks(ah, 0x3, 0x3); | ||
852 | else | ||
853 | ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask, | ||
854 | pCap->tx_chainmask); | ||
748 | 855 | ||
749 | /* Do Tx IQ Calibration */ | 856 | /* Do Tx IQ Calibration */ |
750 | ar9003_hw_tx_iq_cal(ah); | 857 | REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, |
751 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | 858 | AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, |
752 | udelay(5); | 859 | DELPT); |
753 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | 860 | |
861 | /* | ||
862 | * For AR9485 or later chips, TxIQ cal runs as part of | ||
863 | * AGC calibration | ||
864 | */ | ||
865 | if (AR_SREV_9485_OR_LATER(ah)) | ||
866 | txiqcal_done = true; | ||
867 | else { | ||
868 | txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); | ||
869 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | ||
870 | udelay(5); | ||
871 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
872 | } | ||
754 | 873 | ||
755 | /* Calibrate the AGC */ | 874 | /* Calibrate the AGC */ |
756 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 875 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
@@ -760,12 +879,14 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
760 | /* Poll for offset calibration complete */ | 879 | /* Poll for offset calibration complete */ |
761 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | 880 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, |
762 | 0, AH_WAIT_TIMEOUT)) { | 881 | 0, AH_WAIT_TIMEOUT)) { |
763 | ath_print(common, ATH_DBG_CALIBRATE, | 882 | ath_dbg(common, ATH_DBG_CALIBRATE, |
764 | "offset calibration failed to " | 883 | "offset calibration failed to complete in 1ms; noisy environment?\n"); |
765 | "complete in 1ms; noisy environment?\n"); | ||
766 | return false; | 884 | return false; |
767 | } | 885 | } |
768 | 886 | ||
887 | if (txiqcal_done) | ||
888 | ar9003_hw_tx_iq_cal_post_proc(ah); | ||
889 | |||
769 | /* Revert chainmasks to their original values before NF cal */ | 890 | /* Revert chainmasks to their original values before NF cal */ |
770 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | 891 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); |
771 | 892 | ||
@@ -773,19 +894,20 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
773 | 894 | ||
774 | /* Initialize list pointers */ | 895 | /* Initialize list pointers */ |
775 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 896 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
897 | ah->supp_cals = IQ_MISMATCH_CAL; | ||
776 | 898 | ||
777 | if (ar9003_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { | 899 | if (ah->supp_cals & IQ_MISMATCH_CAL) { |
778 | INIT_CAL(&ah->iq_caldata); | 900 | INIT_CAL(&ah->iq_caldata); |
779 | INSERT_CAL(ah, &ah->iq_caldata); | 901 | INSERT_CAL(ah, &ah->iq_caldata); |
780 | ath_print(common, ATH_DBG_CALIBRATE, | 902 | ath_dbg(common, ATH_DBG_CALIBRATE, |
781 | "enabling IQ Calibration.\n"); | 903 | "enabling IQ Calibration.\n"); |
782 | } | 904 | } |
783 | 905 | ||
784 | if (ar9003_hw_iscal_supported(ah, TEMP_COMP_CAL)) { | 906 | if (ah->supp_cals & TEMP_COMP_CAL) { |
785 | INIT_CAL(&ah->tempCompCalData); | 907 | INIT_CAL(&ah->tempCompCalData); |
786 | INSERT_CAL(ah, &ah->tempCompCalData); | 908 | INSERT_CAL(ah, &ah->tempCompCalData); |
787 | ath_print(common, ATH_DBG_CALIBRATE, | 909 | ath_dbg(common, ATH_DBG_CALIBRATE, |
788 | "enabling Temperature Compensation Calibration.\n"); | 910 | "enabling Temperature Compensation Calibration.\n"); |
789 | } | 911 | } |
790 | 912 | ||
791 | /* Initialize current pointer to first element in list */ | 913 | /* Initialize current pointer to first element in list */ |
@@ -808,7 +930,6 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah) | |||
808 | priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; | 930 | priv_ops->init_cal_settings = ar9003_hw_init_cal_settings; |
809 | priv_ops->init_cal = ar9003_hw_init_cal; | 931 | priv_ops->init_cal = ar9003_hw_init_cal; |
810 | priv_ops->setup_calibration = ar9003_hw_setup_calibration; | 932 | priv_ops->setup_calibration = ar9003_hw_setup_calibration; |
811 | priv_ops->iscal_supported = ar9003_hw_iscal_supported; | ||
812 | 933 | ||
813 | ops->calibrate = ar9003_hw_calibrate; | 934 | ops->calibrate = ar9003_hw_calibrate; |
814 | } | 935 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 057fb69ddf7f..ff8150e46f0e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -22,12 +22,14 @@ | |||
22 | #define COMP_CKSUM_LEN 2 | 22 | #define COMP_CKSUM_LEN 2 |
23 | 23 | ||
24 | #define AR_CH0_TOP (0x00016288) | 24 | #define AR_CH0_TOP (0x00016288) |
25 | #define AR_CH0_TOP_XPABIASLVL (0x3) | 25 | #define AR_CH0_TOP_XPABIASLVL (0x300) |
26 | #define AR_CH0_TOP_XPABIASLVL_S (8) | 26 | #define AR_CH0_TOP_XPABIASLVL_S (8) |
27 | 27 | ||
28 | #define AR_CH0_THERM (0x00016290) | 28 | #define AR_CH0_THERM (0x00016290) |
29 | #define AR_CH0_THERM_SPARE (0x3f) | 29 | #define AR_CH0_THERM_XPABIASLVL_MSB 0x3 |
30 | #define AR_CH0_THERM_SPARE_S (0) | 30 | #define AR_CH0_THERM_XPABIASLVL_MSB_S 0 |
31 | #define AR_CH0_THERM_XPASHORT2GND 0x4 | ||
32 | #define AR_CH0_THERM_XPASHORT2GND_S 2 | ||
31 | 33 | ||
32 | #define AR_SWITCH_TABLE_COM_ALL (0xffff) | 34 | #define AR_SWITCH_TABLE_COM_ALL (0xffff) |
33 | #define AR_SWITCH_TABLE_COM_ALL_S (0) | 35 | #define AR_SWITCH_TABLE_COM_ALL_S (0) |
@@ -55,6 +57,14 @@ | |||
55 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ | 57 | #define SUB_NUM_CTL_MODES_AT_5G_40 2 /* excluding HT40, EXT-OFDM */ |
56 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ | 58 | #define SUB_NUM_CTL_MODES_AT_2G_40 3 /* excluding HT40, EXT-OFDM, EXT-CCK */ |
57 | 59 | ||
60 | #define CTL(_tpower, _flag) ((_tpower) | ((_flag) << 6)) | ||
61 | |||
62 | #define EEPROM_DATA_LEN_9485 1088 | ||
63 | |||
64 | static int ar9003_hw_power_interpolate(int32_t x, | ||
65 | int32_t *px, int32_t *py, u_int16_t np); | ||
66 | |||
67 | |||
58 | static const struct ar9300_eeprom ar9300_default = { | 68 | static const struct ar9300_eeprom ar9300_default = { |
59 | .eepromVersion = 2, | 69 | .eepromVersion = 2, |
60 | .templateVersion = 2, | 70 | .templateVersion = 2, |
@@ -65,7 +75,7 @@ static const struct ar9300_eeprom ar9300_default = { | |||
65 | .regDmn = { LE16(0), LE16(0x1f) }, | 75 | .regDmn = { LE16(0), LE16(0x1f) }, |
66 | .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ | 76 | .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ |
67 | .opCapFlags = { | 77 | .opCapFlags = { |
68 | .opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A, | 78 | .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, |
69 | .eepMisc = 0, | 79 | .eepMisc = 0, |
70 | }, | 80 | }, |
71 | .rfSilent = 0, | 81 | .rfSilent = 0, |
@@ -144,13 +154,16 @@ static const struct ar9300_eeprom ar9300_default = { | |||
144 | .txEndToRxOn = 0x2, | 154 | .txEndToRxOn = 0x2, |
145 | .txFrameToXpaOn = 0xe, | 155 | .txFrameToXpaOn = 0xe, |
146 | .thresh62 = 28, | 156 | .thresh62 = 28, |
147 | .papdRateMaskHt20 = LE32(0x80c080), | 157 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), |
148 | .papdRateMaskHt40 = LE32(0x80c080), | 158 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), |
149 | .futureModal = { | 159 | .futureModal = { |
150 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 160 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
151 | 0, 0, 0, 0, 0, 0, 0, 0 | ||
152 | }, | 161 | }, |
153 | }, | 162 | }, |
163 | .base_ext1 = { | ||
164 | .ant_div_control = 0, | ||
165 | .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
166 | }, | ||
154 | .calFreqPier2G = { | 167 | .calFreqPier2G = { |
155 | FREQ2FBIN(2412, 1), | 168 | FREQ2FBIN(2412, 1), |
156 | FREQ2FBIN(2437, 1), | 169 | FREQ2FBIN(2437, 1), |
@@ -285,25 +298,25 @@ static const struct ar9300_eeprom ar9300_default = { | |||
285 | /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), | 298 | /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), |
286 | /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), | 299 | /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), |
287 | /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), | 300 | /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), |
288 | /* Data[11].ctlEdges[3].bChannel */ | 301 | /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), |
289 | FREQ2FBIN(2462, 1), | ||
290 | } | 302 | } |
291 | }, | 303 | }, |
292 | .ctlPowerData_2G = { | 304 | .ctlPowerData_2G = { |
293 | { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, | 305 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, |
294 | { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, | 306 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, |
295 | { { {60, 1}, {60, 0}, {60, 0}, {60, 1} } }, | 307 | { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, |
296 | 308 | ||
297 | { { {60, 1}, {60, 0}, {0, 0}, {0, 0} } }, | 309 | { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, |
298 | { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, | 310 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, |
299 | { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, | 311 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, |
300 | 312 | ||
301 | { { {60, 0}, {60, 1}, {60, 1}, {60, 0} } }, | 313 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, |
302 | { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, | 314 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, |
303 | { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, | 315 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, |
304 | 316 | ||
305 | { { {60, 0}, {60, 1}, {60, 0}, {60, 0} } }, | 317 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, |
306 | { { {60, 0}, {60, 1}, {60, 1}, {60, 1} } }, | 318 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, |
319 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, | ||
307 | }, | 320 | }, |
308 | .modalHeader5G = { | 321 | .modalHeader5G = { |
309 | /* 4 idle,t1,t2,b (4 bits per setting) */ | 322 | /* 4 idle,t1,t2,b (4 bits per setting) */ |
@@ -343,13 +356,20 @@ static const struct ar9300_eeprom ar9300_default = { | |||
343 | .txEndToRxOn = 0x2, | 356 | .txEndToRxOn = 0x2, |
344 | .txFrameToXpaOn = 0xe, | 357 | .txFrameToXpaOn = 0xe, |
345 | .thresh62 = 28, | 358 | .thresh62 = 28, |
346 | .papdRateMaskHt20 = LE32(0xf0e0e0), | 359 | .papdRateMaskHt20 = LE32(0x0c80c080), |
347 | .papdRateMaskHt40 = LE32(0xf0e0e0), | 360 | .papdRateMaskHt40 = LE32(0x0080c080), |
348 | .futureModal = { | 361 | .futureModal = { |
349 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 362 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
350 | 0, 0, 0, 0, 0, 0, 0, 0 | ||
351 | }, | 363 | }, |
352 | }, | 364 | }, |
365 | .base_ext2 = { | ||
366 | .tempSlopeLow = 0, | ||
367 | .tempSlopeHigh = 0, | ||
368 | .xatten1DBLow = {0, 0, 0}, | ||
369 | .xatten1MarginLow = {0, 0, 0}, | ||
370 | .xatten1DBHigh = {0, 0, 0}, | ||
371 | .xatten1MarginHigh = {0, 0, 0} | ||
372 | }, | ||
353 | .calFreqPier5G = { | 373 | .calFreqPier5G = { |
354 | FREQ2FBIN(5180, 0), | 374 | FREQ2FBIN(5180, 0), |
355 | FREQ2FBIN(5220, 0), | 375 | FREQ2FBIN(5220, 0), |
@@ -568,64 +588,2396 @@ static const struct ar9300_eeprom ar9300_default = { | |||
568 | .ctlPowerData_5G = { | 588 | .ctlPowerData_5G = { |
569 | { | 589 | { |
570 | { | 590 | { |
571 | {60, 1}, {60, 1}, {60, 1}, {60, 1}, | 591 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), |
572 | {60, 1}, {60, 1}, {60, 1}, {60, 0}, | 592 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), |
593 | } | ||
594 | }, | ||
595 | { | ||
596 | { | ||
597 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
598 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
599 | } | ||
600 | }, | ||
601 | { | ||
602 | { | ||
603 | CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
604 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
605 | } | ||
606 | }, | ||
607 | { | ||
608 | { | ||
609 | CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
610 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
611 | } | ||
612 | }, | ||
613 | { | ||
614 | { | ||
615 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
616 | CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
617 | } | ||
618 | }, | ||
619 | { | ||
620 | { | ||
621 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
622 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
623 | } | ||
624 | }, | ||
625 | { | ||
626 | { | ||
627 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
628 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
629 | } | ||
630 | }, | ||
631 | { | ||
632 | { | ||
633 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
634 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
635 | } | ||
636 | }, | ||
637 | { | ||
638 | { | ||
639 | CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), | ||
640 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
641 | } | ||
642 | }, | ||
643 | } | ||
644 | }; | ||
645 | |||
646 | static const struct ar9300_eeprom ar9300_x113 = { | ||
647 | .eepromVersion = 2, | ||
648 | .templateVersion = 6, | ||
649 | .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, | ||
650 | .custData = {"x113-023-f0000"}, | ||
651 | .baseEepHeader = { | ||
652 | .regDmn = { LE16(0), LE16(0x1f) }, | ||
653 | .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ | ||
654 | .opCapFlags = { | ||
655 | .opFlags = AR5416_OPFLAGS_11A, | ||
656 | .eepMisc = 0, | ||
657 | }, | ||
658 | .rfSilent = 0, | ||
659 | .blueToothOptions = 0, | ||
660 | .deviceCap = 0, | ||
661 | .deviceType = 5, /* takes lower byte in eeprom location */ | ||
662 | .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, | ||
663 | .params_for_tuning_caps = {0, 0}, | ||
664 | .featureEnable = 0x0d, | ||
665 | /* | ||
666 | * bit0 - enable tx temp comp - disabled | ||
667 | * bit1 - enable tx volt comp - disabled | ||
668 | * bit2 - enable fastClock - enabled | ||
669 | * bit3 - enable doubling - enabled | ||
670 | * bit4 - enable internal regulator - disabled | ||
671 | * bit5 - enable pa predistortion - disabled | ||
672 | */ | ||
673 | .miscConfiguration = 0, /* bit0 - turn down drivestrength */ | ||
674 | .eepromWriteEnableGpio = 6, | ||
675 | .wlanDisableGpio = 0, | ||
676 | .wlanLedGpio = 8, | ||
677 | .rxBandSelectGpio = 0xff, | ||
678 | .txrxgain = 0x21, | ||
679 | .swreg = 0, | ||
680 | }, | ||
681 | .modalHeader2G = { | ||
682 | /* ar9300_modal_eep_header 2g */ | ||
683 | /* 4 idle,t1,t2,b(4 bits per setting) */ | ||
684 | .antCtrlCommon = LE32(0x110), | ||
685 | /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ | ||
686 | .antCtrlCommon2 = LE32(0x44444), | ||
687 | |||
688 | /* | ||
689 | * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, | ||
690 | * rx1, rx12, b (2 bits each) | ||
691 | */ | ||
692 | .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) }, | ||
693 | |||
694 | /* | ||
695 | * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db | ||
696 | * for ar9280 (0xa20c/b20c 5:0) | ||
697 | */ | ||
698 | .xatten1DB = {0, 0, 0}, | ||
699 | |||
700 | /* | ||
701 | * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin | ||
702 | * for ar9280 (0xa20c/b20c 16:12 | ||
703 | */ | ||
704 | .xatten1Margin = {0, 0, 0}, | ||
705 | .tempSlope = 25, | ||
706 | .voltSlope = 0, | ||
707 | |||
708 | /* | ||
709 | * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur | ||
710 | * channels in usual fbin coding format | ||
711 | */ | ||
712 | .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, | ||
713 | |||
714 | /* | ||
715 | * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check | ||
716 | * if the register is per chain | ||
717 | */ | ||
718 | .noiseFloorThreshCh = {-1, 0, 0}, | ||
719 | .ob = {1, 1, 1},/* 3 chain */ | ||
720 | .db_stage2 = {1, 1, 1}, /* 3 chain */ | ||
721 | .db_stage3 = {0, 0, 0}, | ||
722 | .db_stage4 = {0, 0, 0}, | ||
723 | .xpaBiasLvl = 0, | ||
724 | .txFrameToDataStart = 0x0e, | ||
725 | .txFrameToPaOn = 0x0e, | ||
726 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ | ||
727 | .antennaGain = 0, | ||
728 | .switchSettling = 0x2c, | ||
729 | .adcDesiredSize = -30, | ||
730 | .txEndToXpaOff = 0, | ||
731 | .txEndToRxOn = 0x2, | ||
732 | .txFrameToXpaOn = 0xe, | ||
733 | .thresh62 = 28, | ||
734 | .papdRateMaskHt20 = LE32(0x0c80c080), | ||
735 | .papdRateMaskHt40 = LE32(0x0080c080), | ||
736 | .futureModal = { | ||
737 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
738 | }, | ||
739 | }, | ||
740 | .base_ext1 = { | ||
741 | .ant_div_control = 0, | ||
742 | .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
743 | }, | ||
744 | .calFreqPier2G = { | ||
745 | FREQ2FBIN(2412, 1), | ||
746 | FREQ2FBIN(2437, 1), | ||
747 | FREQ2FBIN(2472, 1), | ||
748 | }, | ||
749 | /* ar9300_cal_data_per_freq_op_loop 2g */ | ||
750 | .calPierData2G = { | ||
751 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
752 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
753 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
754 | }, | ||
755 | .calTarget_freqbin_Cck = { | ||
756 | FREQ2FBIN(2412, 1), | ||
757 | FREQ2FBIN(2472, 1), | ||
758 | }, | ||
759 | .calTarget_freqbin_2G = { | ||
760 | FREQ2FBIN(2412, 1), | ||
761 | FREQ2FBIN(2437, 1), | ||
762 | FREQ2FBIN(2472, 1) | ||
763 | }, | ||
764 | .calTarget_freqbin_2GHT20 = { | ||
765 | FREQ2FBIN(2412, 1), | ||
766 | FREQ2FBIN(2437, 1), | ||
767 | FREQ2FBIN(2472, 1) | ||
768 | }, | ||
769 | .calTarget_freqbin_2GHT40 = { | ||
770 | FREQ2FBIN(2412, 1), | ||
771 | FREQ2FBIN(2437, 1), | ||
772 | FREQ2FBIN(2472, 1) | ||
773 | }, | ||
774 | .calTargetPowerCck = { | ||
775 | /* 1L-5L,5S,11L,11S */ | ||
776 | { {34, 34, 34, 34} }, | ||
777 | { {34, 34, 34, 34} }, | ||
778 | }, | ||
779 | .calTargetPower2G = { | ||
780 | /* 6-24,36,48,54 */ | ||
781 | { {34, 34, 32, 32} }, | ||
782 | { {34, 34, 32, 32} }, | ||
783 | { {34, 34, 32, 32} }, | ||
784 | }, | ||
785 | .calTargetPower2GHT20 = { | ||
786 | { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} }, | ||
787 | { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} }, | ||
788 | { {32, 32, 32, 32, 32, 28, 32, 32, 30, 28, 0, 0, 0, 0} }, | ||
789 | }, | ||
790 | .calTargetPower2GHT40 = { | ||
791 | { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, | ||
792 | { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, | ||
793 | { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, | ||
794 | }, | ||
795 | .ctlIndex_2G = { | ||
796 | 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, | ||
797 | 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, | ||
798 | }, | ||
799 | .ctl_freqbin_2G = { | ||
800 | { | ||
801 | FREQ2FBIN(2412, 1), | ||
802 | FREQ2FBIN(2417, 1), | ||
803 | FREQ2FBIN(2457, 1), | ||
804 | FREQ2FBIN(2462, 1) | ||
805 | }, | ||
806 | { | ||
807 | FREQ2FBIN(2412, 1), | ||
808 | FREQ2FBIN(2417, 1), | ||
809 | FREQ2FBIN(2462, 1), | ||
810 | 0xFF, | ||
811 | }, | ||
812 | |||
813 | { | ||
814 | FREQ2FBIN(2412, 1), | ||
815 | FREQ2FBIN(2417, 1), | ||
816 | FREQ2FBIN(2462, 1), | ||
817 | 0xFF, | ||
818 | }, | ||
819 | { | ||
820 | FREQ2FBIN(2422, 1), | ||
821 | FREQ2FBIN(2427, 1), | ||
822 | FREQ2FBIN(2447, 1), | ||
823 | FREQ2FBIN(2452, 1) | ||
824 | }, | ||
825 | |||
826 | { | ||
827 | /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
828 | /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
829 | /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
830 | /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), | ||
831 | }, | ||
832 | |||
833 | { | ||
834 | /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
835 | /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
836 | /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
837 | 0, | ||
838 | }, | ||
839 | |||
840 | { | ||
841 | /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
842 | /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
843 | FREQ2FBIN(2472, 1), | ||
844 | 0, | ||
845 | }, | ||
846 | |||
847 | { | ||
848 | /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), | ||
849 | /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), | ||
850 | /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), | ||
851 | /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), | ||
852 | }, | ||
853 | |||
854 | { | ||
855 | /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
856 | /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
857 | /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
858 | }, | ||
859 | |||
860 | { | ||
861 | /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
862 | /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
863 | /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
864 | 0 | ||
865 | }, | ||
866 | |||
867 | { | ||
868 | /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
869 | /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
870 | /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
871 | 0 | ||
872 | }, | ||
873 | |||
874 | { | ||
875 | /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), | ||
876 | /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), | ||
877 | /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), | ||
878 | /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), | ||
879 | } | ||
880 | }, | ||
881 | .ctlPowerData_2G = { | ||
882 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
883 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
884 | { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, | ||
885 | |||
886 | { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, | ||
887 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
888 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
889 | |||
890 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, | ||
891 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
892 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
893 | |||
894 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
895 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, | ||
896 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, | ||
897 | }, | ||
898 | .modalHeader5G = { | ||
899 | /* 4 idle,t1,t2,b (4 bits per setting) */ | ||
900 | .antCtrlCommon = LE32(0x220), | ||
901 | /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ | ||
902 | .antCtrlCommon2 = LE32(0x11111), | ||
903 | /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ | ||
904 | .antCtrlChain = { | ||
905 | LE16(0x150), LE16(0x150), LE16(0x150), | ||
906 | }, | ||
907 | /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ | ||
908 | .xatten1DB = {0, 0, 0}, | ||
909 | |||
910 | /* | ||
911 | * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin | ||
912 | * for merlin (0xa20c/b20c 16:12 | ||
913 | */ | ||
914 | .xatten1Margin = {0, 0, 0}, | ||
915 | .tempSlope = 68, | ||
916 | .voltSlope = 0, | ||
917 | /* spurChans spur channels in usual fbin coding format */ | ||
918 | .spurChans = {FREQ2FBIN(5500, 0), 0, 0, 0, 0}, | ||
919 | /* noiseFloorThreshCh Check if the register is per chain */ | ||
920 | .noiseFloorThreshCh = {-1, 0, 0}, | ||
921 | .ob = {3, 3, 3}, /* 3 chain */ | ||
922 | .db_stage2 = {3, 3, 3}, /* 3 chain */ | ||
923 | .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ | ||
924 | .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ | ||
925 | .xpaBiasLvl = 0xf, | ||
926 | .txFrameToDataStart = 0x0e, | ||
927 | .txFrameToPaOn = 0x0e, | ||
928 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ | ||
929 | .antennaGain = 0, | ||
930 | .switchSettling = 0x2d, | ||
931 | .adcDesiredSize = -30, | ||
932 | .txEndToXpaOff = 0, | ||
933 | .txEndToRxOn = 0x2, | ||
934 | .txFrameToXpaOn = 0xe, | ||
935 | .thresh62 = 28, | ||
936 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), | ||
937 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), | ||
938 | .futureModal = { | ||
939 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
940 | }, | ||
941 | }, | ||
942 | .base_ext2 = { | ||
943 | .tempSlopeLow = 72, | ||
944 | .tempSlopeHigh = 105, | ||
945 | .xatten1DBLow = {0, 0, 0}, | ||
946 | .xatten1MarginLow = {0, 0, 0}, | ||
947 | .xatten1DBHigh = {0, 0, 0}, | ||
948 | .xatten1MarginHigh = {0, 0, 0} | ||
949 | }, | ||
950 | .calFreqPier5G = { | ||
951 | FREQ2FBIN(5180, 0), | ||
952 | FREQ2FBIN(5240, 0), | ||
953 | FREQ2FBIN(5320, 0), | ||
954 | FREQ2FBIN(5400, 0), | ||
955 | FREQ2FBIN(5500, 0), | ||
956 | FREQ2FBIN(5600, 0), | ||
957 | FREQ2FBIN(5745, 0), | ||
958 | FREQ2FBIN(5785, 0) | ||
959 | }, | ||
960 | .calPierData5G = { | ||
961 | { | ||
962 | {0, 0, 0, 0, 0}, | ||
963 | {0, 0, 0, 0, 0}, | ||
964 | {0, 0, 0, 0, 0}, | ||
965 | {0, 0, 0, 0, 0}, | ||
966 | {0, 0, 0, 0, 0}, | ||
967 | {0, 0, 0, 0, 0}, | ||
968 | {0, 0, 0, 0, 0}, | ||
969 | {0, 0, 0, 0, 0}, | ||
970 | }, | ||
971 | { | ||
972 | {0, 0, 0, 0, 0}, | ||
973 | {0, 0, 0, 0, 0}, | ||
974 | {0, 0, 0, 0, 0}, | ||
975 | {0, 0, 0, 0, 0}, | ||
976 | {0, 0, 0, 0, 0}, | ||
977 | {0, 0, 0, 0, 0}, | ||
978 | {0, 0, 0, 0, 0}, | ||
979 | {0, 0, 0, 0, 0}, | ||
980 | }, | ||
981 | { | ||
982 | {0, 0, 0, 0, 0}, | ||
983 | {0, 0, 0, 0, 0}, | ||
984 | {0, 0, 0, 0, 0}, | ||
985 | {0, 0, 0, 0, 0}, | ||
986 | {0, 0, 0, 0, 0}, | ||
987 | {0, 0, 0, 0, 0}, | ||
988 | {0, 0, 0, 0, 0}, | ||
989 | {0, 0, 0, 0, 0}, | ||
990 | }, | ||
991 | |||
992 | }, | ||
993 | .calTarget_freqbin_5G = { | ||
994 | FREQ2FBIN(5180, 0), | ||
995 | FREQ2FBIN(5220, 0), | ||
996 | FREQ2FBIN(5320, 0), | ||
997 | FREQ2FBIN(5400, 0), | ||
998 | FREQ2FBIN(5500, 0), | ||
999 | FREQ2FBIN(5600, 0), | ||
1000 | FREQ2FBIN(5745, 0), | ||
1001 | FREQ2FBIN(5785, 0) | ||
1002 | }, | ||
1003 | .calTarget_freqbin_5GHT20 = { | ||
1004 | FREQ2FBIN(5180, 0), | ||
1005 | FREQ2FBIN(5240, 0), | ||
1006 | FREQ2FBIN(5320, 0), | ||
1007 | FREQ2FBIN(5400, 0), | ||
1008 | FREQ2FBIN(5500, 0), | ||
1009 | FREQ2FBIN(5700, 0), | ||
1010 | FREQ2FBIN(5745, 0), | ||
1011 | FREQ2FBIN(5825, 0) | ||
1012 | }, | ||
1013 | .calTarget_freqbin_5GHT40 = { | ||
1014 | FREQ2FBIN(5190, 0), | ||
1015 | FREQ2FBIN(5230, 0), | ||
1016 | FREQ2FBIN(5320, 0), | ||
1017 | FREQ2FBIN(5410, 0), | ||
1018 | FREQ2FBIN(5510, 0), | ||
1019 | FREQ2FBIN(5670, 0), | ||
1020 | FREQ2FBIN(5755, 0), | ||
1021 | FREQ2FBIN(5825, 0) | ||
1022 | }, | ||
1023 | .calTargetPower5G = { | ||
1024 | /* 6-24,36,48,54 */ | ||
1025 | { {42, 40, 40, 34} }, | ||
1026 | { {42, 40, 40, 34} }, | ||
1027 | { {42, 40, 40, 34} }, | ||
1028 | { {42, 40, 40, 34} }, | ||
1029 | { {42, 40, 40, 34} }, | ||
1030 | { {42, 40, 40, 34} }, | ||
1031 | { {42, 40, 40, 34} }, | ||
1032 | { {42, 40, 40, 34} }, | ||
1033 | }, | ||
1034 | .calTargetPower5GHT20 = { | ||
1035 | /* | ||
1036 | * 0_8_16,1-3_9-11_17-19, | ||
1037 | * 4,5,6,7,12,13,14,15,20,21,22,23 | ||
1038 | */ | ||
1039 | { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, | ||
1040 | { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, | ||
1041 | { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, | ||
1042 | { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, | ||
1043 | { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, | ||
1044 | { {40, 40, 40, 40, 32, 28, 40, 40, 32, 28, 40, 40, 32, 20} }, | ||
1045 | { {38, 38, 38, 38, 32, 28, 38, 38, 32, 28, 38, 38, 32, 26} }, | ||
1046 | { {36, 36, 36, 36, 32, 28, 36, 36, 32, 28, 36, 36, 32, 26} }, | ||
1047 | }, | ||
1048 | .calTargetPower5GHT40 = { | ||
1049 | /* | ||
1050 | * 0_8_16,1-3_9-11_17-19, | ||
1051 | * 4,5,6,7,12,13,14,15,20,21,22,23 | ||
1052 | */ | ||
1053 | { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, | ||
1054 | { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, | ||
1055 | { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, | ||
1056 | { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, | ||
1057 | { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, | ||
1058 | { {40, 40, 40, 38, 30, 26, 40, 40, 30, 26, 40, 40, 30, 24} }, | ||
1059 | { {36, 36, 36, 36, 30, 26, 36, 36, 30, 26, 36, 36, 30, 24} }, | ||
1060 | { {34, 34, 34, 34, 30, 26, 34, 34, 30, 26, 34, 34, 30, 24} }, | ||
1061 | }, | ||
1062 | .ctlIndex_5G = { | ||
1063 | 0x10, 0x16, 0x18, 0x40, 0x46, | ||
1064 | 0x48, 0x30, 0x36, 0x38 | ||
1065 | }, | ||
1066 | .ctl_freqbin_5G = { | ||
1067 | { | ||
1068 | /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1069 | /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
1070 | /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), | ||
1071 | /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), | ||
1072 | /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), | ||
1073 | /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
1074 | /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), | ||
1075 | /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) | ||
1076 | }, | ||
1077 | { | ||
1078 | /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1079 | /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
1080 | /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), | ||
1081 | /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), | ||
1082 | /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), | ||
1083 | /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
1084 | /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), | ||
1085 | /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) | ||
1086 | }, | ||
1087 | |||
1088 | { | ||
1089 | /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), | ||
1090 | /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), | ||
1091 | /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), | ||
1092 | /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), | ||
1093 | /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), | ||
1094 | /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), | ||
1095 | /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), | ||
1096 | /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) | ||
1097 | }, | ||
1098 | |||
1099 | { | ||
1100 | /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1101 | /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), | ||
1102 | /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), | ||
1103 | /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), | ||
1104 | /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), | ||
1105 | /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
1106 | /* Data[3].ctlEdges[6].bChannel */ 0xFF, | ||
1107 | /* Data[3].ctlEdges[7].bChannel */ 0xFF, | ||
1108 | }, | ||
1109 | |||
1110 | { | ||
1111 | /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1112 | /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
1113 | /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), | ||
1114 | /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), | ||
1115 | /* Data[4].ctlEdges[4].bChannel */ 0xFF, | ||
1116 | /* Data[4].ctlEdges[5].bChannel */ 0xFF, | ||
1117 | /* Data[4].ctlEdges[6].bChannel */ 0xFF, | ||
1118 | /* Data[4].ctlEdges[7].bChannel */ 0xFF, | ||
1119 | }, | ||
1120 | |||
1121 | { | ||
1122 | /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), | ||
1123 | /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), | ||
1124 | /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), | ||
1125 | /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), | ||
1126 | /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), | ||
1127 | /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), | ||
1128 | /* Data[5].ctlEdges[6].bChannel */ 0xFF, | ||
1129 | /* Data[5].ctlEdges[7].bChannel */ 0xFF | ||
1130 | }, | ||
1131 | |||
1132 | { | ||
1133 | /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1134 | /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), | ||
1135 | /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), | ||
1136 | /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), | ||
1137 | /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), | ||
1138 | /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), | ||
1139 | /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), | ||
1140 | /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) | ||
1141 | }, | ||
1142 | |||
1143 | { | ||
1144 | /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1145 | /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
1146 | /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), | ||
1147 | /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), | ||
1148 | /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), | ||
1149 | /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
1150 | /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), | ||
1151 | /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) | ||
1152 | }, | ||
1153 | |||
1154 | { | ||
1155 | /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), | ||
1156 | /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), | ||
1157 | /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), | ||
1158 | /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), | ||
1159 | /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), | ||
1160 | /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), | ||
1161 | /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), | ||
1162 | /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) | ||
1163 | } | ||
1164 | }, | ||
1165 | .ctlPowerData_5G = { | ||
1166 | { | ||
1167 | { | ||
1168 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
1169 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
573 | } | 1170 | } |
574 | }, | 1171 | }, |
575 | { | 1172 | { |
576 | { | 1173 | { |
577 | {60, 1}, {60, 1}, {60, 1}, {60, 1}, | 1174 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), |
578 | {60, 1}, {60, 1}, {60, 1}, {60, 0}, | 1175 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), |
579 | } | 1176 | } |
580 | }, | 1177 | }, |
581 | { | 1178 | { |
582 | { | 1179 | { |
583 | {60, 0}, {60, 1}, {60, 0}, {60, 1}, | 1180 | CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), |
584 | {60, 1}, {60, 1}, {60, 1}, {60, 1}, | 1181 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), |
585 | } | 1182 | } |
586 | }, | 1183 | }, |
587 | { | 1184 | { |
588 | { | 1185 | { |
589 | {60, 0}, {60, 1}, {60, 1}, {60, 0}, | 1186 | CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), |
590 | {60, 1}, {60, 0}, {60, 0}, {60, 0}, | 1187 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), |
591 | } | 1188 | } |
592 | }, | 1189 | }, |
593 | { | 1190 | { |
594 | { | 1191 | { |
595 | {60, 1}, {60, 1}, {60, 1}, {60, 0}, | 1192 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), |
596 | {60, 0}, {60, 0}, {60, 0}, {60, 0}, | 1193 | CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), |
597 | } | 1194 | } |
598 | }, | 1195 | }, |
599 | { | 1196 | { |
600 | { | 1197 | { |
601 | {60, 1}, {60, 1}, {60, 1}, {60, 1}, | 1198 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), |
602 | {60, 1}, {60, 0}, {60, 0}, {60, 0}, | 1199 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), |
603 | } | 1200 | } |
604 | }, | 1201 | }, |
605 | { | 1202 | { |
606 | { | 1203 | { |
607 | {60, 1}, {60, 1}, {60, 1}, {60, 1}, | 1204 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), |
608 | {60, 1}, {60, 1}, {60, 1}, {60, 1}, | 1205 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), |
609 | } | 1206 | } |
610 | }, | 1207 | }, |
611 | { | 1208 | { |
612 | { | 1209 | { |
613 | {60, 1}, {60, 1}, {60, 0}, {60, 1}, | 1210 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), |
614 | {60, 1}, {60, 1}, {60, 1}, {60, 0}, | 1211 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), |
615 | } | 1212 | } |
616 | }, | 1213 | }, |
617 | { | 1214 | { |
618 | { | 1215 | { |
619 | {60, 1}, {60, 0}, {60, 1}, {60, 1}, | 1216 | CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), |
620 | {60, 1}, {60, 1}, {60, 0}, {60, 1}, | 1217 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), |
621 | } | 1218 | } |
622 | }, | 1219 | }, |
623 | } | 1220 | } |
624 | }; | 1221 | }; |
625 | 1222 | ||
1223 | |||
1224 | static const struct ar9300_eeprom ar9300_h112 = { | ||
1225 | .eepromVersion = 2, | ||
1226 | .templateVersion = 3, | ||
1227 | .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, | ||
1228 | .custData = {"h112-241-f0000"}, | ||
1229 | .baseEepHeader = { | ||
1230 | .regDmn = { LE16(0), LE16(0x1f) }, | ||
1231 | .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ | ||
1232 | .opCapFlags = { | ||
1233 | .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, | ||
1234 | .eepMisc = 0, | ||
1235 | }, | ||
1236 | .rfSilent = 0, | ||
1237 | .blueToothOptions = 0, | ||
1238 | .deviceCap = 0, | ||
1239 | .deviceType = 5, /* takes lower byte in eeprom location */ | ||
1240 | .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, | ||
1241 | .params_for_tuning_caps = {0, 0}, | ||
1242 | .featureEnable = 0x0d, | ||
1243 | /* | ||
1244 | * bit0 - enable tx temp comp - disabled | ||
1245 | * bit1 - enable tx volt comp - disabled | ||
1246 | * bit2 - enable fastClock - enabled | ||
1247 | * bit3 - enable doubling - enabled | ||
1248 | * bit4 - enable internal regulator - disabled | ||
1249 | * bit5 - enable pa predistortion - disabled | ||
1250 | */ | ||
1251 | .miscConfiguration = 0, /* bit0 - turn down drivestrength */ | ||
1252 | .eepromWriteEnableGpio = 6, | ||
1253 | .wlanDisableGpio = 0, | ||
1254 | .wlanLedGpio = 8, | ||
1255 | .rxBandSelectGpio = 0xff, | ||
1256 | .txrxgain = 0x10, | ||
1257 | .swreg = 0, | ||
1258 | }, | ||
1259 | .modalHeader2G = { | ||
1260 | /* ar9300_modal_eep_header 2g */ | ||
1261 | /* 4 idle,t1,t2,b(4 bits per setting) */ | ||
1262 | .antCtrlCommon = LE32(0x110), | ||
1263 | /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ | ||
1264 | .antCtrlCommon2 = LE32(0x44444), | ||
1265 | |||
1266 | /* | ||
1267 | * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, | ||
1268 | * rx1, rx12, b (2 bits each) | ||
1269 | */ | ||
1270 | .antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) }, | ||
1271 | |||
1272 | /* | ||
1273 | * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db | ||
1274 | * for ar9280 (0xa20c/b20c 5:0) | ||
1275 | */ | ||
1276 | .xatten1DB = {0, 0, 0}, | ||
1277 | |||
1278 | /* | ||
1279 | * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin | ||
1280 | * for ar9280 (0xa20c/b20c 16:12 | ||
1281 | */ | ||
1282 | .xatten1Margin = {0, 0, 0}, | ||
1283 | .tempSlope = 25, | ||
1284 | .voltSlope = 0, | ||
1285 | |||
1286 | /* | ||
1287 | * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur | ||
1288 | * channels in usual fbin coding format | ||
1289 | */ | ||
1290 | .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, | ||
1291 | |||
1292 | /* | ||
1293 | * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check | ||
1294 | * if the register is per chain | ||
1295 | */ | ||
1296 | .noiseFloorThreshCh = {-1, 0, 0}, | ||
1297 | .ob = {1, 1, 1},/* 3 chain */ | ||
1298 | .db_stage2 = {1, 1, 1}, /* 3 chain */ | ||
1299 | .db_stage3 = {0, 0, 0}, | ||
1300 | .db_stage4 = {0, 0, 0}, | ||
1301 | .xpaBiasLvl = 0, | ||
1302 | .txFrameToDataStart = 0x0e, | ||
1303 | .txFrameToPaOn = 0x0e, | ||
1304 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ | ||
1305 | .antennaGain = 0, | ||
1306 | .switchSettling = 0x2c, | ||
1307 | .adcDesiredSize = -30, | ||
1308 | .txEndToXpaOff = 0, | ||
1309 | .txEndToRxOn = 0x2, | ||
1310 | .txFrameToXpaOn = 0xe, | ||
1311 | .thresh62 = 28, | ||
1312 | .papdRateMaskHt20 = LE32(0x80c080), | ||
1313 | .papdRateMaskHt40 = LE32(0x80c080), | ||
1314 | .futureModal = { | ||
1315 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
1316 | }, | ||
1317 | }, | ||
1318 | .base_ext1 = { | ||
1319 | .ant_div_control = 0, | ||
1320 | .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
1321 | }, | ||
1322 | .calFreqPier2G = { | ||
1323 | FREQ2FBIN(2412, 1), | ||
1324 | FREQ2FBIN(2437, 1), | ||
1325 | FREQ2FBIN(2472, 1), | ||
1326 | }, | ||
1327 | /* ar9300_cal_data_per_freq_op_loop 2g */ | ||
1328 | .calPierData2G = { | ||
1329 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
1330 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
1331 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
1332 | }, | ||
1333 | .calTarget_freqbin_Cck = { | ||
1334 | FREQ2FBIN(2412, 1), | ||
1335 | FREQ2FBIN(2484, 1), | ||
1336 | }, | ||
1337 | .calTarget_freqbin_2G = { | ||
1338 | FREQ2FBIN(2412, 1), | ||
1339 | FREQ2FBIN(2437, 1), | ||
1340 | FREQ2FBIN(2472, 1) | ||
1341 | }, | ||
1342 | .calTarget_freqbin_2GHT20 = { | ||
1343 | FREQ2FBIN(2412, 1), | ||
1344 | FREQ2FBIN(2437, 1), | ||
1345 | FREQ2FBIN(2472, 1) | ||
1346 | }, | ||
1347 | .calTarget_freqbin_2GHT40 = { | ||
1348 | FREQ2FBIN(2412, 1), | ||
1349 | FREQ2FBIN(2437, 1), | ||
1350 | FREQ2FBIN(2472, 1) | ||
1351 | }, | ||
1352 | .calTargetPowerCck = { | ||
1353 | /* 1L-5L,5S,11L,11S */ | ||
1354 | { {34, 34, 34, 34} }, | ||
1355 | { {34, 34, 34, 34} }, | ||
1356 | }, | ||
1357 | .calTargetPower2G = { | ||
1358 | /* 6-24,36,48,54 */ | ||
1359 | { {34, 34, 32, 32} }, | ||
1360 | { {34, 34, 32, 32} }, | ||
1361 | { {34, 34, 32, 32} }, | ||
1362 | }, | ||
1363 | .calTargetPower2GHT20 = { | ||
1364 | { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} }, | ||
1365 | { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} }, | ||
1366 | { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 28, 28, 28, 24} }, | ||
1367 | }, | ||
1368 | .calTargetPower2GHT40 = { | ||
1369 | { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} }, | ||
1370 | { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} }, | ||
1371 | { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 26, 26, 26, 22} }, | ||
1372 | }, | ||
1373 | .ctlIndex_2G = { | ||
1374 | 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, | ||
1375 | 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, | ||
1376 | }, | ||
1377 | .ctl_freqbin_2G = { | ||
1378 | { | ||
1379 | FREQ2FBIN(2412, 1), | ||
1380 | FREQ2FBIN(2417, 1), | ||
1381 | FREQ2FBIN(2457, 1), | ||
1382 | FREQ2FBIN(2462, 1) | ||
1383 | }, | ||
1384 | { | ||
1385 | FREQ2FBIN(2412, 1), | ||
1386 | FREQ2FBIN(2417, 1), | ||
1387 | FREQ2FBIN(2462, 1), | ||
1388 | 0xFF, | ||
1389 | }, | ||
1390 | |||
1391 | { | ||
1392 | FREQ2FBIN(2412, 1), | ||
1393 | FREQ2FBIN(2417, 1), | ||
1394 | FREQ2FBIN(2462, 1), | ||
1395 | 0xFF, | ||
1396 | }, | ||
1397 | { | ||
1398 | FREQ2FBIN(2422, 1), | ||
1399 | FREQ2FBIN(2427, 1), | ||
1400 | FREQ2FBIN(2447, 1), | ||
1401 | FREQ2FBIN(2452, 1) | ||
1402 | }, | ||
1403 | |||
1404 | { | ||
1405 | /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
1406 | /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
1407 | /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
1408 | /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), | ||
1409 | }, | ||
1410 | |||
1411 | { | ||
1412 | /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
1413 | /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
1414 | /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
1415 | 0, | ||
1416 | }, | ||
1417 | |||
1418 | { | ||
1419 | /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
1420 | /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
1421 | FREQ2FBIN(2472, 1), | ||
1422 | 0, | ||
1423 | }, | ||
1424 | |||
1425 | { | ||
1426 | /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), | ||
1427 | /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), | ||
1428 | /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), | ||
1429 | /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), | ||
1430 | }, | ||
1431 | |||
1432 | { | ||
1433 | /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
1434 | /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
1435 | /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
1436 | }, | ||
1437 | |||
1438 | { | ||
1439 | /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
1440 | /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
1441 | /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
1442 | 0 | ||
1443 | }, | ||
1444 | |||
1445 | { | ||
1446 | /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
1447 | /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
1448 | /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
1449 | 0 | ||
1450 | }, | ||
1451 | |||
1452 | { | ||
1453 | /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), | ||
1454 | /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), | ||
1455 | /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), | ||
1456 | /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), | ||
1457 | } | ||
1458 | }, | ||
1459 | .ctlPowerData_2G = { | ||
1460 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
1461 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
1462 | { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, | ||
1463 | |||
1464 | { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, | ||
1465 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
1466 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
1467 | |||
1468 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, | ||
1469 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
1470 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
1471 | |||
1472 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
1473 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, | ||
1474 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, | ||
1475 | }, | ||
1476 | .modalHeader5G = { | ||
1477 | /* 4 idle,t1,t2,b (4 bits per setting) */ | ||
1478 | .antCtrlCommon = LE32(0x220), | ||
1479 | /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ | ||
1480 | .antCtrlCommon2 = LE32(0x44444), | ||
1481 | /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ | ||
1482 | .antCtrlChain = { | ||
1483 | LE16(0x150), LE16(0x150), LE16(0x150), | ||
1484 | }, | ||
1485 | /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ | ||
1486 | .xatten1DB = {0, 0, 0}, | ||
1487 | |||
1488 | /* | ||
1489 | * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin | ||
1490 | * for merlin (0xa20c/b20c 16:12 | ||
1491 | */ | ||
1492 | .xatten1Margin = {0, 0, 0}, | ||
1493 | .tempSlope = 45, | ||
1494 | .voltSlope = 0, | ||
1495 | /* spurChans spur channels in usual fbin coding format */ | ||
1496 | .spurChans = {0, 0, 0, 0, 0}, | ||
1497 | /* noiseFloorThreshCh Check if the register is per chain */ | ||
1498 | .noiseFloorThreshCh = {-1, 0, 0}, | ||
1499 | .ob = {3, 3, 3}, /* 3 chain */ | ||
1500 | .db_stage2 = {3, 3, 3}, /* 3 chain */ | ||
1501 | .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ | ||
1502 | .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ | ||
1503 | .xpaBiasLvl = 0, | ||
1504 | .txFrameToDataStart = 0x0e, | ||
1505 | .txFrameToPaOn = 0x0e, | ||
1506 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ | ||
1507 | .antennaGain = 0, | ||
1508 | .switchSettling = 0x2d, | ||
1509 | .adcDesiredSize = -30, | ||
1510 | .txEndToXpaOff = 0, | ||
1511 | .txEndToRxOn = 0x2, | ||
1512 | .txFrameToXpaOn = 0xe, | ||
1513 | .thresh62 = 28, | ||
1514 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), | ||
1515 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), | ||
1516 | .futureModal = { | ||
1517 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
1518 | }, | ||
1519 | }, | ||
1520 | .base_ext2 = { | ||
1521 | .tempSlopeLow = 40, | ||
1522 | .tempSlopeHigh = 50, | ||
1523 | .xatten1DBLow = {0, 0, 0}, | ||
1524 | .xatten1MarginLow = {0, 0, 0}, | ||
1525 | .xatten1DBHigh = {0, 0, 0}, | ||
1526 | .xatten1MarginHigh = {0, 0, 0} | ||
1527 | }, | ||
1528 | .calFreqPier5G = { | ||
1529 | FREQ2FBIN(5180, 0), | ||
1530 | FREQ2FBIN(5220, 0), | ||
1531 | FREQ2FBIN(5320, 0), | ||
1532 | FREQ2FBIN(5400, 0), | ||
1533 | FREQ2FBIN(5500, 0), | ||
1534 | FREQ2FBIN(5600, 0), | ||
1535 | FREQ2FBIN(5700, 0), | ||
1536 | FREQ2FBIN(5825, 0) | ||
1537 | }, | ||
1538 | .calPierData5G = { | ||
1539 | { | ||
1540 | {0, 0, 0, 0, 0}, | ||
1541 | {0, 0, 0, 0, 0}, | ||
1542 | {0, 0, 0, 0, 0}, | ||
1543 | {0, 0, 0, 0, 0}, | ||
1544 | {0, 0, 0, 0, 0}, | ||
1545 | {0, 0, 0, 0, 0}, | ||
1546 | {0, 0, 0, 0, 0}, | ||
1547 | {0, 0, 0, 0, 0}, | ||
1548 | }, | ||
1549 | { | ||
1550 | {0, 0, 0, 0, 0}, | ||
1551 | {0, 0, 0, 0, 0}, | ||
1552 | {0, 0, 0, 0, 0}, | ||
1553 | {0, 0, 0, 0, 0}, | ||
1554 | {0, 0, 0, 0, 0}, | ||
1555 | {0, 0, 0, 0, 0}, | ||
1556 | {0, 0, 0, 0, 0}, | ||
1557 | {0, 0, 0, 0, 0}, | ||
1558 | }, | ||
1559 | { | ||
1560 | {0, 0, 0, 0, 0}, | ||
1561 | {0, 0, 0, 0, 0}, | ||
1562 | {0, 0, 0, 0, 0}, | ||
1563 | {0, 0, 0, 0, 0}, | ||
1564 | {0, 0, 0, 0, 0}, | ||
1565 | {0, 0, 0, 0, 0}, | ||
1566 | {0, 0, 0, 0, 0}, | ||
1567 | {0, 0, 0, 0, 0}, | ||
1568 | }, | ||
1569 | |||
1570 | }, | ||
1571 | .calTarget_freqbin_5G = { | ||
1572 | FREQ2FBIN(5180, 0), | ||
1573 | FREQ2FBIN(5240, 0), | ||
1574 | FREQ2FBIN(5320, 0), | ||
1575 | FREQ2FBIN(5400, 0), | ||
1576 | FREQ2FBIN(5500, 0), | ||
1577 | FREQ2FBIN(5600, 0), | ||
1578 | FREQ2FBIN(5700, 0), | ||
1579 | FREQ2FBIN(5825, 0) | ||
1580 | }, | ||
1581 | .calTarget_freqbin_5GHT20 = { | ||
1582 | FREQ2FBIN(5180, 0), | ||
1583 | FREQ2FBIN(5240, 0), | ||
1584 | FREQ2FBIN(5320, 0), | ||
1585 | FREQ2FBIN(5400, 0), | ||
1586 | FREQ2FBIN(5500, 0), | ||
1587 | FREQ2FBIN(5700, 0), | ||
1588 | FREQ2FBIN(5745, 0), | ||
1589 | FREQ2FBIN(5825, 0) | ||
1590 | }, | ||
1591 | .calTarget_freqbin_5GHT40 = { | ||
1592 | FREQ2FBIN(5180, 0), | ||
1593 | FREQ2FBIN(5240, 0), | ||
1594 | FREQ2FBIN(5320, 0), | ||
1595 | FREQ2FBIN(5400, 0), | ||
1596 | FREQ2FBIN(5500, 0), | ||
1597 | FREQ2FBIN(5700, 0), | ||
1598 | FREQ2FBIN(5745, 0), | ||
1599 | FREQ2FBIN(5825, 0) | ||
1600 | }, | ||
1601 | .calTargetPower5G = { | ||
1602 | /* 6-24,36,48,54 */ | ||
1603 | { {30, 30, 28, 24} }, | ||
1604 | { {30, 30, 28, 24} }, | ||
1605 | { {30, 30, 28, 24} }, | ||
1606 | { {30, 30, 28, 24} }, | ||
1607 | { {30, 30, 28, 24} }, | ||
1608 | { {30, 30, 28, 24} }, | ||
1609 | { {30, 30, 28, 24} }, | ||
1610 | { {30, 30, 28, 24} }, | ||
1611 | }, | ||
1612 | .calTargetPower5GHT20 = { | ||
1613 | /* | ||
1614 | * 0_8_16,1-3_9-11_17-19, | ||
1615 | * 4,5,6,7,12,13,14,15,20,21,22,23 | ||
1616 | */ | ||
1617 | { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} }, | ||
1618 | { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 20, 20, 20, 16} }, | ||
1619 | { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} }, | ||
1620 | { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 18, 18, 18, 16} }, | ||
1621 | { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} }, | ||
1622 | { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 16, 16, 16, 14} }, | ||
1623 | { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} }, | ||
1624 | { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 14, 14, 14, 12} }, | ||
1625 | }, | ||
1626 | .calTargetPower5GHT40 = { | ||
1627 | /* | ||
1628 | * 0_8_16,1-3_9-11_17-19, | ||
1629 | * 4,5,6,7,12,13,14,15,20,21,22,23 | ||
1630 | */ | ||
1631 | { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} }, | ||
1632 | { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 18, 18, 18, 14} }, | ||
1633 | { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} }, | ||
1634 | { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 16, 16, 16, 12} }, | ||
1635 | { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} }, | ||
1636 | { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 14, 14, 14, 10} }, | ||
1637 | { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} }, | ||
1638 | { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 12, 12, 12, 8} }, | ||
1639 | }, | ||
1640 | .ctlIndex_5G = { | ||
1641 | 0x10, 0x16, 0x18, 0x40, 0x46, | ||
1642 | 0x48, 0x30, 0x36, 0x38 | ||
1643 | }, | ||
1644 | .ctl_freqbin_5G = { | ||
1645 | { | ||
1646 | /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1647 | /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
1648 | /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), | ||
1649 | /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), | ||
1650 | /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), | ||
1651 | /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
1652 | /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), | ||
1653 | /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) | ||
1654 | }, | ||
1655 | { | ||
1656 | /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1657 | /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
1658 | /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), | ||
1659 | /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), | ||
1660 | /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), | ||
1661 | /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
1662 | /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), | ||
1663 | /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) | ||
1664 | }, | ||
1665 | |||
1666 | { | ||
1667 | /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), | ||
1668 | /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), | ||
1669 | /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), | ||
1670 | /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), | ||
1671 | /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), | ||
1672 | /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), | ||
1673 | /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), | ||
1674 | /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) | ||
1675 | }, | ||
1676 | |||
1677 | { | ||
1678 | /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1679 | /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), | ||
1680 | /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), | ||
1681 | /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), | ||
1682 | /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), | ||
1683 | /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
1684 | /* Data[3].ctlEdges[6].bChannel */ 0xFF, | ||
1685 | /* Data[3].ctlEdges[7].bChannel */ 0xFF, | ||
1686 | }, | ||
1687 | |||
1688 | { | ||
1689 | /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1690 | /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
1691 | /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), | ||
1692 | /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), | ||
1693 | /* Data[4].ctlEdges[4].bChannel */ 0xFF, | ||
1694 | /* Data[4].ctlEdges[5].bChannel */ 0xFF, | ||
1695 | /* Data[4].ctlEdges[6].bChannel */ 0xFF, | ||
1696 | /* Data[4].ctlEdges[7].bChannel */ 0xFF, | ||
1697 | }, | ||
1698 | |||
1699 | { | ||
1700 | /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), | ||
1701 | /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), | ||
1702 | /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), | ||
1703 | /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), | ||
1704 | /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), | ||
1705 | /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), | ||
1706 | /* Data[5].ctlEdges[6].bChannel */ 0xFF, | ||
1707 | /* Data[5].ctlEdges[7].bChannel */ 0xFF | ||
1708 | }, | ||
1709 | |||
1710 | { | ||
1711 | /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1712 | /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), | ||
1713 | /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), | ||
1714 | /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), | ||
1715 | /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), | ||
1716 | /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), | ||
1717 | /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), | ||
1718 | /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) | ||
1719 | }, | ||
1720 | |||
1721 | { | ||
1722 | /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
1723 | /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
1724 | /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), | ||
1725 | /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), | ||
1726 | /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), | ||
1727 | /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
1728 | /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), | ||
1729 | /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) | ||
1730 | }, | ||
1731 | |||
1732 | { | ||
1733 | /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), | ||
1734 | /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), | ||
1735 | /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), | ||
1736 | /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), | ||
1737 | /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), | ||
1738 | /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), | ||
1739 | /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), | ||
1740 | /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) | ||
1741 | } | ||
1742 | }, | ||
1743 | .ctlPowerData_5G = { | ||
1744 | { | ||
1745 | { | ||
1746 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
1747 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
1748 | } | ||
1749 | }, | ||
1750 | { | ||
1751 | { | ||
1752 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
1753 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
1754 | } | ||
1755 | }, | ||
1756 | { | ||
1757 | { | ||
1758 | CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
1759 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
1760 | } | ||
1761 | }, | ||
1762 | { | ||
1763 | { | ||
1764 | CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
1765 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
1766 | } | ||
1767 | }, | ||
1768 | { | ||
1769 | { | ||
1770 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
1771 | CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
1772 | } | ||
1773 | }, | ||
1774 | { | ||
1775 | { | ||
1776 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
1777 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
1778 | } | ||
1779 | }, | ||
1780 | { | ||
1781 | { | ||
1782 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
1783 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
1784 | } | ||
1785 | }, | ||
1786 | { | ||
1787 | { | ||
1788 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
1789 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
1790 | } | ||
1791 | }, | ||
1792 | { | ||
1793 | { | ||
1794 | CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), | ||
1795 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
1796 | } | ||
1797 | }, | ||
1798 | } | ||
1799 | }; | ||
1800 | |||
1801 | |||
1802 | static const struct ar9300_eeprom ar9300_x112 = { | ||
1803 | .eepromVersion = 2, | ||
1804 | .templateVersion = 5, | ||
1805 | .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, | ||
1806 | .custData = {"x112-041-f0000"}, | ||
1807 | .baseEepHeader = { | ||
1808 | .regDmn = { LE16(0), LE16(0x1f) }, | ||
1809 | .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ | ||
1810 | .opCapFlags = { | ||
1811 | .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, | ||
1812 | .eepMisc = 0, | ||
1813 | }, | ||
1814 | .rfSilent = 0, | ||
1815 | .blueToothOptions = 0, | ||
1816 | .deviceCap = 0, | ||
1817 | .deviceType = 5, /* takes lower byte in eeprom location */ | ||
1818 | .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, | ||
1819 | .params_for_tuning_caps = {0, 0}, | ||
1820 | .featureEnable = 0x0d, | ||
1821 | /* | ||
1822 | * bit0 - enable tx temp comp - disabled | ||
1823 | * bit1 - enable tx volt comp - disabled | ||
1824 | * bit2 - enable fastclock - enabled | ||
1825 | * bit3 - enable doubling - enabled | ||
1826 | * bit4 - enable internal regulator - disabled | ||
1827 | * bit5 - enable pa predistortion - disabled | ||
1828 | */ | ||
1829 | .miscConfiguration = 0, /* bit0 - turn down drivestrength */ | ||
1830 | .eepromWriteEnableGpio = 6, | ||
1831 | .wlanDisableGpio = 0, | ||
1832 | .wlanLedGpio = 8, | ||
1833 | .rxBandSelectGpio = 0xff, | ||
1834 | .txrxgain = 0x0, | ||
1835 | .swreg = 0, | ||
1836 | }, | ||
1837 | .modalHeader2G = { | ||
1838 | /* ar9300_modal_eep_header 2g */ | ||
1839 | /* 4 idle,t1,t2,b(4 bits per setting) */ | ||
1840 | .antCtrlCommon = LE32(0x110), | ||
1841 | /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ | ||
1842 | .antCtrlCommon2 = LE32(0x22222), | ||
1843 | |||
1844 | /* | ||
1845 | * antCtrlChain[ar9300_max_chains]; 6 idle, t, r, | ||
1846 | * rx1, rx12, b (2 bits each) | ||
1847 | */ | ||
1848 | .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) }, | ||
1849 | |||
1850 | /* | ||
1851 | * xatten1DB[AR9300_max_chains]; 3 xatten1_db | ||
1852 | * for ar9280 (0xa20c/b20c 5:0) | ||
1853 | */ | ||
1854 | .xatten1DB = {0x1b, 0x1b, 0x1b}, | ||
1855 | |||
1856 | /* | ||
1857 | * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin | ||
1858 | * for ar9280 (0xa20c/b20c 16:12 | ||
1859 | */ | ||
1860 | .xatten1Margin = {0x15, 0x15, 0x15}, | ||
1861 | .tempSlope = 50, | ||
1862 | .voltSlope = 0, | ||
1863 | |||
1864 | /* | ||
1865 | * spurChans[OSPrey_eeprom_modal_sPURS]; spur | ||
1866 | * channels in usual fbin coding format | ||
1867 | */ | ||
1868 | .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, | ||
1869 | |||
1870 | /* | ||
1871 | * noiseFloorThreshch[ar9300_max_cHAINS]; 3 Check | ||
1872 | * if the register is per chain | ||
1873 | */ | ||
1874 | .noiseFloorThreshCh = {-1, 0, 0}, | ||
1875 | .ob = {1, 1, 1},/* 3 chain */ | ||
1876 | .db_stage2 = {1, 1, 1}, /* 3 chain */ | ||
1877 | .db_stage3 = {0, 0, 0}, | ||
1878 | .db_stage4 = {0, 0, 0}, | ||
1879 | .xpaBiasLvl = 0, | ||
1880 | .txFrameToDataStart = 0x0e, | ||
1881 | .txFrameToPaOn = 0x0e, | ||
1882 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ | ||
1883 | .antennaGain = 0, | ||
1884 | .switchSettling = 0x2c, | ||
1885 | .adcDesiredSize = -30, | ||
1886 | .txEndToXpaOff = 0, | ||
1887 | .txEndToRxOn = 0x2, | ||
1888 | .txFrameToXpaOn = 0xe, | ||
1889 | .thresh62 = 28, | ||
1890 | .papdRateMaskHt20 = LE32(0x0c80c080), | ||
1891 | .papdRateMaskHt40 = LE32(0x0080c080), | ||
1892 | .futureModal = { | ||
1893 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
1894 | }, | ||
1895 | }, | ||
1896 | .base_ext1 = { | ||
1897 | .ant_div_control = 0, | ||
1898 | .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
1899 | }, | ||
1900 | .calFreqPier2G = { | ||
1901 | FREQ2FBIN(2412, 1), | ||
1902 | FREQ2FBIN(2437, 1), | ||
1903 | FREQ2FBIN(2472, 1), | ||
1904 | }, | ||
1905 | /* ar9300_cal_data_per_freq_op_loop 2g */ | ||
1906 | .calPierData2G = { | ||
1907 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
1908 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
1909 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
1910 | }, | ||
1911 | .calTarget_freqbin_Cck = { | ||
1912 | FREQ2FBIN(2412, 1), | ||
1913 | FREQ2FBIN(2472, 1), | ||
1914 | }, | ||
1915 | .calTarget_freqbin_2G = { | ||
1916 | FREQ2FBIN(2412, 1), | ||
1917 | FREQ2FBIN(2437, 1), | ||
1918 | FREQ2FBIN(2472, 1) | ||
1919 | }, | ||
1920 | .calTarget_freqbin_2GHT20 = { | ||
1921 | FREQ2FBIN(2412, 1), | ||
1922 | FREQ2FBIN(2437, 1), | ||
1923 | FREQ2FBIN(2472, 1) | ||
1924 | }, | ||
1925 | .calTarget_freqbin_2GHT40 = { | ||
1926 | FREQ2FBIN(2412, 1), | ||
1927 | FREQ2FBIN(2437, 1), | ||
1928 | FREQ2FBIN(2472, 1) | ||
1929 | }, | ||
1930 | .calTargetPowerCck = { | ||
1931 | /* 1L-5L,5S,11L,11s */ | ||
1932 | { {38, 38, 38, 38} }, | ||
1933 | { {38, 38, 38, 38} }, | ||
1934 | }, | ||
1935 | .calTargetPower2G = { | ||
1936 | /* 6-24,36,48,54 */ | ||
1937 | { {38, 38, 36, 34} }, | ||
1938 | { {38, 38, 36, 34} }, | ||
1939 | { {38, 38, 34, 32} }, | ||
1940 | }, | ||
1941 | .calTargetPower2GHT20 = { | ||
1942 | { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} }, | ||
1943 | { {36, 36, 36, 36, 36, 34, 36, 34, 32, 30, 30, 30, 28, 26} }, | ||
1944 | { {36, 36, 36, 36, 36, 34, 34, 32, 30, 28, 28, 28, 28, 26} }, | ||
1945 | }, | ||
1946 | .calTargetPower2GHT40 = { | ||
1947 | { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} }, | ||
1948 | { {36, 36, 36, 36, 34, 32, 34, 32, 30, 28, 28, 28, 28, 24} }, | ||
1949 | { {36, 36, 36, 36, 34, 32, 32, 30, 28, 26, 26, 26, 26, 24} }, | ||
1950 | }, | ||
1951 | .ctlIndex_2G = { | ||
1952 | 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, | ||
1953 | 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, | ||
1954 | }, | ||
1955 | .ctl_freqbin_2G = { | ||
1956 | { | ||
1957 | FREQ2FBIN(2412, 1), | ||
1958 | FREQ2FBIN(2417, 1), | ||
1959 | FREQ2FBIN(2457, 1), | ||
1960 | FREQ2FBIN(2462, 1) | ||
1961 | }, | ||
1962 | { | ||
1963 | FREQ2FBIN(2412, 1), | ||
1964 | FREQ2FBIN(2417, 1), | ||
1965 | FREQ2FBIN(2462, 1), | ||
1966 | 0xFF, | ||
1967 | }, | ||
1968 | |||
1969 | { | ||
1970 | FREQ2FBIN(2412, 1), | ||
1971 | FREQ2FBIN(2417, 1), | ||
1972 | FREQ2FBIN(2462, 1), | ||
1973 | 0xFF, | ||
1974 | }, | ||
1975 | { | ||
1976 | FREQ2FBIN(2422, 1), | ||
1977 | FREQ2FBIN(2427, 1), | ||
1978 | FREQ2FBIN(2447, 1), | ||
1979 | FREQ2FBIN(2452, 1) | ||
1980 | }, | ||
1981 | |||
1982 | { | ||
1983 | /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), | ||
1984 | /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), | ||
1985 | /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), | ||
1986 | /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(2484, 1), | ||
1987 | }, | ||
1988 | |||
1989 | { | ||
1990 | /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), | ||
1991 | /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), | ||
1992 | /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), | ||
1993 | 0, | ||
1994 | }, | ||
1995 | |||
1996 | { | ||
1997 | /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), | ||
1998 | /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), | ||
1999 | FREQ2FBIN(2472, 1), | ||
2000 | 0, | ||
2001 | }, | ||
2002 | |||
2003 | { | ||
2004 | /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(2422, 1), | ||
2005 | /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(2427, 1), | ||
2006 | /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(2447, 1), | ||
2007 | /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(2462, 1), | ||
2008 | }, | ||
2009 | |||
2010 | { | ||
2011 | /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), | ||
2012 | /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), | ||
2013 | /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), | ||
2014 | }, | ||
2015 | |||
2016 | { | ||
2017 | /* Data[9].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), | ||
2018 | /* Data[9].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), | ||
2019 | /* Data[9].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), | ||
2020 | 0 | ||
2021 | }, | ||
2022 | |||
2023 | { | ||
2024 | /* Data[10].ctledges[0].bchannel */ FREQ2FBIN(2412, 1), | ||
2025 | /* Data[10].ctledges[1].bchannel */ FREQ2FBIN(2417, 1), | ||
2026 | /* Data[10].ctledges[2].bchannel */ FREQ2FBIN(2472, 1), | ||
2027 | 0 | ||
2028 | }, | ||
2029 | |||
2030 | { | ||
2031 | /* Data[11].ctledges[0].bchannel */ FREQ2FBIN(2422, 1), | ||
2032 | /* Data[11].ctledges[1].bchannel */ FREQ2FBIN(2427, 1), | ||
2033 | /* Data[11].ctledges[2].bchannel */ FREQ2FBIN(2447, 1), | ||
2034 | /* Data[11].ctledges[3].bchannel */ FREQ2FBIN(2462, 1), | ||
2035 | } | ||
2036 | }, | ||
2037 | .ctlPowerData_2G = { | ||
2038 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2039 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2040 | { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, | ||
2041 | |||
2042 | { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, | ||
2043 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2044 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2045 | |||
2046 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, | ||
2047 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2048 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2049 | |||
2050 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2051 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, | ||
2052 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, | ||
2053 | }, | ||
2054 | .modalHeader5G = { | ||
2055 | /* 4 idle,t1,t2,b (4 bits per setting) */ | ||
2056 | .antCtrlCommon = LE32(0x110), | ||
2057 | /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ | ||
2058 | .antCtrlCommon2 = LE32(0x22222), | ||
2059 | /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ | ||
2060 | .antCtrlChain = { | ||
2061 | LE16(0x0), LE16(0x0), LE16(0x0), | ||
2062 | }, | ||
2063 | /* xatten1DB 3 xatten1_db for ar9280 (0xa20c/b20c 5:0) */ | ||
2064 | .xatten1DB = {0x13, 0x19, 0x17}, | ||
2065 | |||
2066 | /* | ||
2067 | * xatten1Margin[ar9300_max_chains]; 3 xatten1_margin | ||
2068 | * for merlin (0xa20c/b20c 16:12 | ||
2069 | */ | ||
2070 | .xatten1Margin = {0x19, 0x19, 0x19}, | ||
2071 | .tempSlope = 70, | ||
2072 | .voltSlope = 15, | ||
2073 | /* spurChans spur channels in usual fbin coding format */ | ||
2074 | .spurChans = {0, 0, 0, 0, 0}, | ||
2075 | /* noiseFloorThreshch check if the register is per chain */ | ||
2076 | .noiseFloorThreshCh = {-1, 0, 0}, | ||
2077 | .ob = {3, 3, 3}, /* 3 chain */ | ||
2078 | .db_stage2 = {3, 3, 3}, /* 3 chain */ | ||
2079 | .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ | ||
2080 | .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ | ||
2081 | .xpaBiasLvl = 0, | ||
2082 | .txFrameToDataStart = 0x0e, | ||
2083 | .txFrameToPaOn = 0x0e, | ||
2084 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ | ||
2085 | .antennaGain = 0, | ||
2086 | .switchSettling = 0x2d, | ||
2087 | .adcDesiredSize = -30, | ||
2088 | .txEndToXpaOff = 0, | ||
2089 | .txEndToRxOn = 0x2, | ||
2090 | .txFrameToXpaOn = 0xe, | ||
2091 | .thresh62 = 28, | ||
2092 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), | ||
2093 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), | ||
2094 | .futureModal = { | ||
2095 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
2096 | }, | ||
2097 | }, | ||
2098 | .base_ext2 = { | ||
2099 | .tempSlopeLow = 72, | ||
2100 | .tempSlopeHigh = 105, | ||
2101 | .xatten1DBLow = {0x10, 0x14, 0x10}, | ||
2102 | .xatten1MarginLow = {0x19, 0x19 , 0x19}, | ||
2103 | .xatten1DBHigh = {0x1d, 0x20, 0x24}, | ||
2104 | .xatten1MarginHigh = {0x10, 0x10, 0x10} | ||
2105 | }, | ||
2106 | .calFreqPier5G = { | ||
2107 | FREQ2FBIN(5180, 0), | ||
2108 | FREQ2FBIN(5220, 0), | ||
2109 | FREQ2FBIN(5320, 0), | ||
2110 | FREQ2FBIN(5400, 0), | ||
2111 | FREQ2FBIN(5500, 0), | ||
2112 | FREQ2FBIN(5600, 0), | ||
2113 | FREQ2FBIN(5700, 0), | ||
2114 | FREQ2FBIN(5785, 0) | ||
2115 | }, | ||
2116 | .calPierData5G = { | ||
2117 | { | ||
2118 | {0, 0, 0, 0, 0}, | ||
2119 | {0, 0, 0, 0, 0}, | ||
2120 | {0, 0, 0, 0, 0}, | ||
2121 | {0, 0, 0, 0, 0}, | ||
2122 | {0, 0, 0, 0, 0}, | ||
2123 | {0, 0, 0, 0, 0}, | ||
2124 | {0, 0, 0, 0, 0}, | ||
2125 | {0, 0, 0, 0, 0}, | ||
2126 | }, | ||
2127 | { | ||
2128 | {0, 0, 0, 0, 0}, | ||
2129 | {0, 0, 0, 0, 0}, | ||
2130 | {0, 0, 0, 0, 0}, | ||
2131 | {0, 0, 0, 0, 0}, | ||
2132 | {0, 0, 0, 0, 0}, | ||
2133 | {0, 0, 0, 0, 0}, | ||
2134 | {0, 0, 0, 0, 0}, | ||
2135 | {0, 0, 0, 0, 0}, | ||
2136 | }, | ||
2137 | { | ||
2138 | {0, 0, 0, 0, 0}, | ||
2139 | {0, 0, 0, 0, 0}, | ||
2140 | {0, 0, 0, 0, 0}, | ||
2141 | {0, 0, 0, 0, 0}, | ||
2142 | {0, 0, 0, 0, 0}, | ||
2143 | {0, 0, 0, 0, 0}, | ||
2144 | {0, 0, 0, 0, 0}, | ||
2145 | {0, 0, 0, 0, 0}, | ||
2146 | }, | ||
2147 | |||
2148 | }, | ||
2149 | .calTarget_freqbin_5G = { | ||
2150 | FREQ2FBIN(5180, 0), | ||
2151 | FREQ2FBIN(5220, 0), | ||
2152 | FREQ2FBIN(5320, 0), | ||
2153 | FREQ2FBIN(5400, 0), | ||
2154 | FREQ2FBIN(5500, 0), | ||
2155 | FREQ2FBIN(5600, 0), | ||
2156 | FREQ2FBIN(5725, 0), | ||
2157 | FREQ2FBIN(5825, 0) | ||
2158 | }, | ||
2159 | .calTarget_freqbin_5GHT20 = { | ||
2160 | FREQ2FBIN(5180, 0), | ||
2161 | FREQ2FBIN(5220, 0), | ||
2162 | FREQ2FBIN(5320, 0), | ||
2163 | FREQ2FBIN(5400, 0), | ||
2164 | FREQ2FBIN(5500, 0), | ||
2165 | FREQ2FBIN(5600, 0), | ||
2166 | FREQ2FBIN(5725, 0), | ||
2167 | FREQ2FBIN(5825, 0) | ||
2168 | }, | ||
2169 | .calTarget_freqbin_5GHT40 = { | ||
2170 | FREQ2FBIN(5180, 0), | ||
2171 | FREQ2FBIN(5220, 0), | ||
2172 | FREQ2FBIN(5320, 0), | ||
2173 | FREQ2FBIN(5400, 0), | ||
2174 | FREQ2FBIN(5500, 0), | ||
2175 | FREQ2FBIN(5600, 0), | ||
2176 | FREQ2FBIN(5725, 0), | ||
2177 | FREQ2FBIN(5825, 0) | ||
2178 | }, | ||
2179 | .calTargetPower5G = { | ||
2180 | /* 6-24,36,48,54 */ | ||
2181 | { {32, 32, 28, 26} }, | ||
2182 | { {32, 32, 28, 26} }, | ||
2183 | { {32, 32, 28, 26} }, | ||
2184 | { {32, 32, 26, 24} }, | ||
2185 | { {32, 32, 26, 24} }, | ||
2186 | { {32, 32, 24, 22} }, | ||
2187 | { {30, 30, 24, 22} }, | ||
2188 | { {30, 30, 24, 22} }, | ||
2189 | }, | ||
2190 | .calTargetPower5GHT20 = { | ||
2191 | /* | ||
2192 | * 0_8_16,1-3_9-11_17-19, | ||
2193 | * 4,5,6,7,12,13,14,15,20,21,22,23 | ||
2194 | */ | ||
2195 | { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} }, | ||
2196 | { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} }, | ||
2197 | { {32, 32, 32, 32, 28, 26, 32, 28, 26, 24, 24, 24, 22, 22} }, | ||
2198 | { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 22, 22, 20, 20} }, | ||
2199 | { {32, 32, 32, 32, 28, 26, 32, 26, 24, 22, 20, 18, 16, 16} }, | ||
2200 | { {32, 32, 32, 32, 28, 26, 32, 24, 20, 16, 18, 16, 14, 14} }, | ||
2201 | { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} }, | ||
2202 | { {30, 30, 30, 30, 28, 26, 30, 24, 20, 16, 18, 16, 14, 14} }, | ||
2203 | }, | ||
2204 | .calTargetPower5GHT40 = { | ||
2205 | /* | ||
2206 | * 0_8_16,1-3_9-11_17-19, | ||
2207 | * 4,5,6,7,12,13,14,15,20,21,22,23 | ||
2208 | */ | ||
2209 | { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} }, | ||
2210 | { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} }, | ||
2211 | { {32, 32, 32, 30, 28, 26, 30, 28, 26, 24, 24, 24, 22, 22} }, | ||
2212 | { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 22, 22, 20, 20} }, | ||
2213 | { {32, 32, 32, 30, 28, 26, 30, 26, 24, 22, 20, 18, 16, 16} }, | ||
2214 | { {32, 32, 32, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} }, | ||
2215 | { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} }, | ||
2216 | { {30, 30, 30, 30, 28, 26, 30, 22, 20, 16, 18, 16, 14, 14} }, | ||
2217 | }, | ||
2218 | .ctlIndex_5G = { | ||
2219 | 0x10, 0x16, 0x18, 0x40, 0x46, | ||
2220 | 0x48, 0x30, 0x36, 0x38 | ||
2221 | }, | ||
2222 | .ctl_freqbin_5G = { | ||
2223 | { | ||
2224 | /* Data[0].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), | ||
2225 | /* Data[0].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), | ||
2226 | /* Data[0].ctledges[2].bchannel */ FREQ2FBIN(5280, 0), | ||
2227 | /* Data[0].ctledges[3].bchannel */ FREQ2FBIN(5500, 0), | ||
2228 | /* Data[0].ctledges[4].bchannel */ FREQ2FBIN(5600, 0), | ||
2229 | /* Data[0].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), | ||
2230 | /* Data[0].ctledges[6].bchannel */ FREQ2FBIN(5745, 0), | ||
2231 | /* Data[0].ctledges[7].bchannel */ FREQ2FBIN(5825, 0) | ||
2232 | }, | ||
2233 | { | ||
2234 | /* Data[1].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), | ||
2235 | /* Data[1].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), | ||
2236 | /* Data[1].ctledges[2].bchannel */ FREQ2FBIN(5280, 0), | ||
2237 | /* Data[1].ctledges[3].bchannel */ FREQ2FBIN(5500, 0), | ||
2238 | /* Data[1].ctledges[4].bchannel */ FREQ2FBIN(5520, 0), | ||
2239 | /* Data[1].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), | ||
2240 | /* Data[1].ctledges[6].bchannel */ FREQ2FBIN(5745, 0), | ||
2241 | /* Data[1].ctledges[7].bchannel */ FREQ2FBIN(5825, 0) | ||
2242 | }, | ||
2243 | |||
2244 | { | ||
2245 | /* Data[2].ctledges[0].bchannel */ FREQ2FBIN(5190, 0), | ||
2246 | /* Data[2].ctledges[1].bchannel */ FREQ2FBIN(5230, 0), | ||
2247 | /* Data[2].ctledges[2].bchannel */ FREQ2FBIN(5270, 0), | ||
2248 | /* Data[2].ctledges[3].bchannel */ FREQ2FBIN(5310, 0), | ||
2249 | /* Data[2].ctledges[4].bchannel */ FREQ2FBIN(5510, 0), | ||
2250 | /* Data[2].ctledges[5].bchannel */ FREQ2FBIN(5550, 0), | ||
2251 | /* Data[2].ctledges[6].bchannel */ FREQ2FBIN(5670, 0), | ||
2252 | /* Data[2].ctledges[7].bchannel */ FREQ2FBIN(5755, 0) | ||
2253 | }, | ||
2254 | |||
2255 | { | ||
2256 | /* Data[3].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), | ||
2257 | /* Data[3].ctledges[1].bchannel */ FREQ2FBIN(5200, 0), | ||
2258 | /* Data[3].ctledges[2].bchannel */ FREQ2FBIN(5260, 0), | ||
2259 | /* Data[3].ctledges[3].bchannel */ FREQ2FBIN(5320, 0), | ||
2260 | /* Data[3].ctledges[4].bchannel */ FREQ2FBIN(5500, 0), | ||
2261 | /* Data[3].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), | ||
2262 | /* Data[3].ctledges[6].bchannel */ 0xFF, | ||
2263 | /* Data[3].ctledges[7].bchannel */ 0xFF, | ||
2264 | }, | ||
2265 | |||
2266 | { | ||
2267 | /* Data[4].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), | ||
2268 | /* Data[4].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), | ||
2269 | /* Data[4].ctledges[2].bchannel */ FREQ2FBIN(5500, 0), | ||
2270 | /* Data[4].ctledges[3].bchannel */ FREQ2FBIN(5700, 0), | ||
2271 | /* Data[4].ctledges[4].bchannel */ 0xFF, | ||
2272 | /* Data[4].ctledges[5].bchannel */ 0xFF, | ||
2273 | /* Data[4].ctledges[6].bchannel */ 0xFF, | ||
2274 | /* Data[4].ctledges[7].bchannel */ 0xFF, | ||
2275 | }, | ||
2276 | |||
2277 | { | ||
2278 | /* Data[5].ctledges[0].bchannel */ FREQ2FBIN(5190, 0), | ||
2279 | /* Data[5].ctledges[1].bchannel */ FREQ2FBIN(5270, 0), | ||
2280 | /* Data[5].ctledges[2].bchannel */ FREQ2FBIN(5310, 0), | ||
2281 | /* Data[5].ctledges[3].bchannel */ FREQ2FBIN(5510, 0), | ||
2282 | /* Data[5].ctledges[4].bchannel */ FREQ2FBIN(5590, 0), | ||
2283 | /* Data[5].ctledges[5].bchannel */ FREQ2FBIN(5670, 0), | ||
2284 | /* Data[5].ctledges[6].bchannel */ 0xFF, | ||
2285 | /* Data[5].ctledges[7].bchannel */ 0xFF | ||
2286 | }, | ||
2287 | |||
2288 | { | ||
2289 | /* Data[6].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), | ||
2290 | /* Data[6].ctledges[1].bchannel */ FREQ2FBIN(5200, 0), | ||
2291 | /* Data[6].ctledges[2].bchannel */ FREQ2FBIN(5220, 0), | ||
2292 | /* Data[6].ctledges[3].bchannel */ FREQ2FBIN(5260, 0), | ||
2293 | /* Data[6].ctledges[4].bchannel */ FREQ2FBIN(5500, 0), | ||
2294 | /* Data[6].ctledges[5].bchannel */ FREQ2FBIN(5600, 0), | ||
2295 | /* Data[6].ctledges[6].bchannel */ FREQ2FBIN(5700, 0), | ||
2296 | /* Data[6].ctledges[7].bchannel */ FREQ2FBIN(5745, 0) | ||
2297 | }, | ||
2298 | |||
2299 | { | ||
2300 | /* Data[7].ctledges[0].bchannel */ FREQ2FBIN(5180, 0), | ||
2301 | /* Data[7].ctledges[1].bchannel */ FREQ2FBIN(5260, 0), | ||
2302 | /* Data[7].ctledges[2].bchannel */ FREQ2FBIN(5320, 0), | ||
2303 | /* Data[7].ctledges[3].bchannel */ FREQ2FBIN(5500, 0), | ||
2304 | /* Data[7].ctledges[4].bchannel */ FREQ2FBIN(5560, 0), | ||
2305 | /* Data[7].ctledges[5].bchannel */ FREQ2FBIN(5700, 0), | ||
2306 | /* Data[7].ctledges[6].bchannel */ FREQ2FBIN(5745, 0), | ||
2307 | /* Data[7].ctledges[7].bchannel */ FREQ2FBIN(5825, 0) | ||
2308 | }, | ||
2309 | |||
2310 | { | ||
2311 | /* Data[8].ctledges[0].bchannel */ FREQ2FBIN(5190, 0), | ||
2312 | /* Data[8].ctledges[1].bchannel */ FREQ2FBIN(5230, 0), | ||
2313 | /* Data[8].ctledges[2].bchannel */ FREQ2FBIN(5270, 0), | ||
2314 | /* Data[8].ctledges[3].bchannel */ FREQ2FBIN(5510, 0), | ||
2315 | /* Data[8].ctledges[4].bchannel */ FREQ2FBIN(5550, 0), | ||
2316 | /* Data[8].ctledges[5].bchannel */ FREQ2FBIN(5670, 0), | ||
2317 | /* Data[8].ctledges[6].bchannel */ FREQ2FBIN(5755, 0), | ||
2318 | /* Data[8].ctledges[7].bchannel */ FREQ2FBIN(5795, 0) | ||
2319 | } | ||
2320 | }, | ||
2321 | .ctlPowerData_5G = { | ||
2322 | { | ||
2323 | { | ||
2324 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2325 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2326 | } | ||
2327 | }, | ||
2328 | { | ||
2329 | { | ||
2330 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2331 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2332 | } | ||
2333 | }, | ||
2334 | { | ||
2335 | { | ||
2336 | CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
2337 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2338 | } | ||
2339 | }, | ||
2340 | { | ||
2341 | { | ||
2342 | CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2343 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
2344 | } | ||
2345 | }, | ||
2346 | { | ||
2347 | { | ||
2348 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2349 | CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
2350 | } | ||
2351 | }, | ||
2352 | { | ||
2353 | { | ||
2354 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2355 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
2356 | } | ||
2357 | }, | ||
2358 | { | ||
2359 | { | ||
2360 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2361 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2362 | } | ||
2363 | }, | ||
2364 | { | ||
2365 | { | ||
2366 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
2367 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2368 | } | ||
2369 | }, | ||
2370 | { | ||
2371 | { | ||
2372 | CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), | ||
2373 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
2374 | } | ||
2375 | }, | ||
2376 | } | ||
2377 | }; | ||
2378 | |||
2379 | static const struct ar9300_eeprom ar9300_h116 = { | ||
2380 | .eepromVersion = 2, | ||
2381 | .templateVersion = 4, | ||
2382 | .macAddr = {0x00, 0x03, 0x7f, 0x0, 0x0, 0x0}, | ||
2383 | .custData = {"h116-041-f0000"}, | ||
2384 | .baseEepHeader = { | ||
2385 | .regDmn = { LE16(0), LE16(0x1f) }, | ||
2386 | .txrxMask = 0x33, /* 4 bits tx and 4 bits rx */ | ||
2387 | .opCapFlags = { | ||
2388 | .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, | ||
2389 | .eepMisc = 0, | ||
2390 | }, | ||
2391 | .rfSilent = 0, | ||
2392 | .blueToothOptions = 0, | ||
2393 | .deviceCap = 0, | ||
2394 | .deviceType = 5, /* takes lower byte in eeprom location */ | ||
2395 | .pwrTableOffset = AR9300_PWR_TABLE_OFFSET, | ||
2396 | .params_for_tuning_caps = {0, 0}, | ||
2397 | .featureEnable = 0x0d, | ||
2398 | /* | ||
2399 | * bit0 - enable tx temp comp - disabled | ||
2400 | * bit1 - enable tx volt comp - disabled | ||
2401 | * bit2 - enable fastClock - enabled | ||
2402 | * bit3 - enable doubling - enabled | ||
2403 | * bit4 - enable internal regulator - disabled | ||
2404 | * bit5 - enable pa predistortion - disabled | ||
2405 | */ | ||
2406 | .miscConfiguration = 0, /* bit0 - turn down drivestrength */ | ||
2407 | .eepromWriteEnableGpio = 6, | ||
2408 | .wlanDisableGpio = 0, | ||
2409 | .wlanLedGpio = 8, | ||
2410 | .rxBandSelectGpio = 0xff, | ||
2411 | .txrxgain = 0x10, | ||
2412 | .swreg = 0, | ||
2413 | }, | ||
2414 | .modalHeader2G = { | ||
2415 | /* ar9300_modal_eep_header 2g */ | ||
2416 | /* 4 idle,t1,t2,b(4 bits per setting) */ | ||
2417 | .antCtrlCommon = LE32(0x110), | ||
2418 | /* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */ | ||
2419 | .antCtrlCommon2 = LE32(0x44444), | ||
2420 | |||
2421 | /* | ||
2422 | * antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r, | ||
2423 | * rx1, rx12, b (2 bits each) | ||
2424 | */ | ||
2425 | .antCtrlChain = { LE16(0x10), LE16(0x10), LE16(0x10) }, | ||
2426 | |||
2427 | /* | ||
2428 | * xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db | ||
2429 | * for ar9280 (0xa20c/b20c 5:0) | ||
2430 | */ | ||
2431 | .xatten1DB = {0x1f, 0x1f, 0x1f}, | ||
2432 | |||
2433 | /* | ||
2434 | * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin | ||
2435 | * for ar9280 (0xa20c/b20c 16:12 | ||
2436 | */ | ||
2437 | .xatten1Margin = {0x12, 0x12, 0x12}, | ||
2438 | .tempSlope = 25, | ||
2439 | .voltSlope = 0, | ||
2440 | |||
2441 | /* | ||
2442 | * spurChans[OSPREY_EEPROM_MODAL_SPURS]; spur | ||
2443 | * channels in usual fbin coding format | ||
2444 | */ | ||
2445 | .spurChans = {FREQ2FBIN(2464, 1), 0, 0, 0, 0}, | ||
2446 | |||
2447 | /* | ||
2448 | * noiseFloorThreshCh[AR9300_MAX_CHAINS]; 3 Check | ||
2449 | * if the register is per chain | ||
2450 | */ | ||
2451 | .noiseFloorThreshCh = {-1, 0, 0}, | ||
2452 | .ob = {1, 1, 1},/* 3 chain */ | ||
2453 | .db_stage2 = {1, 1, 1}, /* 3 chain */ | ||
2454 | .db_stage3 = {0, 0, 0}, | ||
2455 | .db_stage4 = {0, 0, 0}, | ||
2456 | .xpaBiasLvl = 0, | ||
2457 | .txFrameToDataStart = 0x0e, | ||
2458 | .txFrameToPaOn = 0x0e, | ||
2459 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ | ||
2460 | .antennaGain = 0, | ||
2461 | .switchSettling = 0x2c, | ||
2462 | .adcDesiredSize = -30, | ||
2463 | .txEndToXpaOff = 0, | ||
2464 | .txEndToRxOn = 0x2, | ||
2465 | .txFrameToXpaOn = 0xe, | ||
2466 | .thresh62 = 28, | ||
2467 | .papdRateMaskHt20 = LE32(0x0c80C080), | ||
2468 | .papdRateMaskHt40 = LE32(0x0080C080), | ||
2469 | .futureModal = { | ||
2470 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
2471 | }, | ||
2472 | }, | ||
2473 | .base_ext1 = { | ||
2474 | .ant_div_control = 0, | ||
2475 | .future = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | ||
2476 | }, | ||
2477 | .calFreqPier2G = { | ||
2478 | FREQ2FBIN(2412, 1), | ||
2479 | FREQ2FBIN(2437, 1), | ||
2480 | FREQ2FBIN(2472, 1), | ||
2481 | }, | ||
2482 | /* ar9300_cal_data_per_freq_op_loop 2g */ | ||
2483 | .calPierData2G = { | ||
2484 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
2485 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
2486 | { {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0} }, | ||
2487 | }, | ||
2488 | .calTarget_freqbin_Cck = { | ||
2489 | FREQ2FBIN(2412, 1), | ||
2490 | FREQ2FBIN(2472, 1), | ||
2491 | }, | ||
2492 | .calTarget_freqbin_2G = { | ||
2493 | FREQ2FBIN(2412, 1), | ||
2494 | FREQ2FBIN(2437, 1), | ||
2495 | FREQ2FBIN(2472, 1) | ||
2496 | }, | ||
2497 | .calTarget_freqbin_2GHT20 = { | ||
2498 | FREQ2FBIN(2412, 1), | ||
2499 | FREQ2FBIN(2437, 1), | ||
2500 | FREQ2FBIN(2472, 1) | ||
2501 | }, | ||
2502 | .calTarget_freqbin_2GHT40 = { | ||
2503 | FREQ2FBIN(2412, 1), | ||
2504 | FREQ2FBIN(2437, 1), | ||
2505 | FREQ2FBIN(2472, 1) | ||
2506 | }, | ||
2507 | .calTargetPowerCck = { | ||
2508 | /* 1L-5L,5S,11L,11S */ | ||
2509 | { {34, 34, 34, 34} }, | ||
2510 | { {34, 34, 34, 34} }, | ||
2511 | }, | ||
2512 | .calTargetPower2G = { | ||
2513 | /* 6-24,36,48,54 */ | ||
2514 | { {34, 34, 32, 32} }, | ||
2515 | { {34, 34, 32, 32} }, | ||
2516 | { {34, 34, 32, 32} }, | ||
2517 | }, | ||
2518 | .calTargetPower2GHT20 = { | ||
2519 | { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} }, | ||
2520 | { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} }, | ||
2521 | { {32, 32, 32, 32, 32, 30, 32, 32, 30, 28, 0, 0, 0, 0} }, | ||
2522 | }, | ||
2523 | .calTargetPower2GHT40 = { | ||
2524 | { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, | ||
2525 | { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, | ||
2526 | { {30, 30, 30, 30, 30, 28, 30, 30, 28, 26, 0, 0, 0, 0} }, | ||
2527 | }, | ||
2528 | .ctlIndex_2G = { | ||
2529 | 0x11, 0x12, 0x15, 0x17, 0x41, 0x42, | ||
2530 | 0x45, 0x47, 0x31, 0x32, 0x35, 0x37, | ||
2531 | }, | ||
2532 | .ctl_freqbin_2G = { | ||
2533 | { | ||
2534 | FREQ2FBIN(2412, 1), | ||
2535 | FREQ2FBIN(2417, 1), | ||
2536 | FREQ2FBIN(2457, 1), | ||
2537 | FREQ2FBIN(2462, 1) | ||
2538 | }, | ||
2539 | { | ||
2540 | FREQ2FBIN(2412, 1), | ||
2541 | FREQ2FBIN(2417, 1), | ||
2542 | FREQ2FBIN(2462, 1), | ||
2543 | 0xFF, | ||
2544 | }, | ||
2545 | |||
2546 | { | ||
2547 | FREQ2FBIN(2412, 1), | ||
2548 | FREQ2FBIN(2417, 1), | ||
2549 | FREQ2FBIN(2462, 1), | ||
2550 | 0xFF, | ||
2551 | }, | ||
2552 | { | ||
2553 | FREQ2FBIN(2422, 1), | ||
2554 | FREQ2FBIN(2427, 1), | ||
2555 | FREQ2FBIN(2447, 1), | ||
2556 | FREQ2FBIN(2452, 1) | ||
2557 | }, | ||
2558 | |||
2559 | { | ||
2560 | /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
2561 | /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
2562 | /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
2563 | /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(2484, 1), | ||
2564 | }, | ||
2565 | |||
2566 | { | ||
2567 | /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
2568 | /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
2569 | /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
2570 | 0, | ||
2571 | }, | ||
2572 | |||
2573 | { | ||
2574 | /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
2575 | /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
2576 | FREQ2FBIN(2472, 1), | ||
2577 | 0, | ||
2578 | }, | ||
2579 | |||
2580 | { | ||
2581 | /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), | ||
2582 | /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), | ||
2583 | /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), | ||
2584 | /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), | ||
2585 | }, | ||
2586 | |||
2587 | { | ||
2588 | /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
2589 | /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
2590 | /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
2591 | }, | ||
2592 | |||
2593 | { | ||
2594 | /* Data[9].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
2595 | /* Data[9].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
2596 | /* Data[9].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
2597 | 0 | ||
2598 | }, | ||
2599 | |||
2600 | { | ||
2601 | /* Data[10].ctlEdges[0].bChannel */ FREQ2FBIN(2412, 1), | ||
2602 | /* Data[10].ctlEdges[1].bChannel */ FREQ2FBIN(2417, 1), | ||
2603 | /* Data[10].ctlEdges[2].bChannel */ FREQ2FBIN(2472, 1), | ||
2604 | 0 | ||
2605 | }, | ||
2606 | |||
2607 | { | ||
2608 | /* Data[11].ctlEdges[0].bChannel */ FREQ2FBIN(2422, 1), | ||
2609 | /* Data[11].ctlEdges[1].bChannel */ FREQ2FBIN(2427, 1), | ||
2610 | /* Data[11].ctlEdges[2].bChannel */ FREQ2FBIN(2447, 1), | ||
2611 | /* Data[11].ctlEdges[3].bChannel */ FREQ2FBIN(2462, 1), | ||
2612 | } | ||
2613 | }, | ||
2614 | .ctlPowerData_2G = { | ||
2615 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2616 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2617 | { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } }, | ||
2618 | |||
2619 | { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } }, | ||
2620 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2621 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2622 | |||
2623 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0) } }, | ||
2624 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2625 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2626 | |||
2627 | { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } }, | ||
2628 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, | ||
2629 | { { CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 1) } }, | ||
2630 | }, | ||
2631 | .modalHeader5G = { | ||
2632 | /* 4 idle,t1,t2,b (4 bits per setting) */ | ||
2633 | .antCtrlCommon = LE32(0x220), | ||
2634 | /* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */ | ||
2635 | .antCtrlCommon2 = LE32(0x44444), | ||
2636 | /* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */ | ||
2637 | .antCtrlChain = { | ||
2638 | LE16(0x150), LE16(0x150), LE16(0x150), | ||
2639 | }, | ||
2640 | /* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */ | ||
2641 | .xatten1DB = {0x19, 0x19, 0x19}, | ||
2642 | |||
2643 | /* | ||
2644 | * xatten1Margin[AR9300_MAX_CHAINS]; 3 xatten1_margin | ||
2645 | * for merlin (0xa20c/b20c 16:12 | ||
2646 | */ | ||
2647 | .xatten1Margin = {0x14, 0x14, 0x14}, | ||
2648 | .tempSlope = 70, | ||
2649 | .voltSlope = 0, | ||
2650 | /* spurChans spur channels in usual fbin coding format */ | ||
2651 | .spurChans = {0, 0, 0, 0, 0}, | ||
2652 | /* noiseFloorThreshCh Check if the register is per chain */ | ||
2653 | .noiseFloorThreshCh = {-1, 0, 0}, | ||
2654 | .ob = {3, 3, 3}, /* 3 chain */ | ||
2655 | .db_stage2 = {3, 3, 3}, /* 3 chain */ | ||
2656 | .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ | ||
2657 | .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ | ||
2658 | .xpaBiasLvl = 0, | ||
2659 | .txFrameToDataStart = 0x0e, | ||
2660 | .txFrameToPaOn = 0x0e, | ||
2661 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ | ||
2662 | .antennaGain = 0, | ||
2663 | .switchSettling = 0x2d, | ||
2664 | .adcDesiredSize = -30, | ||
2665 | .txEndToXpaOff = 0, | ||
2666 | .txEndToRxOn = 0x2, | ||
2667 | .txFrameToXpaOn = 0xe, | ||
2668 | .thresh62 = 28, | ||
2669 | .papdRateMaskHt20 = LE32(0x0cf0e0e0), | ||
2670 | .papdRateMaskHt40 = LE32(0x6cf0e0e0), | ||
2671 | .futureModal = { | ||
2672 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
2673 | }, | ||
2674 | }, | ||
2675 | .base_ext2 = { | ||
2676 | .tempSlopeLow = 35, | ||
2677 | .tempSlopeHigh = 50, | ||
2678 | .xatten1DBLow = {0, 0, 0}, | ||
2679 | .xatten1MarginLow = {0, 0, 0}, | ||
2680 | .xatten1DBHigh = {0, 0, 0}, | ||
2681 | .xatten1MarginHigh = {0, 0, 0} | ||
2682 | }, | ||
2683 | .calFreqPier5G = { | ||
2684 | FREQ2FBIN(5180, 0), | ||
2685 | FREQ2FBIN(5220, 0), | ||
2686 | FREQ2FBIN(5320, 0), | ||
2687 | FREQ2FBIN(5400, 0), | ||
2688 | FREQ2FBIN(5500, 0), | ||
2689 | FREQ2FBIN(5600, 0), | ||
2690 | FREQ2FBIN(5700, 0), | ||
2691 | FREQ2FBIN(5785, 0) | ||
2692 | }, | ||
2693 | .calPierData5G = { | ||
2694 | { | ||
2695 | {0, 0, 0, 0, 0}, | ||
2696 | {0, 0, 0, 0, 0}, | ||
2697 | {0, 0, 0, 0, 0}, | ||
2698 | {0, 0, 0, 0, 0}, | ||
2699 | {0, 0, 0, 0, 0}, | ||
2700 | {0, 0, 0, 0, 0}, | ||
2701 | {0, 0, 0, 0, 0}, | ||
2702 | {0, 0, 0, 0, 0}, | ||
2703 | }, | ||
2704 | { | ||
2705 | {0, 0, 0, 0, 0}, | ||
2706 | {0, 0, 0, 0, 0}, | ||
2707 | {0, 0, 0, 0, 0}, | ||
2708 | {0, 0, 0, 0, 0}, | ||
2709 | {0, 0, 0, 0, 0}, | ||
2710 | {0, 0, 0, 0, 0}, | ||
2711 | {0, 0, 0, 0, 0}, | ||
2712 | {0, 0, 0, 0, 0}, | ||
2713 | }, | ||
2714 | { | ||
2715 | {0, 0, 0, 0, 0}, | ||
2716 | {0, 0, 0, 0, 0}, | ||
2717 | {0, 0, 0, 0, 0}, | ||
2718 | {0, 0, 0, 0, 0}, | ||
2719 | {0, 0, 0, 0, 0}, | ||
2720 | {0, 0, 0, 0, 0}, | ||
2721 | {0, 0, 0, 0, 0}, | ||
2722 | {0, 0, 0, 0, 0}, | ||
2723 | }, | ||
2724 | |||
2725 | }, | ||
2726 | .calTarget_freqbin_5G = { | ||
2727 | FREQ2FBIN(5180, 0), | ||
2728 | FREQ2FBIN(5240, 0), | ||
2729 | FREQ2FBIN(5320, 0), | ||
2730 | FREQ2FBIN(5400, 0), | ||
2731 | FREQ2FBIN(5500, 0), | ||
2732 | FREQ2FBIN(5600, 0), | ||
2733 | FREQ2FBIN(5700, 0), | ||
2734 | FREQ2FBIN(5825, 0) | ||
2735 | }, | ||
2736 | .calTarget_freqbin_5GHT20 = { | ||
2737 | FREQ2FBIN(5180, 0), | ||
2738 | FREQ2FBIN(5240, 0), | ||
2739 | FREQ2FBIN(5320, 0), | ||
2740 | FREQ2FBIN(5400, 0), | ||
2741 | FREQ2FBIN(5500, 0), | ||
2742 | FREQ2FBIN(5700, 0), | ||
2743 | FREQ2FBIN(5745, 0), | ||
2744 | FREQ2FBIN(5825, 0) | ||
2745 | }, | ||
2746 | .calTarget_freqbin_5GHT40 = { | ||
2747 | FREQ2FBIN(5180, 0), | ||
2748 | FREQ2FBIN(5240, 0), | ||
2749 | FREQ2FBIN(5320, 0), | ||
2750 | FREQ2FBIN(5400, 0), | ||
2751 | FREQ2FBIN(5500, 0), | ||
2752 | FREQ2FBIN(5700, 0), | ||
2753 | FREQ2FBIN(5745, 0), | ||
2754 | FREQ2FBIN(5825, 0) | ||
2755 | }, | ||
2756 | .calTargetPower5G = { | ||
2757 | /* 6-24,36,48,54 */ | ||
2758 | { {30, 30, 28, 24} }, | ||
2759 | { {30, 30, 28, 24} }, | ||
2760 | { {30, 30, 28, 24} }, | ||
2761 | { {30, 30, 28, 24} }, | ||
2762 | { {30, 30, 28, 24} }, | ||
2763 | { {30, 30, 28, 24} }, | ||
2764 | { {30, 30, 28, 24} }, | ||
2765 | { {30, 30, 28, 24} }, | ||
2766 | }, | ||
2767 | .calTargetPower5GHT20 = { | ||
2768 | /* | ||
2769 | * 0_8_16,1-3_9-11_17-19, | ||
2770 | * 4,5,6,7,12,13,14,15,20,21,22,23 | ||
2771 | */ | ||
2772 | { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} }, | ||
2773 | { {30, 30, 30, 28, 24, 20, 30, 28, 24, 20, 0, 0, 0, 0} }, | ||
2774 | { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} }, | ||
2775 | { {30, 30, 30, 26, 22, 18, 30, 26, 22, 18, 0, 0, 0, 0} }, | ||
2776 | { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} }, | ||
2777 | { {30, 30, 30, 24, 20, 16, 30, 24, 20, 16, 0, 0, 0, 0} }, | ||
2778 | { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} }, | ||
2779 | { {30, 30, 30, 22, 18, 14, 30, 22, 18, 14, 0, 0, 0, 0} }, | ||
2780 | }, | ||
2781 | .calTargetPower5GHT40 = { | ||
2782 | /* | ||
2783 | * 0_8_16,1-3_9-11_17-19, | ||
2784 | * 4,5,6,7,12,13,14,15,20,21,22,23 | ||
2785 | */ | ||
2786 | { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} }, | ||
2787 | { {28, 28, 28, 26, 22, 18, 28, 26, 22, 18, 0, 0, 0, 0} }, | ||
2788 | { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} }, | ||
2789 | { {28, 28, 28, 24, 20, 16, 28, 24, 20, 16, 0, 0, 0, 0} }, | ||
2790 | { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} }, | ||
2791 | { {28, 28, 28, 22, 18, 14, 28, 22, 18, 14, 0, 0, 0, 0} }, | ||
2792 | { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} }, | ||
2793 | { {28, 28, 28, 20, 16, 12, 28, 20, 16, 12, 0, 0, 0, 0} }, | ||
2794 | }, | ||
2795 | .ctlIndex_5G = { | ||
2796 | 0x10, 0x16, 0x18, 0x40, 0x46, | ||
2797 | 0x48, 0x30, 0x36, 0x38 | ||
2798 | }, | ||
2799 | .ctl_freqbin_5G = { | ||
2800 | { | ||
2801 | /* Data[0].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
2802 | /* Data[0].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
2803 | /* Data[0].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), | ||
2804 | /* Data[0].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), | ||
2805 | /* Data[0].ctlEdges[4].bChannel */ FREQ2FBIN(5600, 0), | ||
2806 | /* Data[0].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
2807 | /* Data[0].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), | ||
2808 | /* Data[0].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) | ||
2809 | }, | ||
2810 | { | ||
2811 | /* Data[1].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
2812 | /* Data[1].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
2813 | /* Data[1].ctlEdges[2].bChannel */ FREQ2FBIN(5280, 0), | ||
2814 | /* Data[1].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), | ||
2815 | /* Data[1].ctlEdges[4].bChannel */ FREQ2FBIN(5520, 0), | ||
2816 | /* Data[1].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
2817 | /* Data[1].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), | ||
2818 | /* Data[1].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) | ||
2819 | }, | ||
2820 | |||
2821 | { | ||
2822 | /* Data[2].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), | ||
2823 | /* Data[2].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), | ||
2824 | /* Data[2].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), | ||
2825 | /* Data[2].ctlEdges[3].bChannel */ FREQ2FBIN(5310, 0), | ||
2826 | /* Data[2].ctlEdges[4].bChannel */ FREQ2FBIN(5510, 0), | ||
2827 | /* Data[2].ctlEdges[5].bChannel */ FREQ2FBIN(5550, 0), | ||
2828 | /* Data[2].ctlEdges[6].bChannel */ FREQ2FBIN(5670, 0), | ||
2829 | /* Data[2].ctlEdges[7].bChannel */ FREQ2FBIN(5755, 0) | ||
2830 | }, | ||
2831 | |||
2832 | { | ||
2833 | /* Data[3].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
2834 | /* Data[3].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), | ||
2835 | /* Data[3].ctlEdges[2].bChannel */ FREQ2FBIN(5260, 0), | ||
2836 | /* Data[3].ctlEdges[3].bChannel */ FREQ2FBIN(5320, 0), | ||
2837 | /* Data[3].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), | ||
2838 | /* Data[3].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
2839 | /* Data[3].ctlEdges[6].bChannel */ 0xFF, | ||
2840 | /* Data[3].ctlEdges[7].bChannel */ 0xFF, | ||
2841 | }, | ||
2842 | |||
2843 | { | ||
2844 | /* Data[4].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
2845 | /* Data[4].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
2846 | /* Data[4].ctlEdges[2].bChannel */ FREQ2FBIN(5500, 0), | ||
2847 | /* Data[4].ctlEdges[3].bChannel */ FREQ2FBIN(5700, 0), | ||
2848 | /* Data[4].ctlEdges[4].bChannel */ 0xFF, | ||
2849 | /* Data[4].ctlEdges[5].bChannel */ 0xFF, | ||
2850 | /* Data[4].ctlEdges[6].bChannel */ 0xFF, | ||
2851 | /* Data[4].ctlEdges[7].bChannel */ 0xFF, | ||
2852 | }, | ||
2853 | |||
2854 | { | ||
2855 | /* Data[5].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), | ||
2856 | /* Data[5].ctlEdges[1].bChannel */ FREQ2FBIN(5270, 0), | ||
2857 | /* Data[5].ctlEdges[2].bChannel */ FREQ2FBIN(5310, 0), | ||
2858 | /* Data[5].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), | ||
2859 | /* Data[5].ctlEdges[4].bChannel */ FREQ2FBIN(5590, 0), | ||
2860 | /* Data[5].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), | ||
2861 | /* Data[5].ctlEdges[6].bChannel */ 0xFF, | ||
2862 | /* Data[5].ctlEdges[7].bChannel */ 0xFF | ||
2863 | }, | ||
2864 | |||
2865 | { | ||
2866 | /* Data[6].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
2867 | /* Data[6].ctlEdges[1].bChannel */ FREQ2FBIN(5200, 0), | ||
2868 | /* Data[6].ctlEdges[2].bChannel */ FREQ2FBIN(5220, 0), | ||
2869 | /* Data[6].ctlEdges[3].bChannel */ FREQ2FBIN(5260, 0), | ||
2870 | /* Data[6].ctlEdges[4].bChannel */ FREQ2FBIN(5500, 0), | ||
2871 | /* Data[6].ctlEdges[5].bChannel */ FREQ2FBIN(5600, 0), | ||
2872 | /* Data[6].ctlEdges[6].bChannel */ FREQ2FBIN(5700, 0), | ||
2873 | /* Data[6].ctlEdges[7].bChannel */ FREQ2FBIN(5745, 0) | ||
2874 | }, | ||
2875 | |||
2876 | { | ||
2877 | /* Data[7].ctlEdges[0].bChannel */ FREQ2FBIN(5180, 0), | ||
2878 | /* Data[7].ctlEdges[1].bChannel */ FREQ2FBIN(5260, 0), | ||
2879 | /* Data[7].ctlEdges[2].bChannel */ FREQ2FBIN(5320, 0), | ||
2880 | /* Data[7].ctlEdges[3].bChannel */ FREQ2FBIN(5500, 0), | ||
2881 | /* Data[7].ctlEdges[4].bChannel */ FREQ2FBIN(5560, 0), | ||
2882 | /* Data[7].ctlEdges[5].bChannel */ FREQ2FBIN(5700, 0), | ||
2883 | /* Data[7].ctlEdges[6].bChannel */ FREQ2FBIN(5745, 0), | ||
2884 | /* Data[7].ctlEdges[7].bChannel */ FREQ2FBIN(5825, 0) | ||
2885 | }, | ||
2886 | |||
2887 | { | ||
2888 | /* Data[8].ctlEdges[0].bChannel */ FREQ2FBIN(5190, 0), | ||
2889 | /* Data[8].ctlEdges[1].bChannel */ FREQ2FBIN(5230, 0), | ||
2890 | /* Data[8].ctlEdges[2].bChannel */ FREQ2FBIN(5270, 0), | ||
2891 | /* Data[8].ctlEdges[3].bChannel */ FREQ2FBIN(5510, 0), | ||
2892 | /* Data[8].ctlEdges[4].bChannel */ FREQ2FBIN(5550, 0), | ||
2893 | /* Data[8].ctlEdges[5].bChannel */ FREQ2FBIN(5670, 0), | ||
2894 | /* Data[8].ctlEdges[6].bChannel */ FREQ2FBIN(5755, 0), | ||
2895 | /* Data[8].ctlEdges[7].bChannel */ FREQ2FBIN(5795, 0) | ||
2896 | } | ||
2897 | }, | ||
2898 | .ctlPowerData_5G = { | ||
2899 | { | ||
2900 | { | ||
2901 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2902 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2903 | } | ||
2904 | }, | ||
2905 | { | ||
2906 | { | ||
2907 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2908 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2909 | } | ||
2910 | }, | ||
2911 | { | ||
2912 | { | ||
2913 | CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
2914 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2915 | } | ||
2916 | }, | ||
2917 | { | ||
2918 | { | ||
2919 | CTL(60, 0), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2920 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
2921 | } | ||
2922 | }, | ||
2923 | { | ||
2924 | { | ||
2925 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2926 | CTL(60, 0), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
2927 | } | ||
2928 | }, | ||
2929 | { | ||
2930 | { | ||
2931 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2932 | CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0), | ||
2933 | } | ||
2934 | }, | ||
2935 | { | ||
2936 | { | ||
2937 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2938 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 1), | ||
2939 | } | ||
2940 | }, | ||
2941 | { | ||
2942 | { | ||
2943 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
2944 | CTL(60, 1), CTL(60, 1), CTL(60, 1), CTL(60, 0), | ||
2945 | } | ||
2946 | }, | ||
2947 | { | ||
2948 | { | ||
2949 | CTL(60, 1), CTL(60, 0), CTL(60, 1), CTL(60, 1), | ||
2950 | CTL(60, 1), CTL(60, 1), CTL(60, 0), CTL(60, 1), | ||
2951 | } | ||
2952 | }, | ||
2953 | } | ||
2954 | }; | ||
2955 | |||
2956 | |||
2957 | static const struct ar9300_eeprom *ar9300_eep_templates[] = { | ||
2958 | &ar9300_default, | ||
2959 | &ar9300_x112, | ||
2960 | &ar9300_h116, | ||
2961 | &ar9300_h112, | ||
2962 | &ar9300_x113, | ||
2963 | }; | ||
2964 | |||
2965 | static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id) | ||
2966 | { | ||
2967 | #define N_LOOP (sizeof(ar9300_eep_templates) / sizeof(ar9300_eep_templates[0])) | ||
2968 | int it; | ||
2969 | |||
2970 | for (it = 0; it < N_LOOP; it++) | ||
2971 | if (ar9300_eep_templates[it]->templateVersion == id) | ||
2972 | return ar9300_eep_templates[it]; | ||
2973 | return NULL; | ||
2974 | #undef N_LOOP | ||
2975 | } | ||
2976 | |||
2977 | |||
626 | static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) | 2978 | static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) |
627 | { | 2979 | { |
628 | if (fbin == AR9300_BCHAN_UNUSED) | 2980 | if (fbin == AR5416_BCHAN_UNUSED) |
629 | return fbin; | 2981 | return fbin; |
630 | 2982 | ||
631 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); | 2983 | return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); |
@@ -636,6 +2988,16 @@ static int ath9k_hw_ar9300_check_eeprom(struct ath_hw *ah) | |||
636 | return 0; | 2988 | return 0; |
637 | } | 2989 | } |
638 | 2990 | ||
2991 | static int interpolate(int x, int xa, int xb, int ya, int yb) | ||
2992 | { | ||
2993 | int bf, factor, plus; | ||
2994 | |||
2995 | bf = 2 * (yb - ya) * (x - xa) / (xb - xa); | ||
2996 | factor = bf / 2; | ||
2997 | plus = bf % 2; | ||
2998 | return ya + factor + plus; | ||
2999 | } | ||
3000 | |||
639 | static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | 3001 | static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, |
640 | enum eeprom_param param) | 3002 | enum eeprom_param param) |
641 | { | 3003 | { |
@@ -673,6 +3035,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | |||
673 | return le32_to_cpu(pBase->swreg); | 3035 | return le32_to_cpu(pBase->swreg); |
674 | case EEP_PAPRD: | 3036 | case EEP_PAPRD: |
675 | return !!(pBase->featureEnable & BIT(5)); | 3037 | return !!(pBase->featureEnable & BIT(5)); |
3038 | case EEP_CHAIN_MASK_REDUCE: | ||
3039 | return (pBase->miscConfiguration >> 0x3) & 0x1; | ||
3040 | case EEP_ANT_DIV_CTL1: | ||
3041 | return le32_to_cpu(eep->base_ext1.ant_div_control); | ||
676 | default: | 3042 | default: |
677 | return 0; | 3043 | return 0; |
678 | } | 3044 | } |
@@ -711,8 +3077,8 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer, | |||
711 | int i; | 3077 | int i; |
712 | 3078 | ||
713 | if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) { | 3079 | if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) { |
714 | ath_print(common, ATH_DBG_EEPROM, | 3080 | ath_dbg(common, ATH_DBG_EEPROM, |
715 | "eeprom address not in range\n"); | 3081 | "eeprom address not in range\n"); |
716 | return false; | 3082 | return false; |
717 | } | 3083 | } |
718 | 3084 | ||
@@ -743,11 +3109,41 @@ static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer, | |||
743 | return true; | 3109 | return true; |
744 | 3110 | ||
745 | error: | 3111 | error: |
746 | ath_print(common, ATH_DBG_EEPROM, | 3112 | ath_dbg(common, ATH_DBG_EEPROM, |
747 | "unable to read eeprom region at offset %d\n", address); | 3113 | "unable to read eeprom region at offset %d\n", address); |
748 | return false; | 3114 | return false; |
749 | } | 3115 | } |
750 | 3116 | ||
3117 | static bool ar9300_otp_read_word(struct ath_hw *ah, int addr, u32 *data) | ||
3118 | { | ||
3119 | REG_READ(ah, AR9300_OTP_BASE + (4 * addr)); | ||
3120 | |||
3121 | if (!ath9k_hw_wait(ah, AR9300_OTP_STATUS, AR9300_OTP_STATUS_TYPE, | ||
3122 | AR9300_OTP_STATUS_VALID, 1000)) | ||
3123 | return false; | ||
3124 | |||
3125 | *data = REG_READ(ah, AR9300_OTP_READ_DATA); | ||
3126 | return true; | ||
3127 | } | ||
3128 | |||
3129 | static bool ar9300_read_otp(struct ath_hw *ah, int address, u8 *buffer, | ||
3130 | int count) | ||
3131 | { | ||
3132 | u32 data; | ||
3133 | int i; | ||
3134 | |||
3135 | for (i = 0; i < count; i++) { | ||
3136 | int offset = 8 * ((address - i) % 4); | ||
3137 | if (!ar9300_otp_read_word(ah, (address - i) / 4, &data)) | ||
3138 | return false; | ||
3139 | |||
3140 | buffer[i] = (data >> offset) & 0xff; | ||
3141 | } | ||
3142 | |||
3143 | return true; | ||
3144 | } | ||
3145 | |||
3146 | |||
751 | static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference, | 3147 | static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference, |
752 | int *length, int *major, int *minor) | 3148 | int *length, int *major, int *minor) |
753 | { | 3149 | { |
@@ -798,17 +3194,15 @@ static bool ar9300_uncompress_block(struct ath_hw *ah, | |||
798 | length &= 0xff; | 3194 | length &= 0xff; |
799 | 3195 | ||
800 | if (length > 0 && spot >= 0 && spot+length <= mdataSize) { | 3196 | if (length > 0 && spot >= 0 && spot+length <= mdataSize) { |
801 | ath_print(common, ATH_DBG_EEPROM, | 3197 | ath_dbg(common, ATH_DBG_EEPROM, |
802 | "Restore at %d: spot=%d " | 3198 | "Restore at %d: spot=%d offset=%d length=%d\n", |
803 | "offset=%d length=%d\n", | 3199 | it, spot, offset, length); |
804 | it, spot, offset, length); | ||
805 | memcpy(&mptr[spot], &block[it+2], length); | 3200 | memcpy(&mptr[spot], &block[it+2], length); |
806 | spot += length; | 3201 | spot += length; |
807 | } else if (length > 0) { | 3202 | } else if (length > 0) { |
808 | ath_print(common, ATH_DBG_EEPROM, | 3203 | ath_dbg(common, ATH_DBG_EEPROM, |
809 | "Bad restore at %d: spot=%d " | 3204 | "Bad restore at %d: spot=%d offset=%d length=%d\n", |
810 | "offset=%d length=%d\n", | 3205 | it, spot, offset, length); |
811 | it, spot, offset, length); | ||
812 | return false; | 3206 | return false; |
813 | } | 3207 | } |
814 | } | 3208 | } |
@@ -823,46 +3217,79 @@ static int ar9300_compress_decision(struct ath_hw *ah, | |||
823 | u8 *word, int length, int mdata_size) | 3217 | u8 *word, int length, int mdata_size) |
824 | { | 3218 | { |
825 | struct ath_common *common = ath9k_hw_common(ah); | 3219 | struct ath_common *common = ath9k_hw_common(ah); |
826 | u8 *dptr; | 3220 | const struct ar9300_eeprom *eep = NULL; |
827 | 3221 | ||
828 | switch (code) { | 3222 | switch (code) { |
829 | case _CompressNone: | 3223 | case _CompressNone: |
830 | if (length != mdata_size) { | 3224 | if (length != mdata_size) { |
831 | ath_print(common, ATH_DBG_EEPROM, | 3225 | ath_dbg(common, ATH_DBG_EEPROM, |
832 | "EEPROM structure size mismatch" | 3226 | "EEPROM structure size mismatch memory=%d eeprom=%d\n", |
833 | "memory=%d eeprom=%d\n", mdata_size, length); | 3227 | mdata_size, length); |
834 | return -1; | 3228 | return -1; |
835 | } | 3229 | } |
836 | memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length); | 3230 | memcpy(mptr, (u8 *) (word + COMP_HDR_LEN), length); |
837 | ath_print(common, ATH_DBG_EEPROM, "restored eeprom %d:" | 3231 | ath_dbg(common, ATH_DBG_EEPROM, |
838 | " uncompressed, length %d\n", it, length); | 3232 | "restored eeprom %d: uncompressed, length %d\n", |
3233 | it, length); | ||
839 | break; | 3234 | break; |
840 | case _CompressBlock: | 3235 | case _CompressBlock: |
841 | if (reference == 0) { | 3236 | if (reference == 0) { |
842 | dptr = mptr; | ||
843 | } else { | 3237 | } else { |
844 | if (reference != 2) { | 3238 | eep = ar9003_eeprom_struct_find_by_id(reference); |
845 | ath_print(common, ATH_DBG_EEPROM, | 3239 | if (eep == NULL) { |
846 | "cant find reference eeprom" | 3240 | ath_dbg(common, ATH_DBG_EEPROM, |
847 | "struct %d\n", reference); | 3241 | "can't find reference eeprom struct %d\n", |
3242 | reference); | ||
848 | return -1; | 3243 | return -1; |
849 | } | 3244 | } |
850 | memcpy(mptr, &ar9300_default, mdata_size); | 3245 | memcpy(mptr, eep, mdata_size); |
851 | } | 3246 | } |
852 | ath_print(common, ATH_DBG_EEPROM, | 3247 | ath_dbg(common, ATH_DBG_EEPROM, |
853 | "restore eeprom %d: block, reference %d," | 3248 | "restore eeprom %d: block, reference %d, length %d\n", |
854 | " length %d\n", it, reference, length); | 3249 | it, reference, length); |
855 | ar9300_uncompress_block(ah, mptr, mdata_size, | 3250 | ar9300_uncompress_block(ah, mptr, mdata_size, |
856 | (u8 *) (word + COMP_HDR_LEN), length); | 3251 | (u8 *) (word + COMP_HDR_LEN), length); |
857 | break; | 3252 | break; |
858 | default: | 3253 | default: |
859 | ath_print(common, ATH_DBG_EEPROM, "unknown compression" | 3254 | ath_dbg(common, ATH_DBG_EEPROM, |
860 | " code %d\n", code); | 3255 | "unknown compression code %d\n", code); |
861 | return -1; | 3256 | return -1; |
862 | } | 3257 | } |
863 | return 0; | 3258 | return 0; |
864 | } | 3259 | } |
865 | 3260 | ||
3261 | typedef bool (*eeprom_read_op)(struct ath_hw *ah, int address, u8 *buffer, | ||
3262 | int count); | ||
3263 | |||
3264 | static bool ar9300_check_header(void *data) | ||
3265 | { | ||
3266 | u32 *word = data; | ||
3267 | return !(*word == 0 || *word == ~0); | ||
3268 | } | ||
3269 | |||
3270 | static bool ar9300_check_eeprom_header(struct ath_hw *ah, eeprom_read_op read, | ||
3271 | int base_addr) | ||
3272 | { | ||
3273 | u8 header[4]; | ||
3274 | |||
3275 | if (!read(ah, base_addr, header, 4)) | ||
3276 | return false; | ||
3277 | |||
3278 | return ar9300_check_header(header); | ||
3279 | } | ||
3280 | |||
3281 | static int ar9300_eeprom_restore_flash(struct ath_hw *ah, u8 *mptr, | ||
3282 | int mdata_size) | ||
3283 | { | ||
3284 | struct ath_common *common = ath9k_hw_common(ah); | ||
3285 | u16 *data = (u16 *) mptr; | ||
3286 | int i; | ||
3287 | |||
3288 | for (i = 0; i < mdata_size / 2; i++, data++) | ||
3289 | ath9k_hw_nvram_read(common, i, data); | ||
3290 | |||
3291 | return 0; | ||
3292 | } | ||
866 | /* | 3293 | /* |
867 | * Read the configuration data from the eeprom. | 3294 | * Read the configuration data from the eeprom. |
868 | * The data can be put in any specified memory buffer. | 3295 | * The data can be put in any specified memory buffer. |
@@ -883,6 +3310,10 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, | |||
883 | int it; | 3310 | int it; |
884 | u16 checksum, mchecksum; | 3311 | u16 checksum, mchecksum; |
885 | struct ath_common *common = ath9k_hw_common(ah); | 3312 | struct ath_common *common = ath9k_hw_common(ah); |
3313 | eeprom_read_op read; | ||
3314 | |||
3315 | if (ath9k_hw_use_flash(ah)) | ||
3316 | return ar9300_eeprom_restore_flash(ah, mptr, mdata_size); | ||
886 | 3317 | ||
887 | word = kzalloc(2048, GFP_KERNEL); | 3318 | word = kzalloc(2048, GFP_KERNEL); |
888 | if (!word) | 3319 | if (!word) |
@@ -890,43 +3321,73 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, | |||
890 | 3321 | ||
891 | memcpy(mptr, &ar9300_default, mdata_size); | 3322 | memcpy(mptr, &ar9300_default, mdata_size); |
892 | 3323 | ||
3324 | read = ar9300_read_eeprom; | ||
3325 | if (AR_SREV_9485(ah)) | ||
3326 | cptr = AR9300_BASE_ADDR_4K; | ||
3327 | else | ||
3328 | cptr = AR9300_BASE_ADDR; | ||
3329 | ath_dbg(common, ATH_DBG_EEPROM, | ||
3330 | "Trying EEPROM access at Address 0x%04x\n", cptr); | ||
3331 | if (ar9300_check_eeprom_header(ah, read, cptr)) | ||
3332 | goto found; | ||
3333 | |||
3334 | cptr = AR9300_BASE_ADDR_512; | ||
3335 | ath_dbg(common, ATH_DBG_EEPROM, | ||
3336 | "Trying EEPROM access at Address 0x%04x\n", cptr); | ||
3337 | if (ar9300_check_eeprom_header(ah, read, cptr)) | ||
3338 | goto found; | ||
3339 | |||
3340 | read = ar9300_read_otp; | ||
893 | cptr = AR9300_BASE_ADDR; | 3341 | cptr = AR9300_BASE_ADDR; |
3342 | ath_dbg(common, ATH_DBG_EEPROM, | ||
3343 | "Trying OTP access at Address 0x%04x\n", cptr); | ||
3344 | if (ar9300_check_eeprom_header(ah, read, cptr)) | ||
3345 | goto found; | ||
3346 | |||
3347 | cptr = AR9300_BASE_ADDR_512; | ||
3348 | ath_dbg(common, ATH_DBG_EEPROM, | ||
3349 | "Trying OTP access at Address 0x%04x\n", cptr); | ||
3350 | if (ar9300_check_eeprom_header(ah, read, cptr)) | ||
3351 | goto found; | ||
3352 | |||
3353 | goto fail; | ||
3354 | |||
3355 | found: | ||
3356 | ath_dbg(common, ATH_DBG_EEPROM, "Found valid EEPROM data\n"); | ||
3357 | |||
894 | for (it = 0; it < MSTATE; it++) { | 3358 | for (it = 0; it < MSTATE; it++) { |
895 | if (!ar9300_read_eeprom(ah, cptr, word, COMP_HDR_LEN)) | 3359 | if (!read(ah, cptr, word, COMP_HDR_LEN)) |
896 | goto fail; | 3360 | goto fail; |
897 | 3361 | ||
898 | if ((word[0] == 0 && word[1] == 0 && word[2] == 0 && | 3362 | if (!ar9300_check_header(word)) |
899 | word[3] == 0) || (word[0] == 0xff && word[1] == 0xff | ||
900 | && word[2] == 0xff && word[3] == 0xff)) | ||
901 | break; | 3363 | break; |
902 | 3364 | ||
903 | ar9300_comp_hdr_unpack(word, &code, &reference, | 3365 | ar9300_comp_hdr_unpack(word, &code, &reference, |
904 | &length, &major, &minor); | 3366 | &length, &major, &minor); |
905 | ath_print(common, ATH_DBG_EEPROM, | 3367 | ath_dbg(common, ATH_DBG_EEPROM, |
906 | "Found block at %x: code=%d ref=%d" | 3368 | "Found block at %x: code=%d ref=%d length=%d major=%d minor=%d\n", |
907 | "length=%d major=%d minor=%d\n", cptr, code, | 3369 | cptr, code, reference, length, major, minor); |
908 | reference, length, major, minor); | 3370 | if ((!AR_SREV_9485(ah) && length >= 1024) || |
909 | if (length >= 1024) { | 3371 | (AR_SREV_9485(ah) && length > EEPROM_DATA_LEN_9485)) { |
910 | ath_print(common, ATH_DBG_EEPROM, | 3372 | ath_dbg(common, ATH_DBG_EEPROM, |
911 | "Skipping bad header\n"); | 3373 | "Skipping bad header\n"); |
912 | cptr -= COMP_HDR_LEN; | 3374 | cptr -= COMP_HDR_LEN; |
913 | continue; | 3375 | continue; |
914 | } | 3376 | } |
915 | 3377 | ||
916 | osize = length; | 3378 | osize = length; |
917 | ar9300_read_eeprom(ah, cptr, word, | 3379 | read(ah, cptr, word, COMP_HDR_LEN + osize + COMP_CKSUM_LEN); |
918 | COMP_HDR_LEN + osize + COMP_CKSUM_LEN); | ||
919 | checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length); | 3380 | checksum = ar9300_comp_cksum(&word[COMP_HDR_LEN], length); |
920 | mchecksum = word[COMP_HDR_LEN + osize] | | 3381 | mchecksum = word[COMP_HDR_LEN + osize] | |
921 | (word[COMP_HDR_LEN + osize + 1] << 8); | 3382 | (word[COMP_HDR_LEN + osize + 1] << 8); |
922 | ath_print(common, ATH_DBG_EEPROM, | 3383 | ath_dbg(common, ATH_DBG_EEPROM, |
923 | "checksum %x %x\n", checksum, mchecksum); | 3384 | "checksum %x %x\n", checksum, mchecksum); |
924 | if (checksum == mchecksum) { | 3385 | if (checksum == mchecksum) { |
925 | ar9300_compress_decision(ah, it, code, reference, mptr, | 3386 | ar9300_compress_decision(ah, it, code, reference, mptr, |
926 | word, length, mdata_size); | 3387 | word, length, mdata_size); |
927 | } else { | 3388 | } else { |
928 | ath_print(common, ATH_DBG_EEPROM, | 3389 | ath_dbg(common, ATH_DBG_EEPROM, |
929 | "skipping block with bad checksum\n"); | 3390 | "skipping block with bad checksum\n"); |
930 | } | 3391 | } |
931 | cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN); | 3392 | cptr -= (COMP_HDR_LEN + osize + COMP_CKSUM_LEN); |
932 | } | 3393 | } |
@@ -967,18 +3428,6 @@ static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah) | |||
967 | return 0; | 3428 | return 0; |
968 | } | 3429 | } |
969 | 3430 | ||
970 | static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah, | ||
971 | enum ieee80211_band freq_band) | ||
972 | { | ||
973 | return 1; | ||
974 | } | ||
975 | |||
976 | static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
977 | struct ath9k_channel *chan) | ||
978 | { | ||
979 | return -EINVAL; | ||
980 | } | ||
981 | |||
982 | static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz) | 3431 | static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz) |
983 | { | 3432 | { |
984 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | 3433 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
@@ -992,9 +3441,17 @@ static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz) | |||
992 | static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) | 3441 | static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) |
993 | { | 3442 | { |
994 | int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); | 3443 | int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); |
995 | REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, (bias & 0x3)); | 3444 | |
996 | REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_SPARE, | 3445 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) |
997 | ((bias >> 2) & 0x3)); | 3446 | REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); |
3447 | else { | ||
3448 | REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); | ||
3449 | REG_RMW_FIELD(ah, AR_CH0_THERM, | ||
3450 | AR_CH0_THERM_XPABIASLVL_MSB, | ||
3451 | bias >> 2); | ||
3452 | REG_RMW_FIELD(ah, AR_CH0_THERM, | ||
3453 | AR_CH0_THERM_XPASHORT2GND, 1); | ||
3454 | } | ||
998 | } | 3455 | } |
999 | 3456 | ||
1000 | static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) | 3457 | static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz) |
@@ -1040,20 +3497,77 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, | |||
1040 | 3497 | ||
1041 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | 3498 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) |
1042 | { | 3499 | { |
3500 | int chain; | ||
3501 | u32 regval; | ||
3502 | u32 ant_div_ctl1; | ||
3503 | static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { | ||
3504 | AR_PHY_SWITCH_CHAIN_0, | ||
3505 | AR_PHY_SWITCH_CHAIN_1, | ||
3506 | AR_PHY_SWITCH_CHAIN_2, | ||
3507 | }; | ||
3508 | |||
1043 | u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); | 3509 | u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); |
3510 | |||
1044 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); | 3511 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); |
1045 | 3512 | ||
1046 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); | 3513 | value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); |
1047 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); | 3514 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); |
1048 | 3515 | ||
1049 | value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz); | 3516 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
1050 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); | 3517 | if ((ah->rxchainmask & BIT(chain)) || |
3518 | (ah->txchainmask & BIT(chain))) { | ||
3519 | value = ar9003_hw_ant_ctrl_chain_get(ah, chain, | ||
3520 | is2ghz); | ||
3521 | REG_RMW_FIELD(ah, switch_chain_reg[chain], | ||
3522 | AR_SWITCH_TABLE_ALL, value); | ||
3523 | } | ||
3524 | } | ||
3525 | |||
3526 | if (AR_SREV_9485(ah)) { | ||
3527 | value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1); | ||
3528 | /* | ||
3529 | * main_lnaconf, alt_lnaconf, main_tb, alt_tb | ||
3530 | * are the fields present | ||
3531 | */ | ||
3532 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
3533 | regval &= (~AR_ANT_DIV_CTRL_ALL); | ||
3534 | regval |= (value & 0x3f) << AR_ANT_DIV_CTRL_ALL_S; | ||
3535 | /* enable_lnadiv */ | ||
3536 | regval &= (~AR_PHY_9485_ANT_DIV_LNADIV); | ||
3537 | regval |= ((value >> 6) & 0x1) << | ||
3538 | AR_PHY_9485_ANT_DIV_LNADIV_S; | ||
3539 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
3540 | |||
3541 | /*enable fast_div */ | ||
3542 | regval = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
3543 | regval &= (~AR_FAST_DIV_ENABLE); | ||
3544 | regval |= ((value >> 7) & 0x1) << | ||
3545 | AR_FAST_DIV_ENABLE_S; | ||
3546 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); | ||
3547 | ant_div_ctl1 = | ||
3548 | ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | ||
3549 | /* check whether antenna diversity is enabled */ | ||
3550 | if ((ant_div_ctl1 >> 0x6) == 0x3) { | ||
3551 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
3552 | /* | ||
3553 | * clear bits 25-30 main_lnaconf, alt_lnaconf, | ||
3554 | * main_tb, alt_tb | ||
3555 | */ | ||
3556 | regval &= (~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF | | ||
3557 | AR_PHY_9485_ANT_DIV_ALT_LNACONF | | ||
3558 | AR_PHY_9485_ANT_DIV_ALT_GAINTB | | ||
3559 | AR_PHY_9485_ANT_DIV_MAIN_GAINTB)); | ||
3560 | /* by default use LNA1 for the main antenna */ | ||
3561 | regval |= (AR_PHY_9485_ANT_DIV_LNA1 << | ||
3562 | AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S); | ||
3563 | regval |= (AR_PHY_9485_ANT_DIV_LNA2 << | ||
3564 | AR_PHY_9485_ANT_DIV_ALT_LNACONF_S); | ||
3565 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
3566 | } | ||
3567 | |||
1051 | 3568 | ||
1052 | value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); | 3569 | } |
1053 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value); | ||
1054 | 3570 | ||
1055 | value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); | ||
1056 | REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value); | ||
1057 | } | 3571 | } |
1058 | 3572 | ||
1059 | static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) | 3573 | static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) |
@@ -1097,28 +3611,180 @@ static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) | |||
1097 | REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg); | 3611 | REG_WRITE(ah, AR_PHY_65NM_CH0_BIAS4, reg); |
1098 | } | 3612 | } |
1099 | 3613 | ||
3614 | static u16 ar9003_hw_atten_chain_get(struct ath_hw *ah, int chain, | ||
3615 | struct ath9k_channel *chan) | ||
3616 | { | ||
3617 | int f[3], t[3]; | ||
3618 | u16 value; | ||
3619 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
3620 | |||
3621 | if (chain >= 0 && chain < 3) { | ||
3622 | if (IS_CHAN_2GHZ(chan)) | ||
3623 | return eep->modalHeader2G.xatten1DB[chain]; | ||
3624 | else if (eep->base_ext2.xatten1DBLow[chain] != 0) { | ||
3625 | t[0] = eep->base_ext2.xatten1DBLow[chain]; | ||
3626 | f[0] = 5180; | ||
3627 | t[1] = eep->modalHeader5G.xatten1DB[chain]; | ||
3628 | f[1] = 5500; | ||
3629 | t[2] = eep->base_ext2.xatten1DBHigh[chain]; | ||
3630 | f[2] = 5785; | ||
3631 | value = ar9003_hw_power_interpolate((s32) chan->channel, | ||
3632 | f, t, 3); | ||
3633 | return value; | ||
3634 | } else | ||
3635 | return eep->modalHeader5G.xatten1DB[chain]; | ||
3636 | } | ||
3637 | |||
3638 | return 0; | ||
3639 | } | ||
3640 | |||
3641 | |||
3642 | static u16 ar9003_hw_atten_chain_get_margin(struct ath_hw *ah, int chain, | ||
3643 | struct ath9k_channel *chan) | ||
3644 | { | ||
3645 | int f[3], t[3]; | ||
3646 | u16 value; | ||
3647 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
3648 | |||
3649 | if (chain >= 0 && chain < 3) { | ||
3650 | if (IS_CHAN_2GHZ(chan)) | ||
3651 | return eep->modalHeader2G.xatten1Margin[chain]; | ||
3652 | else if (eep->base_ext2.xatten1MarginLow[chain] != 0) { | ||
3653 | t[0] = eep->base_ext2.xatten1MarginLow[chain]; | ||
3654 | f[0] = 5180; | ||
3655 | t[1] = eep->modalHeader5G.xatten1Margin[chain]; | ||
3656 | f[1] = 5500; | ||
3657 | t[2] = eep->base_ext2.xatten1MarginHigh[chain]; | ||
3658 | f[2] = 5785; | ||
3659 | value = ar9003_hw_power_interpolate((s32) chan->channel, | ||
3660 | f, t, 3); | ||
3661 | return value; | ||
3662 | } else | ||
3663 | return eep->modalHeader5G.xatten1Margin[chain]; | ||
3664 | } | ||
3665 | |||
3666 | return 0; | ||
3667 | } | ||
3668 | |||
3669 | static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) | ||
3670 | { | ||
3671 | int i; | ||
3672 | u16 value; | ||
3673 | unsigned long ext_atten_reg[3] = {AR_PHY_EXT_ATTEN_CTL_0, | ||
3674 | AR_PHY_EXT_ATTEN_CTL_1, | ||
3675 | AR_PHY_EXT_ATTEN_CTL_2, | ||
3676 | }; | ||
3677 | |||
3678 | /* Test value. if 0 then attenuation is unused. Don't load anything. */ | ||
3679 | for (i = 0; i < 3; i++) { | ||
3680 | if (ah->txchainmask & BIT(i)) { | ||
3681 | value = ar9003_hw_atten_chain_get(ah, i, chan); | ||
3682 | REG_RMW_FIELD(ah, ext_atten_reg[i], | ||
3683 | AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); | ||
3684 | |||
3685 | value = ar9003_hw_atten_chain_get_margin(ah, i, chan); | ||
3686 | REG_RMW_FIELD(ah, ext_atten_reg[i], | ||
3687 | AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, | ||
3688 | value); | ||
3689 | } | ||
3690 | } | ||
3691 | } | ||
3692 | |||
3693 | static bool is_pmu_set(struct ath_hw *ah, u32 pmu_reg, int pmu_set) | ||
3694 | { | ||
3695 | int timeout = 100; | ||
3696 | |||
3697 | while (pmu_set != REG_READ(ah, pmu_reg)) { | ||
3698 | if (timeout-- == 0) | ||
3699 | return false; | ||
3700 | REG_WRITE(ah, pmu_reg, pmu_set); | ||
3701 | udelay(10); | ||
3702 | } | ||
3703 | |||
3704 | return true; | ||
3705 | } | ||
3706 | |||
1100 | static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah) | 3707 | static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah) |
1101 | { | 3708 | { |
1102 | int internal_regulator = | 3709 | int internal_regulator = |
1103 | ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR); | 3710 | ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR); |
1104 | 3711 | ||
1105 | if (internal_regulator) { | 3712 | if (internal_regulator) { |
1106 | /* Internal regulator is ON. Write swreg register. */ | 3713 | if (AR_SREV_9485(ah)) { |
1107 | int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG); | 3714 | int reg_pmu_set; |
1108 | REG_WRITE(ah, AR_RTC_REG_CONTROL1, | 3715 | |
1109 | REG_READ(ah, AR_RTC_REG_CONTROL1) & | 3716 | reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM; |
1110 | (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM)); | 3717 | REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); |
1111 | REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg); | 3718 | if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) |
1112 | /* Set REG_CONTROL1.SWREG_PROGRAM */ | 3719 | return; |
1113 | REG_WRITE(ah, AR_RTC_REG_CONTROL1, | 3720 | |
1114 | REG_READ(ah, | 3721 | reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) | |
1115 | AR_RTC_REG_CONTROL1) | | 3722 | (2 << 14) | (6 << 17) | (1 << 20) | |
1116 | AR_RTC_REG_CONTROL1_SWREG_PROGRAM); | 3723 | (3 << 24) | (1 << 28); |
3724 | |||
3725 | REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set); | ||
3726 | if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set)) | ||
3727 | return; | ||
3728 | |||
3729 | reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0xFFC00000) | ||
3730 | | (4 << 26); | ||
3731 | REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); | ||
3732 | if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) | ||
3733 | return; | ||
3734 | |||
3735 | reg_pmu_set = (REG_READ(ah, AR_PHY_PMU2) & ~0x00200000) | ||
3736 | | (1 << 21); | ||
3737 | REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set); | ||
3738 | if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set)) | ||
3739 | return; | ||
3740 | } else { | ||
3741 | /* Internal regulator is ON. Write swreg register. */ | ||
3742 | int swreg = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG); | ||
3743 | REG_WRITE(ah, AR_RTC_REG_CONTROL1, | ||
3744 | REG_READ(ah, AR_RTC_REG_CONTROL1) & | ||
3745 | (~AR_RTC_REG_CONTROL1_SWREG_PROGRAM)); | ||
3746 | REG_WRITE(ah, AR_RTC_REG_CONTROL0, swreg); | ||
3747 | /* Set REG_CONTROL1.SWREG_PROGRAM */ | ||
3748 | REG_WRITE(ah, AR_RTC_REG_CONTROL1, | ||
3749 | REG_READ(ah, | ||
3750 | AR_RTC_REG_CONTROL1) | | ||
3751 | AR_RTC_REG_CONTROL1_SWREG_PROGRAM); | ||
3752 | } | ||
1117 | } else { | 3753 | } else { |
1118 | REG_WRITE(ah, AR_RTC_SLEEP_CLK, | 3754 | if (AR_SREV_9485(ah)) { |
1119 | (REG_READ(ah, | 3755 | REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0); |
1120 | AR_RTC_SLEEP_CLK) | | 3756 | while (REG_READ_FIELD(ah, AR_PHY_PMU2, |
1121 | AR_RTC_FORCE_SWREG_PRD)); | 3757 | AR_PHY_PMU2_PGM)) |
3758 | udelay(10); | ||
3759 | |||
3760 | REG_RMW_FIELD(ah, AR_PHY_PMU1, AR_PHY_PMU1_PWD, 0x1); | ||
3761 | while (!REG_READ_FIELD(ah, AR_PHY_PMU1, | ||
3762 | AR_PHY_PMU1_PWD)) | ||
3763 | udelay(10); | ||
3764 | REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0x1); | ||
3765 | while (!REG_READ_FIELD(ah, AR_PHY_PMU2, | ||
3766 | AR_PHY_PMU2_PGM)) | ||
3767 | udelay(10); | ||
3768 | } else | ||
3769 | REG_WRITE(ah, AR_RTC_SLEEP_CLK, | ||
3770 | (REG_READ(ah, | ||
3771 | AR_RTC_SLEEP_CLK) | | ||
3772 | AR_RTC_FORCE_SWREG_PRD)); | ||
3773 | } | ||
3774 | |||
3775 | } | ||
3776 | |||
3777 | static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah) | ||
3778 | { | ||
3779 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
3780 | u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0]; | ||
3781 | |||
3782 | if (eep->baseEepHeader.featureEnable & 0x40) { | ||
3783 | tuning_caps_param &= 0x7f; | ||
3784 | REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPINDAC, | ||
3785 | tuning_caps_param); | ||
3786 | REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPOUTDAC, | ||
3787 | tuning_caps_param); | ||
1122 | } | 3788 | } |
1123 | } | 3789 | } |
1124 | 3790 | ||
@@ -1128,7 +3794,11 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, | |||
1128 | ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan)); | 3794 | ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan)); |
1129 | ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); | 3795 | ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); |
1130 | ar9003_hw_drive_strength_apply(ah); | 3796 | ar9003_hw_drive_strength_apply(ah); |
1131 | ar9003_hw_internal_regulator_apply(ah); | 3797 | ar9003_hw_atten_apply(ah, chan); |
3798 | if (!AR_SREV_9340(ah)) | ||
3799 | ar9003_hw_internal_regulator_apply(ah); | ||
3800 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) | ||
3801 | ar9003_hw_apply_tuning_caps(ah); | ||
1132 | } | 3802 | } |
1133 | 3803 | ||
1134 | static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah, | 3804 | static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah, |
@@ -1189,7 +3859,7 @@ static int ar9003_hw_power_interpolate(int32_t x, | |||
1189 | if (hx == lx) | 3859 | if (hx == lx) |
1190 | y = ly; | 3860 | y = ly; |
1191 | else /* interpolate */ | 3861 | else /* interpolate */ |
1192 | y = ly + (((x - lx) * (hy - ly)) / (hx - lx)); | 3862 | y = interpolate(x, lx, hx, ly, hy); |
1193 | } else /* only low is good, use it */ | 3863 | } else /* only low is good, use it */ |
1194 | y = ly; | 3864 | y = ly; |
1195 | } else if (hhave) /* only high is good, use it */ | 3865 | } else if (hhave) /* only high is good, use it */ |
@@ -1336,19 +4006,19 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1336 | { | 4006 | { |
1337 | #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) | 4007 | #define POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) |
1338 | /* make sure forced gain is not set */ | 4008 | /* make sure forced gain is not set */ |
1339 | REG_WRITE(ah, 0xa458, 0); | 4009 | REG_WRITE(ah, AR_PHY_TX_FORCED_GAIN, 0); |
1340 | 4010 | ||
1341 | /* Write the OFDM power per rate set */ | 4011 | /* Write the OFDM power per rate set */ |
1342 | 4012 | ||
1343 | /* 6 (LSB), 9, 12, 18 (MSB) */ | 4013 | /* 6 (LSB), 9, 12, 18 (MSB) */ |
1344 | REG_WRITE(ah, 0xa3c0, | 4014 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(0), |
1345 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | | 4015 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | |
1346 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) | | 4016 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) | |
1347 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | | 4017 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | |
1348 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0)); | 4018 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0)); |
1349 | 4019 | ||
1350 | /* 24 (LSB), 36, 48, 54 (MSB) */ | 4020 | /* 24 (LSB), 36, 48, 54 (MSB) */ |
1351 | REG_WRITE(ah, 0xa3c4, | 4021 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(1), |
1352 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) | | 4022 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) | |
1353 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) | | 4023 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) | |
1354 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) | | 4024 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) | |
@@ -1357,24 +4027,34 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1357 | /* Write the CCK power per rate set */ | 4027 | /* Write the CCK power per rate set */ |
1358 | 4028 | ||
1359 | /* 1L (LSB), reserved, 2L, 2S (MSB) */ | 4029 | /* 1L (LSB), reserved, 2L, 2S (MSB) */ |
1360 | REG_WRITE(ah, 0xa3c8, | 4030 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(2), |
1361 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) | | 4031 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) | |
1362 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | | 4032 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | |
1363 | /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */ | 4033 | /* POW_SM(txPowerTimes2, 8) | this is reserved for AR9003 */ |
1364 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)); | 4034 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)); |
1365 | 4035 | ||
1366 | /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */ | 4036 | /* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */ |
1367 | REG_WRITE(ah, 0xa3cc, | 4037 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(3), |
1368 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) | | 4038 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) | |
1369 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) | | 4039 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) | |
1370 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) | | 4040 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) | |
1371 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) | 4041 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) |
1372 | ); | 4042 | ); |
1373 | 4043 | ||
4044 | /* Write the power for duplicated frames - HT40 */ | ||
4045 | |||
4046 | /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */ | ||
4047 | REG_WRITE(ah, 0xa3e0, | ||
4048 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | | ||
4049 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | | ||
4050 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | | ||
4051 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) | ||
4052 | ); | ||
4053 | |||
1374 | /* Write the HT20 power per rate set */ | 4054 | /* Write the HT20 power per rate set */ |
1375 | 4055 | ||
1376 | /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ | 4056 | /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ |
1377 | REG_WRITE(ah, 0xa3d0, | 4057 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(4), |
1378 | POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) | | 4058 | POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) | |
1379 | POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) | | 4059 | POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) | |
1380 | POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) | | 4060 | POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) | |
@@ -1382,7 +4062,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1382 | ); | 4062 | ); |
1383 | 4063 | ||
1384 | /* 6 (LSB), 7, 12, 13 (MSB) */ | 4064 | /* 6 (LSB), 7, 12, 13 (MSB) */ |
1385 | REG_WRITE(ah, 0xa3d4, | 4065 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(5), |
1386 | POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) | | 4066 | POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) | |
1387 | POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) | | 4067 | POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) | |
1388 | POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) | | 4068 | POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) | |
@@ -1390,7 +4070,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1390 | ); | 4070 | ); |
1391 | 4071 | ||
1392 | /* 14 (LSB), 15, 20, 21 */ | 4072 | /* 14 (LSB), 15, 20, 21 */ |
1393 | REG_WRITE(ah, 0xa3e4, | 4073 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(9), |
1394 | POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) | | 4074 | POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) | |
1395 | POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) | | 4075 | POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) | |
1396 | POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) | | 4076 | POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) | |
@@ -1400,7 +4080,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1400 | /* Mixed HT20 and HT40 rates */ | 4080 | /* Mixed HT20 and HT40 rates */ |
1401 | 4081 | ||
1402 | /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */ | 4082 | /* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */ |
1403 | REG_WRITE(ah, 0xa3e8, | 4083 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(10), |
1404 | POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) | | 4084 | POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) | |
1405 | POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) | | 4085 | POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) | |
1406 | POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) | | 4086 | POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) | |
@@ -1412,7 +4092,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1412 | * correct PAR difference between HT40 and HT20/LEGACY | 4092 | * correct PAR difference between HT40 and HT20/LEGACY |
1413 | * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) | 4093 | * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) |
1414 | */ | 4094 | */ |
1415 | REG_WRITE(ah, 0xa3d8, | 4095 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(6), |
1416 | POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) | | 4096 | POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) | |
1417 | POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) | | 4097 | POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) | |
1418 | POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | | 4098 | POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) | |
@@ -1420,7 +4100,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1420 | ); | 4100 | ); |
1421 | 4101 | ||
1422 | /* 6 (LSB), 7, 12, 13 (MSB) */ | 4102 | /* 6 (LSB), 7, 12, 13 (MSB) */ |
1423 | REG_WRITE(ah, 0xa3dc, | 4103 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(7), |
1424 | POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) | | 4104 | POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) | |
1425 | POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) | | 4105 | POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) | |
1426 | POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) | | 4106 | POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) | |
@@ -1428,7 +4108,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
1428 | ); | 4108 | ); |
1429 | 4109 | ||
1430 | /* 14 (LSB), 15, 20, 21 */ | 4110 | /* 14 (LSB), 15, 20, 21 */ |
1431 | REG_WRITE(ah, 0xa3ec, | 4111 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE(11), |
1432 | POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) | | 4112 | POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) | |
1433 | POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) | | 4113 | POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) | |
1434 | POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) | | 4114 | POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) | |
@@ -1558,22 +4238,9 @@ static void ar9003_hw_set_target_power_eeprom(struct ath_hw *ah, u16 freq, | |||
1558 | ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq, | 4238 | ar9003_hw_eeprom_get_ht40_tgt_pwr(ah, HT_TARGET_RATE_23, freq, |
1559 | is2GHz) + ht40PowerIncForPdadc; | 4239 | is2GHz) + ht40PowerIncForPdadc; |
1560 | 4240 | ||
1561 | while (i < ar9300RateSize) { | 4241 | for (i = 0; i < ar9300RateSize; i++) { |
1562 | ath_print(common, ATH_DBG_EEPROM, | 4242 | ath_dbg(common, ATH_DBG_EEPROM, |
1563 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | 4243 | "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); |
1564 | i++; | ||
1565 | |||
1566 | ath_print(common, ATH_DBG_EEPROM, | ||
1567 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | ||
1568 | i++; | ||
1569 | |||
1570 | ath_print(common, ATH_DBG_EEPROM, | ||
1571 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | ||
1572 | i++; | ||
1573 | |||
1574 | ath_print(common, ATH_DBG_EEPROM, | ||
1575 | "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); | ||
1576 | i++; | ||
1577 | } | 4244 | } |
1578 | } | 4245 | } |
1579 | 4246 | ||
@@ -1592,18 +4259,17 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, | |||
1592 | struct ath_common *common = ath9k_hw_common(ah); | 4259 | struct ath_common *common = ath9k_hw_common(ah); |
1593 | 4260 | ||
1594 | if (ichain >= AR9300_MAX_CHAINS) { | 4261 | if (ichain >= AR9300_MAX_CHAINS) { |
1595 | ath_print(common, ATH_DBG_EEPROM, | 4262 | ath_dbg(common, ATH_DBG_EEPROM, |
1596 | "Invalid chain index, must be less than %d\n", | 4263 | "Invalid chain index, must be less than %d\n", |
1597 | AR9300_MAX_CHAINS); | 4264 | AR9300_MAX_CHAINS); |
1598 | return -1; | 4265 | return -1; |
1599 | } | 4266 | } |
1600 | 4267 | ||
1601 | if (mode) { /* 5GHz */ | 4268 | if (mode) { /* 5GHz */ |
1602 | if (ipier >= AR9300_NUM_5G_CAL_PIERS) { | 4269 | if (ipier >= AR9300_NUM_5G_CAL_PIERS) { |
1603 | ath_print(common, ATH_DBG_EEPROM, | 4270 | ath_dbg(common, ATH_DBG_EEPROM, |
1604 | "Invalid 5GHz cal pier index, must " | 4271 | "Invalid 5GHz cal pier index, must be less than %d\n", |
1605 | "be less than %d\n", | 4272 | AR9300_NUM_5G_CAL_PIERS); |
1606 | AR9300_NUM_5G_CAL_PIERS); | ||
1607 | return -1; | 4273 | return -1; |
1608 | } | 4274 | } |
1609 | pCalPier = &(eep->calFreqPier5G[ipier]); | 4275 | pCalPier = &(eep->calFreqPier5G[ipier]); |
@@ -1611,9 +4277,9 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, | |||
1611 | is2GHz = 0; | 4277 | is2GHz = 0; |
1612 | } else { | 4278 | } else { |
1613 | if (ipier >= AR9300_NUM_2G_CAL_PIERS) { | 4279 | if (ipier >= AR9300_NUM_2G_CAL_PIERS) { |
1614 | ath_print(common, ATH_DBG_EEPROM, | 4280 | ath_dbg(common, ATH_DBG_EEPROM, |
1615 | "Invalid 2GHz cal pier index, must " | 4281 | "Invalid 2GHz cal pier index, must be less than %d\n", |
1616 | "be less than %d\n", AR9300_NUM_2G_CAL_PIERS); | 4282 | AR9300_NUM_2G_CAL_PIERS); |
1617 | return -1; | 4283 | return -1; |
1618 | } | 4284 | } |
1619 | 4285 | ||
@@ -1637,27 +4303,32 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah, | |||
1637 | { | 4303 | { |
1638 | int tempSlope = 0; | 4304 | int tempSlope = 0; |
1639 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | 4305 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
4306 | int f[3], t[3]; | ||
1640 | 4307 | ||
1641 | REG_RMW(ah, AR_PHY_TPC_11_B0, | 4308 | REG_RMW(ah, AR_PHY_TPC_11_B0, |
1642 | (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), | 4309 | (correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), |
1643 | AR_PHY_TPC_OLPC_GAIN_DELTA); | 4310 | AR_PHY_TPC_OLPC_GAIN_DELTA); |
1644 | REG_RMW(ah, AR_PHY_TPC_11_B1, | 4311 | if (ah->caps.tx_chainmask & BIT(1)) |
1645 | (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), | 4312 | REG_RMW(ah, AR_PHY_TPC_11_B1, |
1646 | AR_PHY_TPC_OLPC_GAIN_DELTA); | 4313 | (correction[1] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), |
1647 | REG_RMW(ah, AR_PHY_TPC_11_B2, | 4314 | AR_PHY_TPC_OLPC_GAIN_DELTA); |
1648 | (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), | 4315 | if (ah->caps.tx_chainmask & BIT(2)) |
1649 | AR_PHY_TPC_OLPC_GAIN_DELTA); | 4316 | REG_RMW(ah, AR_PHY_TPC_11_B2, |
4317 | (correction[2] << AR_PHY_TPC_OLPC_GAIN_DELTA_S), | ||
4318 | AR_PHY_TPC_OLPC_GAIN_DELTA); | ||
1650 | 4319 | ||
1651 | /* enable open loop power control on chip */ | 4320 | /* enable open loop power control on chip */ |
1652 | REG_RMW(ah, AR_PHY_TPC_6_B0, | 4321 | REG_RMW(ah, AR_PHY_TPC_6_B0, |
1653 | (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), | 4322 | (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), |
1654 | AR_PHY_TPC_6_ERROR_EST_MODE); | 4323 | AR_PHY_TPC_6_ERROR_EST_MODE); |
1655 | REG_RMW(ah, AR_PHY_TPC_6_B1, | 4324 | if (ah->caps.tx_chainmask & BIT(1)) |
1656 | (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), | 4325 | REG_RMW(ah, AR_PHY_TPC_6_B1, |
1657 | AR_PHY_TPC_6_ERROR_EST_MODE); | 4326 | (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), |
1658 | REG_RMW(ah, AR_PHY_TPC_6_B2, | 4327 | AR_PHY_TPC_6_ERROR_EST_MODE); |
1659 | (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), | 4328 | if (ah->caps.tx_chainmask & BIT(2)) |
1660 | AR_PHY_TPC_6_ERROR_EST_MODE); | 4329 | REG_RMW(ah, AR_PHY_TPC_6_B2, |
4330 | (3 << AR_PHY_TPC_6_ERROR_EST_MODE_S), | ||
4331 | AR_PHY_TPC_6_ERROR_EST_MODE); | ||
1661 | 4332 | ||
1662 | /* | 4333 | /* |
1663 | * enable temperature compensation | 4334 | * enable temperature compensation |
@@ -1665,7 +4336,16 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah, | |||
1665 | */ | 4336 | */ |
1666 | if (frequency < 4000) | 4337 | if (frequency < 4000) |
1667 | tempSlope = eep->modalHeader2G.tempSlope; | 4338 | tempSlope = eep->modalHeader2G.tempSlope; |
1668 | else | 4339 | else if (eep->base_ext2.tempSlopeLow != 0) { |
4340 | t[0] = eep->base_ext2.tempSlopeLow; | ||
4341 | f[0] = 5180; | ||
4342 | t[1] = eep->modalHeader5G.tempSlope; | ||
4343 | f[1] = 5500; | ||
4344 | t[2] = eep->base_ext2.tempSlopeHigh; | ||
4345 | f[2] = 5785; | ||
4346 | tempSlope = ar9003_hw_power_interpolate((s32) frequency, | ||
4347 | f, t, 3); | ||
4348 | } else | ||
1669 | tempSlope = eep->modalHeader5G.tempSlope; | 4349 | tempSlope = eep->modalHeader5G.tempSlope; |
1670 | 4350 | ||
1671 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope); | 4351 | REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope); |
@@ -1753,11 +4433,11 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
1753 | 4433 | ||
1754 | /* interpolate */ | 4434 | /* interpolate */ |
1755 | for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { | 4435 | for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { |
1756 | ath_print(common, ATH_DBG_EEPROM, | 4436 | ath_dbg(common, ATH_DBG_EEPROM, |
1757 | "ch=%d f=%d low=%d %d h=%d %d\n", | 4437 | "ch=%d f=%d low=%d %d h=%d %d\n", |
1758 | ichain, frequency, lfrequency[ichain], | 4438 | ichain, frequency, lfrequency[ichain], |
1759 | lcorrection[ichain], hfrequency[ichain], | 4439 | lcorrection[ichain], hfrequency[ichain], |
1760 | hcorrection[ichain]); | 4440 | hcorrection[ichain]); |
1761 | /* they're the same, so just pick one */ | 4441 | /* they're the same, so just pick one */ |
1762 | if (hfrequency[ichain] == lfrequency[ichain]) { | 4442 | if (hfrequency[ichain] == lfrequency[ichain]) { |
1763 | correction[ichain] = lcorrection[ichain]; | 4443 | correction[ichain] = lcorrection[ichain]; |
@@ -1769,25 +4449,23 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
1769 | /* so is the high frequency, interpolate */ | 4449 | /* so is the high frequency, interpolate */ |
1770 | if (hfrequency[ichain] - frequency < 1000) { | 4450 | if (hfrequency[ichain] - frequency < 1000) { |
1771 | 4451 | ||
1772 | correction[ichain] = lcorrection[ichain] + | 4452 | correction[ichain] = interpolate(frequency, |
1773 | (((frequency - lfrequency[ichain]) * | 4453 | lfrequency[ichain], |
1774 | (hcorrection[ichain] - | 4454 | hfrequency[ichain], |
1775 | lcorrection[ichain])) / | 4455 | lcorrection[ichain], |
1776 | (hfrequency[ichain] - lfrequency[ichain])); | 4456 | hcorrection[ichain]); |
1777 | 4457 | ||
1778 | temperature[ichain] = ltemperature[ichain] + | 4458 | temperature[ichain] = interpolate(frequency, |
1779 | (((frequency - lfrequency[ichain]) * | 4459 | lfrequency[ichain], |
1780 | (htemperature[ichain] - | 4460 | hfrequency[ichain], |
1781 | ltemperature[ichain])) / | 4461 | ltemperature[ichain], |
1782 | (hfrequency[ichain] - lfrequency[ichain])); | 4462 | htemperature[ichain]); |
1783 | 4463 | ||
1784 | voltage[ichain] = | 4464 | voltage[ichain] = interpolate(frequency, |
1785 | lvoltage[ichain] + | 4465 | lfrequency[ichain], |
1786 | (((frequency - | 4466 | hfrequency[ichain], |
1787 | lfrequency[ichain]) * (hvoltage[ichain] - | 4467 | lvoltage[ichain], |
1788 | lvoltage[ichain])) | 4468 | hvoltage[ichain]); |
1789 | / (hfrequency[ichain] - | ||
1790 | lfrequency[ichain])); | ||
1791 | } | 4469 | } |
1792 | /* only low is good, use it */ | 4470 | /* only low is good, use it */ |
1793 | else { | 4471 | else { |
@@ -1811,9 +4489,9 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) | |||
1811 | ar9003_hw_power_control_override(ah, frequency, correction, voltage, | 4489 | ar9003_hw_power_control_override(ah, frequency, correction, voltage, |
1812 | temperature); | 4490 | temperature); |
1813 | 4491 | ||
1814 | ath_print(common, ATH_DBG_EEPROM, | 4492 | ath_dbg(common, ATH_DBG_EEPROM, |
1815 | "for frequency=%d, calibration correction = %d %d %d\n", | 4493 | "for frequency=%d, calibration correction = %d %d %d\n", |
1816 | frequency, correction[0], correction[1], correction[2]); | 4494 | frequency, correction[0], correction[1], correction[2]); |
1817 | 4495 | ||
1818 | return 0; | 4496 | return 0; |
1819 | } | 4497 | } |
@@ -1827,9 +4505,9 @@ static u16 ar9003_hw_get_direct_edge_power(struct ar9300_eeprom *eep, | |||
1827 | struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G; | 4505 | struct cal_ctl_data_5g *ctl_5g = eep->ctlPowerData_5G; |
1828 | 4506 | ||
1829 | if (is2GHz) | 4507 | if (is2GHz) |
1830 | return ctl_2g[idx].ctlEdges[edge].tPower; | 4508 | return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge]); |
1831 | else | 4509 | else |
1832 | return ctl_5g[idx].ctlEdges[edge].tPower; | 4510 | return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge]); |
1833 | } | 4511 | } |
1834 | 4512 | ||
1835 | static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep, | 4513 | static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep, |
@@ -1847,15 +4525,15 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep, | |||
1847 | 4525 | ||
1848 | if (is2GHz) { | 4526 | if (is2GHz) { |
1849 | if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq && | 4527 | if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 1) < freq && |
1850 | ctl_2g[idx].ctlEdges[edge - 1].flag) | 4528 | CTL_EDGE_FLAGS(ctl_2g[idx].ctlEdges[edge - 1])) |
1851 | return ctl_2g[idx].ctlEdges[edge - 1].tPower; | 4529 | return CTL_EDGE_TPOWER(ctl_2g[idx].ctlEdges[edge - 1]); |
1852 | } else { | 4530 | } else { |
1853 | if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq && | 4531 | if (ath9k_hw_fbin2freq(ctl_freqbin[edge - 1], 0) < freq && |
1854 | ctl_5g[idx].ctlEdges[edge - 1].flag) | 4532 | CTL_EDGE_FLAGS(ctl_5g[idx].ctlEdges[edge - 1])) |
1855 | return ctl_5g[idx].ctlEdges[edge - 1].tPower; | 4533 | return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]); |
1856 | } | 4534 | } |
1857 | 4535 | ||
1858 | return AR9300_MAX_RATE_POWER; | 4536 | return MAX_RATE_POWER; |
1859 | } | 4537 | } |
1860 | 4538 | ||
1861 | /* | 4539 | /* |
@@ -1864,7 +4542,7 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep, | |||
1864 | static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep, | 4542 | static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep, |
1865 | u16 freq, int idx, bool is2GHz) | 4543 | u16 freq, int idx, bool is2GHz) |
1866 | { | 4544 | { |
1867 | u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER; | 4545 | u16 twiceMaxEdgePower = MAX_RATE_POWER; |
1868 | u8 *ctl_freqbin = is2GHz ? | 4546 | u8 *ctl_freqbin = is2GHz ? |
1869 | &eep->ctl_freqbin_2G[idx][0] : | 4547 | &eep->ctl_freqbin_2G[idx][0] : |
1870 | &eep->ctl_freqbin_5G[idx][0]; | 4548 | &eep->ctl_freqbin_5G[idx][0]; |
@@ -1874,7 +4552,7 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep, | |||
1874 | 4552 | ||
1875 | /* Get the edge power */ | 4553 | /* Get the edge power */ |
1876 | for (edge = 0; | 4554 | for (edge = 0; |
1877 | (edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED); | 4555 | (edge < num_edges) && (ctl_freqbin[edge] != AR5416_BCHAN_UNUSED); |
1878 | edge++) { | 4556 | edge++) { |
1879 | /* | 4557 | /* |
1880 | * If there's an exact channel match or an inband flag set | 4558 | * If there's an exact channel match or an inband flag set |
@@ -1912,21 +4590,23 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
1912 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 4590 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
1913 | struct ath_common *common = ath9k_hw_common(ah); | 4591 | struct ath_common *common = ath9k_hw_common(ah); |
1914 | struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; | 4592 | struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep; |
1915 | u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER; | 4593 | u16 twiceMaxEdgePower = MAX_RATE_POWER; |
1916 | static const u16 tpScaleReductionTable[5] = { | 4594 | static const u16 tpScaleReductionTable[5] = { |
1917 | 0, 3, 6, 9, AR9300_MAX_RATE_POWER | 4595 | 0, 3, 6, 9, MAX_RATE_POWER |
1918 | }; | 4596 | }; |
1919 | int i; | 4597 | int i; |
1920 | int16_t twiceLargestAntenna; | 4598 | int16_t twiceLargestAntenna; |
1921 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | 4599 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; |
1922 | u16 ctlModesFor11a[] = { | 4600 | static const u16 ctlModesFor11a[] = { |
1923 | CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 | 4601 | CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 |
1924 | }; | 4602 | }; |
1925 | u16 ctlModesFor11g[] = { | 4603 | static const u16 ctlModesFor11g[] = { |
1926 | CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, | 4604 | CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, |
1927 | CTL_11G_EXT, CTL_2GHT40 | 4605 | CTL_11G_EXT, CTL_2GHT40 |
1928 | }; | 4606 | }; |
1929 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | 4607 | u16 numCtlModes; |
4608 | const u16 *pCtlMode; | ||
4609 | u16 ctlMode, freq; | ||
1930 | struct chan_centers centers; | 4610 | struct chan_centers centers; |
1931 | u8 *ctlIndex; | 4611 | u8 *ctlIndex; |
1932 | u8 ctlNum; | 4612 | u8 ctlNum; |
@@ -1965,10 +4645,16 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
1965 | case 1: | 4645 | case 1: |
1966 | break; | 4646 | break; |
1967 | case 2: | 4647 | case 2: |
1968 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | 4648 | if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) |
4649 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
4650 | else | ||
4651 | scaledPower = 0; | ||
1969 | break; | 4652 | break; |
1970 | case 3: | 4653 | case 3: |
1971 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | 4654 | if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) |
4655 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
4656 | else | ||
4657 | scaledPower = 0; | ||
1972 | break; | 4658 | break; |
1973 | } | 4659 | } |
1974 | 4660 | ||
@@ -2016,11 +4702,10 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
2016 | else | 4702 | else |
2017 | freq = centers.ctl_center; | 4703 | freq = centers.ctl_center; |
2018 | 4704 | ||
2019 | ath_print(common, ATH_DBG_REGULATORY, | 4705 | ath_dbg(common, ATH_DBG_REGULATORY, |
2020 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, " | 4706 | "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, EXT_ADDITIVE %d\n", |
2021 | "EXT_ADDITIVE %d\n", | 4707 | ctlMode, numCtlModes, isHt40CtlMode, |
2022 | ctlMode, numCtlModes, isHt40CtlMode, | 4708 | (pCtlMode[ctlMode] & EXT_ADDITIVE)); |
2023 | (pCtlMode[ctlMode] & EXT_ADDITIVE)); | ||
2024 | 4709 | ||
2025 | /* walk through each CTL index stored in EEPROM */ | 4710 | /* walk through each CTL index stored in EEPROM */ |
2026 | if (is2ghz) { | 4711 | if (is2ghz) { |
@@ -2032,12 +4717,10 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
2032 | } | 4717 | } |
2033 | 4718 | ||
2034 | for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) { | 4719 | for (i = 0; (i < ctlNum) && ctlIndex[i]; i++) { |
2035 | ath_print(common, ATH_DBG_REGULATORY, | 4720 | ath_dbg(common, ATH_DBG_REGULATORY, |
2036 | "LOOP-Ctlidx %d: cfgCtl 0x%2.2x " | 4721 | "LOOP-Ctlidx %d: cfgCtl 0x%2.2x pCtlMode 0x%2.2x ctlIndex 0x%2.2x chan %d\n", |
2037 | "pCtlMode 0x%2.2x ctlIndex 0x%2.2x " | 4722 | i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i], |
2038 | "chan %dn", | 4723 | chan->channel); |
2039 | i, cfgCtl, pCtlMode[ctlMode], ctlIndex[i], | ||
2040 | chan->channel); | ||
2041 | 4724 | ||
2042 | /* | 4725 | /* |
2043 | * compare test group from regulatory | 4726 | * compare test group from regulatory |
@@ -2076,11 +4759,10 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
2076 | 4759 | ||
2077 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); | 4760 | minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); |
2078 | 4761 | ||
2079 | ath_print(common, ATH_DBG_REGULATORY, | 4762 | ath_dbg(common, ATH_DBG_REGULATORY, |
2080 | "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d " | 4763 | "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d sP %d minCtlPwr %d\n", |
2081 | "sP %d minCtlPwr %d\n", | 4764 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, |
2082 | ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower, | 4765 | scaledPower, minCtlPower); |
2083 | scaledPower, minCtlPower); | ||
2084 | 4766 | ||
2085 | /* Apply ctl mode to correct target power set */ | 4767 | /* Apply ctl mode to correct target power set */ |
2086 | switch (pCtlMode[ctlMode]) { | 4768 | switch (pCtlMode[ctlMode]) { |
@@ -2127,40 +4809,101 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
2127 | } /* end ctl mode checking */ | 4809 | } /* end ctl mode checking */ |
2128 | } | 4810 | } |
2129 | 4811 | ||
4812 | static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx) | ||
4813 | { | ||
4814 | u8 mod_idx = mcs_idx % 8; | ||
4815 | |||
4816 | if (mod_idx <= 3) | ||
4817 | return mod_idx ? (base_pwridx + 1) : base_pwridx; | ||
4818 | else | ||
4819 | return base_pwridx + 4 * (mcs_idx / 8) + mod_idx - 2; | ||
4820 | } | ||
4821 | |||
2130 | static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, | 4822 | static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, |
2131 | struct ath9k_channel *chan, u16 cfgCtl, | 4823 | struct ath9k_channel *chan, u16 cfgCtl, |
2132 | u8 twiceAntennaReduction, | 4824 | u8 twiceAntennaReduction, |
2133 | u8 twiceMaxRegulatoryPower, | 4825 | u8 twiceMaxRegulatoryPower, |
2134 | u8 powerLimit) | 4826 | u8 powerLimit, bool test) |
2135 | { | 4827 | { |
4828 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
2136 | struct ath_common *common = ath9k_hw_common(ah); | 4829 | struct ath_common *common = ath9k_hw_common(ah); |
4830 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
4831 | struct ar9300_modal_eep_header *modal_hdr; | ||
2137 | u8 targetPowerValT2[ar9300RateSize]; | 4832 | u8 targetPowerValT2[ar9300RateSize]; |
2138 | unsigned int i = 0; | 4833 | u8 target_power_val_t2_eep[ar9300RateSize]; |
4834 | unsigned int i = 0, paprd_scale_factor = 0; | ||
4835 | u8 pwr_idx, min_pwridx = 0; | ||
2139 | 4836 | ||
2140 | ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2); | 4837 | ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2); |
4838 | |||
4839 | if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) { | ||
4840 | if (IS_CHAN_2GHZ(chan)) | ||
4841 | modal_hdr = &eep->modalHeader2G; | ||
4842 | else | ||
4843 | modal_hdr = &eep->modalHeader5G; | ||
4844 | |||
4845 | ah->paprd_ratemask = | ||
4846 | le32_to_cpu(modal_hdr->papdRateMaskHt20) & | ||
4847 | AR9300_PAPRD_RATE_MASK; | ||
4848 | |||
4849 | ah->paprd_ratemask_ht40 = | ||
4850 | le32_to_cpu(modal_hdr->papdRateMaskHt40) & | ||
4851 | AR9300_PAPRD_RATE_MASK; | ||
4852 | |||
4853 | paprd_scale_factor = ar9003_get_paprd_scale_factor(ah, chan); | ||
4854 | min_pwridx = IS_CHAN_HT40(chan) ? ALL_TARGET_HT40_0_8_16 : | ||
4855 | ALL_TARGET_HT20_0_8_16; | ||
4856 | |||
4857 | if (!ah->paprd_table_write_done) { | ||
4858 | memcpy(target_power_val_t2_eep, targetPowerValT2, | ||
4859 | sizeof(targetPowerValT2)); | ||
4860 | for (i = 0; i < 24; i++) { | ||
4861 | pwr_idx = mcsidx_to_tgtpwridx(i, min_pwridx); | ||
4862 | if (ah->paprd_ratemask & (1 << i)) { | ||
4863 | if (targetPowerValT2[pwr_idx] && | ||
4864 | targetPowerValT2[pwr_idx] == | ||
4865 | target_power_val_t2_eep[pwr_idx]) | ||
4866 | targetPowerValT2[pwr_idx] -= | ||
4867 | paprd_scale_factor; | ||
4868 | } | ||
4869 | } | ||
4870 | } | ||
4871 | memcpy(target_power_val_t2_eep, targetPowerValT2, | ||
4872 | sizeof(targetPowerValT2)); | ||
4873 | } | ||
4874 | |||
2141 | ar9003_hw_set_power_per_rate_table(ah, chan, | 4875 | ar9003_hw_set_power_per_rate_table(ah, chan, |
2142 | targetPowerValT2, cfgCtl, | 4876 | targetPowerValT2, cfgCtl, |
2143 | twiceAntennaReduction, | 4877 | twiceAntennaReduction, |
2144 | twiceMaxRegulatoryPower, | 4878 | twiceMaxRegulatoryPower, |
2145 | powerLimit); | 4879 | powerLimit); |
2146 | 4880 | ||
2147 | while (i < ar9300RateSize) { | 4881 | if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) { |
2148 | ath_print(common, ATH_DBG_EEPROM, | 4882 | for (i = 0; i < ar9300RateSize; i++) { |
2149 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | 4883 | if ((ah->paprd_ratemask & (1 << i)) && |
2150 | i++; | 4884 | (abs(targetPowerValT2[i] - |
2151 | ath_print(common, ATH_DBG_EEPROM, | 4885 | target_power_val_t2_eep[i]) > |
2152 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | 4886 | paprd_scale_factor)) { |
2153 | i++; | 4887 | ah->paprd_ratemask &= ~(1 << i); |
2154 | ath_print(common, ATH_DBG_EEPROM, | 4888 | ath_dbg(common, ATH_DBG_EEPROM, |
2155 | "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]); | 4889 | "paprd disabled for mcs %d\n", i); |
2156 | i++; | 4890 | } |
2157 | ath_print(common, ATH_DBG_EEPROM, | 4891 | } |
2158 | "TPC[%02d] 0x%08x\n\n", i, targetPowerValT2[i]); | ||
2159 | i++; | ||
2160 | } | 4892 | } |
2161 | 4893 | ||
2162 | /* Write target power array to registers */ | 4894 | regulatory->max_power_level = 0; |
2163 | ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); | 4895 | for (i = 0; i < ar9300RateSize; i++) { |
4896 | if (targetPowerValT2[i] > regulatory->max_power_level) | ||
4897 | regulatory->max_power_level = targetPowerValT2[i]; | ||
4898 | } | ||
4899 | |||
4900 | if (test) | ||
4901 | return; | ||
4902 | |||
4903 | for (i = 0; i < ar9300RateSize; i++) { | ||
4904 | ath_dbg(common, ATH_DBG_EEPROM, | ||
4905 | "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); | ||
4906 | } | ||
2164 | 4907 | ||
2165 | /* | 4908 | /* |
2166 | * This is the TX power we send back to driver core, | 4909 | * This is the TX power we send back to driver core, |
@@ -2180,8 +4923,24 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, | |||
2180 | i = ALL_TARGET_HT20_0_8_16; /* ht20 */ | 4923 | i = ALL_TARGET_HT20_0_8_16; /* ht20 */ |
2181 | 4924 | ||
2182 | ah->txpower_limit = targetPowerValT2[i]; | 4925 | ah->txpower_limit = targetPowerValT2[i]; |
4926 | regulatory->max_power_level = targetPowerValT2[i]; | ||
2183 | 4927 | ||
4928 | /* Write target power array to registers */ | ||
4929 | ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); | ||
2184 | ar9003_hw_calibration_apply(ah, chan->channel); | 4930 | ar9003_hw_calibration_apply(ah, chan->channel); |
4931 | |||
4932 | if (IS_CHAN_2GHZ(chan)) { | ||
4933 | if (IS_CHAN_HT40(chan)) | ||
4934 | i = ALL_TARGET_HT40_0_8_16; | ||
4935 | else | ||
4936 | i = ALL_TARGET_HT20_0_8_16; | ||
4937 | } else { | ||
4938 | if (IS_CHAN_HT40(chan)) | ||
4939 | i = ALL_TARGET_HT40_7; | ||
4940 | else | ||
4941 | i = ALL_TARGET_HT20_7; | ||
4942 | } | ||
4943 | ah->paprd_target_power = targetPowerValT2[i]; | ||
2185 | } | 4944 | } |
2186 | 4945 | ||
2187 | static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah, | 4946 | static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah, |
@@ -2204,14 +4963,43 @@ s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah) | |||
2204 | return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */ | 4963 | return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */ |
2205 | } | 4964 | } |
2206 | 4965 | ||
4966 | u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz) | ||
4967 | { | ||
4968 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
4969 | |||
4970 | if (is_2ghz) | ||
4971 | return eep->modalHeader2G.spurChans; | ||
4972 | else | ||
4973 | return eep->modalHeader5G.spurChans; | ||
4974 | } | ||
4975 | |||
4976 | unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, | ||
4977 | struct ath9k_channel *chan) | ||
4978 | { | ||
4979 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
4980 | |||
4981 | if (IS_CHAN_2GHZ(chan)) | ||
4982 | return MS(le32_to_cpu(eep->modalHeader2G.papdRateMaskHt20), | ||
4983 | AR9300_PAPRD_SCALE_1); | ||
4984 | else { | ||
4985 | if (chan->channel >= 5700) | ||
4986 | return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20), | ||
4987 | AR9300_PAPRD_SCALE_1); | ||
4988 | else if (chan->channel >= 5400) | ||
4989 | return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), | ||
4990 | AR9300_PAPRD_SCALE_2); | ||
4991 | else | ||
4992 | return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), | ||
4993 | AR9300_PAPRD_SCALE_1); | ||
4994 | } | ||
4995 | } | ||
4996 | |||
2207 | const struct eeprom_ops eep_ar9300_ops = { | 4997 | const struct eeprom_ops eep_ar9300_ops = { |
2208 | .check_eeprom = ath9k_hw_ar9300_check_eeprom, | 4998 | .check_eeprom = ath9k_hw_ar9300_check_eeprom, |
2209 | .get_eeprom = ath9k_hw_ar9300_get_eeprom, | 4999 | .get_eeprom = ath9k_hw_ar9300_get_eeprom, |
2210 | .fill_eeprom = ath9k_hw_ar9300_fill_eeprom, | 5000 | .fill_eeprom = ath9k_hw_ar9300_fill_eeprom, |
2211 | .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver, | 5001 | .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver, |
2212 | .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev, | 5002 | .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev, |
2213 | .get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config, | ||
2214 | .get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg, | ||
2215 | .set_board_values = ath9k_hw_ar9300_set_board_values, | 5003 | .set_board_values = ath9k_hw_ar9300_set_board_values, |
2216 | .set_addac = ath9k_hw_ar9300_set_addac, | 5004 | .set_addac = ath9k_hw_ar9300_set_addac, |
2217 | .set_txpower = ath9k_hw_ar9300_set_txpower, | 5005 | .set_txpower = ath9k_hw_ar9300_set_txpower, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 3c533bb983c7..ab21a4915981 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | |||
@@ -1,3 +1,19 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 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 | |||
1 | #ifndef AR9003_EEPROM_H | 17 | #ifndef AR9003_EEPROM_H |
2 | #define AR9003_EEPROM_H | 18 | #define AR9003_EEPROM_H |
3 | 19 | ||
@@ -20,47 +36,22 @@ | |||
20 | /* #define AR9300_NUM_CTLS 21 */ | 36 | /* #define AR9300_NUM_CTLS 21 */ |
21 | #define AR9300_NUM_CTLS_5G 9 | 37 | #define AR9300_NUM_CTLS_5G 9 |
22 | #define AR9300_NUM_CTLS_2G 12 | 38 | #define AR9300_NUM_CTLS_2G 12 |
23 | #define AR9300_CTL_MODE_M 0xF | ||
24 | #define AR9300_NUM_BAND_EDGES_5G 8 | 39 | #define AR9300_NUM_BAND_EDGES_5G 8 |
25 | #define AR9300_NUM_BAND_EDGES_2G 4 | 40 | #define AR9300_NUM_BAND_EDGES_2G 4 |
26 | #define AR9300_NUM_PD_GAINS 4 | ||
27 | #define AR9300_PD_GAINS_IN_MASK 4 | ||
28 | #define AR9300_PD_GAIN_ICEPTS 5 | ||
29 | #define AR9300_EEPROM_MODAL_SPURS 5 | ||
30 | #define AR9300_MAX_RATE_POWER 63 | ||
31 | #define AR9300_NUM_PDADC_VALUES 128 | ||
32 | #define AR9300_NUM_RATES 16 | ||
33 | #define AR9300_BCHAN_UNUSED 0xFF | ||
34 | #define AR9300_MAX_PWR_RANGE_IN_HALF_DB 64 | ||
35 | #define AR9300_OPFLAGS_11A 0x01 | ||
36 | #define AR9300_OPFLAGS_11G 0x02 | ||
37 | #define AR9300_OPFLAGS_5G_HT40 0x04 | ||
38 | #define AR9300_OPFLAGS_2G_HT40 0x08 | ||
39 | #define AR9300_OPFLAGS_5G_HT20 0x10 | ||
40 | #define AR9300_OPFLAGS_2G_HT20 0x20 | ||
41 | #define AR9300_EEPMISC_BIG_ENDIAN 0x01 | 41 | #define AR9300_EEPMISC_BIG_ENDIAN 0x01 |
42 | #define AR9300_EEPMISC_WOW 0x02 | 42 | #define AR9300_EEPMISC_WOW 0x02 |
43 | #define AR9300_CUSTOMER_DATA_SIZE 20 | 43 | #define AR9300_CUSTOMER_DATA_SIZE 20 |
44 | 44 | ||
45 | #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) | ||
46 | #define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x)) | 45 | #define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x)) |
47 | #define AR9300_MAX_CHAINS 3 | 46 | #define AR9300_MAX_CHAINS 3 |
48 | #define AR9300_ANT_16S 25 | 47 | #define AR9300_ANT_16S 25 |
49 | #define AR9300_FUTURE_MODAL_SZ 6 | 48 | #define AR9300_FUTURE_MODAL_SZ 6 |
50 | 49 | ||
51 | #define AR9300_NUM_ANT_CHAIN_FIELDS 7 | 50 | #define AR9300_PAPRD_RATE_MASK 0x01ffffff |
52 | #define AR9300_NUM_ANT_COMMON_FIELDS 4 | 51 | #define AR9300_PAPRD_SCALE_1 0x0e000000 |
53 | #define AR9300_SIZE_ANT_CHAIN_FIELD 3 | 52 | #define AR9300_PAPRD_SCALE_1_S 25 |
54 | #define AR9300_SIZE_ANT_COMMON_FIELD 4 | 53 | #define AR9300_PAPRD_SCALE_2 0x70000000 |
55 | #define AR9300_ANT_CHAIN_MASK 0x7 | 54 | #define AR9300_PAPRD_SCALE_2_S 28 |
56 | #define AR9300_ANT_COMMON_MASK 0xf | ||
57 | #define AR9300_CHAIN_0_IDX 0 | ||
58 | #define AR9300_CHAIN_1_IDX 1 | ||
59 | #define AR9300_CHAIN_2_IDX 2 | ||
60 | |||
61 | #define AR928X_NUM_ANT_CHAIN_FIELDS 6 | ||
62 | #define AR928X_SIZE_ANT_CHAIN_FIELD 2 | ||
63 | #define AR928X_ANT_CHAIN_MASK 0x3 | ||
64 | 55 | ||
65 | /* Delta from which to start power to pdadc table */ | 56 | /* Delta from which to start power to pdadc table */ |
66 | /* This offset is used in both open loop and closed loop power control | 57 | /* This offset is used in both open loop and closed loop power control |
@@ -71,14 +62,20 @@ | |||
71 | */ | 62 | */ |
72 | #define AR9300_PWR_TABLE_OFFSET 0 | 63 | #define AR9300_PWR_TABLE_OFFSET 0 |
73 | 64 | ||
74 | /* enable flags for voltage and temp compensation */ | ||
75 | #define ENABLE_TEMP_COMPENSATION 0x01 | ||
76 | #define ENABLE_VOLT_COMPENSATION 0x02 | ||
77 | /* byte addressable */ | 65 | /* byte addressable */ |
78 | #define AR9300_EEPROM_SIZE (16*1024) | 66 | #define AR9300_EEPROM_SIZE (16*1024) |
79 | #define FIXED_CCA_THRESHOLD 15 | ||
80 | 67 | ||
68 | #define AR9300_BASE_ADDR_4K 0xfff | ||
81 | #define AR9300_BASE_ADDR 0x3ff | 69 | #define AR9300_BASE_ADDR 0x3ff |
70 | #define AR9300_BASE_ADDR_512 0x1ff | ||
71 | |||
72 | #define AR9300_OTP_BASE 0x14000 | ||
73 | #define AR9300_OTP_STATUS 0x15f18 | ||
74 | #define AR9300_OTP_STATUS_TYPE 0x7 | ||
75 | #define AR9300_OTP_STATUS_VALID 0x4 | ||
76 | #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 | ||
77 | #define AR9300_OTP_STATUS_SM_BUSY 0x1 | ||
78 | #define AR9300_OTP_READ_DATA 0x15f1c | ||
82 | 79 | ||
83 | enum targetPowerHTRates { | 80 | enum targetPowerHTRates { |
84 | HT_TARGET_RATE_0_8_16, | 81 | HT_TARGET_RATE_0_8_16, |
@@ -216,7 +213,7 @@ struct ar9300_modal_eep_header { | |||
216 | int8_t tempSlope; | 213 | int8_t tempSlope; |
217 | int8_t voltSlope; | 214 | int8_t voltSlope; |
218 | /* spur channels in usual fbin coding format */ | 215 | /* spur channels in usual fbin coding format */ |
219 | u8 spurChans[AR9300_EEPROM_MODAL_SPURS]; | 216 | u8 spurChans[AR_EEPROM_MODAL_SPURS]; |
220 | /* 3 Check if the register is per chain */ | 217 | /* 3 Check if the register is per chain */ |
221 | int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS]; | 218 | int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS]; |
222 | u8 ob[AR9300_MAX_CHAINS]; | 219 | u8 ob[AR9300_MAX_CHAINS]; |
@@ -236,7 +233,7 @@ struct ar9300_modal_eep_header { | |||
236 | u8 thresh62; | 233 | u8 thresh62; |
237 | __le32 papdRateMaskHt20; | 234 | __le32 papdRateMaskHt20; |
238 | __le32 papdRateMaskHt40; | 235 | __le32 papdRateMaskHt40; |
239 | u8 futureModal[24]; | 236 | u8 futureModal[10]; |
240 | } __packed; | 237 | } __packed; |
241 | 238 | ||
242 | struct ar9300_cal_data_per_freq_op_loop { | 239 | struct ar9300_cal_data_per_freq_op_loop { |
@@ -261,17 +258,26 @@ struct cal_tgt_pow_ht { | |||
261 | u8 tPow2x[14]; | 258 | u8 tPow2x[14]; |
262 | } __packed; | 259 | } __packed; |
263 | 260 | ||
264 | struct cal_ctl_edge_pwr { | ||
265 | u8 tPower:6, | ||
266 | flag:2; | ||
267 | } __packed; | ||
268 | |||
269 | struct cal_ctl_data_2g { | 261 | struct cal_ctl_data_2g { |
270 | struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_2G]; | 262 | u8 ctlEdges[AR9300_NUM_BAND_EDGES_2G]; |
271 | } __packed; | 263 | } __packed; |
272 | 264 | ||
273 | struct cal_ctl_data_5g { | 265 | struct cal_ctl_data_5g { |
274 | struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G]; | 266 | u8 ctlEdges[AR9300_NUM_BAND_EDGES_5G]; |
267 | } __packed; | ||
268 | |||
269 | struct ar9300_BaseExtension_1 { | ||
270 | u8 ant_div_control; | ||
271 | u8 future[13]; | ||
272 | } __packed; | ||
273 | |||
274 | struct ar9300_BaseExtension_2 { | ||
275 | int8_t tempSlopeLow; | ||
276 | int8_t tempSlopeHigh; | ||
277 | u8 xatten1DBLow[AR9300_MAX_CHAINS]; | ||
278 | u8 xatten1MarginLow[AR9300_MAX_CHAINS]; | ||
279 | u8 xatten1DBHigh[AR9300_MAX_CHAINS]; | ||
280 | u8 xatten1MarginHigh[AR9300_MAX_CHAINS]; | ||
275 | } __packed; | 281 | } __packed; |
276 | 282 | ||
277 | struct ar9300_eeprom { | 283 | struct ar9300_eeprom { |
@@ -283,6 +289,7 @@ struct ar9300_eeprom { | |||
283 | struct ar9300_base_eep_hdr baseEepHeader; | 289 | struct ar9300_base_eep_hdr baseEepHeader; |
284 | 290 | ||
285 | struct ar9300_modal_eep_header modalHeader2G; | 291 | struct ar9300_modal_eep_header modalHeader2G; |
292 | struct ar9300_BaseExtension_1 base_ext1; | ||
286 | u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS]; | 293 | u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS]; |
287 | struct ar9300_cal_data_per_freq_op_loop | 294 | struct ar9300_cal_data_per_freq_op_loop |
288 | calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS]; | 295 | calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS]; |
@@ -302,6 +309,7 @@ struct ar9300_eeprom { | |||
302 | u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G]; | 309 | u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G]; |
303 | struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G]; | 310 | struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G]; |
304 | struct ar9300_modal_eep_header modalHeader5G; | 311 | struct ar9300_modal_eep_header modalHeader5G; |
312 | struct ar9300_BaseExtension_2 base_ext2; | ||
305 | u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS]; | 313 | u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS]; |
306 | struct ar9300_cal_data_per_freq_op_loop | 314 | struct ar9300_cal_data_per_freq_op_loop |
307 | calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS]; | 315 | calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS]; |
@@ -322,4 +330,8 @@ struct ar9300_eeprom { | |||
322 | s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah); | 330 | s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah); |
323 | s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah); | 331 | s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah); |
324 | 332 | ||
333 | u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz); | ||
334 | |||
335 | unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, | ||
336 | struct ath9k_channel *chan); | ||
325 | #endif | 337 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 064168909108..392bf0f8ff16 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -16,174 +16,203 @@ | |||
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "ar9003_mac.h" | 18 | #include "ar9003_mac.h" |
19 | #include "ar9003_2p0_initvals.h" | ||
20 | #include "ar9003_2p2_initvals.h" | 19 | #include "ar9003_2p2_initvals.h" |
20 | #include "ar9485_initvals.h" | ||
21 | #include "ar9340_initvals.h" | ||
21 | 22 | ||
22 | /* General hardware code for the AR9003 hadware family */ | 23 | /* General hardware code for the AR9003 hadware family */ |
23 | 24 | ||
24 | static bool ar9003_hw_macversion_supported(u32 macversion) | ||
25 | { | ||
26 | switch (macversion) { | ||
27 | case AR_SREV_VERSION_9300: | ||
28 | return true; | ||
29 | default: | ||
30 | break; | ||
31 | } | ||
32 | return false; | ||
33 | } | ||
34 | |||
35 | /* AR9003 2.0 */ | ||
36 | static void ar9003_2p0_hw_init_mode_regs(struct ath_hw *ah) | ||
37 | { | ||
38 | /* mac */ | ||
39 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); | ||
40 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | ||
41 | ar9300_2p0_mac_core, | ||
42 | ARRAY_SIZE(ar9300_2p0_mac_core), 2); | ||
43 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], | ||
44 | ar9300_2p0_mac_postamble, | ||
45 | ARRAY_SIZE(ar9300_2p0_mac_postamble), 5); | ||
46 | |||
47 | /* bb */ | ||
48 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); | ||
49 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], | ||
50 | ar9300_2p0_baseband_core, | ||
51 | ARRAY_SIZE(ar9300_2p0_baseband_core), 2); | ||
52 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], | ||
53 | ar9300_2p0_baseband_postamble, | ||
54 | ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5); | ||
55 | |||
56 | /* radio */ | ||
57 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); | ||
58 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], | ||
59 | ar9300_2p0_radio_core, | ||
60 | ARRAY_SIZE(ar9300_2p0_radio_core), 2); | ||
61 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], | ||
62 | ar9300_2p0_radio_postamble, | ||
63 | ARRAY_SIZE(ar9300_2p0_radio_postamble), 5); | ||
64 | |||
65 | /* soc */ | ||
66 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], | ||
67 | ar9300_2p0_soc_preamble, | ||
68 | ARRAY_SIZE(ar9300_2p0_soc_preamble), 2); | ||
69 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); | ||
70 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], | ||
71 | ar9300_2p0_soc_postamble, | ||
72 | ARRAY_SIZE(ar9300_2p0_soc_postamble), 5); | ||
73 | |||
74 | /* rx/tx gain */ | ||
75 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
76 | ar9300Common_rx_gain_table_2p0, | ||
77 | ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2); | ||
78 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
79 | ar9300Modes_lowest_ob_db_tx_gain_table_2p0, | ||
80 | ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), | ||
81 | 5); | ||
82 | |||
83 | /* Load PCIE SERDES settings from INI */ | ||
84 | |||
85 | /* Awake Setting */ | ||
86 | |||
87 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
88 | ar9300PciePhy_pll_on_clkreq_disable_L1_2p0, | ||
89 | ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0), | ||
90 | 2); | ||
91 | |||
92 | /* Sleep Setting */ | ||
93 | |||
94 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
95 | ar9300PciePhy_clkreq_enable_L1_2p0, | ||
96 | ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0), | ||
97 | 2); | ||
98 | |||
99 | /* Fast clock modal settings */ | ||
100 | INIT_INI_ARRAY(&ah->iniModesAdditional, | ||
101 | ar9300Modes_fast_clock_2p0, | ||
102 | ARRAY_SIZE(ar9300Modes_fast_clock_2p0), | ||
103 | 3); | ||
104 | } | ||
105 | |||
106 | /* AR9003 2.2 */ | ||
107 | static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah) | ||
108 | { | ||
109 | /* mac */ | ||
110 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); | ||
111 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | ||
112 | ar9300_2p2_mac_core, | ||
113 | ARRAY_SIZE(ar9300_2p2_mac_core), 2); | ||
114 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], | ||
115 | ar9300_2p2_mac_postamble, | ||
116 | ARRAY_SIZE(ar9300_2p2_mac_postamble), 5); | ||
117 | |||
118 | /* bb */ | ||
119 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); | ||
120 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], | ||
121 | ar9300_2p2_baseband_core, | ||
122 | ARRAY_SIZE(ar9300_2p2_baseband_core), 2); | ||
123 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], | ||
124 | ar9300_2p2_baseband_postamble, | ||
125 | ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5); | ||
126 | |||
127 | /* radio */ | ||
128 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); | ||
129 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], | ||
130 | ar9300_2p2_radio_core, | ||
131 | ARRAY_SIZE(ar9300_2p2_radio_core), 2); | ||
132 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], | ||
133 | ar9300_2p2_radio_postamble, | ||
134 | ARRAY_SIZE(ar9300_2p2_radio_postamble), 5); | ||
135 | |||
136 | /* soc */ | ||
137 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], | ||
138 | ar9300_2p2_soc_preamble, | ||
139 | ARRAY_SIZE(ar9300_2p2_soc_preamble), 2); | ||
140 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); | ||
141 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], | ||
142 | ar9300_2p2_soc_postamble, | ||
143 | ARRAY_SIZE(ar9300_2p2_soc_postamble), 5); | ||
144 | |||
145 | /* rx/tx gain */ | ||
146 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
147 | ar9300Common_rx_gain_table_2p2, | ||
148 | ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2); | ||
149 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
150 | ar9300Modes_lowest_ob_db_tx_gain_table_2p2, | ||
151 | ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), | ||
152 | 5); | ||
153 | |||
154 | /* Load PCIE SERDES settings from INI */ | ||
155 | |||
156 | /* Awake Setting */ | ||
157 | |||
158 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
159 | ar9300PciePhy_pll_on_clkreq_disable_L1_2p2, | ||
160 | ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2), | ||
161 | 2); | ||
162 | |||
163 | /* Sleep Setting */ | ||
164 | |||
165 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
166 | ar9300PciePhy_clkreq_enable_L1_2p2, | ||
167 | ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2), | ||
168 | 2); | ||
169 | |||
170 | /* Fast clock modal settings */ | ||
171 | INIT_INI_ARRAY(&ah->iniModesAdditional, | ||
172 | ar9300Modes_fast_clock_2p2, | ||
173 | ARRAY_SIZE(ar9300Modes_fast_clock_2p2), | ||
174 | 3); | ||
175 | } | ||
176 | |||
177 | /* | 25 | /* |
178 | * The AR9003 family uses a new INI format (pre, core, post | 26 | * The AR9003 family uses a new INI format (pre, core, post |
179 | * arrays per subsystem). | 27 | * arrays per subsystem). This provides support for the |
28 | * AR9003 2.2 chipsets. | ||
180 | */ | 29 | */ |
181 | static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | 30 | static void ar9003_hw_init_mode_regs(struct ath_hw *ah) |
182 | { | 31 | { |
183 | if (AR_SREV_9300_20(ah)) | 32 | if (AR_SREV_9340(ah)) { |
184 | ar9003_2p0_hw_init_mode_regs(ah); | 33 | /* mac */ |
185 | else | 34 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); |
186 | ar9003_2p2_hw_init_mode_regs(ah); | 35 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], |
36 | ar9340_1p0_mac_core, | ||
37 | ARRAY_SIZE(ar9340_1p0_mac_core), 2); | ||
38 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], | ||
39 | ar9340_1p0_mac_postamble, | ||
40 | ARRAY_SIZE(ar9340_1p0_mac_postamble), 5); | ||
41 | |||
42 | /* bb */ | ||
43 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); | ||
44 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], | ||
45 | ar9340_1p0_baseband_core, | ||
46 | ARRAY_SIZE(ar9340_1p0_baseband_core), 2); | ||
47 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], | ||
48 | ar9340_1p0_baseband_postamble, | ||
49 | ARRAY_SIZE(ar9340_1p0_baseband_postamble), 5); | ||
50 | |||
51 | /* radio */ | ||
52 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); | ||
53 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], | ||
54 | ar9340_1p0_radio_core, | ||
55 | ARRAY_SIZE(ar9340_1p0_radio_core), 2); | ||
56 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], | ||
57 | ar9340_1p0_radio_postamble, | ||
58 | ARRAY_SIZE(ar9340_1p0_radio_postamble), 5); | ||
59 | |||
60 | /* soc */ | ||
61 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], | ||
62 | ar9340_1p0_soc_preamble, | ||
63 | ARRAY_SIZE(ar9340_1p0_soc_preamble), 2); | ||
64 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); | ||
65 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], | ||
66 | ar9340_1p0_soc_postamble, | ||
67 | ARRAY_SIZE(ar9340_1p0_soc_postamble), 5); | ||
68 | |||
69 | /* rx/tx gain */ | ||
70 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
71 | ar9340Common_wo_xlna_rx_gain_table_1p0, | ||
72 | ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0), | ||
73 | 5); | ||
74 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
75 | ar9340Modes_high_ob_db_tx_gain_table_1p0, | ||
76 | ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0), | ||
77 | 5); | ||
78 | |||
79 | INIT_INI_ARRAY(&ah->iniModesAdditional, | ||
80 | ar9340Modes_fast_clock_1p0, | ||
81 | ARRAY_SIZE(ar9340Modes_fast_clock_1p0), | ||
82 | 3); | ||
83 | |||
84 | INIT_INI_ARRAY(&ah->iniModesAdditional_40M, | ||
85 | ar9340_1p0_radio_core_40M, | ||
86 | ARRAY_SIZE(ar9340_1p0_radio_core_40M), | ||
87 | 2); | ||
88 | } else if (AR_SREV_9485_11(ah)) { | ||
89 | /* mac */ | ||
90 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); | ||
91 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | ||
92 | ar9485_1_1_mac_core, | ||
93 | ARRAY_SIZE(ar9485_1_1_mac_core), 2); | ||
94 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], | ||
95 | ar9485_1_1_mac_postamble, | ||
96 | ARRAY_SIZE(ar9485_1_1_mac_postamble), 5); | ||
97 | |||
98 | /* bb */ | ||
99 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1, | ||
100 | ARRAY_SIZE(ar9485_1_1), 2); | ||
101 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], | ||
102 | ar9485_1_1_baseband_core, | ||
103 | ARRAY_SIZE(ar9485_1_1_baseband_core), 2); | ||
104 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], | ||
105 | ar9485_1_1_baseband_postamble, | ||
106 | ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5); | ||
107 | |||
108 | /* radio */ | ||
109 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); | ||
110 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], | ||
111 | ar9485_1_1_radio_core, | ||
112 | ARRAY_SIZE(ar9485_1_1_radio_core), 2); | ||
113 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], | ||
114 | ar9485_1_1_radio_postamble, | ||
115 | ARRAY_SIZE(ar9485_1_1_radio_postamble), 2); | ||
116 | |||
117 | /* soc */ | ||
118 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], | ||
119 | ar9485_1_1_soc_preamble, | ||
120 | ARRAY_SIZE(ar9485_1_1_soc_preamble), 2); | ||
121 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); | ||
122 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0); | ||
123 | |||
124 | /* rx/tx gain */ | ||
125 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
126 | ar9485Common_wo_xlna_rx_gain_1_1, | ||
127 | ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2); | ||
128 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
129 | ar9485_modes_lowest_ob_db_tx_gain_1_1, | ||
130 | ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), | ||
131 | 5); | ||
132 | |||
133 | /* Load PCIE SERDES settings from INI */ | ||
134 | |||
135 | /* Awake Setting */ | ||
136 | |||
137 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
138 | ar9485_1_1_pcie_phy_clkreq_disable_L1, | ||
139 | ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), | ||
140 | 2); | ||
141 | |||
142 | /* Sleep Setting */ | ||
143 | |||
144 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
145 | ar9485_1_1_pcie_phy_clkreq_disable_L1, | ||
146 | ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), | ||
147 | 2); | ||
148 | } else { | ||
149 | /* mac */ | ||
150 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); | ||
151 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], | ||
152 | ar9300_2p2_mac_core, | ||
153 | ARRAY_SIZE(ar9300_2p2_mac_core), 2); | ||
154 | INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], | ||
155 | ar9300_2p2_mac_postamble, | ||
156 | ARRAY_SIZE(ar9300_2p2_mac_postamble), 5); | ||
157 | |||
158 | /* bb */ | ||
159 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); | ||
160 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], | ||
161 | ar9300_2p2_baseband_core, | ||
162 | ARRAY_SIZE(ar9300_2p2_baseband_core), 2); | ||
163 | INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], | ||
164 | ar9300_2p2_baseband_postamble, | ||
165 | ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5); | ||
166 | |||
167 | /* radio */ | ||
168 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); | ||
169 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], | ||
170 | ar9300_2p2_radio_core, | ||
171 | ARRAY_SIZE(ar9300_2p2_radio_core), 2); | ||
172 | INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], | ||
173 | ar9300_2p2_radio_postamble, | ||
174 | ARRAY_SIZE(ar9300_2p2_radio_postamble), 5); | ||
175 | |||
176 | /* soc */ | ||
177 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], | ||
178 | ar9300_2p2_soc_preamble, | ||
179 | ARRAY_SIZE(ar9300_2p2_soc_preamble), 2); | ||
180 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); | ||
181 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], | ||
182 | ar9300_2p2_soc_postamble, | ||
183 | ARRAY_SIZE(ar9300_2p2_soc_postamble), 5); | ||
184 | |||
185 | /* rx/tx gain */ | ||
186 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
187 | ar9300Common_rx_gain_table_2p2, | ||
188 | ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2); | ||
189 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
190 | ar9300Modes_lowest_ob_db_tx_gain_table_2p2, | ||
191 | ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), | ||
192 | 5); | ||
193 | |||
194 | /* Load PCIE SERDES settings from INI */ | ||
195 | |||
196 | /* Awake Setting */ | ||
197 | |||
198 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | ||
199 | ar9300PciePhy_pll_on_clkreq_disable_L1_2p2, | ||
200 | ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2), | ||
201 | 2); | ||
202 | |||
203 | /* Sleep Setting */ | ||
204 | |||
205 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | ||
206 | ar9300PciePhy_pll_on_clkreq_disable_L1_2p2, | ||
207 | ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2), | ||
208 | 2); | ||
209 | |||
210 | /* Fast clock modal settings */ | ||
211 | INIT_INI_ARRAY(&ah->iniModesAdditional, | ||
212 | ar9300Modes_fast_clock_2p2, | ||
213 | ARRAY_SIZE(ar9300Modes_fast_clock_2p2), | ||
214 | 3); | ||
215 | } | ||
187 | } | 216 | } |
188 | 217 | ||
189 | static void ar9003_tx_gain_table_apply(struct ath_hw *ah) | 218 | static void ar9003_tx_gain_table_apply(struct ath_hw *ah) |
@@ -191,10 +220,15 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) | |||
191 | switch (ar9003_hw_get_tx_gain_idx(ah)) { | 220 | switch (ar9003_hw_get_tx_gain_idx(ah)) { |
192 | case 0: | 221 | case 0: |
193 | default: | 222 | default: |
194 | if (AR_SREV_9300_20(ah)) | 223 | if (AR_SREV_9340(ah)) |
224 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
225 | ar9340Modes_lowest_ob_db_tx_gain_table_1p0, | ||
226 | ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), | ||
227 | 5); | ||
228 | else if (AR_SREV_9485_11(ah)) | ||
195 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 229 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
196 | ar9300Modes_lowest_ob_db_tx_gain_table_2p0, | 230 | ar9485_modes_lowest_ob_db_tx_gain_1_1, |
197 | ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), | 231 | ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1), |
198 | 5); | 232 | 5); |
199 | else | 233 | else |
200 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 234 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
@@ -203,10 +237,15 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) | |||
203 | 5); | 237 | 5); |
204 | break; | 238 | break; |
205 | case 1: | 239 | case 1: |
206 | if (AR_SREV_9300_20(ah)) | 240 | if (AR_SREV_9340(ah)) |
241 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
242 | ar9340Modes_lowest_ob_db_tx_gain_table_1p0, | ||
243 | ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), | ||
244 | 5); | ||
245 | else if (AR_SREV_9485_11(ah)) | ||
207 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 246 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
208 | ar9300Modes_high_ob_db_tx_gain_table_2p0, | 247 | ar9485Modes_high_ob_db_tx_gain_1_1, |
209 | ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0), | 248 | ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1), |
210 | 5); | 249 | 5); |
211 | else | 250 | else |
212 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 251 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
@@ -215,10 +254,15 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) | |||
215 | 5); | 254 | 5); |
216 | break; | 255 | break; |
217 | case 2: | 256 | case 2: |
218 | if (AR_SREV_9300_20(ah)) | 257 | if (AR_SREV_9340(ah)) |
258 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
259 | ar9340Modes_lowest_ob_db_tx_gain_table_1p0, | ||
260 | ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), | ||
261 | 5); | ||
262 | else if (AR_SREV_9485_11(ah)) | ||
219 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 263 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
220 | ar9300Modes_low_ob_db_tx_gain_table_2p0, | 264 | ar9485Modes_low_ob_db_tx_gain_1_1, |
221 | ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0), | 265 | ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1), |
222 | 5); | 266 | 5); |
223 | else | 267 | else |
224 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 268 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
@@ -226,6 +270,23 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah) | |||
226 | ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2), | 270 | ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2), |
227 | 5); | 271 | 5); |
228 | break; | 272 | break; |
273 | case 3: | ||
274 | if (AR_SREV_9340(ah)) | ||
275 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
276 | ar9340Modes_lowest_ob_db_tx_gain_table_1p0, | ||
277 | ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0), | ||
278 | 5); | ||
279 | else if (AR_SREV_9485_11(ah)) | ||
280 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
281 | ar9485Modes_high_power_tx_gain_1_1, | ||
282 | ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1), | ||
283 | 5); | ||
284 | else | ||
285 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
286 | ar9300Modes_high_power_tx_gain_table_2p2, | ||
287 | ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2), | ||
288 | 5); | ||
289 | break; | ||
229 | } | 290 | } |
230 | } | 291 | } |
231 | 292 | ||
@@ -234,10 +295,15 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) | |||
234 | switch (ar9003_hw_get_rx_gain_idx(ah)) { | 295 | switch (ar9003_hw_get_rx_gain_idx(ah)) { |
235 | case 0: | 296 | case 0: |
236 | default: | 297 | default: |
237 | if (AR_SREV_9300_20(ah)) | 298 | if (AR_SREV_9340(ah)) |
299 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
300 | ar9340Common_rx_gain_table_1p0, | ||
301 | ARRAY_SIZE(ar9340Common_rx_gain_table_1p0), | ||
302 | 2); | ||
303 | else if (AR_SREV_9485_11(ah)) | ||
238 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 304 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
239 | ar9300Common_rx_gain_table_2p0, | 305 | ar9485Common_wo_xlna_rx_gain_1_1, |
240 | ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), | 306 | ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), |
241 | 2); | 307 | 2); |
242 | else | 308 | else |
243 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 309 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
@@ -246,10 +312,15 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) | |||
246 | 2); | 312 | 2); |
247 | break; | 313 | break; |
248 | case 1: | 314 | case 1: |
249 | if (AR_SREV_9300_20(ah)) | 315 | if (AR_SREV_9340(ah)) |
316 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
317 | ar9340Common_wo_xlna_rx_gain_table_1p0, | ||
318 | ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0), | ||
319 | 2); | ||
320 | else if (AR_SREV_9485_11(ah)) | ||
250 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 321 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
251 | ar9300Common_wo_xlna_rx_gain_table_2p0, | 322 | ar9485Common_wo_xlna_rx_gain_1_1, |
252 | ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0), | 323 | ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), |
253 | 2); | 324 | 2); |
254 | else | 325 | else |
255 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 326 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
@@ -326,13 +397,10 @@ void ar9003_hw_attach_ops(struct ath_hw *ah) | |||
326 | 397 | ||
327 | priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; | 398 | priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; |
328 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; | 399 | priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; |
329 | priv_ops->macversion_supported = ar9003_hw_macversion_supported; | ||
330 | 400 | ||
331 | ops->config_pci_powersave = ar9003_hw_configpcipowersave; | 401 | ops->config_pci_powersave = ar9003_hw_configpcipowersave; |
332 | 402 | ||
333 | ar9003_hw_attach_phy_ops(ah); | 403 | ar9003_hw_attach_phy_ops(ah); |
334 | ar9003_hw_attach_calib_ops(ah); | 404 | ar9003_hw_attach_calib_ops(ah); |
335 | ar9003_hw_attach_mac_ops(ah); | 405 | ar9003_hw_attach_mac_ops(ah); |
336 | |||
337 | ath9k_hw_attach_ani_ops_new(ah); | ||
338 | } | 406 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 5b995bee70ae..10d71f7d3fc2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -182,10 +182,10 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
182 | } | 182 | } |
183 | 183 | ||
184 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) | 184 | if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) |
185 | ath_print(common, ATH_DBG_INTERRUPT, | 185 | ath_dbg(common, ATH_DBG_INTERRUPT, |
186 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); | 186 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); |
187 | 187 | ||
188 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); | 188 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); |
189 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); | 189 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); |
190 | 190 | ||
191 | } | 191 | } |
@@ -237,73 +237,76 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, | |||
237 | struct ath_tx_status *ts) | 237 | struct ath_tx_status *ts) |
238 | { | 238 | { |
239 | struct ar9003_txs *ads; | 239 | struct ar9003_txs *ads; |
240 | u32 status; | ||
240 | 241 | ||
241 | ads = &ah->ts_ring[ah->ts_tail]; | 242 | ads = &ah->ts_ring[ah->ts_tail]; |
242 | 243 | ||
243 | if ((ads->status8 & AR_TxDone) == 0) | 244 | status = ACCESS_ONCE(ads->status8); |
245 | if ((status & AR_TxDone) == 0) | ||
244 | return -EINPROGRESS; | 246 | return -EINPROGRESS; |
245 | 247 | ||
246 | ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; | 248 | ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size; |
247 | 249 | ||
248 | if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || | 250 | if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || |
249 | (MS(ads->ds_info, AR_TxRxDesc) != 1)) { | 251 | (MS(ads->ds_info, AR_TxRxDesc) != 1)) { |
250 | ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, | 252 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, |
251 | "Tx Descriptor error %x\n", ads->ds_info); | 253 | "Tx Descriptor error %x\n", ads->ds_info); |
252 | memset(ads, 0, sizeof(*ads)); | 254 | memset(ads, 0, sizeof(*ads)); |
253 | return -EIO; | 255 | return -EIO; |
254 | } | 256 | } |
255 | 257 | ||
258 | if (status & AR_TxOpExceeded) | ||
259 | ts->ts_status |= ATH9K_TXERR_XTXOP; | ||
260 | ts->ts_rateindex = MS(status, AR_FinalTxIdx); | ||
261 | ts->ts_seqnum = MS(status, AR_SeqNum); | ||
262 | ts->tid = MS(status, AR_TxTid); | ||
263 | |||
256 | ts->qid = MS(ads->ds_info, AR_TxQcuNum); | 264 | ts->qid = MS(ads->ds_info, AR_TxQcuNum); |
257 | ts->desc_id = MS(ads->status1, AR_TxDescId); | 265 | ts->desc_id = MS(ads->status1, AR_TxDescId); |
258 | ts->ts_seqnum = MS(ads->status8, AR_SeqNum); | ||
259 | ts->ts_tstamp = ads->status4; | 266 | ts->ts_tstamp = ads->status4; |
260 | ts->ts_status = 0; | 267 | ts->ts_status = 0; |
261 | ts->ts_flags = 0; | 268 | ts->ts_flags = 0; |
262 | 269 | ||
263 | if (ads->status3 & AR_ExcessiveRetries) | 270 | status = ACCESS_ONCE(ads->status2); |
271 | ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); | ||
272 | ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); | ||
273 | ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); | ||
274 | if (status & AR_TxBaStatus) { | ||
275 | ts->ts_flags |= ATH9K_TX_BA; | ||
276 | ts->ba_low = ads->status5; | ||
277 | ts->ba_high = ads->status6; | ||
278 | } | ||
279 | |||
280 | status = ACCESS_ONCE(ads->status3); | ||
281 | if (status & AR_ExcessiveRetries) | ||
264 | ts->ts_status |= ATH9K_TXERR_XRETRY; | 282 | ts->ts_status |= ATH9K_TXERR_XRETRY; |
265 | if (ads->status3 & AR_Filtered) | 283 | if (status & AR_Filtered) |
266 | ts->ts_status |= ATH9K_TXERR_FILT; | 284 | ts->ts_status |= ATH9K_TXERR_FILT; |
267 | if (ads->status3 & AR_FIFOUnderrun) { | 285 | if (status & AR_FIFOUnderrun) { |
268 | ts->ts_status |= ATH9K_TXERR_FIFO; | 286 | ts->ts_status |= ATH9K_TXERR_FIFO; |
269 | ath9k_hw_updatetxtriglevel(ah, true); | 287 | ath9k_hw_updatetxtriglevel(ah, true); |
270 | } | 288 | } |
271 | if (ads->status8 & AR_TxOpExceeded) | 289 | if (status & AR_TxTimerExpired) |
272 | ts->ts_status |= ATH9K_TXERR_XTXOP; | ||
273 | if (ads->status3 & AR_TxTimerExpired) | ||
274 | ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; | 290 | ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED; |
275 | 291 | if (status & AR_DescCfgErr) | |
276 | if (ads->status3 & AR_DescCfgErr) | ||
277 | ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; | 292 | ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR; |
278 | if (ads->status3 & AR_TxDataUnderrun) { | 293 | if (status & AR_TxDataUnderrun) { |
279 | ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; | 294 | ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN; |
280 | ath9k_hw_updatetxtriglevel(ah, true); | 295 | ath9k_hw_updatetxtriglevel(ah, true); |
281 | } | 296 | } |
282 | if (ads->status3 & AR_TxDelimUnderrun) { | 297 | if (status & AR_TxDelimUnderrun) { |
283 | ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; | 298 | ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN; |
284 | ath9k_hw_updatetxtriglevel(ah, true); | 299 | ath9k_hw_updatetxtriglevel(ah, true); |
285 | } | 300 | } |
286 | if (ads->status2 & AR_TxBaStatus) { | 301 | ts->ts_shortretry = MS(status, AR_RTSFailCnt); |
287 | ts->ts_flags |= ATH9K_TX_BA; | 302 | ts->ts_longretry = MS(status, AR_DataFailCnt); |
288 | ts->ba_low = ads->status5; | 303 | ts->ts_virtcol = MS(status, AR_VirtRetryCnt); |
289 | ts->ba_high = ads->status6; | ||
290 | } | ||
291 | |||
292 | ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx); | ||
293 | |||
294 | ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined); | ||
295 | ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00); | ||
296 | ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01); | ||
297 | ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02); | ||
298 | ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10); | ||
299 | ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11); | ||
300 | ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12); | ||
301 | ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt); | ||
302 | ts->ts_longretry = MS(ads->status3, AR_DataFailCnt); | ||
303 | ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt); | ||
304 | ts->ts_antenna = 0; | ||
305 | 304 | ||
306 | ts->tid = MS(ads->status8, AR_TxTid); | 305 | status = ACCESS_ONCE(ads->status7); |
306 | ts->ts_rssi = MS(status, AR_TxRSSICombined); | ||
307 | ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); | ||
308 | ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); | ||
309 | ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); | ||
307 | 310 | ||
308 | memset(ads, 0, sizeof(*ads)); | 311 | memset(ads, 0, sizeof(*ads)); |
309 | 312 | ||
@@ -319,7 +322,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
319 | if (txpower > ah->txpower_limit) | 322 | if (txpower > ah->txpower_limit) |
320 | txpower = ah->txpower_limit; | 323 | txpower = ah->txpower_limit; |
321 | 324 | ||
322 | txpower += ah->txpower_indexoffset; | ||
323 | if (txpower > 63) | 325 | if (txpower > 63) |
324 | txpower = 63; | 326 | txpower = 63; |
325 | 327 | ||
@@ -327,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
327 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | 329 | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
328 | | SM(txpower, AR_XmitPower) | 330 | | SM(txpower, AR_XmitPower) |
329 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) | 331 | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
330 | | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | ||
331 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | 332 | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) |
332 | | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); | 333 | | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); |
333 | 334 | ||
@@ -348,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds, | |||
348 | ads->ctl22 = 0; | 349 | ads->ctl22 = 0; |
349 | } | 350 | } |
350 | 351 | ||
352 | static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) | ||
353 | { | ||
354 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
355 | |||
356 | if (val) | ||
357 | ads->ctl11 |= AR_ClrDestMask; | ||
358 | else | ||
359 | ads->ctl11 &= ~AR_ClrDestMask; | ||
360 | } | ||
361 | |||
351 | static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, | 362 | static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, |
352 | void *lastds, | 363 | void *lastds, |
353 | u32 durUpdateEn, u32 rtsctsRate, | 364 | u32 durUpdateEn, u32 rtsctsRate, |
@@ -407,12 +418,36 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, | |||
407 | static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, | 418 | static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds, |
408 | u32 aggrLen) | 419 | u32 aggrLen) |
409 | { | 420 | { |
421 | #define FIRST_DESC_NDELIMS 60 | ||
410 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | 422 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; |
411 | 423 | ||
412 | ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); | 424 | ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); |
413 | 425 | ||
414 | ads->ctl17 &= ~AR_AggrLen; | 426 | if (ah->ent_mode & AR_ENT_OTP_MPSD) { |
415 | ads->ctl17 |= SM(aggrLen, AR_AggrLen); | 427 | u32 ctl17, ndelim; |
428 | /* | ||
429 | * Add delimiter when using RTS/CTS with aggregation | ||
430 | * and non enterprise AR9003 card | ||
431 | */ | ||
432 | ctl17 = ads->ctl17; | ||
433 | ndelim = MS(ctl17, AR_PadDelim); | ||
434 | |||
435 | if (ndelim < FIRST_DESC_NDELIMS) { | ||
436 | aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4; | ||
437 | ndelim = FIRST_DESC_NDELIMS; | ||
438 | } | ||
439 | |||
440 | ctl17 &= ~AR_AggrLen; | ||
441 | ctl17 |= SM(aggrLen, AR_AggrLen); | ||
442 | |||
443 | ctl17 &= ~AR_PadDelim; | ||
444 | ctl17 |= SM(ndelim, AR_PadDelim); | ||
445 | |||
446 | ads->ctl17 = ctl17; | ||
447 | } else { | ||
448 | ads->ctl17 &= ~AR_AggrLen; | ||
449 | ads->ctl17 |= SM(aggrLen, AR_AggrLen); | ||
450 | } | ||
416 | } | 451 | } |
417 | 452 | ||
418 | static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, | 453 | static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, |
@@ -449,27 +484,6 @@ static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) | |||
449 | ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); | 484 | ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); |
450 | } | 485 | } |
451 | 486 | ||
452 | static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds, | ||
453 | u32 burstDuration) | ||
454 | { | ||
455 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
456 | |||
457 | ads->ctl13 &= ~AR_BurstDur; | ||
458 | ads->ctl13 |= SM(burstDuration, AR_BurstDur); | ||
459 | |||
460 | } | ||
461 | |||
462 | static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | ||
463 | u32 vmf) | ||
464 | { | ||
465 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
466 | |||
467 | if (vmf) | ||
468 | ads->ctl11 |= AR_VirtMoreFrag; | ||
469 | else | ||
470 | ads->ctl11 &= ~AR_VirtMoreFrag; | ||
471 | } | ||
472 | |||
473 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) | 487 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) |
474 | { | 488 | { |
475 | struct ar9003_txc *ads = ds; | 489 | struct ar9003_txc *ads = ds; |
@@ -494,8 +508,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | |||
494 | ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; | 508 | ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; |
495 | ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; | 509 | ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; |
496 | ops->clr11n_aggr = ar9003_hw_clr11n_aggr; | 510 | ops->clr11n_aggr = ar9003_hw_clr11n_aggr; |
497 | ops->set11n_burstduration = ar9003_hw_set11n_burstduration; | 511 | ops->set_clrdmask = ar9003_hw_set_clrdmask; |
498 | ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag; | ||
499 | } | 512 | } |
500 | 513 | ||
501 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) | 514 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) |
@@ -587,9 +600,9 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, | |||
587 | * possibly be reviewing the last subframe. AR_CRCErr | 600 | * possibly be reviewing the last subframe. AR_CRCErr |
588 | * is the CRC of the actual data. | 601 | * is the CRC of the actual data. |
589 | */ | 602 | */ |
590 | if (rxsp->status11 & AR_CRCErr) { | 603 | if (rxsp->status11 & AR_CRCErr) |
591 | rxs->rs_status |= ATH9K_RXERR_CRC; | 604 | rxs->rs_status |= ATH9K_RXERR_CRC; |
592 | } else if (rxsp->status11 & AR_PHYErr) { | 605 | else if (rxsp->status11 & AR_PHYErr) { |
593 | phyerr = MS(rxsp->status11, AR_PHYErrCode); | 606 | phyerr = MS(rxsp->status11, AR_PHYErrCode); |
594 | /* | 607 | /* |
595 | * If we reach a point here where AR_PostDelimCRCErr is | 608 | * If we reach a point here where AR_PostDelimCRCErr is |
@@ -612,11 +625,13 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs, | |||
612 | rxs->rs_phyerr = phyerr; | 625 | rxs->rs_phyerr = phyerr; |
613 | } | 626 | } |
614 | 627 | ||
615 | } else if (rxsp->status11 & AR_DecryptCRCErr) { | 628 | } else if (rxsp->status11 & AR_DecryptCRCErr) |
616 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; | 629 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; |
617 | } else if (rxsp->status11 & AR_MichaelErr) { | 630 | else if (rxsp->status11 & AR_MichaelErr) |
618 | rxs->rs_status |= ATH9K_RXERR_MIC; | 631 | rxs->rs_status |= ATH9K_RXERR_MIC; |
619 | } | 632 | |
633 | if (rxsp->status11 & AR_KeyMiss) | ||
634 | rxs->rs_status |= ATH9K_RXERR_DECRYPT; | ||
620 | } | 635 | } |
621 | 636 | ||
622 | return 0; | 637 | return 0; |
@@ -630,10 +645,10 @@ void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah) | |||
630 | memset((void *) ah->ts_ring, 0, | 645 | memset((void *) ah->ts_ring, 0, |
631 | ah->ts_size * sizeof(struct ar9003_txs)); | 646 | ah->ts_size * sizeof(struct ar9003_txs)); |
632 | 647 | ||
633 | ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, | 648 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, |
634 | "TS Start 0x%x End 0x%x Virt %p, Size %d\n", | 649 | "TS Start 0x%x End 0x%x Virt %p, Size %d\n", |
635 | ah->ts_paddr_start, ah->ts_paddr_end, | 650 | ah->ts_paddr_start, ah->ts_paddr_end, |
636 | ah->ts_ring, ah->ts_size); | 651 | ah->ts_ring, ah->ts_size); |
637 | 652 | ||
638 | REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start); | 653 | REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start); |
639 | REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end); | 654 | REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h index 9f2cea70a840..c50449387bf1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -65,7 +65,7 @@ struct ar9003_rxs { | |||
65 | u32 status9; | 65 | u32 status9; |
66 | u32 status10; | 66 | u32 status10; |
67 | u32 status11; | 67 | u32 status11; |
68 | } __packed; | 68 | } __packed __aligned(4); |
69 | 69 | ||
70 | /* Transmit Control Descriptor */ | 70 | /* Transmit Control Descriptor */ |
71 | struct ar9003_txc { | 71 | struct ar9003_txc { |
@@ -93,7 +93,7 @@ struct ar9003_txc { | |||
93 | u32 ctl21; /* DMA control 21 */ | 93 | u32 ctl21; /* DMA control 21 */ |
94 | u32 ctl22; /* DMA control 22 */ | 94 | u32 ctl22; /* DMA control 22 */ |
95 | u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */ | 95 | u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */ |
96 | } __packed; | 96 | } __packed __aligned(4); |
97 | 97 | ||
98 | struct ar9003_txs { | 98 | struct ar9003_txs { |
99 | u32 ds_info; | 99 | u32 ds_info; |
@@ -105,7 +105,7 @@ struct ar9003_txs { | |||
105 | u32 status6; | 105 | u32 status6; |
106 | u32 status7; | 106 | u32 status7; |
107 | u32 status8; | 107 | u32 status8; |
108 | } __packed; | 108 | } __packed __aligned(4); |
109 | 109 | ||
110 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw); | 110 | void ar9003_hw_attach_mac_ops(struct ath_hw *hw); |
111 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size); | 111 | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 7c38229ba670..e4d6a87ec538 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -19,45 +19,124 @@ | |||
19 | 19 | ||
20 | void ar9003_paprd_enable(struct ath_hw *ah, bool val) | 20 | void ar9003_paprd_enable(struct ath_hw *ah, bool val) |
21 | { | 21 | { |
22 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
23 | struct ath9k_channel *chan = ah->curchan; | ||
24 | |||
25 | if (val) { | ||
26 | ah->paprd_table_write_done = true; | ||
27 | |||
28 | ah->eep_ops->set_txpower(ah, chan, | ||
29 | ath9k_regd_get_ctl(regulatory, chan), | ||
30 | chan->chan->max_antenna_gain * 2, | ||
31 | chan->chan->max_power * 2, | ||
32 | min((u32) MAX_RATE_POWER, | ||
33 | (u32) regulatory->power_limit), false); | ||
34 | } | ||
35 | |||
22 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, | 36 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0, |
23 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | 37 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); |
24 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, | 38 | if (ah->caps.tx_chainmask & BIT(1)) |
25 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | 39 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B1, |
26 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, | 40 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); |
27 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | 41 | if (ah->caps.tx_chainmask & BIT(2)) |
42 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B2, | ||
43 | AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val); | ||
28 | } | 44 | } |
29 | EXPORT_SYMBOL(ar9003_paprd_enable); | 45 | EXPORT_SYMBOL(ar9003_paprd_enable); |
30 | 46 | ||
31 | static void ar9003_paprd_setup_single_table(struct ath_hw *ah) | 47 | static int ar9003_get_training_power_2g(struct ath_hw *ah) |
48 | { | ||
49 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | ||
50 | struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G; | ||
51 | unsigned int power, scale, delta; | ||
52 | |||
53 | scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1); | ||
54 | power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | ||
55 | AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | ||
56 | |||
57 | delta = abs((int) ah->paprd_target_power - (int) power); | ||
58 | if (delta > scale) | ||
59 | return -1; | ||
60 | |||
61 | if (delta < 4) | ||
62 | power -= 4 - delta; | ||
63 | |||
64 | return power; | ||
65 | } | ||
66 | |||
67 | static int ar9003_get_training_power_5g(struct ath_hw *ah) | ||
32 | { | 68 | { |
69 | struct ath_common *common = ath9k_hw_common(ah); | ||
33 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; | 70 | struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; |
34 | struct ar9300_modal_eep_header *hdr; | 71 | struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G; |
35 | const u32 ctrl0[3] = { | 72 | struct ath9k_channel *chan = ah->curchan; |
73 | unsigned int power, scale, delta; | ||
74 | |||
75 | if (chan->channel >= 5700) | ||
76 | scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), | ||
77 | AR9300_PAPRD_SCALE_1); | ||
78 | else if (chan->channel >= 5400) | ||
79 | scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), | ||
80 | AR9300_PAPRD_SCALE_2); | ||
81 | else | ||
82 | scale = MS(le32_to_cpu(hdr->papdRateMaskHt40), | ||
83 | AR9300_PAPRD_SCALE_1); | ||
84 | |||
85 | if (IS_CHAN_HT40(chan)) | ||
86 | power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8, | ||
87 | AR_PHY_POWERTX_RATE8_POWERTXHT40_5); | ||
88 | else | ||
89 | power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6, | ||
90 | AR_PHY_POWERTX_RATE6_POWERTXHT20_5); | ||
91 | |||
92 | power += scale; | ||
93 | delta = abs((int) ah->paprd_target_power - (int) power); | ||
94 | if (delta > scale) | ||
95 | return -1; | ||
96 | |||
97 | power += 2 * get_streams(common->tx_chainmask); | ||
98 | return power; | ||
99 | } | ||
100 | |||
101 | static int ar9003_paprd_setup_single_table(struct ath_hw *ah) | ||
102 | { | ||
103 | struct ath_common *common = ath9k_hw_common(ah); | ||
104 | static const u32 ctrl0[3] = { | ||
36 | AR_PHY_PAPRD_CTRL0_B0, | 105 | AR_PHY_PAPRD_CTRL0_B0, |
37 | AR_PHY_PAPRD_CTRL0_B1, | 106 | AR_PHY_PAPRD_CTRL0_B1, |
38 | AR_PHY_PAPRD_CTRL0_B2 | 107 | AR_PHY_PAPRD_CTRL0_B2 |
39 | }; | 108 | }; |
40 | const u32 ctrl1[3] = { | 109 | static const u32 ctrl1[3] = { |
41 | AR_PHY_PAPRD_CTRL1_B0, | 110 | AR_PHY_PAPRD_CTRL1_B0, |
42 | AR_PHY_PAPRD_CTRL1_B1, | 111 | AR_PHY_PAPRD_CTRL1_B1, |
43 | AR_PHY_PAPRD_CTRL1_B2 | 112 | AR_PHY_PAPRD_CTRL1_B2 |
44 | }; | 113 | }; |
45 | u32 am_mask, ht40_mask; | 114 | int training_power; |
46 | int i; | 115 | int i; |
47 | 116 | ||
48 | if (ah->curchan && IS_CHAN_5GHZ(ah->curchan)) | 117 | if (IS_CHAN_2GHZ(ah->curchan)) |
49 | hdr = &eep->modalHeader5G; | 118 | training_power = ar9003_get_training_power_2g(ah); |
50 | else | 119 | else |
51 | hdr = &eep->modalHeader2G; | 120 | training_power = ar9003_get_training_power_5g(ah); |
52 | |||
53 | am_mask = le32_to_cpu(hdr->papdRateMaskHt20); | ||
54 | ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40); | ||
55 | 121 | ||
56 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask); | 122 | if (training_power < 0) { |
57 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask); | 123 | ath_dbg(common, ATH_DBG_CALIBRATE, |
58 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask); | 124 | "PAPRD target power delta out of range"); |
59 | 125 | return -ERANGE; | |
60 | for (i = 0; i < 3; i++) { | 126 | } |
127 | ah->paprd_training_power = training_power; | ||
128 | ath_dbg(common, ATH_DBG_CALIBRATE, | ||
129 | "Training power: %d, Target power: %d\n", | ||
130 | ah->paprd_training_power, ah->paprd_target_power); | ||
131 | |||
132 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, | ||
133 | ah->paprd_ratemask); | ||
134 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, | ||
135 | ah->paprd_ratemask); | ||
136 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, | ||
137 | ah->paprd_ratemask_ht40); | ||
138 | |||
139 | for (i = 0; i < ah->caps.max_txchains; i++) { | ||
61 | REG_RMW_FIELD(ah, ctrl0[i], | 140 | REG_RMW_FIELD(ah, ctrl0[i], |
62 | AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1); | 141 | AR_PHY_PAPRD_CTRL0_USE_SINGLE_TABLE_MASK, 1); |
63 | REG_RMW_FIELD(ah, ctrl1[i], | 142 | REG_RMW_FIELD(ah, ctrl1[i], |
@@ -102,8 +181,14 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah) | |||
102 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); | 181 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_NUM_CORR_STAGES, 7); |
103 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | 182 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, |
104 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); | 183 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_MIN_LOOPBACK_DEL, 1); |
105 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | 184 | if (AR_SREV_9485(ah)) |
106 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, -6); | 185 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, |
186 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, | ||
187 | -3); | ||
188 | else | ||
189 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | ||
190 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, | ||
191 | -6); | ||
107 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, | 192 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, |
108 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, | 193 | AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE, |
109 | -15); | 194 | -15); |
@@ -132,6 +217,7 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah) | |||
132 | AR_PHY_PAPRD_PRE_POST_SCALING, 185706); | 217 | AR_PHY_PAPRD_PRE_POST_SCALING, 185706); |
133 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, | 218 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0, |
134 | AR_PHY_PAPRD_PRE_POST_SCALING, 175487); | 219 | AR_PHY_PAPRD_PRE_POST_SCALING, 175487); |
220 | return 0; | ||
135 | } | 221 | } |
136 | 222 | ||
137 | static void ar9003_paprd_get_gain_table(struct ath_hw *ah) | 223 | static void ar9003_paprd_get_gain_table(struct ath_hw *ah) |
@@ -347,6 +433,10 @@ static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) | |||
347 | (((Y[6] - Y[3]) * 1 << scale_factor) + | 433 | (((Y[6] - Y[3]) * 1 << scale_factor) + |
348 | (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]); | 434 | (x_est[6] - x_est[3])) / (x_est[6] - x_est[3]); |
349 | 435 | ||
436 | /* prevent division by zero */ | ||
437 | if (G_fxp == 0) | ||
438 | return false; | ||
439 | |||
350 | Y_intercept = | 440 | Y_intercept = |
351 | (G_fxp * (x_est[0] - x_est[3]) + | 441 | (G_fxp * (x_est[0] - x_est[3]) + |
352 | (1 << scale_factor)) / (1 << scale_factor) + Y[3]; | 442 | (1 << scale_factor)) / (1 << scale_factor) + Y[3]; |
@@ -356,14 +446,12 @@ static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) | |||
356 | 446 | ||
357 | for (i = 0; i <= 3; i++) { | 447 | for (i = 0; i <= 3; i++) { |
358 | y_est[i] = i * 32; | 448 | y_est[i] = i * 32; |
359 | |||
360 | /* prevent division by zero */ | ||
361 | if (G_fxp == 0) | ||
362 | return false; | ||
363 | |||
364 | x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp; | 449 | x_est[i] = ((y_est[i] * 1 << scale_factor) + G_fxp) / G_fxp; |
365 | } | 450 | } |
366 | 451 | ||
452 | if (y_est[max_index] == 0) | ||
453 | return false; | ||
454 | |||
367 | x_est_fxp1_nonlin = | 455 | x_est_fxp1_nonlin = |
368 | x_est[max_index] - ((1 << scale_factor) * y_est[max_index] + | 456 | x_est[max_index] - ((1 << scale_factor) * y_est[max_index] + |
369 | G_fxp) / G_fxp; | 457 | G_fxp) / G_fxp; |
@@ -457,6 +545,8 @@ static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain) | |||
457 | 545 | ||
458 | Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10); | 546 | Q_scale_B = find_proper_scale(find_expn(abs(scale_B)), 10); |
459 | scale_B = scale_B / (1 << Q_scale_B); | 547 | scale_B = scale_B / (1 << Q_scale_B); |
548 | if (scale_B == 0) | ||
549 | return false; | ||
460 | Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); | 550 | Q_beta = find_proper_scale(find_expn(abs(beta_raw)), 10); |
461 | Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); | 551 | Q_alpha = find_proper_scale(find_expn(abs(alpha_raw)), 10); |
462 | beta_raw = beta_raw / (1 << Q_beta); | 552 | beta_raw = beta_raw / (1 << Q_beta); |
@@ -582,15 +672,10 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah, | |||
582 | { | 672 | { |
583 | u32 *paprd_table_val = caldata->pa_table[chain]; | 673 | u32 *paprd_table_val = caldata->pa_table[chain]; |
584 | u32 small_signal_gain = caldata->small_signal_gain[chain]; | 674 | u32 small_signal_gain = caldata->small_signal_gain[chain]; |
585 | u32 training_power; | 675 | u32 training_power = ah->paprd_training_power; |
586 | u32 reg = 0; | 676 | u32 reg = 0; |
587 | int i; | 677 | int i; |
588 | 678 | ||
589 | training_power = | ||
590 | REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | ||
591 | AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | ||
592 | training_power -= 4; | ||
593 | |||
594 | if (chain == 0) | 679 | if (chain == 0) |
595 | reg = AR_PHY_PAPRD_MEM_TAB_B0; | 680 | reg = AR_PHY_PAPRD_MEM_TAB_B0; |
596 | else if (chain == 1) | 681 | else if (chain == 1) |
@@ -616,26 +701,22 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah, | |||
616 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | 701 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, |
617 | training_power); | 702 | training_power); |
618 | 703 | ||
619 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1, | 704 | if (ah->caps.tx_chainmask & BIT(1)) |
620 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | 705 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B1, |
621 | training_power); | 706 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, |
707 | training_power); | ||
622 | 708 | ||
623 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, | 709 | if (ah->caps.tx_chainmask & BIT(2)) |
624 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, | 710 | REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL1_B2, |
625 | training_power); | 711 | AR_PHY_PAPRD_CTRL1_PAPRD_POWER_AT_AM2AM_CAL, |
712 | training_power); | ||
626 | } | 713 | } |
627 | EXPORT_SYMBOL(ar9003_paprd_populate_single_table); | 714 | EXPORT_SYMBOL(ar9003_paprd_populate_single_table); |
628 | 715 | ||
629 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) | 716 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain) |
630 | { | 717 | { |
631 | |||
632 | unsigned int i, desired_gain, gain_index; | 718 | unsigned int i, desired_gain, gain_index; |
633 | unsigned int train_power; | 719 | unsigned int train_power = ah->paprd_training_power; |
634 | |||
635 | train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5, | ||
636 | AR_PHY_POWERTX_RATE5_POWERTXHT20_0); | ||
637 | |||
638 | train_power = train_power - 4; | ||
639 | 720 | ||
640 | desired_gain = ar9003_get_desired_gain(ah, chain, train_power); | 721 | desired_gain = ar9003_get_desired_gain(ah, chain, train_power); |
641 | 722 | ||
@@ -701,7 +782,12 @@ EXPORT_SYMBOL(ar9003_paprd_create_curve); | |||
701 | 782 | ||
702 | int ar9003_paprd_init_table(struct ath_hw *ah) | 783 | int ar9003_paprd_init_table(struct ath_hw *ah) |
703 | { | 784 | { |
704 | ar9003_paprd_setup_single_table(ah); | 785 | int ret; |
786 | |||
787 | ret = ar9003_paprd_setup_single_table(ah); | ||
788 | if (ret < 0) | ||
789 | return ret; | ||
790 | |||
705 | ar9003_paprd_get_gain_table(ah); | 791 | ar9003_paprd_get_gain_table(ah); |
706 | return 0; | 792 | return 0; |
707 | } | 793 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index a491854fa38a..892c48b15434 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -75,13 +75,42 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
75 | freq = centers.synth_center; | 75 | freq = centers.synth_center; |
76 | 76 | ||
77 | if (freq < 4800) { /* 2 GHz, fractional mode */ | 77 | if (freq < 4800) { /* 2 GHz, fractional mode */ |
78 | channelSel = CHANSEL_2G(freq); | 78 | if (AR_SREV_9485(ah)) { |
79 | u32 chan_frac; | ||
80 | |||
81 | /* | ||
82 | * freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0 | ||
83 | * ndiv = ((chan_mhz * 4) / 3) / freq_ref; | ||
84 | * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 | ||
85 | */ | ||
86 | channelSel = (freq * 4) / 120; | ||
87 | chan_frac = (((freq * 4) % 120) * 0x20000) / 120; | ||
88 | channelSel = (channelSel << 17) | chan_frac; | ||
89 | } else if (AR_SREV_9340(ah)) { | ||
90 | if (ah->is_clk_25mhz) { | ||
91 | u32 chan_frac; | ||
92 | |||
93 | channelSel = (freq * 2) / 75; | ||
94 | chan_frac = (((freq * 2) % 75) * 0x20000) / 75; | ||
95 | channelSel = (channelSel << 17) | chan_frac; | ||
96 | } else | ||
97 | channelSel = CHANSEL_2G(freq) >> 1; | ||
98 | } else | ||
99 | channelSel = CHANSEL_2G(freq); | ||
79 | /* Set to 2G mode */ | 100 | /* Set to 2G mode */ |
80 | bMode = 1; | 101 | bMode = 1; |
81 | } else { | 102 | } else { |
82 | channelSel = CHANSEL_5G(freq); | 103 | if (AR_SREV_9340(ah) && ah->is_clk_25mhz) { |
83 | /* Doubler is ON, so, divide channelSel by 2. */ | 104 | u32 chan_frac; |
84 | channelSel >>= 1; | 105 | |
106 | channelSel = (freq * 2) / 75; | ||
107 | chan_frac = ((freq % 75) * 0x20000) / 75; | ||
108 | channelSel = (channelSel << 17) | chan_frac; | ||
109 | } else { | ||
110 | channelSel = CHANSEL_5G(freq); | ||
111 | /* Doubler is ON, so, divide channelSel by 2. */ | ||
112 | channelSel >>= 1; | ||
113 | } | ||
85 | /* Set to 5G mode */ | 114 | /* Set to 5G mode */ |
86 | bMode = 0; | 115 | bMode = 0; |
87 | } | 116 | } |
@@ -128,24 +157,53 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
128 | static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, | 157 | static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah, |
129 | struct ath9k_channel *chan) | 158 | struct ath9k_channel *chan) |
130 | { | 159 | { |
131 | u32 spur_freq[4] = { 2420, 2440, 2464, 2480 }; | 160 | static const u32 spur_freq[4] = { 2420, 2440, 2464, 2480 }; |
132 | int cur_bb_spur, negative = 0, cck_spur_freq; | 161 | int cur_bb_spur, negative = 0, cck_spur_freq; |
133 | int i; | 162 | int i; |
163 | int range, max_spur_cnts, synth_freq; | ||
164 | u8 *spur_fbin_ptr = NULL; | ||
134 | 165 | ||
135 | /* | 166 | /* |
136 | * Need to verify range +/- 10 MHz in control channel, otherwise spur | 167 | * Need to verify range +/- 10 MHz in control channel, otherwise spur |
137 | * is out-of-band and can be ignored. | 168 | * is out-of-band and can be ignored. |
138 | */ | 169 | */ |
139 | 170 | ||
140 | for (i = 0; i < 4; i++) { | 171 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) { |
172 | spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, | ||
173 | IS_CHAN_2GHZ(chan)); | ||
174 | if (spur_fbin_ptr[0] == 0) /* No spur */ | ||
175 | return; | ||
176 | max_spur_cnts = 5; | ||
177 | if (IS_CHAN_HT40(chan)) { | ||
178 | range = 19; | ||
179 | if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, | ||
180 | AR_PHY_GC_DYN2040_PRI_CH) == 0) | ||
181 | synth_freq = chan->channel + 10; | ||
182 | else | ||
183 | synth_freq = chan->channel - 10; | ||
184 | } else { | ||
185 | range = 10; | ||
186 | synth_freq = chan->channel; | ||
187 | } | ||
188 | } else { | ||
189 | range = 10; | ||
190 | max_spur_cnts = 4; | ||
191 | synth_freq = chan->channel; | ||
192 | } | ||
193 | |||
194 | for (i = 0; i < max_spur_cnts; i++) { | ||
141 | negative = 0; | 195 | negative = 0; |
142 | cur_bb_spur = spur_freq[i] - chan->channel; | 196 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) |
197 | cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i], | ||
198 | IS_CHAN_2GHZ(chan)) - synth_freq; | ||
199 | else | ||
200 | cur_bb_spur = spur_freq[i] - synth_freq; | ||
143 | 201 | ||
144 | if (cur_bb_spur < 0) { | 202 | if (cur_bb_spur < 0) { |
145 | negative = 1; | 203 | negative = 1; |
146 | cur_bb_spur = -cur_bb_spur; | 204 | cur_bb_spur = -cur_bb_spur; |
147 | } | 205 | } |
148 | if (cur_bb_spur < 10) { | 206 | if (cur_bb_spur < range) { |
149 | cck_spur_freq = (int)((cur_bb_spur << 19) / 11); | 207 | cck_spur_freq = (int)((cur_bb_spur << 19) / 11); |
150 | 208 | ||
151 | if (negative == 1) | 209 | if (negative == 1) |
@@ -369,7 +427,7 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, | |||
369 | 427 | ||
370 | ar9003_hw_spur_ofdm_clear(ah); | 428 | ar9003_hw_spur_ofdm_clear(ah); |
371 | 429 | ||
372 | for (i = 0; spurChansPtr[i] && i < 5; i++) { | 430 | for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) { |
373 | freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; | 431 | freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; |
374 | if (abs(freq_offset) < range) { | 432 | if (abs(freq_offset) < range) { |
375 | ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); | 433 | ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); |
@@ -487,7 +545,11 @@ void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) | |||
487 | break; | 545 | break; |
488 | } | 546 | } |
489 | 547 | ||
490 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); | 548 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) |
549 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); | ||
550 | else | ||
551 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); | ||
552 | |||
491 | if (tx == 0x5) { | 553 | if (tx == 0x5) { |
492 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 554 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
493 | AR_PHY_SWAP_ALT_CHAIN); | 555 | AR_PHY_SWAP_ALT_CHAIN); |
@@ -542,10 +604,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah, | |||
542 | u32 reg = INI_RA(iniArr, i, 0); | 604 | u32 reg = INI_RA(iniArr, i, 0); |
543 | u32 val = INI_RA(iniArr, i, column); | 605 | u32 val = INI_RA(iniArr, i, column); |
544 | 606 | ||
545 | if (reg >= 0x16000 && reg < 0x17000) | 607 | REG_WRITE(ah, reg, val); |
546 | ath9k_hw_analog_shift_regwrite(ah, reg, val); | ||
547 | else | ||
548 | REG_WRITE(ah, reg, val); | ||
549 | 608 | ||
550 | DO_DELAY(regWrites); | 609 | DO_DELAY(regWrites); |
551 | } | 610 | } |
@@ -557,29 +616,25 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
557 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 616 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
558 | unsigned int regWrites = 0, i; | 617 | unsigned int regWrites = 0, i; |
559 | struct ieee80211_channel *channel = chan->chan; | 618 | struct ieee80211_channel *channel = chan->chan; |
560 | u32 modesIndex, freqIndex; | 619 | u32 modesIndex; |
561 | 620 | ||
562 | switch (chan->chanmode) { | 621 | switch (chan->chanmode) { |
563 | case CHANNEL_A: | 622 | case CHANNEL_A: |
564 | case CHANNEL_A_HT20: | 623 | case CHANNEL_A_HT20: |
565 | modesIndex = 1; | 624 | modesIndex = 1; |
566 | freqIndex = 1; | ||
567 | break; | 625 | break; |
568 | case CHANNEL_A_HT40PLUS: | 626 | case CHANNEL_A_HT40PLUS: |
569 | case CHANNEL_A_HT40MINUS: | 627 | case CHANNEL_A_HT40MINUS: |
570 | modesIndex = 2; | 628 | modesIndex = 2; |
571 | freqIndex = 1; | ||
572 | break; | 629 | break; |
573 | case CHANNEL_G: | 630 | case CHANNEL_G: |
574 | case CHANNEL_G_HT20: | 631 | case CHANNEL_G_HT20: |
575 | case CHANNEL_B: | 632 | case CHANNEL_B: |
576 | modesIndex = 4; | 633 | modesIndex = 4; |
577 | freqIndex = 2; | ||
578 | break; | 634 | break; |
579 | case CHANNEL_G_HT40PLUS: | 635 | case CHANNEL_G_HT40PLUS: |
580 | case CHANNEL_G_HT40MINUS: | 636 | case CHANNEL_G_HT40MINUS: |
581 | modesIndex = 3; | 637 | modesIndex = 3; |
582 | freqIndex = 2; | ||
583 | break; | 638 | break; |
584 | 639 | ||
585 | default: | 640 | default: |
@@ -604,6 +659,9 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
604 | REG_WRITE_ARRAY(&ah->iniModesAdditional, | 659 | REG_WRITE_ARRAY(&ah->iniModesAdditional, |
605 | modesIndex, regWrites); | 660 | modesIndex, regWrites); |
606 | 661 | ||
662 | if (AR_SREV_9340(ah) && !ah->is_clk_25mhz) | ||
663 | REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites); | ||
664 | |||
607 | ar9003_hw_override_ini(ah); | 665 | ar9003_hw_override_ini(ah); |
608 | ar9003_hw_set_channel_regs(ah, chan); | 666 | ar9003_hw_set_channel_regs(ah, chan); |
609 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | 667 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); |
@@ -614,7 +672,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
614 | channel->max_antenna_gain * 2, | 672 | channel->max_antenna_gain * 2, |
615 | channel->max_power * 2, | 673 | channel->max_power * 2, |
616 | min((u32) MAX_RATE_POWER, | 674 | min((u32) MAX_RATE_POWER, |
617 | (u32) regulatory->power_limit)); | 675 | (u32) regulatory->power_limit), false); |
618 | 676 | ||
619 | return 0; | 677 | return 0; |
620 | } | 678 | } |
@@ -712,28 +770,6 @@ static void ar9003_hw_rfbus_done(struct ath_hw *ah) | |||
712 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); | 770 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); |
713 | } | 771 | } |
714 | 772 | ||
715 | /* | ||
716 | * Set the interrupt and GPIO values so the ISR can disable RF | ||
717 | * on a switch signal. Assumes GPIO port and interrupt polarity | ||
718 | * are set prior to call. | ||
719 | */ | ||
720 | static void ar9003_hw_enable_rfkill(struct ath_hw *ah) | ||
721 | { | ||
722 | /* Connect rfsilent_bb_l to baseband */ | ||
723 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
724 | AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); | ||
725 | /* Set input mux for rfsilent_bb_l to GPIO #0 */ | ||
726 | REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, | ||
727 | AR_GPIO_INPUT_MUX2_RFSILENT); | ||
728 | |||
729 | /* | ||
730 | * Configure the desired GPIO port for input and | ||
731 | * enable baseband rf silence. | ||
732 | */ | ||
733 | ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); | ||
734 | REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); | ||
735 | } | ||
736 | |||
737 | static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) | 773 | static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) |
738 | { | 774 | { |
739 | u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); | 775 | u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); |
@@ -747,9 +783,9 @@ static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) | |||
747 | static bool ar9003_hw_ani_control(struct ath_hw *ah, | 783 | static bool ar9003_hw_ani_control(struct ath_hw *ah, |
748 | enum ath9k_ani_cmd cmd, int param) | 784 | enum ath9k_ani_cmd cmd, int param) |
749 | { | 785 | { |
750 | struct ar5416AniState *aniState = ah->curani; | ||
751 | struct ath_common *common = ath9k_hw_common(ah); | 786 | struct ath_common *common = ath9k_hw_common(ah); |
752 | struct ath9k_channel *chan = ah->curchan; | 787 | struct ath9k_channel *chan = ah->curchan; |
788 | struct ar5416AniState *aniState = &chan->ani; | ||
753 | s32 value, value2; | 789 | s32 value, value2; |
754 | 790 | ||
755 | switch (cmd & ah->ani_function) { | 791 | switch (cmd & ah->ani_function) { |
@@ -820,12 +856,12 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
820 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | 856 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); |
821 | 857 | ||
822 | if (!on != aniState->ofdmWeakSigDetectOff) { | 858 | if (!on != aniState->ofdmWeakSigDetectOff) { |
823 | ath_print(common, ATH_DBG_ANI, | 859 | ath_dbg(common, ATH_DBG_ANI, |
824 | "** ch %d: ofdm weak signal: %s=>%s\n", | 860 | "** ch %d: ofdm weak signal: %s=>%s\n", |
825 | chan->channel, | 861 | chan->channel, |
826 | !aniState->ofdmWeakSigDetectOff ? | 862 | !aniState->ofdmWeakSigDetectOff ? |
827 | "on" : "off", | 863 | "on" : "off", |
828 | on ? "on" : "off"); | 864 | on ? "on" : "off"); |
829 | if (on) | 865 | if (on) |
830 | ah->stats.ast_ani_ofdmon++; | 866 | ah->stats.ast_ani_ofdmon++; |
831 | else | 867 | else |
@@ -838,11 +874,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
838 | u32 level = param; | 874 | u32 level = param; |
839 | 875 | ||
840 | if (level >= ARRAY_SIZE(firstep_table)) { | 876 | if (level >= ARRAY_SIZE(firstep_table)) { |
841 | ath_print(common, ATH_DBG_ANI, | 877 | ath_dbg(common, ATH_DBG_ANI, |
842 | "ATH9K_ANI_FIRSTEP_LEVEL: level " | 878 | "ATH9K_ANI_FIRSTEP_LEVEL: level out of range (%u > %zu)\n", |
843 | "out of range (%u > %u)\n", | 879 | level, ARRAY_SIZE(firstep_table)); |
844 | level, | ||
845 | (unsigned) ARRAY_SIZE(firstep_table)); | ||
846 | return false; | 880 | return false; |
847 | } | 881 | } |
848 | 882 | ||
@@ -877,24 +911,22 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
877 | AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2); | 911 | AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW, value2); |
878 | 912 | ||
879 | if (level != aniState->firstepLevel) { | 913 | if (level != aniState->firstepLevel) { |
880 | ath_print(common, ATH_DBG_ANI, | 914 | ath_dbg(common, ATH_DBG_ANI, |
881 | "** ch %d: level %d=>%d[def:%d] " | 915 | "** ch %d: level %d=>%d[def:%d] firstep[level]=%d ini=%d\n", |
882 | "firstep[level]=%d ini=%d\n", | 916 | chan->channel, |
883 | chan->channel, | 917 | aniState->firstepLevel, |
884 | aniState->firstepLevel, | 918 | level, |
885 | level, | 919 | ATH9K_ANI_FIRSTEP_LVL_NEW, |
886 | ATH9K_ANI_FIRSTEP_LVL_NEW, | 920 | value, |
887 | value, | 921 | aniState->iniDef.firstep); |
888 | aniState->iniDef.firstep); | 922 | ath_dbg(common, ATH_DBG_ANI, |
889 | ath_print(common, ATH_DBG_ANI, | 923 | "** ch %d: level %d=>%d[def:%d] firstep_low[level]=%d ini=%d\n", |
890 | "** ch %d: level %d=>%d[def:%d] " | 924 | chan->channel, |
891 | "firstep_low[level]=%d ini=%d\n", | 925 | aniState->firstepLevel, |
892 | chan->channel, | 926 | level, |
893 | aniState->firstepLevel, | 927 | ATH9K_ANI_FIRSTEP_LVL_NEW, |
894 | level, | 928 | value2, |
895 | ATH9K_ANI_FIRSTEP_LVL_NEW, | 929 | aniState->iniDef.firstepLow); |
896 | value2, | ||
897 | aniState->iniDef.firstepLow); | ||
898 | if (level > aniState->firstepLevel) | 930 | if (level > aniState->firstepLevel) |
899 | ah->stats.ast_ani_stepup++; | 931 | ah->stats.ast_ani_stepup++; |
900 | else if (level < aniState->firstepLevel) | 932 | else if (level < aniState->firstepLevel) |
@@ -907,11 +939,9 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
907 | u32 level = param; | 939 | u32 level = param; |
908 | 940 | ||
909 | if (level >= ARRAY_SIZE(cycpwrThr1_table)) { | 941 | if (level >= ARRAY_SIZE(cycpwrThr1_table)) { |
910 | ath_print(common, ATH_DBG_ANI, | 942 | ath_dbg(common, ATH_DBG_ANI, |
911 | "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level " | 943 | "ATH9K_ANI_SPUR_IMMUNITY_LEVEL: level out of range (%u > %zu)\n", |
912 | "out of range (%u > %u)\n", | 944 | level, ARRAY_SIZE(cycpwrThr1_table)); |
913 | level, | ||
914 | (unsigned) ARRAY_SIZE(cycpwrThr1_table)); | ||
915 | return false; | 945 | return false; |
916 | } | 946 | } |
917 | /* | 947 | /* |
@@ -945,24 +975,22 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
945 | AR_PHY_EXT_CYCPWR_THR1, value2); | 975 | AR_PHY_EXT_CYCPWR_THR1, value2); |
946 | 976 | ||
947 | if (level != aniState->spurImmunityLevel) { | 977 | if (level != aniState->spurImmunityLevel) { |
948 | ath_print(common, ATH_DBG_ANI, | 978 | ath_dbg(common, ATH_DBG_ANI, |
949 | "** ch %d: level %d=>%d[def:%d] " | 979 | "** ch %d: level %d=>%d[def:%d] cycpwrThr1[level]=%d ini=%d\n", |
950 | "cycpwrThr1[level]=%d ini=%d\n", | 980 | chan->channel, |
951 | chan->channel, | 981 | aniState->spurImmunityLevel, |
952 | aniState->spurImmunityLevel, | 982 | level, |
953 | level, | 983 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, |
954 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | 984 | value, |
955 | value, | 985 | aniState->iniDef.cycpwrThr1); |
956 | aniState->iniDef.cycpwrThr1); | 986 | ath_dbg(common, ATH_DBG_ANI, |
957 | ath_print(common, ATH_DBG_ANI, | 987 | "** ch %d: level %d=>%d[def:%d] cycpwrThr1Ext[level]=%d ini=%d\n", |
958 | "** ch %d: level %d=>%d[def:%d] " | 988 | chan->channel, |
959 | "cycpwrThr1Ext[level]=%d ini=%d\n", | 989 | aniState->spurImmunityLevel, |
960 | chan->channel, | 990 | level, |
961 | aniState->spurImmunityLevel, | 991 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, |
962 | level, | 992 | value2, |
963 | ATH9K_ANI_SPUR_IMMUNE_LVL_NEW, | 993 | aniState->iniDef.cycpwrThr1Ext); |
964 | value2, | ||
965 | aniState->iniDef.cycpwrThr1Ext); | ||
966 | if (level > aniState->spurImmunityLevel) | 994 | if (level > aniState->spurImmunityLevel) |
967 | ah->stats.ast_ani_spurup++; | 995 | ah->stats.ast_ani_spurup++; |
968 | else if (level < aniState->spurImmunityLevel) | 996 | else if (level < aniState->spurImmunityLevel) |
@@ -982,11 +1010,11 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
982 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, | 1010 | REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, |
983 | AR_PHY_MRC_CCK_MUX_REG, is_on); | 1011 | AR_PHY_MRC_CCK_MUX_REG, is_on); |
984 | if (!is_on != aniState->mrcCCKOff) { | 1012 | if (!is_on != aniState->mrcCCKOff) { |
985 | ath_print(common, ATH_DBG_ANI, | 1013 | ath_dbg(common, ATH_DBG_ANI, |
986 | "** ch %d: MRC CCK: %s=>%s\n", | 1014 | "** ch %d: MRC CCK: %s=>%s\n", |
987 | chan->channel, | 1015 | chan->channel, |
988 | !aniState->mrcCCKOff ? "on" : "off", | 1016 | !aniState->mrcCCKOff ? "on" : "off", |
989 | is_on ? "on" : "off"); | 1017 | is_on ? "on" : "off"); |
990 | if (is_on) | 1018 | if (is_on) |
991 | ah->stats.ast_ani_ccklow++; | 1019 | ah->stats.ast_ani_ccklow++; |
992 | else | 1020 | else |
@@ -998,52 +1026,48 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
998 | case ATH9K_ANI_PRESENT: | 1026 | case ATH9K_ANI_PRESENT: |
999 | break; | 1027 | break; |
1000 | default: | 1028 | default: |
1001 | ath_print(common, ATH_DBG_ANI, | 1029 | ath_dbg(common, ATH_DBG_ANI, "invalid cmd %u\n", cmd); |
1002 | "invalid cmd %u\n", cmd); | ||
1003 | return false; | 1030 | return false; |
1004 | } | 1031 | } |
1005 | 1032 | ||
1006 | ath_print(common, ATH_DBG_ANI, | 1033 | ath_dbg(common, ATH_DBG_ANI, |
1007 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d " | 1034 | "ANI parameters: SI=%d, ofdmWS=%s FS=%d MRCcck=%s listenTime=%d ofdmErrs=%d cckErrs=%d\n", |
1008 | "MRCcck=%s listenTime=%d CC=%d listen=%d " | 1035 | aniState->spurImmunityLevel, |
1009 | "ofdmErrs=%d cckErrs=%d\n", | 1036 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", |
1010 | aniState->spurImmunityLevel, | 1037 | aniState->firstepLevel, |
1011 | !aniState->ofdmWeakSigDetectOff ? "on" : "off", | 1038 | !aniState->mrcCCKOff ? "on" : "off", |
1012 | aniState->firstepLevel, | 1039 | aniState->listenTime, |
1013 | !aniState->mrcCCKOff ? "on" : "off", | 1040 | aniState->ofdmPhyErrCount, |
1014 | aniState->listenTime, | 1041 | aniState->cckPhyErrCount); |
1015 | aniState->cycleCount, | ||
1016 | aniState->listenTime, | ||
1017 | aniState->ofdmPhyErrCount, | ||
1018 | aniState->cckPhyErrCount); | ||
1019 | return true; | 1042 | return true; |
1020 | } | 1043 | } |
1021 | 1044 | ||
1022 | static void ar9003_hw_do_getnf(struct ath_hw *ah, | 1045 | static void ar9003_hw_do_getnf(struct ath_hw *ah, |
1023 | int16_t nfarray[NUM_NF_READINGS]) | 1046 | int16_t nfarray[NUM_NF_READINGS]) |
1024 | { | 1047 | { |
1025 | int16_t nf; | 1048 | #define AR_PHY_CH_MINCCA_PWR 0x1FF00000 |
1026 | 1049 | #define AR_PHY_CH_MINCCA_PWR_S 20 | |
1027 | nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR); | 1050 | #define AR_PHY_CH_EXT_MINCCA_PWR 0x01FF0000 |
1028 | nfarray[0] = sign_extend(nf, 9); | 1051 | #define AR_PHY_CH_EXT_MINCCA_PWR_S 16 |
1029 | 1052 | ||
1030 | nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR); | 1053 | int16_t nf; |
1031 | nfarray[1] = sign_extend(nf, 9); | 1054 | int i; |
1032 | |||
1033 | nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR); | ||
1034 | nfarray[2] = sign_extend(nf, 9); | ||
1035 | |||
1036 | if (!IS_CHAN_HT40(ah->curchan)) | ||
1037 | return; | ||
1038 | 1055 | ||
1039 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); | 1056 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { |
1040 | nfarray[3] = sign_extend(nf, 9); | 1057 | if (ah->rxchainmask & BIT(i)) { |
1058 | nf = MS(REG_READ(ah, ah->nf_regs[i]), | ||
1059 | AR_PHY_CH_MINCCA_PWR); | ||
1060 | nfarray[i] = sign_extend32(nf, 8); | ||
1041 | 1061 | ||
1042 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR); | 1062 | if (IS_CHAN_HT40(ah->curchan)) { |
1043 | nfarray[4] = sign_extend(nf, 9); | 1063 | u8 ext_idx = AR9300_MAX_CHAINS + i; |
1044 | 1064 | ||
1045 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR); | 1065 | nf = MS(REG_READ(ah, ah->nf_regs[ext_idx]), |
1046 | nfarray[5] = sign_extend(nf, 9); | 1066 | AR_PHY_CH_EXT_MINCCA_PWR); |
1067 | nfarray[ext_idx] = sign_extend32(nf, 8); | ||
1068 | } | ||
1069 | } | ||
1070 | } | ||
1047 | } | 1071 | } |
1048 | 1072 | ||
1049 | static void ar9003_hw_set_nf_limits(struct ath_hw *ah) | 1073 | static void ar9003_hw_set_nf_limits(struct ath_hw *ah) |
@@ -1067,21 +1091,18 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1067 | struct ath_common *common = ath9k_hw_common(ah); | 1091 | struct ath_common *common = ath9k_hw_common(ah); |
1068 | struct ath9k_channel *chan = ah->curchan; | 1092 | struct ath9k_channel *chan = ah->curchan; |
1069 | struct ath9k_ani_default *iniDef; | 1093 | struct ath9k_ani_default *iniDef; |
1070 | int index; | ||
1071 | u32 val; | 1094 | u32 val; |
1072 | 1095 | ||
1073 | index = ath9k_hw_get_ani_channel_idx(ah, chan); | 1096 | aniState = &ah->curchan->ani; |
1074 | aniState = &ah->ani[index]; | ||
1075 | ah->curani = aniState; | ||
1076 | iniDef = &aniState->iniDef; | 1097 | iniDef = &aniState->iniDef; |
1077 | 1098 | ||
1078 | ath_print(common, ATH_DBG_ANI, | 1099 | ath_dbg(common, ATH_DBG_ANI, |
1079 | "ver %d.%d opmode %u chan %d Mhz/0x%x\n", | 1100 | "ver %d.%d opmode %u chan %d Mhz/0x%x\n", |
1080 | ah->hw_version.macVersion, | 1101 | ah->hw_version.macVersion, |
1081 | ah->hw_version.macRev, | 1102 | ah->hw_version.macRev, |
1082 | ah->opmode, | 1103 | ah->opmode, |
1083 | chan->channel, | 1104 | chan->channel, |
1084 | chan->channelFlags); | 1105 | chan->channelFlags); |
1085 | 1106 | ||
1086 | val = REG_READ(ah, AR_PHY_SFCORR); | 1107 | val = REG_READ(ah, AR_PHY_SFCORR); |
1087 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); | 1108 | iniDef->m1Thresh = MS(val, AR_PHY_SFCORR_M1_THRESH); |
@@ -1116,14 +1137,100 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1116 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; | 1137 | aniState->firstepLevel = ATH9K_ANI_FIRSTEP_LVL_NEW; |
1117 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; | 1138 | aniState->ofdmWeakSigDetectOff = !ATH9K_ANI_USE_OFDM_WEAK_SIG; |
1118 | aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; | 1139 | aniState->mrcCCKOff = !ATH9K_ANI_ENABLE_MRC_CCK; |
1140 | } | ||
1141 | |||
1142 | static void ar9003_hw_set_radar_params(struct ath_hw *ah, | ||
1143 | struct ath_hw_radar_conf *conf) | ||
1144 | { | ||
1145 | u32 radar_0 = 0, radar_1 = 0; | ||
1146 | |||
1147 | if (!conf) { | ||
1148 | REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); | ||
1149 | return; | ||
1150 | } | ||
1151 | |||
1152 | radar_0 |= AR_PHY_RADAR_0_ENA | AR_PHY_RADAR_0_FFT_ENA; | ||
1153 | radar_0 |= SM(conf->fir_power, AR_PHY_RADAR_0_FIRPWR); | ||
1154 | radar_0 |= SM(conf->radar_rssi, AR_PHY_RADAR_0_RRSSI); | ||
1155 | radar_0 |= SM(conf->pulse_height, AR_PHY_RADAR_0_HEIGHT); | ||
1156 | radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); | ||
1157 | radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); | ||
1158 | |||
1159 | radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; | ||
1160 | radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; | ||
1161 | radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); | ||
1162 | radar_1 |= SM(conf->pulse_inband_step, AR_PHY_RADAR_1_RELSTEP_THRESH); | ||
1163 | radar_1 |= SM(conf->radar_inband, AR_PHY_RADAR_1_RELPWR_THRESH); | ||
1164 | |||
1165 | REG_WRITE(ah, AR_PHY_RADAR_0, radar_0); | ||
1166 | REG_WRITE(ah, AR_PHY_RADAR_1, radar_1); | ||
1167 | if (conf->ext_channel) | ||
1168 | REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); | ||
1169 | else | ||
1170 | REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA); | ||
1171 | } | ||
1172 | |||
1173 | static void ar9003_hw_set_radar_conf(struct ath_hw *ah) | ||
1174 | { | ||
1175 | struct ath_hw_radar_conf *conf = &ah->radar_conf; | ||
1176 | |||
1177 | conf->fir_power = -28; | ||
1178 | conf->radar_rssi = 0; | ||
1179 | conf->pulse_height = 10; | ||
1180 | conf->pulse_rssi = 24; | ||
1181 | conf->pulse_inband = 8; | ||
1182 | conf->pulse_maxlen = 255; | ||
1183 | conf->pulse_inband_step = 12; | ||
1184 | conf->radar_inband = 8; | ||
1185 | } | ||
1186 | |||
1187 | static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah, | ||
1188 | struct ath_hw_antcomb_conf *antconf) | ||
1189 | { | ||
1190 | u32 regval; | ||
1191 | |||
1192 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
1193 | antconf->main_lna_conf = (regval & AR_PHY_9485_ANT_DIV_MAIN_LNACONF) >> | ||
1194 | AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S; | ||
1195 | antconf->alt_lna_conf = (regval & AR_PHY_9485_ANT_DIV_ALT_LNACONF) >> | ||
1196 | AR_PHY_9485_ANT_DIV_ALT_LNACONF_S; | ||
1197 | antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >> | ||
1198 | AR_PHY_9485_ANT_FAST_DIV_BIAS_S; | ||
1199 | antconf->lna1_lna2_delta = -9; | ||
1200 | antconf->div_group = 2; | ||
1201 | } | ||
1119 | 1202 | ||
1120 | aniState->cycleCount = 0; | 1203 | static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah, |
1204 | struct ath_hw_antcomb_conf *antconf) | ||
1205 | { | ||
1206 | u32 regval; | ||
1207 | |||
1208 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
1209 | regval &= ~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF | | ||
1210 | AR_PHY_9485_ANT_DIV_ALT_LNACONF | | ||
1211 | AR_PHY_9485_ANT_FAST_DIV_BIAS | | ||
1212 | AR_PHY_9485_ANT_DIV_MAIN_GAINTB | | ||
1213 | AR_PHY_9485_ANT_DIV_ALT_GAINTB); | ||
1214 | regval |= ((antconf->main_lna_conf << | ||
1215 | AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S) | ||
1216 | & AR_PHY_9485_ANT_DIV_MAIN_LNACONF); | ||
1217 | regval |= ((antconf->alt_lna_conf << AR_PHY_9485_ANT_DIV_ALT_LNACONF_S) | ||
1218 | & AR_PHY_9485_ANT_DIV_ALT_LNACONF); | ||
1219 | regval |= ((antconf->fast_div_bias << AR_PHY_9485_ANT_FAST_DIV_BIAS_S) | ||
1220 | & AR_PHY_9485_ANT_FAST_DIV_BIAS); | ||
1221 | regval |= ((antconf->main_gaintb << AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S) | ||
1222 | & AR_PHY_9485_ANT_DIV_MAIN_GAINTB); | ||
1223 | regval |= ((antconf->alt_gaintb << AR_PHY_9485_ANT_DIV_ALT_GAINTB_S) | ||
1224 | & AR_PHY_9485_ANT_DIV_ALT_GAINTB); | ||
1225 | |||
1226 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
1121 | } | 1227 | } |
1122 | 1228 | ||
1123 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1229 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
1124 | { | 1230 | { |
1125 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1231 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
1126 | const u32 ar9300_cca_regs[6] = { | 1232 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); |
1233 | static const u32 ar9300_cca_regs[6] = { | ||
1127 | AR_PHY_CCA_0, | 1234 | AR_PHY_CCA_0, |
1128 | AR_PHY_CCA_1, | 1235 | AR_PHY_CCA_1, |
1129 | AR_PHY_CCA_2, | 1236 | AR_PHY_CCA_2, |
@@ -1143,13 +1250,17 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
1143 | priv_ops->set_delta_slope = ar9003_hw_set_delta_slope; | 1250 | priv_ops->set_delta_slope = ar9003_hw_set_delta_slope; |
1144 | priv_ops->rfbus_req = ar9003_hw_rfbus_req; | 1251 | priv_ops->rfbus_req = ar9003_hw_rfbus_req; |
1145 | priv_ops->rfbus_done = ar9003_hw_rfbus_done; | 1252 | priv_ops->rfbus_done = ar9003_hw_rfbus_done; |
1146 | priv_ops->enable_rfkill = ar9003_hw_enable_rfkill; | ||
1147 | priv_ops->set_diversity = ar9003_hw_set_diversity; | 1253 | priv_ops->set_diversity = ar9003_hw_set_diversity; |
1148 | priv_ops->ani_control = ar9003_hw_ani_control; | 1254 | priv_ops->ani_control = ar9003_hw_ani_control; |
1149 | priv_ops->do_getnf = ar9003_hw_do_getnf; | 1255 | priv_ops->do_getnf = ar9003_hw_do_getnf; |
1150 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; | 1256 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; |
1257 | priv_ops->set_radar_params = ar9003_hw_set_radar_params; | ||
1258 | |||
1259 | ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; | ||
1260 | ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; | ||
1151 | 1261 | ||
1152 | ar9003_hw_set_nf_limits(ah); | 1262 | ar9003_hw_set_nf_limits(ah); |
1263 | ar9003_hw_set_radar_conf(ah); | ||
1153 | memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); | 1264 | memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); |
1154 | } | 1265 | } |
1155 | 1266 | ||
@@ -1172,7 +1283,7 @@ void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) | |||
1172 | ~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE | | 1283 | ~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE | |
1173 | AR_PHY_WATCHDOG_IDLE_ENABLE)); | 1284 | AR_PHY_WATCHDOG_IDLE_ENABLE)); |
1174 | 1285 | ||
1175 | ath_print(common, ATH_DBG_RESET, "Disabled BB Watchdog\n"); | 1286 | ath_dbg(common, ATH_DBG_RESET, "Disabled BB Watchdog\n"); |
1176 | return; | 1287 | return; |
1177 | } | 1288 | } |
1178 | 1289 | ||
@@ -1208,9 +1319,9 @@ void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) | |||
1208 | AR_PHY_WATCHDOG_IDLE_MASK | | 1319 | AR_PHY_WATCHDOG_IDLE_MASK | |
1209 | (AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2))); | 1320 | (AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2))); |
1210 | 1321 | ||
1211 | ath_print(common, ATH_DBG_RESET, | 1322 | ath_dbg(common, ATH_DBG_RESET, |
1212 | "Enabled BB Watchdog timeout (%u ms)\n", | 1323 | "Enabled BB Watchdog timeout (%u ms)\n", |
1213 | idle_tmo_ms); | 1324 | idle_tmo_ms); |
1214 | } | 1325 | } |
1215 | 1326 | ||
1216 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah) | 1327 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah) |
@@ -1232,42 +1343,63 @@ void ar9003_hw_bb_watchdog_read(struct ath_hw *ah) | |||
1232 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah) | 1343 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah) |
1233 | { | 1344 | { |
1234 | struct ath_common *common = ath9k_hw_common(ah); | 1345 | struct ath_common *common = ath9k_hw_common(ah); |
1235 | u32 rxc_pcnt = 0, rxf_pcnt = 0, txf_pcnt = 0, status; | 1346 | u32 status; |
1236 | 1347 | ||
1237 | if (likely(!(common->debug_mask & ATH_DBG_RESET))) | 1348 | if (likely(!(common->debug_mask & ATH_DBG_RESET))) |
1238 | return; | 1349 | return; |
1239 | 1350 | ||
1240 | status = ah->bb_watchdog_last_status; | 1351 | status = ah->bb_watchdog_last_status; |
1241 | ath_print(common, ATH_DBG_RESET, | 1352 | ath_dbg(common, ATH_DBG_RESET, |
1242 | "\n==== BB update: BB status=0x%08x ====\n", status); | 1353 | "\n==== BB update: BB status=0x%08x ====\n", status); |
1243 | ath_print(common, ATH_DBG_RESET, | 1354 | ath_dbg(common, ATH_DBG_RESET, |
1244 | "** BB state: wd=%u det=%u rdar=%u rOFDM=%d " | 1355 | "** BB state: wd=%u det=%u rdar=%u rOFDM=%d rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n", |
1245 | "rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n", | 1356 | MS(status, AR_PHY_WATCHDOG_INFO), |
1246 | MS(status, AR_PHY_WATCHDOG_INFO), | 1357 | MS(status, AR_PHY_WATCHDOG_DET_HANG), |
1247 | MS(status, AR_PHY_WATCHDOG_DET_HANG), | 1358 | MS(status, AR_PHY_WATCHDOG_RADAR_SM), |
1248 | MS(status, AR_PHY_WATCHDOG_RADAR_SM), | 1359 | MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM), |
1249 | MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM), | 1360 | MS(status, AR_PHY_WATCHDOG_RX_CCK_SM), |
1250 | MS(status, AR_PHY_WATCHDOG_RX_CCK_SM), | 1361 | MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM), |
1251 | MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM), | 1362 | MS(status, AR_PHY_WATCHDOG_TX_CCK_SM), |
1252 | MS(status, AR_PHY_WATCHDOG_TX_CCK_SM), | 1363 | MS(status, AR_PHY_WATCHDOG_AGC_SM), |
1253 | MS(status, AR_PHY_WATCHDOG_AGC_SM), | 1364 | MS(status, AR_PHY_WATCHDOG_SRCH_SM)); |
1254 | MS(status,AR_PHY_WATCHDOG_SRCH_SM)); | 1365 | |
1255 | 1366 | ath_dbg(common, ATH_DBG_RESET, | |
1256 | ath_print(common, ATH_DBG_RESET, | 1367 | "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n", |
1257 | "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n", | 1368 | REG_READ(ah, AR_PHY_WATCHDOG_CTL_1), |
1258 | REG_READ(ah, AR_PHY_WATCHDOG_CTL_1), | 1369 | REG_READ(ah, AR_PHY_WATCHDOG_CTL_2)); |
1259 | REG_READ(ah, AR_PHY_WATCHDOG_CTL_2)); | 1370 | ath_dbg(common, ATH_DBG_RESET, |
1260 | ath_print(common, ATH_DBG_RESET, | 1371 | "** BB mode: BB_gen_controls=0x%08x **\n", |
1261 | "** BB mode: BB_gen_controls=0x%08x **\n", | 1372 | REG_READ(ah, AR_PHY_GEN_CTRL)); |
1262 | REG_READ(ah, AR_PHY_GEN_CTRL)); | 1373 | |
1263 | 1374 | #define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles) | |
1264 | if (ath9k_hw_GetMibCycleCountsPct(ah, &rxc_pcnt, &rxf_pcnt, &txf_pcnt)) | 1375 | if (common->cc_survey.cycles) |
1265 | ath_print(common, ATH_DBG_RESET, | 1376 | ath_dbg(common, ATH_DBG_RESET, |
1266 | "** BB busy times: rx_clear=%d%%, " | 1377 | "** BB busy times: rx_clear=%d%%, rx_frame=%d%%, tx_frame=%d%% **\n", |
1267 | "rx_frame=%d%%, tx_frame=%d%% **\n", | 1378 | PCT(rx_busy), PCT(rx_frame), PCT(tx_frame)); |
1268 | rxc_pcnt, rxf_pcnt, txf_pcnt); | 1379 | |
1269 | 1380 | ath_dbg(common, ATH_DBG_RESET, | |
1270 | ath_print(common, ATH_DBG_RESET, | 1381 | "==== BB update: done ====\n\n"); |
1271 | "==== BB update: done ====\n\n"); | ||
1272 | } | 1382 | } |
1273 | EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info); | 1383 | EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info); |
1384 | |||
1385 | void ar9003_hw_disable_phy_restart(struct ath_hw *ah) | ||
1386 | { | ||
1387 | u32 val; | ||
1388 | |||
1389 | /* While receiving unsupported rate frame rx state machine | ||
1390 | * gets into a state 0xb and if phy_restart happens in that | ||
1391 | * state, BB would go hang. If RXSM is in 0xb state after | ||
1392 | * first bb panic, ensure to disable the phy_restart. | ||
1393 | */ | ||
1394 | if (!((MS(ah->bb_watchdog_last_status, | ||
1395 | AR_PHY_WATCHDOG_RX_OFDM_SM) == 0xb) || | ||
1396 | ah->bb_hang_rx_ofdm)) | ||
1397 | return; | ||
1398 | |||
1399 | ah->bb_hang_rx_ofdm = true; | ||
1400 | val = REG_READ(ah, AR_PHY_RESTART); | ||
1401 | val &= ~AR_PHY_RESTART_ENA; | ||
1402 | |||
1403 | REG_WRITE(ah, AR_PHY_RESTART, val); | ||
1404 | } | ||
1405 | EXPORT_SYMBOL(ar9003_hw_disable_phy_restart); | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 3394dfe52b42..443090d278e3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2002-2010 Atheros Communications, Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications, Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -260,7 +260,35 @@ | |||
260 | #define AR_PHY_CCA_0 (AR_AGC_BASE + 0x1c) | 260 | #define AR_PHY_CCA_0 (AR_AGC_BASE + 0x1c) |
261 | #define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20) | 261 | #define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20) |
262 | #define AR_PHY_RESTART (AR_AGC_BASE + 0x24) | 262 | #define AR_PHY_RESTART (AR_AGC_BASE + 0x24) |
263 | |||
264 | /* | ||
265 | * Antenna Diversity settings | ||
266 | */ | ||
263 | #define AR_PHY_MC_GAIN_CTRL (AR_AGC_BASE + 0x28) | 267 | #define AR_PHY_MC_GAIN_CTRL (AR_AGC_BASE + 0x28) |
268 | #define AR_ANT_DIV_CTRL_ALL 0x7e000000 | ||
269 | #define AR_ANT_DIV_CTRL_ALL_S 25 | ||
270 | #define AR_ANT_DIV_ENABLE 0x1000000 | ||
271 | #define AR_ANT_DIV_ENABLE_S 24 | ||
272 | |||
273 | |||
274 | #define AR_PHY_9485_ANT_FAST_DIV_BIAS 0x00007e00 | ||
275 | #define AR_PHY_9485_ANT_FAST_DIV_BIAS_S 9 | ||
276 | #define AR_PHY_9485_ANT_DIV_LNADIV 0x01000000 | ||
277 | #define AR_PHY_9485_ANT_DIV_LNADIV_S 24 | ||
278 | #define AR_PHY_9485_ANT_DIV_ALT_LNACONF 0x06000000 | ||
279 | #define AR_PHY_9485_ANT_DIV_ALT_LNACONF_S 25 | ||
280 | #define AR_PHY_9485_ANT_DIV_MAIN_LNACONF 0x18000000 | ||
281 | #define AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S 27 | ||
282 | #define AR_PHY_9485_ANT_DIV_ALT_GAINTB 0x20000000 | ||
283 | #define AR_PHY_9485_ANT_DIV_ALT_GAINTB_S 29 | ||
284 | #define AR_PHY_9485_ANT_DIV_MAIN_GAINTB 0x40000000 | ||
285 | #define AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S 30 | ||
286 | |||
287 | #define AR_PHY_9485_ANT_DIV_LNA1_MINUS_LNA2 0x0 | ||
288 | #define AR_PHY_9485_ANT_DIV_LNA2 0x1 | ||
289 | #define AR_PHY_9485_ANT_DIV_LNA1 0x2 | ||
290 | #define AR_PHY_9485_ANT_DIV_LNA1_PLUS_LNA2 0x3 | ||
291 | |||
264 | #define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) | 292 | #define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) |
265 | #define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) | 293 | #define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) |
266 | #define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34) | 294 | #define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34) |
@@ -271,7 +299,11 @@ | |||
271 | #define AR_PHY_RX_GAIN_BOUNDS_2 (AR_AGC_BASE + 0x48) | 299 | #define AR_PHY_RX_GAIN_BOUNDS_2 (AR_AGC_BASE + 0x48) |
272 | #define AR_PHY_RSSI_0 (AR_AGC_BASE + 0x180) | 300 | #define AR_PHY_RSSI_0 (AR_AGC_BASE + 0x180) |
273 | #define AR_PHY_SPUR_CCK_REP0 (AR_AGC_BASE + 0x184) | 301 | #define AR_PHY_SPUR_CCK_REP0 (AR_AGC_BASE + 0x184) |
302 | |||
274 | #define AR_PHY_CCK_DETECT (AR_AGC_BASE + 0x1c0) | 303 | #define AR_PHY_CCK_DETECT (AR_AGC_BASE + 0x1c0) |
304 | #define AR_FAST_DIV_ENABLE 0x2000 | ||
305 | #define AR_FAST_DIV_ENABLE_S 13 | ||
306 | |||
275 | #define AR_PHY_DAG_CTRLCCK (AR_AGC_BASE + 0x1c4) | 307 | #define AR_PHY_DAG_CTRLCCK (AR_AGC_BASE + 0x1c4) |
276 | #define AR_PHY_IQCORR_CTRL_CCK (AR_AGC_BASE + 0x1c8) | 308 | #define AR_PHY_IQCORR_CTRL_CCK (AR_AGC_BASE + 0x1c8) |
277 | 309 | ||
@@ -476,6 +508,8 @@ | |||
476 | #define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac) | 508 | #define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac) |
477 | #define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0) | 509 | #define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0) |
478 | 510 | ||
511 | #define AR_PHY_POWER_TX_RATE(_d) (AR_SM_BASE + 0x1c0 + ((_d) << 2)) | ||
512 | |||
479 | #define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) | 513 | #define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0) |
480 | #define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) | 514 | #define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4) |
481 | 515 | ||
@@ -536,10 +570,15 @@ | |||
536 | 570 | ||
537 | #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) | 571 | #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) |
538 | 572 | ||
539 | #define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) | 573 | #define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \ |
540 | #define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) | 574 | 0x3c8 : 0x448) |
541 | #define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) | 575 | #define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \ |
542 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450) | 576 | 0x3c4 : 0x440) |
577 | #define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \ | ||
578 | 0x3f0 : 0x48c) | ||
579 | #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \ | ||
580 | (AR_SREV_9485(ah) ? \ | ||
581 | 0x3d0 : 0x450) + ((_i) << 2)) | ||
543 | 582 | ||
544 | #define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0) | 583 | #define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0) |
545 | #define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4) | 584 | #define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4) |
@@ -568,7 +607,7 @@ | |||
568 | #define AR_PHY_65NM_CH0_BIAS2 0x160c4 | 607 | #define AR_PHY_65NM_CH0_BIAS2 0x160c4 |
569 | #define AR_PHY_65NM_CH0_BIAS4 0x160cc | 608 | #define AR_PHY_65NM_CH0_BIAS4 0x160cc |
570 | #define AR_PHY_65NM_CH0_RXTX4 0x1610c | 609 | #define AR_PHY_65NM_CH0_RXTX4 0x1610c |
571 | #define AR_PHY_65NM_CH0_THERM 0x16290 | 610 | #define AR_PHY_65NM_CH0_THERM (AR_SREV_9300(ah) ? 0x16290 : 0x1628c) |
572 | 611 | ||
573 | #define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 | 612 | #define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000 |
574 | #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 | 613 | #define AR_PHY_65NM_CH0_THERM_LOCAL_S 31 |
@@ -584,6 +623,24 @@ | |||
584 | #define AR_PHY_65NM_CH2_RXTX1 0x16900 | 623 | #define AR_PHY_65NM_CH2_RXTX1 0x16900 |
585 | #define AR_PHY_65NM_CH2_RXTX2 0x16904 | 624 | #define AR_PHY_65NM_CH2_RXTX2 0x16904 |
586 | 625 | ||
626 | #define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c) | ||
627 | #define AR_CH0_TOP2_XPABIASLVL 0xf000 | ||
628 | #define AR_CH0_TOP2_XPABIASLVL_S 12 | ||
629 | |||
630 | #define AR_CH0_XTAL (AR_SREV_9485(ah) ? 0x16290 : 0x16294) | ||
631 | #define AR_CH0_XTAL_CAPINDAC 0x7f000000 | ||
632 | #define AR_CH0_XTAL_CAPINDAC_S 24 | ||
633 | #define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000 | ||
634 | #define AR_CH0_XTAL_CAPOUTDAC_S 17 | ||
635 | |||
636 | #define AR_PHY_PMU1 0x16c40 | ||
637 | #define AR_PHY_PMU1_PWD 0x1 | ||
638 | #define AR_PHY_PMU1_PWD_S 0 | ||
639 | |||
640 | #define AR_PHY_PMU2 0x16c44 | ||
641 | #define AR_PHY_PMU2_PGM 0x00200000 | ||
642 | #define AR_PHY_PMU2_PGM_S 21 | ||
643 | |||
587 | #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT 0x00380000 | 644 | #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT 0x00380000 |
588 | #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S 19 | 645 | #define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S 19 |
589 | #define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT 0x00c00000 | 646 | #define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT 0x00c00000 |
@@ -683,6 +740,7 @@ | |||
683 | #define AR_PHY_TPCGR1_FORCED_DAC_GAIN_S 1 | 740 | #define AR_PHY_TPCGR1_FORCED_DAC_GAIN_S 1 |
684 | #define AR_PHY_TPCGR1_FORCE_DAC_GAIN 0x00000001 | 741 | #define AR_PHY_TPCGR1_FORCE_DAC_GAIN 0x00000001 |
685 | #define AR_PHY_TXGAIN_FORCE 0x00000001 | 742 | #define AR_PHY_TXGAIN_FORCE 0x00000001 |
743 | #define AR_PHY_TXGAIN_FORCE_S 0 | ||
686 | #define AR_PHY_TXGAIN_FORCED_PADVGNRA 0x00003c00 | 744 | #define AR_PHY_TXGAIN_FORCED_PADVGNRA 0x00003c00 |
687 | #define AR_PHY_TXGAIN_FORCED_PADVGNRA_S 10 | 745 | #define AR_PHY_TXGAIN_FORCED_PADVGNRA_S 10 |
688 | #define AR_PHY_TXGAIN_FORCED_PADVGNRB 0x0003c000 | 746 | #define AR_PHY_TXGAIN_FORCED_PADVGNRB 0x0003c000 |
@@ -719,14 +777,19 @@ | |||
719 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 | 777 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 |
720 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 | 778 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 |
721 | #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 | 779 | #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 |
722 | #define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 | 780 | #define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 |
723 | #define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 | 781 | #define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 |
724 | #define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 | 782 | #define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 |
725 | #define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 | 783 | #define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 |
726 | 784 | ||
727 | #define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001 | 785 | #define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001 |
728 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x00003fff | 786 | #define AR_PHY_CALIBRATED_GAINS_0 0x3e |
729 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 0 | 787 | #define AR_PHY_CALIBRATED_GAINS_0_S 1 |
788 | |||
789 | #define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE 0x00003fff | ||
790 | #define AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE_S 0 | ||
791 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x0fffc000 | ||
792 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 14 | ||
730 | 793 | ||
731 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 | 794 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000 |
732 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 | 795 | #define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28 |
@@ -785,7 +848,7 @@ | |||
785 | #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) | 848 | #define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220) |
786 | #define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240) | 849 | #define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240) |
787 | #define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c) | 850 | #define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c) |
788 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_B1 (AR_SM1_BASE + 0x450) | 851 | #define AR_PHY_TX_IQCAL_CORR_COEFF_B1(_i) (AR_SM_BASE + 0x450 + ((_i) << 2)) |
789 | 852 | ||
790 | /* | 853 | /* |
791 | * Channel 2 Register Map | 854 | * Channel 2 Register Map |
@@ -838,7 +901,7 @@ | |||
838 | #define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220) | 901 | #define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220) |
839 | #define AR_PHY_PDADC_TAB_2 (AR_SM2_BASE + 0x240) | 902 | #define AR_PHY_PDADC_TAB_2 (AR_SM2_BASE + 0x240) |
840 | #define AR_PHY_TX_IQCAL_STATUS_B2 (AR_SM2_BASE + 0x48c) | 903 | #define AR_PHY_TX_IQCAL_STATUS_B2 (AR_SM2_BASE + 0x48c) |
841 | #define AR_PHY_TX_IQCAL_CORR_COEFF_01_B2 (AR_SM2_BASE + 0x450) | 904 | #define AR_PHY_TX_IQCAL_CORR_COEFF_B2(_i) (AR_SM2_BASE + 0x450 + ((_i) << 2)) |
842 | 905 | ||
843 | #define AR_PHY_TX_IQCAL_STATUS_B2_FAILED 0x00000001 | 906 | #define AR_PHY_TX_IQCAL_STATUS_B2_FAILED 0x00000001 |
844 | 907 | ||
@@ -945,7 +1008,9 @@ | |||
945 | #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT 0x0ffe0000 | 1008 | #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT 0x0ffe0000 |
946 | #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S 17 | 1009 | #define AR_PHY_PAPRD_CTRL1_PAPRD_MAG_SCALE_FACT_S 17 |
947 | 1010 | ||
948 | #define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + 0x490) | 1011 | #define AR_PHY_PAPRD_TRAINER_CNTL1 (AR_SM_BASE + \ |
1012 | (AR_SREV_9485(ah) ? \ | ||
1013 | 0x580 : 0x490)) | ||
949 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE 0x00000001 | 1014 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE 0x00000001 |
950 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S 0 | 1015 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_CF_PAPRD_TRAIN_ENABLE_S 0 |
951 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING 0x0000007e | 1016 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_AGC2_SETTLING 0x0000007e |
@@ -961,11 +1026,15 @@ | |||
961 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP 0x0003f000 | 1026 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP 0x0003f000 |
962 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S 12 | 1027 | #define AR_PHY_PAPRD_TRAINER_CNTL1_CF_PAPRD_LB_SKIP_S 12 |
963 | 1028 | ||
964 | #define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + 0x494) | 1029 | #define AR_PHY_PAPRD_TRAINER_CNTL2 (AR_SM_BASE + \ |
1030 | (AR_SREV_9485(ah) ? \ | ||
1031 | 0x584 : 0x494)) | ||
965 | #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN 0xFFFFFFFF | 1032 | #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN 0xFFFFFFFF |
966 | #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S 0 | 1033 | #define AR_PHY_PAPRD_TRAINER_CNTL2_CF_PAPRD_INIT_RX_BB_GAIN_S 0 |
967 | 1034 | ||
968 | #define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + 0x498) | 1035 | #define AR_PHY_PAPRD_TRAINER_CNTL3 (AR_SM_BASE + \ |
1036 | (AR_SREV_9485(ah) ? \ | ||
1037 | 0x588 : 0x498)) | ||
969 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE 0x0000003f | 1038 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE 0x0000003f |
970 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S 0 | 1039 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_ADC_DESIRED_SIZE_S 0 |
971 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP 0x00000fc0 | 1040 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP 0x00000fc0 |
@@ -981,7 +1050,9 @@ | |||
981 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE 0x20000000 | 1050 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE 0x20000000 |
982 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S 29 | 1051 | #define AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_BBTXMIX_DISABLE_S 29 |
983 | 1052 | ||
984 | #define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + 0x49c) | 1053 | #define AR_PHY_PAPRD_TRAINER_CNTL4 (AR_SM_BASE + \ |
1054 | (AR_SREV_9485(ah) ? \ | ||
1055 | 0x58c : 0x49c)) | ||
985 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES 0x03ff0000 | 1056 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES 0x03ff0000 |
986 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S 16 | 1057 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_NUM_TRAIN_SAMPLES_S 16 |
987 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA 0x0000f000 | 1058 | #define AR_PHY_PAPRD_TRAINER_CNTL4_CF_PAPRD_SAFETY_DELTA 0x0000f000 |
@@ -1040,6 +1111,14 @@ | |||
1040 | #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0 0x3F | 1111 | #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0 0x3F |
1041 | #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S 0 | 1112 | #define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S 0 |
1042 | 1113 | ||
1114 | #define AR_PHY_POWERTX_RATE6 (AR_SM_BASE + 0x1d4) | ||
1115 | #define AR_PHY_POWERTX_RATE6_POWERTXHT20_5 0x3F00 | ||
1116 | #define AR_PHY_POWERTX_RATE6_POWERTXHT20_5_S 8 | ||
1117 | |||
1118 | #define AR_PHY_POWERTX_RATE8 (AR_SM_BASE + 0x1dc) | ||
1119 | #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5 0x3F00 | ||
1120 | #define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S 8 | ||
1121 | |||
1043 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); | 1122 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); |
1044 | 1123 | ||
1045 | #endif /* AR9003_PHY_H */ | 1124 | #endif /* AR9003_PHY_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h index d3375fc4ce8b..815a8af1beef 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9340_initvals.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -14,26 +14,20 @@ | |||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef INITVALS_9003_2P0_H | 17 | #ifndef INITVALS_9340_H |
18 | #define INITVALS_9003_2P0_H | 18 | #define INITVALS_9340_H |
19 | 19 | ||
20 | /* AR9003 2.0 */ | 20 | static const u32 ar9340_1p0_radio_postamble[][5] = { |
21 | 21 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | |
22 | static const u32 ar9300_2p0_radio_postamble[][5] = { | 22 | {0x000160ac, 0xa4646800, 0xa4646800, 0xa4646800, 0xa4646800}, |
23 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 23 | {0x0001610c, 0x08000000, 0x08000000, 0x00000000, 0x00000000}, |
24 | {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, | 24 | {0x00016140, 0x10804000, 0x10804000, 0x50804000, 0x50804000}, |
25 | {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, | 25 | {0x0001650c, 0x08000000, 0x08000000, 0x00000000, 0x00000000}, |
26 | {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, | 26 | {0x00016540, 0x10804000, 0x10804000, 0x50804000, 0x50804000}, |
27 | {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, | ||
28 | {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | ||
29 | {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, | ||
30 | {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | ||
31 | {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, | ||
32 | {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, | ||
33 | }; | 27 | }; |
34 | 28 | ||
35 | static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = { | 29 | static const u32 ar9340Modes_lowest_ob_db_tx_gain_table_1p0[][5] = { |
36 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 30 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
37 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 31 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, |
38 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 32 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
39 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | 33 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, |
@@ -99,19 +93,14 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = { | |||
99 | {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, | 93 | {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, |
100 | {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, | 94 | {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, |
101 | {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, | 95 | {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, |
102 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 96 | {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, |
103 | {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, | 97 | {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, |
104 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 98 | {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, |
105 | {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 99 | {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, |
106 | {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, | ||
107 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
108 | {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | ||
109 | {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, | ||
110 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | ||
111 | }; | 100 | }; |
112 | 101 | ||
113 | static const u32 ar9300Modes_fast_clock_2p0[][3] = { | 102 | static const u32 ar9340Modes_fast_clock_1p0[][3] = { |
114 | /* Addr 5G_HT20 5G_HT40 */ | 103 | /* Addr 5G_HT20 5G_HT40 */ |
115 | {0x00001030, 0x00000268, 0x000004d0}, | 104 | {0x00001030, 0x00000268, 0x000004d0}, |
116 | {0x00001070, 0x0000018c, 0x00000318}, | 105 | {0x00001070, 0x0000018c, 0x00000318}, |
117 | {0x000010b0, 0x00000fd0, 0x00001fa0}, | 106 | {0x000010b0, 0x00000fd0, 0x00001fa0}, |
@@ -123,46 +112,49 @@ static const u32 ar9300Modes_fast_clock_2p0[][3] = { | |||
123 | {0x0000a254, 0x00000898, 0x00001130}, | 112 | {0x0000a254, 0x00000898, 0x00001130}, |
124 | }; | 113 | }; |
125 | 114 | ||
126 | static const u32 ar9300_2p0_radio_core[][2] = { | 115 | static const u32 ar9340_1p0_radio_core[][2] = { |
127 | /* Addr allmodes */ | 116 | /* Addr allmodes */ |
128 | {0x00016000, 0x36db6db6}, | 117 | {0x00016000, 0x36db6db6}, |
129 | {0x00016004, 0x6db6db40}, | 118 | {0x00016004, 0x6db6db40}, |
130 | {0x00016008, 0x73f00000}, | 119 | {0x00016008, 0x73f00000}, |
131 | {0x0001600c, 0x00000000}, | 120 | {0x0001600c, 0x00000000}, |
132 | {0x00016040, 0x7f80fff8}, | 121 | {0x00016040, 0x7f80fff8}, |
133 | {0x0001604c, 0x76d005b5}, | 122 | {0x00016044, 0x03b6d2db}, |
134 | {0x00016050, 0x556cf031}, | 123 | {0x00016048, 0x24925266}, |
135 | {0x00016054, 0x13449440}, | 124 | {0x0001604c, 0x000f0278}, |
136 | {0x00016058, 0x0c51c92c}, | 125 | {0x00016050, 0x6db6db6c}, |
137 | {0x0001605c, 0x3db7fffc}, | 126 | {0x00016054, 0x6db60000}, |
138 | {0x00016060, 0xfffffffc}, | 127 | {0x00016080, 0x00080000}, |
139 | {0x00016064, 0x000f0278}, | ||
140 | {0x0001606c, 0x6db60000}, | ||
141 | {0x00016080, 0x00000000}, | ||
142 | {0x00016084, 0x0e48048c}, | 128 | {0x00016084, 0x0e48048c}, |
143 | {0x00016088, 0x54214514}, | 129 | {0x00016088, 0x14214514}, |
144 | {0x0001608c, 0x119f481e}, | 130 | {0x0001608c, 0x119f081c}, |
145 | {0x00016090, 0x24926490}, | 131 | {0x00016090, 0x24926490}, |
146 | {0x00016098, 0xd2888888}, | 132 | {0x00016094, 0x00000000}, |
147 | {0x000160a0, 0x0a108ffe}, | 133 | {0x00016098, 0xd411eb84}, |
134 | {0x0001609c, 0x03e47f32}, | ||
135 | {0x000160a0, 0xc2108ffe}, | ||
148 | {0x000160a4, 0x812fc370}, | 136 | {0x000160a4, 0x812fc370}, |
149 | {0x000160a8, 0x423c8000}, | 137 | {0x000160a8, 0x423c8000}, |
150 | {0x000160b4, 0x92480080}, | 138 | {0x000160ac, 0xa4646800}, |
151 | {0x000160c0, 0x00adb6d0}, | 139 | {0x000160b0, 0x00fe7f46}, |
140 | {0x000160b4, 0x92480000}, | ||
141 | {0x000160c0, 0x006db6db}, | ||
152 | {0x000160c4, 0x6db6db60}, | 142 | {0x000160c4, 0x6db6db60}, |
153 | {0x000160c8, 0x6db6db6c}, | 143 | {0x000160c8, 0x6db6db6c}, |
154 | {0x000160cc, 0x01e6c000}, | 144 | {0x000160cc, 0x6de6db6c}, |
155 | {0x00016100, 0x3fffbe01}, | 145 | {0x000160d0, 0xb6da4924}, |
146 | {0x00016100, 0x04cb0001}, | ||
156 | {0x00016104, 0xfff80000}, | 147 | {0x00016104, 0xfff80000}, |
157 | {0x00016108, 0x00080010}, | 148 | {0x00016108, 0x00080010}, |
158 | {0x00016144, 0x02084080}, | 149 | {0x0001610c, 0x00000000}, |
159 | {0x00016148, 0x00000000}, | 150 | {0x00016140, 0x50804008}, |
160 | {0x00016280, 0x058a0001}, | 151 | {0x00016144, 0x01884080}, |
161 | {0x00016284, 0x3d840208}, | 152 | {0x00016148, 0x000080c0}, |
162 | {0x00016288, 0x05a20408}, | 153 | {0x00016280, 0x01000015}, |
163 | {0x0001628c, 0x00038c07}, | 154 | {0x00016284, 0x05530000}, |
164 | {0x00016290, 0x40000004}, | 155 | {0x00016288, 0x00318000}, |
165 | {0x00016294, 0x458aa14f}, | 156 | {0x0001628c, 0x50000000}, |
157 | {0x00016290, 0x4080294f}, | ||
166 | {0x00016380, 0x00000000}, | 158 | {0x00016380, 0x00000000}, |
167 | {0x00016384, 0x00000000}, | 159 | {0x00016384, 0x00000000}, |
168 | {0x00016388, 0x00800700}, | 160 | {0x00016388, 0x00800700}, |
@@ -190,19 +182,18 @@ static const u32 ar9300_2p0_radio_core[][2] = { | |||
190 | {0x00016408, 0x73f00000}, | 182 | {0x00016408, 0x73f00000}, |
191 | {0x0001640c, 0x00000000}, | 183 | {0x0001640c, 0x00000000}, |
192 | {0x00016440, 0x7f80fff8}, | 184 | {0x00016440, 0x7f80fff8}, |
193 | {0x0001644c, 0x76d005b5}, | 185 | {0x00016444, 0x03b6d2db}, |
194 | {0x00016450, 0x556cf031}, | 186 | {0x00016448, 0x24927266}, |
195 | {0x00016454, 0x13449440}, | 187 | {0x0001644c, 0x000f0278}, |
196 | {0x00016458, 0x0c51c92c}, | 188 | {0x00016450, 0x6db6db6c}, |
197 | {0x0001645c, 0x3db7fffc}, | 189 | {0x00016454, 0x6db60000}, |
198 | {0x00016460, 0xfffffffc}, | 190 | {0x00016500, 0x04cb0001}, |
199 | {0x00016464, 0x000f0278}, | ||
200 | {0x0001646c, 0x6db60000}, | ||
201 | {0x00016500, 0x3fffbe01}, | ||
202 | {0x00016504, 0xfff80000}, | 191 | {0x00016504, 0xfff80000}, |
203 | {0x00016508, 0x00080010}, | 192 | {0x00016508, 0x00080010}, |
204 | {0x00016544, 0x02084080}, | 193 | {0x0001650c, 0x00000000}, |
205 | {0x00016548, 0x00000000}, | 194 | {0x00016540, 0x50804008}, |
195 | {0x00016544, 0x01884080}, | ||
196 | {0x00016548, 0x000080c0}, | ||
206 | {0x00016780, 0x00000000}, | 197 | {0x00016780, 0x00000000}, |
207 | {0x00016784, 0x00000000}, | 198 | {0x00016784, 0x00000000}, |
208 | {0x00016788, 0x00800700}, | 199 | {0x00016788, 0x00800700}, |
@@ -225,310 +216,16 @@ static const u32 ar9300_2p0_radio_core[][2] = { | |||
225 | {0x000167cc, 0x00001402}, | 216 | {0x000167cc, 0x00001402}, |
226 | {0x000167d0, 0x00000000}, | 217 | {0x000167d0, 0x00000000}, |
227 | {0x000167d4, 0x00000000}, | 218 | {0x000167d4, 0x00000000}, |
228 | {0x00016800, 0x36db6db6}, | ||
229 | {0x00016804, 0x6db6db40}, | ||
230 | {0x00016808, 0x73f00000}, | ||
231 | {0x0001680c, 0x00000000}, | ||
232 | {0x00016840, 0x7f80fff8}, | ||
233 | {0x0001684c, 0x76d005b5}, | ||
234 | {0x00016850, 0x556cf031}, | ||
235 | {0x00016854, 0x13449440}, | ||
236 | {0x00016858, 0x0c51c92c}, | ||
237 | {0x0001685c, 0x3db7fffc}, | ||
238 | {0x00016860, 0xfffffffc}, | ||
239 | {0x00016864, 0x000f0278}, | ||
240 | {0x0001686c, 0x6db60000}, | ||
241 | {0x00016900, 0x3fffbe01}, | ||
242 | {0x00016904, 0xfff80000}, | ||
243 | {0x00016908, 0x00080010}, | ||
244 | {0x00016944, 0x02084080}, | ||
245 | {0x00016948, 0x00000000}, | ||
246 | {0x00016b80, 0x00000000}, | ||
247 | {0x00016b84, 0x00000000}, | ||
248 | {0x00016b88, 0x00800700}, | ||
249 | {0x00016b8c, 0x00800700}, | ||
250 | {0x00016b90, 0x00800700}, | ||
251 | {0x00016b94, 0x00000000}, | ||
252 | {0x00016b98, 0x00000000}, | ||
253 | {0x00016b9c, 0x00000000}, | ||
254 | {0x00016ba0, 0x00000001}, | ||
255 | {0x00016ba4, 0x00000001}, | ||
256 | {0x00016ba8, 0x00000000}, | ||
257 | {0x00016bac, 0x00000000}, | ||
258 | {0x00016bb0, 0x00000000}, | ||
259 | {0x00016bb4, 0x00000000}, | ||
260 | {0x00016bb8, 0x00000000}, | ||
261 | {0x00016bbc, 0x00000000}, | ||
262 | {0x00016bc0, 0x000000a0}, | ||
263 | {0x00016bc4, 0x000c0000}, | ||
264 | {0x00016bc8, 0x14021402}, | ||
265 | {0x00016bcc, 0x00001402}, | ||
266 | {0x00016bd0, 0x00000000}, | ||
267 | {0x00016bd4, 0x00000000}, | ||
268 | }; | 219 | }; |
269 | 220 | ||
270 | static const u32 ar9300Common_rx_gain_table_merlin_2p0[][2] = { | 221 | static const u32 ar9340_1p0_radio_core_40M[][2] = { |
271 | /* Addr allmodes */ | 222 | {0x0001609c, 0x02566f3a}, |
272 | {0x0000a000, 0x02000101}, | 223 | {0x000160ac, 0xa4647c00}, |
273 | {0x0000a004, 0x02000102}, | 224 | {0x000160b0, 0x01885f5a}, |
274 | {0x0000a008, 0x02000103}, | ||
275 | {0x0000a00c, 0x02000104}, | ||
276 | {0x0000a010, 0x02000200}, | ||
277 | {0x0000a014, 0x02000201}, | ||
278 | {0x0000a018, 0x02000202}, | ||
279 | {0x0000a01c, 0x02000203}, | ||
280 | {0x0000a020, 0x02000204}, | ||
281 | {0x0000a024, 0x02000205}, | ||
282 | {0x0000a028, 0x02000208}, | ||
283 | {0x0000a02c, 0x02000302}, | ||
284 | {0x0000a030, 0x02000303}, | ||
285 | {0x0000a034, 0x02000304}, | ||
286 | {0x0000a038, 0x02000400}, | ||
287 | {0x0000a03c, 0x02010300}, | ||
288 | {0x0000a040, 0x02010301}, | ||
289 | {0x0000a044, 0x02010302}, | ||
290 | {0x0000a048, 0x02000500}, | ||
291 | {0x0000a04c, 0x02010400}, | ||
292 | {0x0000a050, 0x02020300}, | ||
293 | {0x0000a054, 0x02020301}, | ||
294 | {0x0000a058, 0x02020302}, | ||
295 | {0x0000a05c, 0x02020303}, | ||
296 | {0x0000a060, 0x02020400}, | ||
297 | {0x0000a064, 0x02030300}, | ||
298 | {0x0000a068, 0x02030301}, | ||
299 | {0x0000a06c, 0x02030302}, | ||
300 | {0x0000a070, 0x02030303}, | ||
301 | {0x0000a074, 0x02030400}, | ||
302 | {0x0000a078, 0x02040300}, | ||
303 | {0x0000a07c, 0x02040301}, | ||
304 | {0x0000a080, 0x02040302}, | ||
305 | {0x0000a084, 0x02040303}, | ||
306 | {0x0000a088, 0x02030500}, | ||
307 | {0x0000a08c, 0x02040400}, | ||
308 | {0x0000a090, 0x02050203}, | ||
309 | {0x0000a094, 0x02050204}, | ||
310 | {0x0000a098, 0x02050205}, | ||
311 | {0x0000a09c, 0x02040500}, | ||
312 | {0x0000a0a0, 0x02050301}, | ||
313 | {0x0000a0a4, 0x02050302}, | ||
314 | {0x0000a0a8, 0x02050303}, | ||
315 | {0x0000a0ac, 0x02050400}, | ||
316 | {0x0000a0b0, 0x02050401}, | ||
317 | {0x0000a0b4, 0x02050402}, | ||
318 | {0x0000a0b8, 0x02050403}, | ||
319 | {0x0000a0bc, 0x02050500}, | ||
320 | {0x0000a0c0, 0x02050501}, | ||
321 | {0x0000a0c4, 0x02050502}, | ||
322 | {0x0000a0c8, 0x02050503}, | ||
323 | {0x0000a0cc, 0x02050504}, | ||
324 | {0x0000a0d0, 0x02050600}, | ||
325 | {0x0000a0d4, 0x02050601}, | ||
326 | {0x0000a0d8, 0x02050602}, | ||
327 | {0x0000a0dc, 0x02050603}, | ||
328 | {0x0000a0e0, 0x02050604}, | ||
329 | {0x0000a0e4, 0x02050700}, | ||
330 | {0x0000a0e8, 0x02050701}, | ||
331 | {0x0000a0ec, 0x02050702}, | ||
332 | {0x0000a0f0, 0x02050703}, | ||
333 | {0x0000a0f4, 0x02050704}, | ||
334 | {0x0000a0f8, 0x02050705}, | ||
335 | {0x0000a0fc, 0x02050708}, | ||
336 | {0x0000a100, 0x02050709}, | ||
337 | {0x0000a104, 0x0205070a}, | ||
338 | {0x0000a108, 0x0205070b}, | ||
339 | {0x0000a10c, 0x0205070c}, | ||
340 | {0x0000a110, 0x0205070d}, | ||
341 | {0x0000a114, 0x02050710}, | ||
342 | {0x0000a118, 0x02050711}, | ||
343 | {0x0000a11c, 0x02050712}, | ||
344 | {0x0000a120, 0x02050713}, | ||
345 | {0x0000a124, 0x02050714}, | ||
346 | {0x0000a128, 0x02050715}, | ||
347 | {0x0000a12c, 0x02050730}, | ||
348 | {0x0000a130, 0x02050731}, | ||
349 | {0x0000a134, 0x02050732}, | ||
350 | {0x0000a138, 0x02050733}, | ||
351 | {0x0000a13c, 0x02050734}, | ||
352 | {0x0000a140, 0x02050735}, | ||
353 | {0x0000a144, 0x02050750}, | ||
354 | {0x0000a148, 0x02050751}, | ||
355 | {0x0000a14c, 0x02050752}, | ||
356 | {0x0000a150, 0x02050753}, | ||
357 | {0x0000a154, 0x02050754}, | ||
358 | {0x0000a158, 0x02050755}, | ||
359 | {0x0000a15c, 0x02050770}, | ||
360 | {0x0000a160, 0x02050771}, | ||
361 | {0x0000a164, 0x02050772}, | ||
362 | {0x0000a168, 0x02050773}, | ||
363 | {0x0000a16c, 0x02050774}, | ||
364 | {0x0000a170, 0x02050775}, | ||
365 | {0x0000a174, 0x00000776}, | ||
366 | {0x0000a178, 0x00000776}, | ||
367 | {0x0000a17c, 0x00000776}, | ||
368 | {0x0000a180, 0x00000776}, | ||
369 | {0x0000a184, 0x00000776}, | ||
370 | {0x0000a188, 0x00000776}, | ||
371 | {0x0000a18c, 0x00000776}, | ||
372 | {0x0000a190, 0x00000776}, | ||
373 | {0x0000a194, 0x00000776}, | ||
374 | {0x0000a198, 0x00000776}, | ||
375 | {0x0000a19c, 0x00000776}, | ||
376 | {0x0000a1a0, 0x00000776}, | ||
377 | {0x0000a1a4, 0x00000776}, | ||
378 | {0x0000a1a8, 0x00000776}, | ||
379 | {0x0000a1ac, 0x00000776}, | ||
380 | {0x0000a1b0, 0x00000776}, | ||
381 | {0x0000a1b4, 0x00000776}, | ||
382 | {0x0000a1b8, 0x00000776}, | ||
383 | {0x0000a1bc, 0x00000776}, | ||
384 | {0x0000a1c0, 0x00000776}, | ||
385 | {0x0000a1c4, 0x00000776}, | ||
386 | {0x0000a1c8, 0x00000776}, | ||
387 | {0x0000a1cc, 0x00000776}, | ||
388 | {0x0000a1d0, 0x00000776}, | ||
389 | {0x0000a1d4, 0x00000776}, | ||
390 | {0x0000a1d8, 0x00000776}, | ||
391 | {0x0000a1dc, 0x00000776}, | ||
392 | {0x0000a1e0, 0x00000776}, | ||
393 | {0x0000a1e4, 0x00000776}, | ||
394 | {0x0000a1e8, 0x00000776}, | ||
395 | {0x0000a1ec, 0x00000776}, | ||
396 | {0x0000a1f0, 0x00000776}, | ||
397 | {0x0000a1f4, 0x00000776}, | ||
398 | {0x0000a1f8, 0x00000776}, | ||
399 | {0x0000a1fc, 0x00000776}, | ||
400 | {0x0000b000, 0x02000101}, | ||
401 | {0x0000b004, 0x02000102}, | ||
402 | {0x0000b008, 0x02000103}, | ||
403 | {0x0000b00c, 0x02000104}, | ||
404 | {0x0000b010, 0x02000200}, | ||
405 | {0x0000b014, 0x02000201}, | ||
406 | {0x0000b018, 0x02000202}, | ||
407 | {0x0000b01c, 0x02000203}, | ||
408 | {0x0000b020, 0x02000204}, | ||
409 | {0x0000b024, 0x02000205}, | ||
410 | {0x0000b028, 0x02000208}, | ||
411 | {0x0000b02c, 0x02000302}, | ||
412 | {0x0000b030, 0x02000303}, | ||
413 | {0x0000b034, 0x02000304}, | ||
414 | {0x0000b038, 0x02000400}, | ||
415 | {0x0000b03c, 0x02010300}, | ||
416 | {0x0000b040, 0x02010301}, | ||
417 | {0x0000b044, 0x02010302}, | ||
418 | {0x0000b048, 0x02000500}, | ||
419 | {0x0000b04c, 0x02010400}, | ||
420 | {0x0000b050, 0x02020300}, | ||
421 | {0x0000b054, 0x02020301}, | ||
422 | {0x0000b058, 0x02020302}, | ||
423 | {0x0000b05c, 0x02020303}, | ||
424 | {0x0000b060, 0x02020400}, | ||
425 | {0x0000b064, 0x02030300}, | ||
426 | {0x0000b068, 0x02030301}, | ||
427 | {0x0000b06c, 0x02030302}, | ||
428 | {0x0000b070, 0x02030303}, | ||
429 | {0x0000b074, 0x02030400}, | ||
430 | {0x0000b078, 0x02040300}, | ||
431 | {0x0000b07c, 0x02040301}, | ||
432 | {0x0000b080, 0x02040302}, | ||
433 | {0x0000b084, 0x02040303}, | ||
434 | {0x0000b088, 0x02030500}, | ||
435 | {0x0000b08c, 0x02040400}, | ||
436 | {0x0000b090, 0x02050203}, | ||
437 | {0x0000b094, 0x02050204}, | ||
438 | {0x0000b098, 0x02050205}, | ||
439 | {0x0000b09c, 0x02040500}, | ||
440 | {0x0000b0a0, 0x02050301}, | ||
441 | {0x0000b0a4, 0x02050302}, | ||
442 | {0x0000b0a8, 0x02050303}, | ||
443 | {0x0000b0ac, 0x02050400}, | ||
444 | {0x0000b0b0, 0x02050401}, | ||
445 | {0x0000b0b4, 0x02050402}, | ||
446 | {0x0000b0b8, 0x02050403}, | ||
447 | {0x0000b0bc, 0x02050500}, | ||
448 | {0x0000b0c0, 0x02050501}, | ||
449 | {0x0000b0c4, 0x02050502}, | ||
450 | {0x0000b0c8, 0x02050503}, | ||
451 | {0x0000b0cc, 0x02050504}, | ||
452 | {0x0000b0d0, 0x02050600}, | ||
453 | {0x0000b0d4, 0x02050601}, | ||
454 | {0x0000b0d8, 0x02050602}, | ||
455 | {0x0000b0dc, 0x02050603}, | ||
456 | {0x0000b0e0, 0x02050604}, | ||
457 | {0x0000b0e4, 0x02050700}, | ||
458 | {0x0000b0e8, 0x02050701}, | ||
459 | {0x0000b0ec, 0x02050702}, | ||
460 | {0x0000b0f0, 0x02050703}, | ||
461 | {0x0000b0f4, 0x02050704}, | ||
462 | {0x0000b0f8, 0x02050705}, | ||
463 | {0x0000b0fc, 0x02050708}, | ||
464 | {0x0000b100, 0x02050709}, | ||
465 | {0x0000b104, 0x0205070a}, | ||
466 | {0x0000b108, 0x0205070b}, | ||
467 | {0x0000b10c, 0x0205070c}, | ||
468 | {0x0000b110, 0x0205070d}, | ||
469 | {0x0000b114, 0x02050710}, | ||
470 | {0x0000b118, 0x02050711}, | ||
471 | {0x0000b11c, 0x02050712}, | ||
472 | {0x0000b120, 0x02050713}, | ||
473 | {0x0000b124, 0x02050714}, | ||
474 | {0x0000b128, 0x02050715}, | ||
475 | {0x0000b12c, 0x02050730}, | ||
476 | {0x0000b130, 0x02050731}, | ||
477 | {0x0000b134, 0x02050732}, | ||
478 | {0x0000b138, 0x02050733}, | ||
479 | {0x0000b13c, 0x02050734}, | ||
480 | {0x0000b140, 0x02050735}, | ||
481 | {0x0000b144, 0x02050750}, | ||
482 | {0x0000b148, 0x02050751}, | ||
483 | {0x0000b14c, 0x02050752}, | ||
484 | {0x0000b150, 0x02050753}, | ||
485 | {0x0000b154, 0x02050754}, | ||
486 | {0x0000b158, 0x02050755}, | ||
487 | {0x0000b15c, 0x02050770}, | ||
488 | {0x0000b160, 0x02050771}, | ||
489 | {0x0000b164, 0x02050772}, | ||
490 | {0x0000b168, 0x02050773}, | ||
491 | {0x0000b16c, 0x02050774}, | ||
492 | {0x0000b170, 0x02050775}, | ||
493 | {0x0000b174, 0x00000776}, | ||
494 | {0x0000b178, 0x00000776}, | ||
495 | {0x0000b17c, 0x00000776}, | ||
496 | {0x0000b180, 0x00000776}, | ||
497 | {0x0000b184, 0x00000776}, | ||
498 | {0x0000b188, 0x00000776}, | ||
499 | {0x0000b18c, 0x00000776}, | ||
500 | {0x0000b190, 0x00000776}, | ||
501 | {0x0000b194, 0x00000776}, | ||
502 | {0x0000b198, 0x00000776}, | ||
503 | {0x0000b19c, 0x00000776}, | ||
504 | {0x0000b1a0, 0x00000776}, | ||
505 | {0x0000b1a4, 0x00000776}, | ||
506 | {0x0000b1a8, 0x00000776}, | ||
507 | {0x0000b1ac, 0x00000776}, | ||
508 | {0x0000b1b0, 0x00000776}, | ||
509 | {0x0000b1b4, 0x00000776}, | ||
510 | {0x0000b1b8, 0x00000776}, | ||
511 | {0x0000b1bc, 0x00000776}, | ||
512 | {0x0000b1c0, 0x00000776}, | ||
513 | {0x0000b1c4, 0x00000776}, | ||
514 | {0x0000b1c8, 0x00000776}, | ||
515 | {0x0000b1cc, 0x00000776}, | ||
516 | {0x0000b1d0, 0x00000776}, | ||
517 | {0x0000b1d4, 0x00000776}, | ||
518 | {0x0000b1d8, 0x00000776}, | ||
519 | {0x0000b1dc, 0x00000776}, | ||
520 | {0x0000b1e0, 0x00000776}, | ||
521 | {0x0000b1e4, 0x00000776}, | ||
522 | {0x0000b1e8, 0x00000776}, | ||
523 | {0x0000b1ec, 0x00000776}, | ||
524 | {0x0000b1f0, 0x00000776}, | ||
525 | {0x0000b1f4, 0x00000776}, | ||
526 | {0x0000b1f8, 0x00000776}, | ||
527 | {0x0000b1fc, 0x00000776}, | ||
528 | }; | 225 | }; |
529 | 226 | ||
530 | static const u32 ar9300_2p0_mac_postamble[][5] = { | 227 | static const u32 ar9340_1p0_mac_postamble[][5] = { |
531 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 228 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
532 | {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, | 229 | {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, |
533 | {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, | 230 | {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, |
534 | {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, | 231 | {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, |
@@ -539,66 +236,24 @@ static const u32 ar9300_2p0_mac_postamble[][5] = { | |||
539 | {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, | 236 | {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, |
540 | }; | 237 | }; |
541 | 238 | ||
542 | static const u32 ar9300_2p0_soc_postamble[][5] = { | 239 | static const u32 ar9340_1p0_soc_postamble[][5] = { |
543 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 240 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
544 | {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, | 241 | {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, |
545 | }; | 242 | }; |
546 | 243 | ||
547 | static const u32 ar9200_merlin_2p0_radio_core[][2] = { | 244 | static const u32 ar9340_1p0_baseband_postamble[][5] = { |
548 | /* Addr allmodes */ | 245 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
549 | {0x00007800, 0x00040000}, | ||
550 | {0x00007804, 0xdb005012}, | ||
551 | {0x00007808, 0x04924914}, | ||
552 | {0x0000780c, 0x21084210}, | ||
553 | {0x00007810, 0x6d801300}, | ||
554 | {0x00007814, 0x0019beff}, | ||
555 | {0x00007818, 0x07e41000}, | ||
556 | {0x0000781c, 0x00392000}, | ||
557 | {0x00007820, 0x92592480}, | ||
558 | {0x00007824, 0x00040000}, | ||
559 | {0x00007828, 0xdb005012}, | ||
560 | {0x0000782c, 0x04924914}, | ||
561 | {0x00007830, 0x21084210}, | ||
562 | {0x00007834, 0x6d801300}, | ||
563 | {0x00007838, 0x0019beff}, | ||
564 | {0x0000783c, 0x07e40000}, | ||
565 | {0x00007840, 0x00392000}, | ||
566 | {0x00007844, 0x92592480}, | ||
567 | {0x00007848, 0x00100000}, | ||
568 | {0x0000784c, 0x773f0567}, | ||
569 | {0x00007850, 0x54214514}, | ||
570 | {0x00007854, 0x12035828}, | ||
571 | {0x00007858, 0x92592692}, | ||
572 | {0x0000785c, 0x00000000}, | ||
573 | {0x00007860, 0x56400000}, | ||
574 | {0x00007864, 0x0a8e370e}, | ||
575 | {0x00007868, 0xc0102850}, | ||
576 | {0x0000786c, 0x812d4000}, | ||
577 | {0x00007870, 0x807ec400}, | ||
578 | {0x00007874, 0x001b6db0}, | ||
579 | {0x00007878, 0x00376b63}, | ||
580 | {0x0000787c, 0x06db6db6}, | ||
581 | {0x00007880, 0x006d8000}, | ||
582 | {0x00007884, 0xffeffffe}, | ||
583 | {0x00007888, 0xffeffffe}, | ||
584 | {0x0000788c, 0x00010000}, | ||
585 | {0x00007890, 0x02060aeb}, | ||
586 | {0x00007894, 0x5a108000}, | ||
587 | }; | ||
588 | |||
589 | static const u32 ar9300_2p0_baseband_postamble[][5] = { | ||
590 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
591 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, | 246 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, |
592 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, | 247 | {0x00009820, 0x206a022e, 0x206a022e, 0x206a022e, 0x206a022e}, |
593 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, | 248 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, |
594 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, | 249 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, |
595 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | 250 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, |
596 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, | 251 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, |
597 | {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, | 252 | {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, |
598 | {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, | 253 | {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, |
599 | {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, | 254 | {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, |
600 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, | 255 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, |
601 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, | 256 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e}, |
602 | {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, | 257 | {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, |
603 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 258 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
604 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | 259 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, |
@@ -607,7 +262,7 @@ static const u32 ar9300_2p0_baseband_postamble[][5] = { | |||
607 | {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, | 262 | {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, |
608 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | 263 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, |
609 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | 264 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, |
610 | {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, | 265 | {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0}, |
611 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, | 266 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, |
612 | {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, | 267 | {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, |
613 | {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, | 268 | {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, |
@@ -619,33 +274,27 @@ static const u32 ar9300_2p0_baseband_postamble[][5] = { | |||
619 | {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, | 274 | {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, |
620 | {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, | 275 | {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, |
621 | {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, | 276 | {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, |
622 | {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, | 277 | {0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110}, |
623 | {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, | 278 | {0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222}, |
624 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | 279 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, |
625 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, | 280 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, |
626 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, | 281 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, |
627 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 282 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
628 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | 283 | {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, |
629 | {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | 284 | {0x0000ae04, 0x00180000, 0x00180000, 0x00180000, 0x00180000}, |
630 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 285 | {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
631 | {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | 286 | {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, |
632 | {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, | 287 | {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, |
633 | {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, | 288 | {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, |
634 | {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
635 | {0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
636 | {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
637 | {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, | ||
638 | {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, | ||
639 | {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, | ||
640 | }; | 289 | }; |
641 | 290 | ||
642 | static const u32 ar9300_2p0_baseband_core[][2] = { | 291 | static const u32 ar9340_1p0_baseband_core[][2] = { |
643 | /* Addr allmodes */ | 292 | /* Addr allmodes */ |
644 | {0x00009800, 0xafe68e30}, | 293 | {0x00009800, 0xafe68e30}, |
645 | {0x00009804, 0xfd14e000}, | 294 | {0x00009804, 0xfd14e000}, |
646 | {0x00009808, 0x9c0a9f6b}, | 295 | {0x00009808, 0x9c0a9f6b}, |
647 | {0x0000980c, 0x04900000}, | 296 | {0x0000980c, 0x04900000}, |
648 | {0x00009814, 0x9280c00a}, | 297 | {0x00009814, 0xb280c00a}, |
649 | {0x00009818, 0x00000000}, | 298 | {0x00009818, 0x00000000}, |
650 | {0x0000981c, 0x00020028}, | 299 | {0x0000981c, 0x00020028}, |
651 | {0x00009834, 0x5f3ca3de}, | 300 | {0x00009834, 0x5f3ca3de}, |
@@ -794,7 +443,7 @@ static const u32 ar9300_2p0_baseband_core[][2] = { | |||
794 | {0x0000a7cc, 0x00000000}, | 443 | {0x0000a7cc, 0x00000000}, |
795 | {0x0000a7d0, 0x00000000}, | 444 | {0x0000a7d0, 0x00000000}, |
796 | {0x0000a7d4, 0x00000004}, | 445 | {0x0000a7d4, 0x00000004}, |
797 | {0x0000a7dc, 0x00000001}, | 446 | {0x0000a7dc, 0x00000000}, |
798 | {0x0000a8d0, 0x004b6a8e}, | 447 | {0x0000a8d0, 0x004b6a8e}, |
799 | {0x0000a8d4, 0x00000820}, | 448 | {0x0000a8d4, 0x00000820}, |
800 | {0x0000a8dc, 0x00000000}, | 449 | {0x0000a8dc, 0x00000000}, |
@@ -813,28 +462,10 @@ static const u32 ar9300_2p0_baseband_core[][2] = { | |||
813 | {0x0000b408, 0x0e79e5c0}, | 462 | {0x0000b408, 0x0e79e5c0}, |
814 | {0x0000b40c, 0x00820820}, | 463 | {0x0000b40c, 0x00820820}, |
815 | {0x0000b420, 0x00000000}, | 464 | {0x0000b420, 0x00000000}, |
816 | {0x0000b8d0, 0x004b6a8e}, | ||
817 | {0x0000b8d4, 0x00000820}, | ||
818 | {0x0000b8dc, 0x00000000}, | ||
819 | {0x0000b8f0, 0x00000000}, | ||
820 | {0x0000b8f4, 0x00000000}, | ||
821 | {0x0000c2d0, 0x00000080}, | ||
822 | {0x0000c2d4, 0x00000000}, | ||
823 | {0x0000c2dc, 0x00000000}, | ||
824 | {0x0000c2e0, 0x00000000}, | ||
825 | {0x0000c2e4, 0x00000000}, | ||
826 | {0x0000c2e8, 0x00000000}, | ||
827 | {0x0000c2ec, 0x00000000}, | ||
828 | {0x0000c2f0, 0x00000000}, | ||
829 | {0x0000c2f4, 0x00000000}, | ||
830 | {0x0000c2f8, 0x00000000}, | ||
831 | {0x0000c408, 0x0e79e5c0}, | ||
832 | {0x0000c40c, 0x00820820}, | ||
833 | {0x0000c420, 0x00000000}, | ||
834 | }; | 465 | }; |
835 | 466 | ||
836 | static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { | 467 | static const u32 ar9340Modes_high_power_tx_gain_table_1p0[][5] = { |
837 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 468 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
838 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, | 469 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
839 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 470 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
840 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | 471 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
@@ -900,19 +531,14 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { | |||
900 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 531 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
901 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 532 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
902 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 533 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
903 | {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | 534 | {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, |
904 | {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | 535 | {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, |
905 | {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | 536 | {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, |
906 | {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | 537 | {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, |
907 | {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | ||
908 | {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | ||
909 | {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, | ||
910 | {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, | ||
911 | {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, | ||
912 | }; | 538 | }; |
913 | 539 | ||
914 | static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { | 540 | static const u32 ar9340Modes_high_ob_db_tx_gain_table_1p0[][5] = { |
915 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 541 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
916 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, | 542 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
917 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, | 543 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
918 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | 544 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, |
@@ -978,19 +604,87 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { | |||
978 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 604 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
979 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 605 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
980 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | 606 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, |
981 | {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | 607 | {0x00016044, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4}, |
982 | {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | 608 | {0x00016048, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266}, |
983 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 609 | {0x00016444, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4, 0x03b6d2e4}, |
984 | {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | 610 | {0x00016448, 0x8e481266, 0x8e481266, 0x8e481266, 0x8e481266}, |
985 | {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | 611 | }; |
986 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 612 | static const u32 ar9340Modes_ub124_tx_gain_table_1p0[][5] = { |
987 | {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, | 613 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
988 | {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, | 614 | {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, |
989 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 615 | {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, |
616 | {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, | ||
617 | {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, | ||
618 | {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, | ||
619 | {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, | ||
620 | {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, | ||
621 | {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, | ||
622 | {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, | ||
623 | {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, | ||
624 | {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, | ||
625 | {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, | ||
626 | {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, | ||
627 | {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, | ||
628 | {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, | ||
629 | {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, | ||
630 | {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, | ||
631 | {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, | ||
632 | {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, | ||
633 | {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, | ||
634 | {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, | ||
635 | {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, | ||
636 | {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, | ||
637 | {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, | ||
638 | {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, | ||
639 | {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, | ||
640 | {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
641 | {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
642 | {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
643 | {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
644 | {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
645 | {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
646 | {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, | ||
647 | {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, | ||
648 | {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, | ||
649 | {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, | ||
650 | {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, | ||
651 | {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, | ||
652 | {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, | ||
653 | {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, | ||
654 | {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, | ||
655 | {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, | ||
656 | {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, | ||
657 | {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, | ||
658 | {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, | ||
659 | {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, | ||
660 | {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, | ||
661 | {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, | ||
662 | {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, | ||
663 | {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, | ||
664 | {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, | ||
665 | {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, | ||
666 | {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, | ||
667 | {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, | ||
668 | {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, | ||
669 | {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, | ||
670 | {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, | ||
671 | {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, | ||
672 | {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
673 | {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
674 | {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
675 | {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
676 | {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
677 | {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
678 | {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, | ||
679 | {0x00016044, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db}, | ||
680 | {0x00016048, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266}, | ||
681 | {0x00016444, 0x036db2db, 0x036db2db, 0x036db2db, 0x036db2db}, | ||
682 | {0x00016448, 0x69b65266, 0x69b65266, 0x69b65266, 0x69b65266}, | ||
990 | }; | 683 | }; |
991 | 684 | ||
992 | static const u32 ar9300Common_rx_gain_table_2p0[][2] = { | 685 | |
993 | /* Addr allmodes */ | 686 | static const u32 ar9340Common_rx_gain_table_1p0[][2] = { |
687 | /* Addr allmodes */ | ||
994 | {0x0000a000, 0x00010000}, | 688 | {0x0000a000, 0x00010000}, |
995 | {0x0000a004, 0x00030002}, | 689 | {0x0000a004, 0x00030002}, |
996 | {0x0000a008, 0x00050004}, | 690 | {0x0000a008, 0x00050004}, |
@@ -1249,8 +943,8 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = { | |||
1249 | {0x0000b1fc, 0x00000196}, | 943 | {0x0000b1fc, 0x00000196}, |
1250 | }; | 944 | }; |
1251 | 945 | ||
1252 | static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = { | 946 | static const u32 ar9340Modes_low_ob_db_tx_gain_table_1p0[][5] = { |
1253 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 947 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
1254 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 948 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, |
1255 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 949 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
1256 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | 950 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, |
@@ -1316,19 +1010,87 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = { | |||
1316 | {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, | 1010 | {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, |
1317 | {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, | 1011 | {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, |
1318 | {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, | 1012 | {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, |
1319 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 1013 | {0x00016044, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, |
1320 | {0x00016048, 0x64000001, 0x64000001, 0x64000001, 0x64000001}, | 1014 | {0x00016048, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, |
1321 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 1015 | {0x00016444, 0x056db2db, 0x056db2db, 0x056db2db, 0x056db2db}, |
1322 | {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 1016 | {0x00016448, 0x24925266, 0x24925266, 0x24925266, 0x24925266}, |
1323 | {0x00016448, 0x64000001, 0x64000001, 0x64000001, 0x64000001}, | 1017 | }; |
1324 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 1018 | |
1325 | {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 1019 | static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = { |
1326 | {0x00016848, 0x64000001, 0x64000001, 0x64000001, 0x64000001}, | 1020 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
1327 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 1021 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, |
1022 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
1023 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | ||
1024 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | ||
1025 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | ||
1026 | {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, | ||
1027 | {0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, | ||
1028 | {0x0000a518, 0x21020220, 0x21020220, 0x15000402, 0x15000402}, | ||
1029 | {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, | ||
1030 | {0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603}, | ||
1031 | {0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02}, | ||
1032 | {0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04}, | ||
1033 | {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20}, | ||
1034 | {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20}, | ||
1035 | {0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, | ||
1036 | {0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, | ||
1037 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, | ||
1038 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, | ||
1039 | {0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, | ||
1040 | {0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, | ||
1041 | {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x42001a83, 0x42001a83}, | ||
1042 | {0x0000a550, 0x61042a6c, 0x61042a6c, 0x44001c84, 0x44001c84}, | ||
1043 | {0x0000a554, 0x66062a6c, 0x66062a6c, 0x48001ce3, 0x48001ce3}, | ||
1044 | {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x4c001ce5, 0x4c001ce5}, | ||
1045 | {0x0000a55c, 0x7006308c, 0x7006308c, 0x50001ce9, 0x50001ce9}, | ||
1046 | {0x0000a560, 0x730a308a, 0x730a308a, 0x54001ceb, 0x54001ceb}, | ||
1047 | {0x0000a564, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, | ||
1048 | {0x0000a568, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, | ||
1049 | {0x0000a56c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, | ||
1050 | {0x0000a570, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, | ||
1051 | {0x0000a574, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, | ||
1052 | {0x0000a578, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, | ||
1053 | {0x0000a57c, 0x770a308c, 0x770a308c, 0x56001eec, 0x56001eec}, | ||
1054 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | ||
1055 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | ||
1056 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | ||
1057 | {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, | ||
1058 | {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, | ||
1059 | {0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, | ||
1060 | {0x0000a598, 0x21820220, 0x21820220, 0x15800402, 0x15800402}, | ||
1061 | {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, | ||
1062 | {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, | ||
1063 | {0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, | ||
1064 | {0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, | ||
1065 | {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, | ||
1066 | {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, | ||
1067 | {0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, | ||
1068 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, | ||
1069 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, | ||
1070 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, | ||
1071 | {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, | ||
1072 | {0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, | ||
1073 | {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42801a83, 0x42801a83}, | ||
1074 | {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x44801c84, 0x44801c84}, | ||
1075 | {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x48801ce3, 0x48801ce3}, | ||
1076 | {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c801ce5, 0x4c801ce5}, | ||
1077 | {0x0000a5dc, 0x7086308c, 0x7086308c, 0x50801ce9, 0x50801ce9}, | ||
1078 | {0x0000a5e0, 0x738a308a, 0x738a308a, 0x54801ceb, 0x54801ceb}, | ||
1079 | {0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1080 | {0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1081 | {0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1082 | {0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1083 | {0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1084 | {0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1085 | {0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801eec, 0x56801eec}, | ||
1086 | {0x00016044, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, | ||
1087 | {0x00016048, 0x24927266, 0x24927266, 0x8e483266, 0x8e483266}, | ||
1088 | {0x00016444, 0x056db2db, 0x056db2db, 0x03b6d2e4, 0x03b6d2e4}, | ||
1089 | {0x00016448, 0x24927266, 0x24927266, 0x8e482266, 0x8e482266}, | ||
1328 | }; | 1090 | }; |
1329 | 1091 | ||
1330 | static const u32 ar9300_2p0_mac_core[][2] = { | 1092 | static const u32 ar9340_1p0_mac_core[][2] = { |
1331 | /* Addr allmodes */ | 1093 | /* Addr allmodes */ |
1332 | {0x00000008, 0x00000000}, | 1094 | {0x00000008, 0x00000000}, |
1333 | {0x00000030, 0x00020085}, | 1095 | {0x00000030, 0x00020085}, |
1334 | {0x00000034, 0x00000005}, | 1096 | {0x00000034, 0x00000005}, |
@@ -1437,7 +1199,7 @@ static const u32 ar9300_2p0_mac_core[][2] = { | |||
1437 | {0x00008258, 0x00000000}, | 1199 | {0x00008258, 0x00000000}, |
1438 | {0x0000825c, 0x40000000}, | 1200 | {0x0000825c, 0x40000000}, |
1439 | {0x00008260, 0x00080922}, | 1201 | {0x00008260, 0x00080922}, |
1440 | {0x00008264, 0x98a00010}, | 1202 | {0x00008264, 0x9d400010}, |
1441 | {0x00008268, 0xffffffff}, | 1203 | {0x00008268, 0xffffffff}, |
1442 | {0x0000826c, 0x0000ffff}, | 1204 | {0x0000826c, 0x0000ffff}, |
1443 | {0x00008270, 0x00000000}, | 1205 | {0x00008270, 0x00000000}, |
@@ -1491,8 +1253,8 @@ static const u32 ar9300_2p0_mac_core[][2] = { | |||
1491 | {0x000083d0, 0x000301ff}, | 1253 | {0x000083d0, 0x000301ff}, |
1492 | }; | 1254 | }; |
1493 | 1255 | ||
1494 | static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { | 1256 | static const u32 ar9340Common_wo_xlna_rx_gain_table_1p0[][2] = { |
1495 | /* Addr allmodes */ | 1257 | /* Addr allmodes */ |
1496 | {0x0000a000, 0x00010000}, | 1258 | {0x0000a000, 0x00010000}, |
1497 | {0x0000a004, 0x00030002}, | 1259 | {0x0000a004, 0x00030002}, |
1498 | {0x0000a008, 0x00050004}, | 1260 | {0x0000a008, 0x00050004}, |
@@ -1751,8 +1513,8 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { | |||
1751 | {0x0000b1fc, 0x00000196}, | 1513 | {0x0000b1fc, 0x00000196}, |
1752 | }; | 1514 | }; |
1753 | 1515 | ||
1754 | static const u32 ar9300_2p0_soc_preamble[][2] = { | 1516 | static const u32 ar9340_1p0_soc_preamble[][2] = { |
1755 | /* Addr allmodes */ | 1517 | /* Addr allmodes */ |
1756 | {0x000040a4, 0x00a0c1c9}, | 1518 | {0x000040a4, 0x00a0c1c9}, |
1757 | {0x00007008, 0x00000000}, | 1519 | {0x00007008, 0x00000000}, |
1758 | {0x00007020, 0x00000000}, | 1520 | {0x00007020, 0x00000000}, |
@@ -1760,25 +1522,4 @@ static const u32 ar9300_2p0_soc_preamble[][2] = { | |||
1760 | {0x00007038, 0x000004c2}, | 1522 | {0x00007038, 0x000004c2}, |
1761 | }; | 1523 | }; |
1762 | 1524 | ||
1763 | static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = { | 1525 | #endif |
1764 | /* Addr allmodes */ | ||
1765 | {0x00004040, 0x08212e5e}, | ||
1766 | {0x00004040, 0x0008003b}, | ||
1767 | {0x00004044, 0x00000000}, | ||
1768 | }; | ||
1769 | |||
1770 | static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = { | ||
1771 | /* Addr allmodes */ | ||
1772 | {0x00004040, 0x08253e5e}, | ||
1773 | {0x00004040, 0x0008003b}, | ||
1774 | {0x00004044, 0x00000000}, | ||
1775 | }; | ||
1776 | |||
1777 | static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = { | ||
1778 | /* Addr allmodes */ | ||
1779 | {0x00004040, 0x08213e5e}, | ||
1780 | {0x00004040, 0x0008003b}, | ||
1781 | {0x00004044, 0x00000000}, | ||
1782 | }; | ||
1783 | |||
1784 | #endif /* INITVALS_9003_2P0_H */ | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h new file mode 100644 index 000000000000..611ea6ce8508 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h | |||
@@ -0,0 +1,1161 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef INITVALS_9485_H | ||
18 | #define INITVALS_9485_H | ||
19 | |||
20 | static const u32 ar9485_1_1_mac_core[][2] = { | ||
21 | /* Addr allmodes */ | ||
22 | {0x00000008, 0x00000000}, | ||
23 | {0x00000030, 0x00020085}, | ||
24 | {0x00000034, 0x00000005}, | ||
25 | {0x00000040, 0x00000000}, | ||
26 | {0x00000044, 0x00000000}, | ||
27 | {0x00000048, 0x00000008}, | ||
28 | {0x0000004c, 0x00000010}, | ||
29 | {0x00000050, 0x00000000}, | ||
30 | {0x00001040, 0x002ffc0f}, | ||
31 | {0x00001044, 0x002ffc0f}, | ||
32 | {0x00001048, 0x002ffc0f}, | ||
33 | {0x0000104c, 0x002ffc0f}, | ||
34 | {0x00001050, 0x002ffc0f}, | ||
35 | {0x00001054, 0x002ffc0f}, | ||
36 | {0x00001058, 0x002ffc0f}, | ||
37 | {0x0000105c, 0x002ffc0f}, | ||
38 | {0x00001060, 0x002ffc0f}, | ||
39 | {0x00001064, 0x002ffc0f}, | ||
40 | {0x000010f0, 0x00000100}, | ||
41 | {0x00001270, 0x00000000}, | ||
42 | {0x000012b0, 0x00000000}, | ||
43 | {0x000012f0, 0x00000000}, | ||
44 | {0x0000143c, 0x00000000}, | ||
45 | {0x0000147c, 0x00000000}, | ||
46 | {0x00008000, 0x00000000}, | ||
47 | {0x00008004, 0x00000000}, | ||
48 | {0x00008008, 0x00000000}, | ||
49 | {0x0000800c, 0x00000000}, | ||
50 | {0x00008018, 0x00000000}, | ||
51 | {0x00008020, 0x00000000}, | ||
52 | {0x00008038, 0x00000000}, | ||
53 | {0x0000803c, 0x00000000}, | ||
54 | {0x00008040, 0x00000000}, | ||
55 | {0x00008044, 0x00000000}, | ||
56 | {0x00008048, 0x00000000}, | ||
57 | {0x0000804c, 0xffffffff}, | ||
58 | {0x00008054, 0x00000000}, | ||
59 | {0x00008058, 0x00000000}, | ||
60 | {0x0000805c, 0x000fc78f}, | ||
61 | {0x00008060, 0x0000000f}, | ||
62 | {0x00008064, 0x00000000}, | ||
63 | {0x00008070, 0x00000310}, | ||
64 | {0x00008074, 0x00000020}, | ||
65 | {0x00008078, 0x00000000}, | ||
66 | {0x0000809c, 0x0000000f}, | ||
67 | {0x000080a0, 0x00000000}, | ||
68 | {0x000080a4, 0x02ff0000}, | ||
69 | {0x000080a8, 0x0e070605}, | ||
70 | {0x000080ac, 0x0000000d}, | ||
71 | {0x000080b0, 0x00000000}, | ||
72 | {0x000080b4, 0x00000000}, | ||
73 | {0x000080b8, 0x00000000}, | ||
74 | {0x000080bc, 0x00000000}, | ||
75 | {0x000080c0, 0x2a800000}, | ||
76 | {0x000080c4, 0x06900168}, | ||
77 | {0x000080c8, 0x13881c22}, | ||
78 | {0x000080cc, 0x01f40000}, | ||
79 | {0x000080d0, 0x00252500}, | ||
80 | {0x000080d4, 0x00a00000}, | ||
81 | {0x000080d8, 0x00400000}, | ||
82 | {0x000080dc, 0x00000000}, | ||
83 | {0x000080e0, 0xffffffff}, | ||
84 | {0x000080e4, 0x0000ffff}, | ||
85 | {0x000080e8, 0x3f3f3f3f}, | ||
86 | {0x000080ec, 0x00000000}, | ||
87 | {0x000080f0, 0x00000000}, | ||
88 | {0x000080f4, 0x00000000}, | ||
89 | {0x000080fc, 0x00020000}, | ||
90 | {0x00008100, 0x00000000}, | ||
91 | {0x00008108, 0x00000052}, | ||
92 | {0x0000810c, 0x00000000}, | ||
93 | {0x00008110, 0x00000000}, | ||
94 | {0x00008114, 0x000007ff}, | ||
95 | {0x00008118, 0x000000aa}, | ||
96 | {0x0000811c, 0x00003210}, | ||
97 | {0x00008124, 0x00000000}, | ||
98 | {0x00008128, 0x00000000}, | ||
99 | {0x0000812c, 0x00000000}, | ||
100 | {0x00008130, 0x00000000}, | ||
101 | {0x00008134, 0x00000000}, | ||
102 | {0x00008138, 0x00000000}, | ||
103 | {0x0000813c, 0x0000ffff}, | ||
104 | {0x00008144, 0xffffffff}, | ||
105 | {0x00008168, 0x00000000}, | ||
106 | {0x0000816c, 0x00000000}, | ||
107 | {0x00008170, 0x18486200}, | ||
108 | {0x00008174, 0x33332210}, | ||
109 | {0x00008178, 0x00000000}, | ||
110 | {0x0000817c, 0x00020000}, | ||
111 | {0x000081c0, 0x00000000}, | ||
112 | {0x000081c4, 0x33332210}, | ||
113 | {0x000081d4, 0x00000000}, | ||
114 | {0x000081ec, 0x00000000}, | ||
115 | {0x000081f0, 0x00000000}, | ||
116 | {0x000081f4, 0x00000000}, | ||
117 | {0x000081f8, 0x00000000}, | ||
118 | {0x000081fc, 0x00000000}, | ||
119 | {0x00008240, 0x00100000}, | ||
120 | {0x00008244, 0x0010f400}, | ||
121 | {0x00008248, 0x00000800}, | ||
122 | {0x0000824c, 0x0001e800}, | ||
123 | {0x00008250, 0x00000000}, | ||
124 | {0x00008254, 0x00000000}, | ||
125 | {0x00008258, 0x00000000}, | ||
126 | {0x0000825c, 0x40000000}, | ||
127 | {0x00008260, 0x00080922}, | ||
128 | {0x00008264, 0x9ca00010}, | ||
129 | {0x00008268, 0xffffffff}, | ||
130 | {0x0000826c, 0x0000ffff}, | ||
131 | {0x00008270, 0x00000000}, | ||
132 | {0x00008274, 0x40000000}, | ||
133 | {0x00008278, 0x003e4180}, | ||
134 | {0x0000827c, 0x00000004}, | ||
135 | {0x00008284, 0x0000002c}, | ||
136 | {0x00008288, 0x0000002c}, | ||
137 | {0x0000828c, 0x000000ff}, | ||
138 | {0x00008294, 0x00000000}, | ||
139 | {0x00008298, 0x00000000}, | ||
140 | {0x0000829c, 0x00000000}, | ||
141 | {0x00008300, 0x00000140}, | ||
142 | {0x00008314, 0x00000000}, | ||
143 | {0x0000831c, 0x0000010d}, | ||
144 | {0x00008328, 0x00000000}, | ||
145 | {0x0000832c, 0x00000007}, | ||
146 | {0x00008330, 0x00000302}, | ||
147 | {0x00008334, 0x00000700}, | ||
148 | {0x00008338, 0x00ff0000}, | ||
149 | {0x0000833c, 0x02400000}, | ||
150 | {0x00008340, 0x000107ff}, | ||
151 | {0x00008344, 0xa248105b}, | ||
152 | {0x00008348, 0x008f0000}, | ||
153 | {0x0000835c, 0x00000000}, | ||
154 | {0x00008360, 0xffffffff}, | ||
155 | {0x00008364, 0xffffffff}, | ||
156 | {0x00008368, 0x00000000}, | ||
157 | {0x00008370, 0x00000000}, | ||
158 | {0x00008374, 0x000000ff}, | ||
159 | {0x00008378, 0x00000000}, | ||
160 | {0x0000837c, 0x00000000}, | ||
161 | {0x00008380, 0xffffffff}, | ||
162 | {0x00008384, 0xffffffff}, | ||
163 | {0x00008390, 0xffffffff}, | ||
164 | {0x00008394, 0xffffffff}, | ||
165 | {0x00008398, 0x00000000}, | ||
166 | {0x0000839c, 0x00000000}, | ||
167 | {0x000083a0, 0x00000000}, | ||
168 | {0x000083a4, 0x0000fa14}, | ||
169 | {0x000083a8, 0x000f0c00}, | ||
170 | {0x000083ac, 0x33332210}, | ||
171 | {0x000083b0, 0x33332210}, | ||
172 | {0x000083b4, 0x33332210}, | ||
173 | {0x000083b8, 0x33332210}, | ||
174 | {0x000083bc, 0x00000000}, | ||
175 | {0x000083c0, 0x00000000}, | ||
176 | {0x000083c4, 0x00000000}, | ||
177 | {0x000083c8, 0x00000000}, | ||
178 | {0x000083cc, 0x00000200}, | ||
179 | {0x000083d0, 0x000301ff}, | ||
180 | }; | ||
181 | |||
182 | static const u32 ar9485_1_1_baseband_core[][2] = { | ||
183 | /* Addr allmodes */ | ||
184 | {0x00009800, 0xafe68e30}, | ||
185 | {0x00009804, 0xfd14e000}, | ||
186 | {0x00009808, 0x9c0a8f6b}, | ||
187 | {0x0000980c, 0x04800000}, | ||
188 | {0x00009814, 0x9280c00a}, | ||
189 | {0x00009818, 0x00000000}, | ||
190 | {0x0000981c, 0x00020028}, | ||
191 | {0x00009834, 0x5f3ca3de}, | ||
192 | {0x00009838, 0x0108ecff}, | ||
193 | {0x0000983c, 0x14750600}, | ||
194 | {0x00009880, 0x201fff00}, | ||
195 | {0x00009884, 0x00001042}, | ||
196 | {0x000098a4, 0x00200400}, | ||
197 | {0x000098b0, 0x52440bbe}, | ||
198 | {0x000098d0, 0x004b6a8e}, | ||
199 | {0x000098d4, 0x00000820}, | ||
200 | {0x000098dc, 0x00000000}, | ||
201 | {0x000098f0, 0x00000000}, | ||
202 | {0x000098f4, 0x00000000}, | ||
203 | {0x00009c04, 0x00000000}, | ||
204 | {0x00009c08, 0x03200000}, | ||
205 | {0x00009c0c, 0x00000000}, | ||
206 | {0x00009c10, 0x00000000}, | ||
207 | {0x00009c14, 0x00046384}, | ||
208 | {0x00009c18, 0x05b6b440}, | ||
209 | {0x00009c1c, 0x00b6b440}, | ||
210 | {0x00009d00, 0xc080a333}, | ||
211 | {0x00009d04, 0x40206c10}, | ||
212 | {0x00009d08, 0x009c4060}, | ||
213 | {0x00009d0c, 0x1883800a}, | ||
214 | {0x00009d10, 0x01834061}, | ||
215 | {0x00009d14, 0x00c00400}, | ||
216 | {0x00009d18, 0x00000000}, | ||
217 | {0x00009d1c, 0x00000000}, | ||
218 | {0x00009e08, 0x0038233c}, | ||
219 | {0x00009e24, 0x9927b515}, | ||
220 | {0x00009e28, 0x12ef0200}, | ||
221 | {0x00009e30, 0x06336f77}, | ||
222 | {0x00009e34, 0x6af6532f}, | ||
223 | {0x00009e38, 0x0cc80c00}, | ||
224 | {0x00009e40, 0x0d261820}, | ||
225 | {0x00009e4c, 0x00001004}, | ||
226 | {0x00009e50, 0x00ff03f1}, | ||
227 | {0x00009fc0, 0x80be4788}, | ||
228 | {0x00009fc4, 0x0001efb5}, | ||
229 | {0x00009fcc, 0x40000014}, | ||
230 | {0x0000a20c, 0x00000000}, | ||
231 | {0x0000a210, 0x00000000}, | ||
232 | {0x0000a220, 0x00000000}, | ||
233 | {0x0000a224, 0x00000000}, | ||
234 | {0x0000a228, 0x10002310}, | ||
235 | {0x0000a23c, 0x00000000}, | ||
236 | {0x0000a244, 0x0c000000}, | ||
237 | {0x0000a2a0, 0x00000001}, | ||
238 | {0x0000a2c0, 0x00000001}, | ||
239 | {0x0000a2c8, 0x00000000}, | ||
240 | {0x0000a2cc, 0x18c43433}, | ||
241 | {0x0000a2d4, 0x00000000}, | ||
242 | {0x0000a2dc, 0x00000000}, | ||
243 | {0x0000a2e0, 0x00000000}, | ||
244 | {0x0000a2e4, 0x00000000}, | ||
245 | {0x0000a2e8, 0x00000000}, | ||
246 | {0x0000a2ec, 0x00000000}, | ||
247 | {0x0000a2f0, 0x00000000}, | ||
248 | {0x0000a2f4, 0x00000000}, | ||
249 | {0x0000a2f8, 0x00000000}, | ||
250 | {0x0000a344, 0x00000000}, | ||
251 | {0x0000a34c, 0x00000000}, | ||
252 | {0x0000a350, 0x0000a000}, | ||
253 | {0x0000a364, 0x00000000}, | ||
254 | {0x0000a370, 0x00000000}, | ||
255 | {0x0000a390, 0x00000001}, | ||
256 | {0x0000a394, 0x00000444}, | ||
257 | {0x0000a398, 0x001f0e0f}, | ||
258 | {0x0000a39c, 0x0075393f}, | ||
259 | {0x0000a3a0, 0xb79f6427}, | ||
260 | {0x0000a3a4, 0x000000ff}, | ||
261 | {0x0000a3a8, 0x3b3b3b3b}, | ||
262 | {0x0000a3ac, 0x2f2f2f2f}, | ||
263 | {0x0000a3c0, 0x20202020}, | ||
264 | {0x0000a3c4, 0x22222220}, | ||
265 | {0x0000a3c8, 0x20200020}, | ||
266 | {0x0000a3cc, 0x20202020}, | ||
267 | {0x0000a3d0, 0x20202020}, | ||
268 | {0x0000a3d4, 0x20202020}, | ||
269 | {0x0000a3d8, 0x20202020}, | ||
270 | {0x0000a3dc, 0x20202020}, | ||
271 | {0x0000a3e0, 0x20202020}, | ||
272 | {0x0000a3e4, 0x20202020}, | ||
273 | {0x0000a3e8, 0x20202020}, | ||
274 | {0x0000a3ec, 0x20202020}, | ||
275 | {0x0000a3f0, 0x00000000}, | ||
276 | {0x0000a3f4, 0x00000006}, | ||
277 | {0x0000a3f8, 0x0cdbd380}, | ||
278 | {0x0000a3fc, 0x000f0f01}, | ||
279 | {0x0000a400, 0x8fa91f01}, | ||
280 | {0x0000a404, 0x00000000}, | ||
281 | {0x0000a408, 0x0e79e5c6}, | ||
282 | {0x0000a40c, 0x00820820}, | ||
283 | {0x0000a414, 0x1ce739cf}, | ||
284 | {0x0000a418, 0x2d0019ce}, | ||
285 | {0x0000a41c, 0x1ce739ce}, | ||
286 | {0x0000a420, 0x000001ce}, | ||
287 | {0x0000a424, 0x1ce739ce}, | ||
288 | {0x0000a428, 0x000001ce}, | ||
289 | {0x0000a42c, 0x1ce739ce}, | ||
290 | {0x0000a430, 0x1ce739ce}, | ||
291 | {0x0000a434, 0x00000000}, | ||
292 | {0x0000a438, 0x00001801}, | ||
293 | {0x0000a43c, 0x00000000}, | ||
294 | {0x0000a440, 0x00000000}, | ||
295 | {0x0000a444, 0x00000000}, | ||
296 | {0x0000a448, 0x04000000}, | ||
297 | {0x0000a44c, 0x00000001}, | ||
298 | {0x0000a450, 0x00010000}, | ||
299 | {0x0000a5c4, 0xbfad9d74}, | ||
300 | {0x0000a5c8, 0x0048060a}, | ||
301 | {0x0000a5cc, 0x00000637}, | ||
302 | {0x0000a760, 0x03020100}, | ||
303 | {0x0000a764, 0x09080504}, | ||
304 | {0x0000a768, 0x0d0c0b0a}, | ||
305 | {0x0000a76c, 0x13121110}, | ||
306 | {0x0000a770, 0x31301514}, | ||
307 | {0x0000a774, 0x35343332}, | ||
308 | {0x0000a778, 0x00000036}, | ||
309 | {0x0000a780, 0x00000838}, | ||
310 | {0x0000a7c0, 0x00000000}, | ||
311 | {0x0000a7c4, 0xfffffffc}, | ||
312 | {0x0000a7c8, 0x00000000}, | ||
313 | {0x0000a7cc, 0x00000000}, | ||
314 | {0x0000a7d0, 0x00000000}, | ||
315 | {0x0000a7d4, 0x00000004}, | ||
316 | {0x0000a7dc, 0x00000000}, | ||
317 | }; | ||
318 | |||
319 | static const u32 ar9485Common_1_1[][2] = { | ||
320 | /* Addr allmodes */ | ||
321 | {0x00007010, 0x00000022}, | ||
322 | {0x00007020, 0x00000000}, | ||
323 | {0x00007034, 0x00000002}, | ||
324 | {0x00007038, 0x000004c2}, | ||
325 | }; | ||
326 | |||
327 | static const u32 ar9485_1_1_baseband_postamble[][5] = { | ||
328 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
329 | {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005}, | ||
330 | {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e}, | ||
331 | {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, | ||
332 | {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, | ||
333 | {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, | ||
334 | {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c}, | ||
335 | {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044}, | ||
336 | {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, | ||
337 | {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020}, | ||
338 | {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, | ||
339 | {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e}, | ||
340 | {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, | ||
341 | {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
342 | {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, | ||
343 | {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, | ||
344 | {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, | ||
345 | {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, | ||
346 | {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, | ||
347 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, | ||
348 | {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, | ||
349 | {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0}, | ||
350 | {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, | ||
351 | {0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b}, | ||
352 | {0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff}, | ||
353 | {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, | ||
354 | {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, | ||
355 | {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, | ||
356 | {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, | ||
357 | {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, | ||
358 | {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501}, | ||
359 | {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, | ||
360 | {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, | ||
361 | {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, | ||
362 | {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
363 | {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
364 | {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, | ||
365 | {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982}, | ||
366 | {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, | ||
367 | {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
368 | {0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, | ||
369 | {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
370 | }; | ||
371 | |||
372 | static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = { | ||
373 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
374 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | ||
375 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | ||
376 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
377 | {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, | ||
378 | {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, | ||
379 | {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, | ||
380 | {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, | ||
381 | {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, | ||
382 | {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, | ||
383 | {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, | ||
384 | {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, | ||
385 | {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, | ||
386 | {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, | ||
387 | {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, | ||
388 | {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, | ||
389 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20}, | ||
390 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21}, | ||
391 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62}, | ||
392 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63}, | ||
393 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65}, | ||
394 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66}, | ||
395 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645}, | ||
396 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | ||
397 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | ||
398 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | ||
399 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, | ||
400 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | ||
401 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
402 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | ||
403 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
404 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
405 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
406 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
407 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
408 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
409 | {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
410 | {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
411 | {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
412 | {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
413 | {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
414 | {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
415 | {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
416 | {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
417 | {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
418 | {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
419 | {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
420 | {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
421 | {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
422 | {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
423 | {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
424 | {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
425 | {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
426 | {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
427 | {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
428 | {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
429 | {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
430 | {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
431 | {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
432 | {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
433 | {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
434 | {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
435 | {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
436 | {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
437 | {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
438 | {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
439 | {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
440 | {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
441 | {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db}, | ||
442 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | ||
443 | }; | ||
444 | |||
445 | static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = { | ||
446 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
447 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | ||
448 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | ||
449 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
450 | {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, | ||
451 | {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, | ||
452 | {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, | ||
453 | {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, | ||
454 | {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, | ||
455 | {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, | ||
456 | {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, | ||
457 | {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, | ||
458 | {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, | ||
459 | {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, | ||
460 | {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, | ||
461 | {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, | ||
462 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20}, | ||
463 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21}, | ||
464 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62}, | ||
465 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63}, | ||
466 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65}, | ||
467 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66}, | ||
468 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645}, | ||
469 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | ||
470 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | ||
471 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | ||
472 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, | ||
473 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | ||
474 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
475 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | ||
476 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
477 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
478 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
479 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
480 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
481 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
482 | {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
483 | {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
484 | {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
485 | {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
486 | {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
487 | {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
488 | {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
489 | {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
490 | {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
491 | {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
492 | {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
493 | {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
494 | {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
495 | {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
496 | {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
497 | {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
498 | {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
499 | {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
500 | {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
501 | {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
502 | {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
503 | {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
504 | {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
505 | {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
506 | {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
507 | {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
508 | {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
509 | {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
510 | {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
511 | {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
512 | {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
513 | {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
514 | {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db}, | ||
515 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | ||
516 | }; | ||
517 | |||
518 | static const u32 ar9485_1_1_radio_postamble[][2] = { | ||
519 | /* Addr allmodes */ | ||
520 | {0x0001609c, 0x0b283f31}, | ||
521 | {0x000160ac, 0x24611800}, | ||
522 | {0x000160b0, 0x03284f3e}, | ||
523 | {0x0001610c, 0x00170000}, | ||
524 | {0x00016140, 0x10804008}, | ||
525 | }; | ||
526 | |||
527 | static const u32 ar9485_1_1_mac_postamble[][5] = { | ||
528 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
529 | {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, | ||
530 | {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, | ||
531 | {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, | ||
532 | {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, | ||
533 | {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, | ||
534 | {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, | ||
535 | {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, | ||
536 | {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, | ||
537 | }; | ||
538 | |||
539 | static const u32 ar9485_1_1_radio_core[][2] = { | ||
540 | /* Addr allmodes */ | ||
541 | {0x00016000, 0x36db6db6}, | ||
542 | {0x00016004, 0x6db6db40}, | ||
543 | {0x00016008, 0x73800000}, | ||
544 | {0x0001600c, 0x00000000}, | ||
545 | {0x00016040, 0x7f80fff8}, | ||
546 | {0x0001604c, 0x000f0278}, | ||
547 | {0x00016050, 0x4db6db8c}, | ||
548 | {0x00016054, 0x6db60000}, | ||
549 | {0x00016080, 0x00080000}, | ||
550 | {0x00016084, 0x0e48048c}, | ||
551 | {0x00016088, 0x14214514}, | ||
552 | {0x0001608c, 0x119f081e}, | ||
553 | {0x00016090, 0x24926490}, | ||
554 | {0x00016098, 0xd28b3330}, | ||
555 | {0x000160a0, 0xc2108ffe}, | ||
556 | {0x000160a4, 0x812fc370}, | ||
557 | {0x000160a8, 0x423c8000}, | ||
558 | {0x000160b4, 0x92480040}, | ||
559 | {0x000160c0, 0x006db6db}, | ||
560 | {0x000160c4, 0x0186db60}, | ||
561 | {0x000160c8, 0x6db6db6c}, | ||
562 | {0x000160cc, 0x6de6fbe0}, | ||
563 | {0x000160d0, 0xf7dfcf3c}, | ||
564 | {0x00016100, 0x04cb0001}, | ||
565 | {0x00016104, 0xfff80015}, | ||
566 | {0x00016108, 0x00080010}, | ||
567 | {0x00016144, 0x01884080}, | ||
568 | {0x00016148, 0x00008040}, | ||
569 | {0x00016240, 0x08400000}, | ||
570 | {0x00016244, 0x1bf90f00}, | ||
571 | {0x00016248, 0x00000000}, | ||
572 | {0x0001624c, 0x00000000}, | ||
573 | {0x00016280, 0x01000015}, | ||
574 | {0x00016284, 0x00d30000}, | ||
575 | {0x00016288, 0x00318000}, | ||
576 | {0x0001628c, 0x50000000}, | ||
577 | {0x00016290, 0x4b96210f}, | ||
578 | {0x00016380, 0x00000000}, | ||
579 | {0x00016384, 0x00000000}, | ||
580 | {0x00016388, 0x00800700}, | ||
581 | {0x0001638c, 0x00800700}, | ||
582 | {0x00016390, 0x00800700}, | ||
583 | {0x00016394, 0x00000000}, | ||
584 | {0x00016398, 0x00000000}, | ||
585 | {0x0001639c, 0x00000000}, | ||
586 | {0x000163a0, 0x00000001}, | ||
587 | {0x000163a4, 0x00000001}, | ||
588 | {0x000163a8, 0x00000000}, | ||
589 | {0x000163ac, 0x00000000}, | ||
590 | {0x000163b0, 0x00000000}, | ||
591 | {0x000163b4, 0x00000000}, | ||
592 | {0x000163b8, 0x00000000}, | ||
593 | {0x000163bc, 0x00000000}, | ||
594 | {0x000163c0, 0x000000a0}, | ||
595 | {0x000163c4, 0x000c0000}, | ||
596 | {0x000163c8, 0x14021402}, | ||
597 | {0x000163cc, 0x00001402}, | ||
598 | {0x000163d0, 0x00000000}, | ||
599 | {0x000163d4, 0x00000000}, | ||
600 | {0x00016c40, 0x13188278}, | ||
601 | {0x00016c44, 0x12000000}, | ||
602 | }; | ||
603 | |||
604 | static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = { | ||
605 | /* Addr allmodes */ | ||
606 | {0x00018c00, 0x10052e5e}, | ||
607 | {0x00018c04, 0x000801d8}, | ||
608 | {0x00018c08, 0x0000080c}, | ||
609 | }; | ||
610 | |||
611 | static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = { | ||
612 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
613 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | ||
614 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | ||
615 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
616 | {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, | ||
617 | {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, | ||
618 | {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, | ||
619 | {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, | ||
620 | {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, | ||
621 | {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, | ||
622 | {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, | ||
623 | {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, | ||
624 | {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, | ||
625 | {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, | ||
626 | {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, | ||
627 | {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, | ||
628 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20}, | ||
629 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21}, | ||
630 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62}, | ||
631 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63}, | ||
632 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65}, | ||
633 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66}, | ||
634 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645}, | ||
635 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | ||
636 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | ||
637 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | ||
638 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, | ||
639 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | ||
640 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
641 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | ||
642 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
643 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
644 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
645 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
646 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
647 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
648 | {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
649 | {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
650 | {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
651 | {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
652 | {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
653 | {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
654 | {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
655 | {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
656 | {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
657 | {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
658 | {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
659 | {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
660 | {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
661 | {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
662 | {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
663 | {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
664 | {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
665 | {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
666 | {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
667 | {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
668 | {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
669 | {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
670 | {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
671 | {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
672 | {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
673 | {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
674 | {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
675 | {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
676 | {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
677 | {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
678 | {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
679 | {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
680 | {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db}, | ||
681 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | ||
682 | }; | ||
683 | |||
684 | static const u32 ar9485_1_1[][2] = { | ||
685 | /* Addr allmodes */ | ||
686 | {0x0000a580, 0x00000000}, | ||
687 | {0x0000a584, 0x00000000}, | ||
688 | {0x0000a588, 0x00000000}, | ||
689 | {0x0000a58c, 0x00000000}, | ||
690 | {0x0000a590, 0x00000000}, | ||
691 | {0x0000a594, 0x00000000}, | ||
692 | {0x0000a598, 0x00000000}, | ||
693 | {0x0000a59c, 0x00000000}, | ||
694 | {0x0000a5a0, 0x00000000}, | ||
695 | {0x0000a5a4, 0x00000000}, | ||
696 | {0x0000a5a8, 0x00000000}, | ||
697 | {0x0000a5ac, 0x00000000}, | ||
698 | {0x0000a5b0, 0x00000000}, | ||
699 | {0x0000a5b4, 0x00000000}, | ||
700 | {0x0000a5b8, 0x00000000}, | ||
701 | {0x0000a5bc, 0x00000000}, | ||
702 | }; | ||
703 | |||
704 | static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = { | ||
705 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
706 | {0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003}, | ||
707 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | ||
708 | {0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000}, | ||
709 | {0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006}, | ||
710 | {0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201}, | ||
711 | {0x0000a508, 0x0c002e00, 0x0c002e00, 0x06000203, 0x06000203}, | ||
712 | {0x0000a50c, 0x11062202, 0x11062202, 0x0a000401, 0x0a000401}, | ||
713 | {0x0000a510, 0x17022e00, 0x17022e00, 0x0e000403, 0x0e000403}, | ||
714 | {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x12000405, 0x12000405}, | ||
715 | {0x0000a518, 0x25020ec0, 0x25020ec0, 0x15000604, 0x15000604}, | ||
716 | {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x18000605, 0x18000605}, | ||
717 | {0x0000a520, 0x2f001f04, 0x2f001f04, 0x1c000a04, 0x1c000a04}, | ||
718 | {0x0000a524, 0x35001fc4, 0x35001fc4, 0x21000a06, 0x21000a06}, | ||
719 | {0x0000a528, 0x3c022f04, 0x3c022f04, 0x29000a24, 0x29000a24}, | ||
720 | {0x0000a52c, 0x41023e85, 0x41023e85, 0x2f000e21, 0x2f000e21}, | ||
721 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000e20, 0x31000e20}, | ||
722 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x33000e20, 0x33000e20}, | ||
723 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62}, | ||
724 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63}, | ||
725 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65}, | ||
726 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66}, | ||
727 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645}, | ||
728 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | ||
729 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | ||
730 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | ||
731 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, | ||
732 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | ||
733 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
734 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | ||
735 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
736 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
737 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
738 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
739 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
740 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
741 | {0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
742 | {0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
743 | {0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
744 | {0x0000b50c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
745 | {0x0000b510, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
746 | {0x0000b514, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
747 | {0x0000b518, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
748 | {0x0000b51c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
749 | {0x0000b520, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
750 | {0x0000b524, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
751 | {0x0000b528, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a}, | ||
752 | {0x0000b52c, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a}, | ||
753 | {0x0000b530, 0x0000003a, 0x0000003a, 0x0000003a, 0x0000003a}, | ||
754 | {0x0000b534, 0x0000004a, 0x0000004a, 0x0000004a, 0x0000004a}, | ||
755 | {0x0000b538, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
756 | {0x0000b53c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
757 | {0x0000b540, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
758 | {0x0000b544, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
759 | {0x0000b548, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
760 | {0x0000b54c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
761 | {0x0000b550, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
762 | {0x0000b554, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
763 | {0x0000b558, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
764 | {0x0000b55c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
765 | {0x0000b560, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
766 | {0x0000b564, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
767 | {0x0000b568, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
768 | {0x0000b56c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
769 | {0x0000b570, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
770 | {0x0000b574, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
771 | {0x0000b578, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
772 | {0x0000b57c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b}, | ||
773 | {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db}, | ||
774 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | ||
775 | }; | ||
776 | |||
777 | static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = { | ||
778 | /* Addr allmodes */ | ||
779 | {0x00018c00, 0x10013e5e}, | ||
780 | {0x00018c04, 0x000801d8}, | ||
781 | {0x00018c08, 0x0000080c}, | ||
782 | }; | ||
783 | |||
784 | static const u32 ar9485_1_1_soc_preamble[][2] = { | ||
785 | /* Addr allmodes */ | ||
786 | {0x00004014, 0xba280400}, | ||
787 | {0x00004090, 0x00aa10aa}, | ||
788 | {0x000040a4, 0x00a0c9c9}, | ||
789 | {0x00007010, 0x00000022}, | ||
790 | {0x00007020, 0x00000000}, | ||
791 | {0x00007034, 0x00000002}, | ||
792 | {0x00007038, 0x000004c2}, | ||
793 | {0x00007048, 0x00000002}, | ||
794 | }; | ||
795 | |||
796 | static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = { | ||
797 | /* Addr allmodes */ | ||
798 | {0x0000a398, 0x00000000}, | ||
799 | {0x0000a39c, 0x6f7f0301}, | ||
800 | {0x0000a3a0, 0xca9228ee}, | ||
801 | }; | ||
802 | |||
803 | static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = { | ||
804 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
805 | {0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002}, | ||
806 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8}, | ||
807 | {0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
808 | {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000}, | ||
809 | {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002}, | ||
810 | {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004}, | ||
811 | {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200}, | ||
812 | {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202}, | ||
813 | {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400}, | ||
814 | {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402}, | ||
815 | {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404}, | ||
816 | {0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603}, | ||
817 | {0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605}, | ||
818 | {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03}, | ||
819 | {0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04}, | ||
820 | {0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20}, | ||
821 | {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21}, | ||
822 | {0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62}, | ||
823 | {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63}, | ||
824 | {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65}, | ||
825 | {0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66}, | ||
826 | {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645}, | ||
827 | {0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865}, | ||
828 | {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86}, | ||
829 | {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9}, | ||
830 | {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb}, | ||
831 | {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb}, | ||
832 | {0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
833 | {0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb}, | ||
834 | {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
835 | {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
836 | {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
837 | {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
838 | {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
839 | {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb}, | ||
840 | {0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
841 | {0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
842 | {0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
843 | {0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
844 | {0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
845 | {0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
846 | {0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
847 | {0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
848 | {0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
849 | {0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
850 | {0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
851 | {0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
852 | {0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
853 | {0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
854 | {0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
855 | {0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
856 | {0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
857 | {0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
858 | {0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
859 | {0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
860 | {0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
861 | {0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
862 | {0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
863 | {0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
864 | {0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
865 | {0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
866 | {0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
867 | {0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
868 | {0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
869 | {0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
870 | {0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
871 | {0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | ||
872 | {0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db}, | ||
873 | {0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260}, | ||
874 | }; | ||
875 | |||
876 | static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = { | ||
877 | /* Addr 5G_HT2 5G_HT40 */ | ||
878 | {0x00009e00, 0x03721821, 0x03721821}, | ||
879 | {0x0000a230, 0x0000400b, 0x00004016}, | ||
880 | {0x0000a254, 0x00000898, 0x00001130}, | ||
881 | }; | ||
882 | |||
883 | static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = { | ||
884 | /* Addr allmodes */ | ||
885 | {0x00018c00, 0x10012e5e}, | ||
886 | {0x00018c04, 0x000801d8}, | ||
887 | {0x00018c08, 0x0000080c}, | ||
888 | }; | ||
889 | |||
890 | static const u32 ar9485_common_rx_gain_1_1[][2] = { | ||
891 | /* Addr allmodes */ | ||
892 | {0x0000a000, 0x00010000}, | ||
893 | {0x0000a004, 0x00030002}, | ||
894 | {0x0000a008, 0x00050004}, | ||
895 | {0x0000a00c, 0x00810080}, | ||
896 | {0x0000a010, 0x01800082}, | ||
897 | {0x0000a014, 0x01820181}, | ||
898 | {0x0000a018, 0x01840183}, | ||
899 | {0x0000a01c, 0x01880185}, | ||
900 | {0x0000a020, 0x018a0189}, | ||
901 | {0x0000a024, 0x02850284}, | ||
902 | {0x0000a028, 0x02890288}, | ||
903 | {0x0000a02c, 0x03850384}, | ||
904 | {0x0000a030, 0x03890388}, | ||
905 | {0x0000a034, 0x038b038a}, | ||
906 | {0x0000a038, 0x038d038c}, | ||
907 | {0x0000a03c, 0x03910390}, | ||
908 | {0x0000a040, 0x03930392}, | ||
909 | {0x0000a044, 0x03950394}, | ||
910 | {0x0000a048, 0x00000396}, | ||
911 | {0x0000a04c, 0x00000000}, | ||
912 | {0x0000a050, 0x00000000}, | ||
913 | {0x0000a054, 0x00000000}, | ||
914 | {0x0000a058, 0x00000000}, | ||
915 | {0x0000a05c, 0x00000000}, | ||
916 | {0x0000a060, 0x00000000}, | ||
917 | {0x0000a064, 0x00000000}, | ||
918 | {0x0000a068, 0x00000000}, | ||
919 | {0x0000a06c, 0x00000000}, | ||
920 | {0x0000a070, 0x00000000}, | ||
921 | {0x0000a074, 0x00000000}, | ||
922 | {0x0000a078, 0x00000000}, | ||
923 | {0x0000a07c, 0x00000000}, | ||
924 | {0x0000a080, 0x28282828}, | ||
925 | {0x0000a084, 0x28282828}, | ||
926 | {0x0000a088, 0x28282828}, | ||
927 | {0x0000a08c, 0x28282828}, | ||
928 | {0x0000a090, 0x28282828}, | ||
929 | {0x0000a094, 0x21212128}, | ||
930 | {0x0000a098, 0x171c1c1c}, | ||
931 | {0x0000a09c, 0x02020212}, | ||
932 | {0x0000a0a0, 0x00000202}, | ||
933 | {0x0000a0a4, 0x00000000}, | ||
934 | {0x0000a0a8, 0x00000000}, | ||
935 | {0x0000a0ac, 0x00000000}, | ||
936 | {0x0000a0b0, 0x00000000}, | ||
937 | {0x0000a0b4, 0x00000000}, | ||
938 | {0x0000a0b8, 0x00000000}, | ||
939 | {0x0000a0bc, 0x00000000}, | ||
940 | {0x0000a0c0, 0x001f0000}, | ||
941 | {0x0000a0c4, 0x111f1100}, | ||
942 | {0x0000a0c8, 0x111d111e}, | ||
943 | {0x0000a0cc, 0x111b111c}, | ||
944 | {0x0000a0d0, 0x22032204}, | ||
945 | {0x0000a0d4, 0x22012202}, | ||
946 | {0x0000a0d8, 0x221f2200}, | ||
947 | {0x0000a0dc, 0x221d221e}, | ||
948 | {0x0000a0e0, 0x33013302}, | ||
949 | {0x0000a0e4, 0x331f3300}, | ||
950 | {0x0000a0e8, 0x4402331e}, | ||
951 | {0x0000a0ec, 0x44004401}, | ||
952 | {0x0000a0f0, 0x441e441f}, | ||
953 | {0x0000a0f4, 0x55015502}, | ||
954 | {0x0000a0f8, 0x551f5500}, | ||
955 | {0x0000a0fc, 0x6602551e}, | ||
956 | {0x0000a100, 0x66006601}, | ||
957 | {0x0000a104, 0x661e661f}, | ||
958 | {0x0000a108, 0x7703661d}, | ||
959 | {0x0000a10c, 0x77017702}, | ||
960 | {0x0000a110, 0x00007700}, | ||
961 | {0x0000a114, 0x00000000}, | ||
962 | {0x0000a118, 0x00000000}, | ||
963 | {0x0000a11c, 0x00000000}, | ||
964 | {0x0000a120, 0x00000000}, | ||
965 | {0x0000a124, 0x00000000}, | ||
966 | {0x0000a128, 0x00000000}, | ||
967 | {0x0000a12c, 0x00000000}, | ||
968 | {0x0000a130, 0x00000000}, | ||
969 | {0x0000a134, 0x00000000}, | ||
970 | {0x0000a138, 0x00000000}, | ||
971 | {0x0000a13c, 0x00000000}, | ||
972 | {0x0000a140, 0x001f0000}, | ||
973 | {0x0000a144, 0x111f1100}, | ||
974 | {0x0000a148, 0x111d111e}, | ||
975 | {0x0000a14c, 0x111b111c}, | ||
976 | {0x0000a150, 0x22032204}, | ||
977 | {0x0000a154, 0x22012202}, | ||
978 | {0x0000a158, 0x221f2200}, | ||
979 | {0x0000a15c, 0x221d221e}, | ||
980 | {0x0000a160, 0x33013302}, | ||
981 | {0x0000a164, 0x331f3300}, | ||
982 | {0x0000a168, 0x4402331e}, | ||
983 | {0x0000a16c, 0x44004401}, | ||
984 | {0x0000a170, 0x441e441f}, | ||
985 | {0x0000a174, 0x55015502}, | ||
986 | {0x0000a178, 0x551f5500}, | ||
987 | {0x0000a17c, 0x6602551e}, | ||
988 | {0x0000a180, 0x66006601}, | ||
989 | {0x0000a184, 0x661e661f}, | ||
990 | {0x0000a188, 0x7703661d}, | ||
991 | {0x0000a18c, 0x77017702}, | ||
992 | {0x0000a190, 0x00007700}, | ||
993 | {0x0000a194, 0x00000000}, | ||
994 | {0x0000a198, 0x00000000}, | ||
995 | {0x0000a19c, 0x00000000}, | ||
996 | {0x0000a1a0, 0x00000000}, | ||
997 | {0x0000a1a4, 0x00000000}, | ||
998 | {0x0000a1a8, 0x00000000}, | ||
999 | {0x0000a1ac, 0x00000000}, | ||
1000 | {0x0000a1b0, 0x00000000}, | ||
1001 | {0x0000a1b4, 0x00000000}, | ||
1002 | {0x0000a1b8, 0x00000000}, | ||
1003 | {0x0000a1bc, 0x00000000}, | ||
1004 | {0x0000a1c0, 0x00000000}, | ||
1005 | {0x0000a1c4, 0x00000000}, | ||
1006 | {0x0000a1c8, 0x00000000}, | ||
1007 | {0x0000a1cc, 0x00000000}, | ||
1008 | {0x0000a1d0, 0x00000000}, | ||
1009 | {0x0000a1d4, 0x00000000}, | ||
1010 | {0x0000a1d8, 0x00000000}, | ||
1011 | {0x0000a1dc, 0x00000000}, | ||
1012 | {0x0000a1e0, 0x00000000}, | ||
1013 | {0x0000a1e4, 0x00000000}, | ||
1014 | {0x0000a1e8, 0x00000000}, | ||
1015 | {0x0000a1ec, 0x00000000}, | ||
1016 | {0x0000a1f0, 0x00000396}, | ||
1017 | {0x0000a1f4, 0x00000396}, | ||
1018 | {0x0000a1f8, 0x00000396}, | ||
1019 | {0x0000a1fc, 0x00000296}, | ||
1020 | }; | ||
1021 | |||
1022 | static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = { | ||
1023 | /* Addr allmodes */ | ||
1024 | {0x00018c00, 0x10053e5e}, | ||
1025 | {0x00018c04, 0x000801d8}, | ||
1026 | {0x00018c08, 0x0000080c}, | ||
1027 | }; | ||
1028 | |||
1029 | static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = { | ||
1030 | /* Addr allmodes */ | ||
1031 | {0x0000a000, 0x00060005}, | ||
1032 | {0x0000a004, 0x00810080}, | ||
1033 | {0x0000a008, 0x00830082}, | ||
1034 | {0x0000a00c, 0x00850084}, | ||
1035 | {0x0000a010, 0x01820181}, | ||
1036 | {0x0000a014, 0x01840183}, | ||
1037 | {0x0000a018, 0x01880185}, | ||
1038 | {0x0000a01c, 0x018a0189}, | ||
1039 | {0x0000a020, 0x02850284}, | ||
1040 | {0x0000a024, 0x02890288}, | ||
1041 | {0x0000a028, 0x028b028a}, | ||
1042 | {0x0000a02c, 0x03850384}, | ||
1043 | {0x0000a030, 0x03890388}, | ||
1044 | {0x0000a034, 0x038b038a}, | ||
1045 | {0x0000a038, 0x038d038c}, | ||
1046 | {0x0000a03c, 0x03910390}, | ||
1047 | {0x0000a040, 0x03930392}, | ||
1048 | {0x0000a044, 0x03950394}, | ||
1049 | {0x0000a048, 0x00000396}, | ||
1050 | {0x0000a04c, 0x00000000}, | ||
1051 | {0x0000a050, 0x00000000}, | ||
1052 | {0x0000a054, 0x00000000}, | ||
1053 | {0x0000a058, 0x00000000}, | ||
1054 | {0x0000a05c, 0x00000000}, | ||
1055 | {0x0000a060, 0x00000000}, | ||
1056 | {0x0000a064, 0x00000000}, | ||
1057 | {0x0000a068, 0x00000000}, | ||
1058 | {0x0000a06c, 0x00000000}, | ||
1059 | {0x0000a070, 0x00000000}, | ||
1060 | {0x0000a074, 0x00000000}, | ||
1061 | {0x0000a078, 0x00000000}, | ||
1062 | {0x0000a07c, 0x00000000}, | ||
1063 | {0x0000a080, 0x28282828}, | ||
1064 | {0x0000a084, 0x28282828}, | ||
1065 | {0x0000a088, 0x28282828}, | ||
1066 | {0x0000a08c, 0x28282828}, | ||
1067 | {0x0000a090, 0x28282828}, | ||
1068 | {0x0000a094, 0x24242428}, | ||
1069 | {0x0000a098, 0x171e1e1e}, | ||
1070 | {0x0000a09c, 0x02020b0b}, | ||
1071 | {0x0000a0a0, 0x02020202}, | ||
1072 | {0x0000a0a4, 0x00000000}, | ||
1073 | {0x0000a0a8, 0x00000000}, | ||
1074 | {0x0000a0ac, 0x00000000}, | ||
1075 | {0x0000a0b0, 0x00000000}, | ||
1076 | {0x0000a0b4, 0x00000000}, | ||
1077 | {0x0000a0b8, 0x00000000}, | ||
1078 | {0x0000a0bc, 0x00000000}, | ||
1079 | {0x0000a0c0, 0x22072208}, | ||
1080 | {0x0000a0c4, 0x22052206}, | ||
1081 | {0x0000a0c8, 0x22032204}, | ||
1082 | {0x0000a0cc, 0x22012202}, | ||
1083 | {0x0000a0d0, 0x221f2200}, | ||
1084 | {0x0000a0d4, 0x221d221e}, | ||
1085 | {0x0000a0d8, 0x33023303}, | ||
1086 | {0x0000a0dc, 0x33003301}, | ||
1087 | {0x0000a0e0, 0x331e331f}, | ||
1088 | {0x0000a0e4, 0x4402331d}, | ||
1089 | {0x0000a0e8, 0x44004401}, | ||
1090 | {0x0000a0ec, 0x441e441f}, | ||
1091 | {0x0000a0f0, 0x55025503}, | ||
1092 | {0x0000a0f4, 0x55005501}, | ||
1093 | {0x0000a0f8, 0x551e551f}, | ||
1094 | {0x0000a0fc, 0x6602551d}, | ||
1095 | {0x0000a100, 0x66006601}, | ||
1096 | {0x0000a104, 0x661e661f}, | ||
1097 | {0x0000a108, 0x7703661d}, | ||
1098 | {0x0000a10c, 0x77017702}, | ||
1099 | {0x0000a110, 0x00007700}, | ||
1100 | {0x0000a114, 0x00000000}, | ||
1101 | {0x0000a118, 0x00000000}, | ||
1102 | {0x0000a11c, 0x00000000}, | ||
1103 | {0x0000a120, 0x00000000}, | ||
1104 | {0x0000a124, 0x00000000}, | ||
1105 | {0x0000a128, 0x00000000}, | ||
1106 | {0x0000a12c, 0x00000000}, | ||
1107 | {0x0000a130, 0x00000000}, | ||
1108 | {0x0000a134, 0x00000000}, | ||
1109 | {0x0000a138, 0x00000000}, | ||
1110 | {0x0000a13c, 0x00000000}, | ||
1111 | {0x0000a140, 0x001f0000}, | ||
1112 | {0x0000a144, 0x111f1100}, | ||
1113 | {0x0000a148, 0x111d111e}, | ||
1114 | {0x0000a14c, 0x111b111c}, | ||
1115 | {0x0000a150, 0x22032204}, | ||
1116 | {0x0000a154, 0x22012202}, | ||
1117 | {0x0000a158, 0x221f2200}, | ||
1118 | {0x0000a15c, 0x221d221e}, | ||
1119 | {0x0000a160, 0x33013302}, | ||
1120 | {0x0000a164, 0x331f3300}, | ||
1121 | {0x0000a168, 0x4402331e}, | ||
1122 | {0x0000a16c, 0x44004401}, | ||
1123 | {0x0000a170, 0x441e441f}, | ||
1124 | {0x0000a174, 0x55015502}, | ||
1125 | {0x0000a178, 0x551f5500}, | ||
1126 | {0x0000a17c, 0x6602551e}, | ||
1127 | {0x0000a180, 0x66006601}, | ||
1128 | {0x0000a184, 0x661e661f}, | ||
1129 | {0x0000a188, 0x7703661d}, | ||
1130 | {0x0000a18c, 0x77017702}, | ||
1131 | {0x0000a190, 0x00007700}, | ||
1132 | {0x0000a194, 0x00000000}, | ||
1133 | {0x0000a198, 0x00000000}, | ||
1134 | {0x0000a19c, 0x00000000}, | ||
1135 | {0x0000a1a0, 0x00000000}, | ||
1136 | {0x0000a1a4, 0x00000000}, | ||
1137 | {0x0000a1a8, 0x00000000}, | ||
1138 | {0x0000a1ac, 0x00000000}, | ||
1139 | {0x0000a1b0, 0x00000000}, | ||
1140 | {0x0000a1b4, 0x00000000}, | ||
1141 | {0x0000a1b8, 0x00000000}, | ||
1142 | {0x0000a1bc, 0x00000000}, | ||
1143 | {0x0000a1c0, 0x00000000}, | ||
1144 | {0x0000a1c4, 0x00000000}, | ||
1145 | {0x0000a1c8, 0x00000000}, | ||
1146 | {0x0000a1cc, 0x00000000}, | ||
1147 | {0x0000a1d0, 0x00000000}, | ||
1148 | {0x0000a1d4, 0x00000000}, | ||
1149 | {0x0000a1d8, 0x00000000}, | ||
1150 | {0x0000a1dc, 0x00000000}, | ||
1151 | {0x0000a1e0, 0x00000000}, | ||
1152 | {0x0000a1e4, 0x00000000}, | ||
1153 | {0x0000a1e8, 0x00000000}, | ||
1154 | {0x0000a1ec, 0x00000000}, | ||
1155 | {0x0000a1f0, 0x00000396}, | ||
1156 | {0x0000a1f4, 0x00000396}, | ||
1157 | {0x0000a1f8, 0x00000396}, | ||
1158 | {0x0000a1fc, 0x00000296}, | ||
1159 | }; | ||
1160 | |||
1161 | #endif | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 07f26ee7a723..f75068b4b310 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -62,7 +62,6 @@ struct ath_node; | |||
62 | #define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i)) | 62 | #define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i)) |
63 | 63 | ||
64 | struct ath_config { | 64 | struct ath_config { |
65 | u32 ath_aggr_prot; | ||
66 | u16 txpowlimit; | 65 | u16 txpowlimit; |
67 | u8 cabqReadytime; | 66 | u8 cabqReadytime; |
68 | }; | 67 | }; |
@@ -86,33 +85,19 @@ struct ath_config { | |||
86 | /** | 85 | /** |
87 | * enum buffer_type - Buffer type flags | 86 | * enum buffer_type - Buffer type flags |
88 | * | 87 | * |
89 | * @BUF_HT: Send this buffer using HT capabilities | ||
90 | * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) | 88 | * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) |
91 | * @BUF_AGGR: Indicates whether the buffer can be aggregated | 89 | * @BUF_AGGR: Indicates whether the buffer can be aggregated |
92 | * (used in aggregation scheduling) | 90 | * (used in aggregation scheduling) |
93 | * @BUF_RETRY: Indicates whether the buffer is retried | ||
94 | * @BUF_XRETRY: To denote excessive retries of the buffer | 91 | * @BUF_XRETRY: To denote excessive retries of the buffer |
95 | */ | 92 | */ |
96 | enum buffer_type { | 93 | enum buffer_type { |
97 | BUF_HT = BIT(1), | 94 | BUF_AMPDU = BIT(0), |
98 | BUF_AMPDU = BIT(2), | 95 | BUF_AGGR = BIT(1), |
99 | BUF_AGGR = BIT(3), | 96 | BUF_XRETRY = BIT(2), |
100 | BUF_RETRY = BIT(4), | ||
101 | BUF_XRETRY = BIT(5), | ||
102 | }; | 97 | }; |
103 | 98 | ||
104 | #define bf_nframes bf_state.bfs_nframes | ||
105 | #define bf_al bf_state.bfs_al | ||
106 | #define bf_frmlen bf_state.bfs_frmlen | ||
107 | #define bf_retries bf_state.bfs_retries | ||
108 | #define bf_seqno bf_state.bfs_seqno | ||
109 | #define bf_tidno bf_state.bfs_tidno | ||
110 | #define bf_keyix bf_state.bfs_keyix | ||
111 | #define bf_keytype bf_state.bfs_keytype | ||
112 | #define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) | ||
113 | #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) | 99 | #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) |
114 | #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) | 100 | #define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) |
115 | #define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) | ||
116 | #define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) | 101 | #define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) |
117 | 102 | ||
118 | #define ATH_TXSTATUS_RING_SIZE 64 | 103 | #define ATH_TXSTATUS_RING_SIZE 64 |
@@ -134,13 +119,11 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
134 | /* RX / TX */ | 119 | /* RX / TX */ |
135 | /***********/ | 120 | /***********/ |
136 | 121 | ||
137 | #define ATH_MAX_ANTENNA 3 | ||
138 | #define ATH_RXBUF 512 | 122 | #define ATH_RXBUF 512 |
139 | #define ATH_TXBUF 512 | 123 | #define ATH_TXBUF 512 |
140 | #define ATH_TXBUF_RESERVE 5 | 124 | #define ATH_TXBUF_RESERVE 5 |
141 | #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) | 125 | #define ATH_MAX_QDEPTH (ATH_TXBUF / 4 - ATH_TXBUF_RESERVE) |
142 | #define ATH_TXMAXTRY 13 | 126 | #define ATH_TXMAXTRY 13 |
143 | #define ATH_MGT_TXMAXTRY 4 | ||
144 | 127 | ||
145 | #define TID_TO_WME_AC(_tid) \ | 128 | #define TID_TO_WME_AC(_tid) \ |
146 | ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ | 129 | ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ |
@@ -148,7 +131,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
148 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ | 131 | (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ |
149 | WME_AC_VO) | 132 | WME_AC_VO) |
150 | 133 | ||
151 | #define ADDBA_EXCHANGE_ATTEMPTS 10 | ||
152 | #define ATH_AGGR_DELIM_SZ 4 | 134 | #define ATH_AGGR_DELIM_SZ 4 |
153 | #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ | 135 | #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ |
154 | /* number of delimiters for encryption padding */ | 136 | /* number of delimiters for encryption padding */ |
@@ -177,8 +159,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, | |||
177 | 159 | ||
178 | /* returns delimiter padding required given the packet length */ | 160 | /* returns delimiter padding required given the packet length */ |
179 | #define ATH_AGGR_GET_NDELIM(_len) \ | 161 | #define ATH_AGGR_GET_NDELIM(_len) \ |
180 | (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ | 162 | (((_len) >= ATH_AGGR_MINPLEN) ? 0 : \ |
181 | (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) | 163 | DIV_ROUND_UP(ATH_AGGR_MINPLEN - (_len), ATH_AGGR_DELIM_SZ)) |
182 | 164 | ||
183 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ | 165 | #define BAW_WITHIN(_start, _bawsz, _seqno) \ |
184 | ((((_seqno) - (_start)) & 4095) < (_bawsz)) | 166 | ((((_seqno) - (_start)) & 4095) < (_bawsz)) |
@@ -195,12 +177,13 @@ enum ATH_AGGR_STATUS { | |||
195 | 177 | ||
196 | #define ATH_TXFIFO_DEPTH 8 | 178 | #define ATH_TXFIFO_DEPTH 8 |
197 | struct ath_txq { | 179 | struct ath_txq { |
198 | int axq_class; | 180 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ |
199 | u32 axq_qnum; | 181 | u32 axq_qnum; /* ath9k hardware queue number */ |
200 | u32 *axq_link; | 182 | u32 *axq_link; |
201 | struct list_head axq_q; | 183 | struct list_head axq_q; |
202 | spinlock_t axq_lock; | 184 | spinlock_t axq_lock; |
203 | u32 axq_depth; | 185 | u32 axq_depth; |
186 | u32 axq_ampdu_depth; | ||
204 | bool stopped; | 187 | bool stopped; |
205 | bool axq_tx_inprogress; | 188 | bool axq_tx_inprogress; |
206 | struct list_head axq_acq; | 189 | struct list_head axq_acq; |
@@ -208,27 +191,30 @@ struct ath_txq { | |||
208 | struct list_head txq_fifo_pending; | 191 | struct list_head txq_fifo_pending; |
209 | u8 txq_headidx; | 192 | u8 txq_headidx; |
210 | u8 txq_tailidx; | 193 | u8 txq_tailidx; |
194 | int pending_frames; | ||
211 | }; | 195 | }; |
212 | 196 | ||
213 | struct ath_atx_ac { | 197 | struct ath_atx_ac { |
198 | struct ath_txq *txq; | ||
214 | int sched; | 199 | int sched; |
215 | int qnum; | ||
216 | struct list_head list; | 200 | struct list_head list; |
217 | struct list_head tid_q; | 201 | struct list_head tid_q; |
202 | bool clear_ps_filter; | ||
203 | }; | ||
204 | |||
205 | struct ath_frame_info { | ||
206 | int framelen; | ||
207 | u32 keyix; | ||
208 | enum ath9k_key_type keytype; | ||
209 | u8 retries; | ||
210 | u16 seqno; | ||
218 | }; | 211 | }; |
219 | 212 | ||
220 | struct ath_buf_state { | 213 | struct ath_buf_state { |
221 | int bfs_nframes; | ||
222 | u16 bfs_al; | ||
223 | u16 bfs_frmlen; | ||
224 | int bfs_seqno; | ||
225 | int bfs_tidno; | ||
226 | int bfs_retries; | ||
227 | u8 bf_type; | 214 | u8 bf_type; |
228 | u8 bfs_paprd; | 215 | u8 bfs_paprd; |
229 | unsigned long bfs_paprd_timestamp; | 216 | unsigned long bfs_paprd_timestamp; |
230 | u32 bfs_keyix; | 217 | enum ath9k_internal_frame_type bfs_ftype; |
231 | enum ath9k_key_type bfs_keytype; | ||
232 | }; | 218 | }; |
233 | 219 | ||
234 | struct ath_buf { | 220 | struct ath_buf { |
@@ -239,14 +225,10 @@ struct ath_buf { | |||
239 | struct sk_buff *bf_mpdu; /* enclosing frame structure */ | 225 | struct sk_buff *bf_mpdu; /* enclosing frame structure */ |
240 | void *bf_desc; /* virtual addr of desc */ | 226 | void *bf_desc; /* virtual addr of desc */ |
241 | dma_addr_t bf_daddr; /* physical addr of desc */ | 227 | dma_addr_t bf_daddr; /* physical addr of desc */ |
242 | dma_addr_t bf_buf_addr; /* physical addr of data buffer */ | 228 | dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */ |
243 | bool bf_stale; | 229 | bool bf_stale; |
244 | bool bf_isnullfunc; | ||
245 | bool bf_tx_aborted; | ||
246 | u16 bf_flags; | 230 | u16 bf_flags; |
247 | struct ath_buf_state bf_state; | 231 | struct ath_buf_state bf_state; |
248 | dma_addr_t bf_dmacontext; | ||
249 | struct ath_wiphy *aphy; | ||
250 | }; | 232 | }; |
251 | 233 | ||
252 | struct ath_atx_tid { | 234 | struct ath_atx_tid { |
@@ -254,7 +236,7 @@ struct ath_atx_tid { | |||
254 | struct list_head buf_q; | 236 | struct list_head buf_q; |
255 | struct ath_node *an; | 237 | struct ath_node *an; |
256 | struct ath_atx_ac *ac; | 238 | struct ath_atx_ac *ac; |
257 | struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; | 239 | unsigned long tx_buf[BITS_TO_LONGS(ATH_TID_MAX_BUFS)]; |
258 | u16 seq_start; | 240 | u16 seq_start; |
259 | u16 seq_next; | 241 | u16 seq_next; |
260 | u16 baw_size; | 242 | u16 baw_size; |
@@ -267,12 +249,18 @@ struct ath_atx_tid { | |||
267 | }; | 249 | }; |
268 | 250 | ||
269 | struct ath_node { | 251 | struct ath_node { |
270 | struct ath_common *common; | 252 | #ifdef CONFIG_ATH9K_DEBUGFS |
253 | struct list_head list; /* for sc->nodes */ | ||
254 | struct ieee80211_sta *sta; /* station struct we're part of */ | ||
255 | #endif | ||
271 | struct ath_atx_tid tid[WME_NUM_TID]; | 256 | struct ath_atx_tid tid[WME_NUM_TID]; |
272 | struct ath_atx_ac ac[WME_NUM_AC]; | 257 | struct ath_atx_ac ac[WME_NUM_AC]; |
258 | int ps_key; | ||
259 | |||
273 | u16 maxampdu; | 260 | u16 maxampdu; |
274 | u8 mpdudensity; | 261 | u8 mpdudensity; |
275 | int last_rssi; | 262 | |
263 | bool sleeping; | ||
276 | }; | 264 | }; |
277 | 265 | ||
278 | #define AGGR_CLEANUP BIT(1) | 266 | #define AGGR_CLEANUP BIT(1) |
@@ -281,6 +269,7 @@ struct ath_node { | |||
281 | 269 | ||
282 | struct ath_tx_control { | 270 | struct ath_tx_control { |
283 | struct ath_txq *txq; | 271 | struct ath_txq *txq; |
272 | struct ath_node *an; | ||
284 | int if_id; | 273 | int if_id; |
285 | enum ath9k_internal_frame_type frame_type; | 274 | enum ath9k_internal_frame_type frame_type; |
286 | u8 paprd; | 275 | u8 paprd; |
@@ -290,15 +279,19 @@ struct ath_tx_control { | |||
290 | #define ATH_TX_XRETRY 0x02 | 279 | #define ATH_TX_XRETRY 0x02 |
291 | #define ATH_TX_BAR 0x04 | 280 | #define ATH_TX_BAR 0x04 |
292 | 281 | ||
282 | /** | ||
283 | * @txq_map: Index is mac80211 queue number. This is | ||
284 | * not necessarily the same as the hardware queue number | ||
285 | * (axq_qnum). | ||
286 | */ | ||
293 | struct ath_tx { | 287 | struct ath_tx { |
294 | u16 seq_no; | 288 | u16 seq_no; |
295 | u32 txqsetup; | 289 | u32 txqsetup; |
296 | int hwq_map[WME_NUM_AC]; | ||
297 | spinlock_t txbuflock; | 290 | spinlock_t txbuflock; |
298 | struct list_head txbuf; | 291 | struct list_head txbuf; |
299 | struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; | 292 | struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; |
300 | struct ath_descdma txdma; | 293 | struct ath_descdma txdma; |
301 | int pending_frames[WME_NUM_AC]; | 294 | struct ath_txq *txq_map[WME_NUM_AC]; |
302 | }; | 295 | }; |
303 | 296 | ||
304 | struct ath_rx_edma { | 297 | struct ath_rx_edma { |
@@ -312,12 +305,13 @@ struct ath_rx { | |||
312 | u8 rxotherant; | 305 | u8 rxotherant; |
313 | u32 *rxlink; | 306 | u32 *rxlink; |
314 | unsigned int rxfilter; | 307 | unsigned int rxfilter; |
315 | spinlock_t rxflushlock; | ||
316 | spinlock_t rxbuflock; | 308 | spinlock_t rxbuflock; |
317 | struct list_head rxbuf; | 309 | struct list_head rxbuf; |
318 | struct ath_descdma rxdma; | 310 | struct ath_descdma rxdma; |
319 | struct ath_buf *rx_bufptr; | 311 | struct ath_buf *rx_bufptr; |
320 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; | 312 | struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; |
313 | |||
314 | struct sk_buff *frag; | ||
321 | }; | 315 | }; |
322 | 316 | ||
323 | int ath_startrecv(struct ath_softc *sc); | 317 | int ath_startrecv(struct ath_softc *sc); |
@@ -329,8 +323,7 @@ void ath_rx_cleanup(struct ath_softc *sc); | |||
329 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); | 323 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp); |
330 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); | 324 | struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); |
331 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); | 325 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); |
332 | int ath_tx_setup(struct ath_softc *sc, int haltype); | 326 | bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); |
333 | void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); | ||
334 | void ath_draintxq(struct ath_softc *sc, | 327 | void ath_draintxq(struct ath_softc *sc, |
335 | struct ath_txq *txq, bool retry_tx); | 328 | struct ath_txq *txq, bool retry_tx); |
336 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); | 329 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); |
@@ -344,13 +337,13 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
344 | struct ath_tx_control *txctl); | 337 | struct ath_tx_control *txctl); |
345 | void ath_tx_tasklet(struct ath_softc *sc); | 338 | void ath_tx_tasklet(struct ath_softc *sc); |
346 | void ath_tx_edma_tasklet(struct ath_softc *sc); | 339 | void ath_tx_edma_tasklet(struct ath_softc *sc); |
347 | void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); | 340 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
348 | bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); | 341 | u16 tid, u16 *ssn); |
349 | void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | ||
350 | u16 tid, u16 *ssn); | ||
351 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 342 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
352 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); | 343 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
353 | void ath9k_enable_ps(struct ath_softc *sc); | 344 | |
345 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); | ||
346 | bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); | ||
354 | 347 | ||
355 | /********/ | 348 | /********/ |
356 | /* VIFs */ | 349 | /* VIFs */ |
@@ -358,11 +351,9 @@ void ath9k_enable_ps(struct ath_softc *sc); | |||
358 | 351 | ||
359 | struct ath_vif { | 352 | struct ath_vif { |
360 | int av_bslot; | 353 | int av_bslot; |
354 | bool is_bslot_active, primary_sta_vif; | ||
361 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ | 355 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ |
362 | enum nl80211_iftype av_opmode; | ||
363 | struct ath_buf *av_bcbuf; | 356 | struct ath_buf *av_bcbuf; |
364 | struct ath_tx_control av_btxctl; | ||
365 | u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */ | ||
366 | }; | 357 | }; |
367 | 358 | ||
368 | /*******************/ | 359 | /*******************/ |
@@ -374,14 +365,14 @@ struct ath_vif { | |||
374 | * number of BSSIDs) if a given beacon does not go out even after waiting this | 365 | * number of BSSIDs) if a given beacon does not go out even after waiting this |
375 | * number of beacon intervals, the game's up. | 366 | * number of beacon intervals, the game's up. |
376 | */ | 367 | */ |
377 | #define BSTUCK_THRESH (9 * ATH_BCBUF) | 368 | #define BSTUCK_THRESH 9 |
378 | #define ATH_BCBUF 4 | 369 | #define ATH_BCBUF 4 |
379 | #define ATH_DEFAULT_BINTVAL 100 /* TU */ | 370 | #define ATH_DEFAULT_BINTVAL 100 /* TU */ |
380 | #define ATH_DEFAULT_BMISS_LIMIT 10 | 371 | #define ATH_DEFAULT_BMISS_LIMIT 10 |
381 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | 372 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) |
382 | 373 | ||
383 | struct ath_beacon_config { | 374 | struct ath_beacon_config { |
384 | u16 beacon_interval; | 375 | int beacon_interval; |
385 | u16 listen_interval; | 376 | u16 listen_interval; |
386 | u16 dtim_period; | 377 | u16 dtim_period; |
387 | u16 bmiss_timeout; | 378 | u16 bmiss_timeout; |
@@ -398,22 +389,26 @@ struct ath_beacon { | |||
398 | u32 beaconq; | 389 | u32 beaconq; |
399 | u32 bmisscnt; | 390 | u32 bmisscnt; |
400 | u32 ast_be_xmit; | 391 | u32 ast_be_xmit; |
401 | u64 bc_tstamp; | 392 | u32 bc_tstamp; |
402 | struct ieee80211_vif *bslot[ATH_BCBUF]; | 393 | struct ieee80211_vif *bslot[ATH_BCBUF]; |
403 | struct ath_wiphy *bslot_aphy[ATH_BCBUF]; | ||
404 | int slottime; | 394 | int slottime; |
405 | int slotupdate; | 395 | int slotupdate; |
406 | struct ath9k_tx_queue_info beacon_qi; | 396 | struct ath9k_tx_queue_info beacon_qi; |
407 | struct ath_descdma bdma; | 397 | struct ath_descdma bdma; |
408 | struct ath_txq *cabq; | 398 | struct ath_txq *cabq; |
409 | struct list_head bbuf; | 399 | struct list_head bbuf; |
400 | |||
401 | bool tx_processed; | ||
402 | bool tx_last; | ||
410 | }; | 403 | }; |
411 | 404 | ||
412 | void ath_beacon_tasklet(unsigned long data); | 405 | void ath_beacon_tasklet(unsigned long data); |
413 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); | 406 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); |
414 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif); | 407 | int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif); |
415 | void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); | 408 | void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); |
416 | int ath_beaconq_config(struct ath_softc *sc); | 409 | int ath_beaconq_config(struct ath_softc *sc); |
410 | void ath_set_beacon(struct ath_softc *sc); | ||
411 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status); | ||
417 | 412 | ||
418 | /*******/ | 413 | /*******/ |
419 | /* ANI */ | 414 | /* ANI */ |
@@ -423,12 +418,14 @@ int ath_beaconq_config(struct ath_softc *sc); | |||
423 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ | 418 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ |
424 | #define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ | 419 | #define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ |
425 | #define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ | 420 | #define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ |
421 | #define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */ | ||
426 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 422 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
427 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 423 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
428 | 424 | ||
429 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ | 425 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ |
430 | 426 | ||
431 | void ath_hw_check(struct work_struct *work); | 427 | void ath_hw_check(struct work_struct *work); |
428 | void ath_hw_pll_work(struct work_struct *work); | ||
432 | void ath_paprd_calibrate(struct work_struct *work); | 429 | void ath_paprd_calibrate(struct work_struct *work); |
433 | void ath_ani_calibrate(unsigned long data); | 430 | void ath_ani_calibrate(unsigned long data); |
434 | 431 | ||
@@ -436,14 +433,6 @@ void ath_ani_calibrate(unsigned long data); | |||
436 | /* BTCOEX */ | 433 | /* BTCOEX */ |
437 | /**********/ | 434 | /**********/ |
438 | 435 | ||
439 | /* Defines the BT AR_BT_COEX_WGHT used */ | ||
440 | enum ath_stomp_type { | ||
441 | ATH_BTCOEX_NO_STOMP, | ||
442 | ATH_BTCOEX_STOMP_ALL, | ||
443 | ATH_BTCOEX_STOMP_LOW, | ||
444 | ATH_BTCOEX_STOMP_NONE | ||
445 | }; | ||
446 | |||
447 | struct ath_btcoex { | 436 | struct ath_btcoex { |
448 | bool hw_timer_enabled; | 437 | bool hw_timer_enabled; |
449 | spinlock_t btcoex_lock; | 438 | spinlock_t btcoex_lock; |
@@ -467,26 +456,75 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc); | |||
467 | 456 | ||
468 | #define ATH_LED_PIN_DEF 1 | 457 | #define ATH_LED_PIN_DEF 1 |
469 | #define ATH_LED_PIN_9287 8 | 458 | #define ATH_LED_PIN_9287 8 |
470 | #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ | 459 | #define ATH_LED_PIN_9300 10 |
471 | #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ | 460 | #define ATH_LED_PIN_9485 6 |
472 | |||
473 | enum ath_led_type { | ||
474 | ATH_LED_RADIO, | ||
475 | ATH_LED_ASSOC, | ||
476 | ATH_LED_TX, | ||
477 | ATH_LED_RX | ||
478 | }; | ||
479 | |||
480 | struct ath_led { | ||
481 | struct ath_softc *sc; | ||
482 | struct led_classdev led_cdev; | ||
483 | enum ath_led_type led_type; | ||
484 | char name[32]; | ||
485 | bool registered; | ||
486 | }; | ||
487 | 461 | ||
462 | #ifdef CONFIG_MAC80211_LEDS | ||
488 | void ath_init_leds(struct ath_softc *sc); | 463 | void ath_init_leds(struct ath_softc *sc); |
489 | void ath_deinit_leds(struct ath_softc *sc); | 464 | void ath_deinit_leds(struct ath_softc *sc); |
465 | #else | ||
466 | static inline void ath_init_leds(struct ath_softc *sc) | ||
467 | { | ||
468 | } | ||
469 | |||
470 | static inline void ath_deinit_leds(struct ath_softc *sc) | ||
471 | { | ||
472 | } | ||
473 | #endif | ||
474 | |||
475 | |||
476 | /* Antenna diversity/combining */ | ||
477 | #define ATH_ANT_RX_CURRENT_SHIFT 4 | ||
478 | #define ATH_ANT_RX_MAIN_SHIFT 2 | ||
479 | #define ATH_ANT_RX_MASK 0x3 | ||
480 | |||
481 | #define ATH_ANT_DIV_COMB_SHORT_SCAN_INTR 50 | ||
482 | #define ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT 0x100 | ||
483 | #define ATH_ANT_DIV_COMB_MAX_PKTCOUNT 0x200 | ||
484 | #define ATH_ANT_DIV_COMB_INIT_COUNT 95 | ||
485 | #define ATH_ANT_DIV_COMB_MAX_COUNT 100 | ||
486 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 | ||
487 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 | ||
488 | |||
489 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 | ||
490 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 | ||
491 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 | ||
492 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_LOW 2 | ||
493 | |||
494 | enum ath9k_ant_div_comb_lna_conf { | ||
495 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2, | ||
496 | ATH_ANT_DIV_COMB_LNA2, | ||
497 | ATH_ANT_DIV_COMB_LNA1, | ||
498 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2, | ||
499 | }; | ||
500 | |||
501 | struct ath_ant_comb { | ||
502 | u16 count; | ||
503 | u16 total_pkt_count; | ||
504 | bool scan; | ||
505 | bool scan_not_start; | ||
506 | int main_total_rssi; | ||
507 | int alt_total_rssi; | ||
508 | int alt_recv_cnt; | ||
509 | int main_recv_cnt; | ||
510 | int rssi_lna1; | ||
511 | int rssi_lna2; | ||
512 | int rssi_add; | ||
513 | int rssi_sub; | ||
514 | int rssi_first; | ||
515 | int rssi_second; | ||
516 | int rssi_third; | ||
517 | bool alt_good; | ||
518 | int quick_scan_cnt; | ||
519 | int main_conf; | ||
520 | enum ath9k_ant_div_comb_lna_conf first_quick_scan_conf; | ||
521 | enum ath9k_ant_div_comb_lna_conf second_quick_scan_conf; | ||
522 | int first_bias; | ||
523 | int second_bias; | ||
524 | bool first_ratio; | ||
525 | bool second_ratio; | ||
526 | unsigned long scan_start_time; | ||
527 | }; | ||
490 | 528 | ||
491 | /********************/ | 529 | /********************/ |
492 | /* Main driver core */ | 530 | /* Main driver core */ |
@@ -501,7 +539,6 @@ void ath_deinit_leds(struct ath_softc *sc); | |||
501 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ | 539 | #define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ |
502 | #define ATH_MAX_SW_RETRIES 10 | 540 | #define ATH_MAX_SW_RETRIES 10 |
503 | #define ATH_CHAN_MAX 255 | 541 | #define ATH_CHAN_MAX 255 |
504 | #define IEEE80211_WEP_NKID 4 /* number of key ids */ | ||
505 | 542 | ||
506 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ | 543 | #define ATH_TXPOWER_MAX 100 /* .5 dBm units */ |
507 | #define ATH_RATE_DUMMY_MARKER 0 | 544 | #define ATH_RATE_DUMMY_MARKER 0 |
@@ -516,11 +553,12 @@ void ath_deinit_leds(struct ath_softc *sc); | |||
516 | #define SC_OP_RXFLUSH BIT(7) | 553 | #define SC_OP_RXFLUSH BIT(7) |
517 | #define SC_OP_LED_ASSOCIATED BIT(8) | 554 | #define SC_OP_LED_ASSOCIATED BIT(8) |
518 | #define SC_OP_LED_ON BIT(9) | 555 | #define SC_OP_LED_ON BIT(9) |
519 | #define SC_OP_SCANNING BIT(10) | ||
520 | #define SC_OP_TSF_RESET BIT(11) | 556 | #define SC_OP_TSF_RESET BIT(11) |
521 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) | 557 | #define SC_OP_BT_PRIORITY_DETECTED BIT(12) |
522 | #define SC_OP_BT_SCAN BIT(13) | 558 | #define SC_OP_BT_SCAN BIT(13) |
523 | #define SC_OP_ANI_RUN BIT(14) | 559 | #define SC_OP_ANI_RUN BIT(14) |
560 | #define SC_OP_ENABLE_APM BIT(15) | ||
561 | #define SC_OP_PRIM_STA_VIF BIT(16) | ||
524 | 562 | ||
525 | /* Powersave flags */ | 563 | /* Powersave flags */ |
526 | #define PS_WAIT_FOR_BEACON BIT(0) | 564 | #define PS_WAIT_FOR_BEACON BIT(0) |
@@ -528,103 +566,91 @@ void ath_deinit_leds(struct ath_softc *sc); | |||
528 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) | 566 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) |
529 | #define PS_WAIT_FOR_TX_ACK BIT(3) | 567 | #define PS_WAIT_FOR_TX_ACK BIT(3) |
530 | #define PS_BEACON_SYNC BIT(4) | 568 | #define PS_BEACON_SYNC BIT(4) |
531 | #define PS_NULLFUNC_COMPLETED BIT(5) | 569 | #define PS_TSFOOR_SYNC BIT(5) |
532 | #define PS_ENABLED BIT(6) | ||
533 | 570 | ||
534 | struct ath_wiphy; | ||
535 | struct ath_rate_table; | 571 | struct ath_rate_table; |
536 | 572 | ||
573 | struct ath9k_vif_iter_data { | ||
574 | const u8 *hw_macaddr; /* phy's hardware address, set | ||
575 | * before starting iteration for | ||
576 | * valid bssid mask. | ||
577 | */ | ||
578 | u8 mask[ETH_ALEN]; /* bssid mask */ | ||
579 | int naps; /* number of AP vifs */ | ||
580 | int nmeshes; /* number of mesh vifs */ | ||
581 | int nstations; /* number of station vifs */ | ||
582 | int nwds; /* number of nwd vifs */ | ||
583 | int nadhocs; /* number of adhoc vifs */ | ||
584 | int nothers; /* number of vifs not specified above. */ | ||
585 | }; | ||
586 | |||
537 | struct ath_softc { | 587 | struct ath_softc { |
538 | struct ieee80211_hw *hw; | 588 | struct ieee80211_hw *hw; |
539 | struct device *dev; | 589 | struct device *dev; |
540 | 590 | ||
541 | spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ | ||
542 | struct ath_wiphy *pri_wiphy; | ||
543 | struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may | ||
544 | * have NULL entries */ | ||
545 | int num_sec_wiphy; /* number of sec_wiphy pointers in the array */ | ||
546 | int chan_idx; | 591 | int chan_idx; |
547 | int chan_is_ht; | 592 | int chan_is_ht; |
548 | struct ath_wiphy *next_wiphy; | 593 | struct survey_info *cur_survey; |
549 | struct work_struct chan_work; | 594 | struct survey_info survey[ATH9K_NUM_CHANNELS]; |
550 | int wiphy_select_failures; | ||
551 | unsigned long wiphy_select_first_fail; | ||
552 | struct delayed_work wiphy_work; | ||
553 | unsigned long wiphy_scheduler_int; | ||
554 | int wiphy_scheduler_index; | ||
555 | 595 | ||
556 | struct tasklet_struct intr_tq; | 596 | struct tasklet_struct intr_tq; |
557 | struct tasklet_struct bcon_tasklet; | 597 | struct tasklet_struct bcon_tasklet; |
558 | struct ath_hw *sc_ah; | 598 | struct ath_hw *sc_ah; |
559 | void __iomem *mem; | 599 | void __iomem *mem; |
560 | int irq; | 600 | int irq; |
561 | spinlock_t sc_resetlock; | ||
562 | spinlock_t sc_serial_rw; | 601 | spinlock_t sc_serial_rw; |
563 | spinlock_t sc_pm_lock; | 602 | spinlock_t sc_pm_lock; |
603 | spinlock_t sc_pcu_lock; | ||
564 | struct mutex mutex; | 604 | struct mutex mutex; |
565 | struct work_struct paprd_work; | 605 | struct work_struct paprd_work; |
566 | struct work_struct hw_check_work; | 606 | struct work_struct hw_check_work; |
567 | struct completion paprd_complete; | 607 | struct completion paprd_complete; |
568 | 608 | ||
609 | unsigned int hw_busy_count; | ||
610 | |||
569 | u32 intrstatus; | 611 | u32 intrstatus; |
570 | u32 sc_flags; /* SC_OP_* */ | 612 | u32 sc_flags; /* SC_OP_* */ |
571 | u16 ps_flags; /* PS_* */ | 613 | u16 ps_flags; /* PS_* */ |
572 | u16 curtxpow; | 614 | u16 curtxpow; |
573 | u8 nbcnvifs; | ||
574 | u16 nvifs; | ||
575 | bool ps_enabled; | 615 | bool ps_enabled; |
576 | bool ps_idle; | 616 | bool ps_idle; |
617 | short nbcnvifs; | ||
618 | short nvifs; | ||
577 | unsigned long ps_usecount; | 619 | unsigned long ps_usecount; |
578 | 620 | ||
579 | struct ath_config config; | 621 | struct ath_config config; |
580 | struct ath_rx rx; | 622 | struct ath_rx rx; |
581 | struct ath_tx tx; | 623 | struct ath_tx tx; |
582 | struct ath_beacon beacon; | 624 | struct ath_beacon beacon; |
583 | const struct ath_rate_table *cur_rate_table; | ||
584 | enum wireless_mode cur_rate_mode; | ||
585 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 625 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
586 | 626 | ||
587 | struct ath_led radio_led; | 627 | #ifdef CONFIG_MAC80211_LEDS |
588 | struct ath_led assoc_led; | 628 | bool led_registered; |
589 | struct ath_led tx_led; | 629 | char led_name[32]; |
590 | struct ath_led rx_led; | 630 | struct led_classdev led_cdev; |
591 | struct delayed_work ath_led_blink_work; | 631 | #endif |
592 | int led_on_duration; | ||
593 | int led_off_duration; | ||
594 | int led_on_cnt; | ||
595 | int led_off_cnt; | ||
596 | 632 | ||
597 | int beacon_interval; | 633 | struct ath9k_hw_cal_data caldata; |
634 | int last_rssi; | ||
598 | 635 | ||
599 | #ifdef CONFIG_ATH9K_DEBUGFS | 636 | #ifdef CONFIG_ATH9K_DEBUGFS |
600 | struct ath9k_debug debug; | 637 | struct ath9k_debug debug; |
638 | spinlock_t nodes_lock; | ||
639 | struct list_head nodes; /* basically, stations */ | ||
640 | unsigned int tx_complete_poll_work_seen; | ||
601 | #endif | 641 | #endif |
602 | struct ath_beacon_config cur_beacon_conf; | 642 | struct ath_beacon_config cur_beacon_conf; |
603 | struct delayed_work tx_complete_work; | 643 | struct delayed_work tx_complete_work; |
644 | struct delayed_work hw_pll_work; | ||
604 | struct ath_btcoex btcoex; | 645 | struct ath_btcoex btcoex; |
605 | 646 | ||
606 | struct ath_descdma txsdma; | 647 | struct ath_descdma txsdma; |
607 | }; | ||
608 | 648 | ||
609 | struct ath_wiphy { | 649 | struct ath_ant_comb ant_comb; |
610 | struct ath_softc *sc; /* shared for all virtual wiphys */ | ||
611 | struct ieee80211_hw *hw; | ||
612 | struct ath9k_hw_cal_data caldata; | ||
613 | enum ath_wiphy_state { | ||
614 | ATH_WIPHY_INACTIVE, | ||
615 | ATH_WIPHY_ACTIVE, | ||
616 | ATH_WIPHY_PAUSING, | ||
617 | ATH_WIPHY_PAUSED, | ||
618 | ATH_WIPHY_SCAN, | ||
619 | } state; | ||
620 | bool idle; | ||
621 | int chan_idx; | ||
622 | int chan_is_ht; | ||
623 | }; | 650 | }; |
624 | 651 | ||
625 | void ath9k_tasklet(unsigned long data); | 652 | void ath9k_tasklet(unsigned long data); |
626 | int ath_reset(struct ath_softc *sc, bool retry_tx); | 653 | int ath_reset(struct ath_softc *sc, bool retry_tx); |
627 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); | ||
628 | int ath_cabq_update(struct ath_softc *); | 654 | int ath_cabq_update(struct ath_softc *); |
629 | 655 | ||
630 | static inline void ath_read_cachesize(struct ath_common *common, int *csz) | 656 | static inline void ath_read_cachesize(struct ath_common *common, int *csz) |
@@ -633,25 +659,25 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) | |||
633 | } | 659 | } |
634 | 660 | ||
635 | extern struct ieee80211_ops ath9k_ops; | 661 | extern struct ieee80211_ops ath9k_ops; |
636 | extern int modparam_nohwcrypt; | 662 | extern int ath9k_modparam_nohwcrypt; |
637 | extern int led_blink; | 663 | extern int led_blink; |
664 | extern bool is_ath9k_unloaded; | ||
638 | 665 | ||
639 | irqreturn_t ath_isr(int irq, void *dev); | 666 | irqreturn_t ath_isr(int irq, void *dev); |
667 | void ath9k_init_crypto(struct ath_softc *sc); | ||
640 | int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | 668 | int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, |
641 | const struct ath_bus_ops *bus_ops); | 669 | const struct ath_bus_ops *bus_ops); |
642 | void ath9k_deinit_device(struct ath_softc *sc); | 670 | void ath9k_deinit_device(struct ath_softc *sc); |
643 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); | 671 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); |
644 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, | ||
645 | struct ath9k_channel *ichan); | ||
646 | void ath_update_chainmask(struct ath_softc *sc, int is_ht); | ||
647 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | 672 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, |
648 | struct ath9k_channel *hchan); | 673 | struct ath9k_channel *hchan); |
649 | 674 | ||
650 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw); | 675 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw); |
651 | void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); | 676 | void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); |
652 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); | 677 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode); |
678 | bool ath9k_uses_beacons(int type); | ||
653 | 679 | ||
654 | #ifdef CONFIG_PCI | 680 | #ifdef CONFIG_ATH9K_PCI |
655 | int ath_pci_init(void); | 681 | int ath_pci_init(void); |
656 | void ath_pci_exit(void); | 682 | void ath_pci_exit(void); |
657 | #else | 683 | #else |
@@ -659,7 +685,7 @@ static inline int ath_pci_init(void) { return 0; }; | |||
659 | static inline void ath_pci_exit(void) {}; | 685 | static inline void ath_pci_exit(void) {}; |
660 | #endif | 686 | #endif |
661 | 687 | ||
662 | #ifdef CONFIG_ATHEROS_AR71XX | 688 | #ifdef CONFIG_ATH9K_AHB |
663 | int ath_ahb_init(void); | 689 | int ath_ahb_init(void); |
664 | void ath_ahb_exit(void); | 690 | void ath_ahb_exit(void); |
665 | #else | 691 | #else |
@@ -670,27 +696,13 @@ static inline void ath_ahb_exit(void) {}; | |||
670 | void ath9k_ps_wakeup(struct ath_softc *sc); | 696 | void ath9k_ps_wakeup(struct ath_softc *sc); |
671 | void ath9k_ps_restore(struct ath_softc *sc); | 697 | void ath9k_ps_restore(struct ath_softc *sc); |
672 | 698 | ||
673 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw); | 699 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate); |
674 | int ath9k_wiphy_add(struct ath_softc *sc); | ||
675 | int ath9k_wiphy_del(struct ath_wiphy *aphy); | ||
676 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); | ||
677 | int ath9k_wiphy_pause(struct ath_wiphy *aphy); | ||
678 | int ath9k_wiphy_unpause(struct ath_wiphy *aphy); | ||
679 | int ath9k_wiphy_select(struct ath_wiphy *aphy); | ||
680 | void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int); | ||
681 | void ath9k_wiphy_chan_work(struct work_struct *work); | ||
682 | bool ath9k_wiphy_started(struct ath_softc *sc); | ||
683 | void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | ||
684 | struct ath_wiphy *selected); | ||
685 | bool ath9k_wiphy_scanning(struct ath_softc *sc); | ||
686 | void ath9k_wiphy_work(struct work_struct *work); | ||
687 | bool ath9k_all_wiphys_idle(struct ath_softc *sc); | ||
688 | void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle); | ||
689 | |||
690 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue); | ||
691 | bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue); | ||
692 | 700 | ||
693 | void ath_start_rfkill_poll(struct ath_softc *sc); | 701 | void ath_start_rfkill_poll(struct ath_softc *sc); |
694 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); | 702 | extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw); |
703 | void ath9k_calculate_iter_data(struct ieee80211_hw *hw, | ||
704 | struct ieee80211_vif *vif, | ||
705 | struct ath9k_vif_iter_data *iter_data); | ||
706 | |||
695 | 707 | ||
696 | #endif /* ATH9K_H */ | 708 | #endif /* ATH9K_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 4d4b22d52dfd..d4d8ceced89b 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -18,6 +18,12 @@ | |||
18 | 18 | ||
19 | #define FUDGE 2 | 19 | #define FUDGE 2 |
20 | 20 | ||
21 | static void ath9k_reset_beacon_status(struct ath_softc *sc) | ||
22 | { | ||
23 | sc->beacon.tx_processed = false; | ||
24 | sc->beacon.tx_last = false; | ||
25 | } | ||
26 | |||
21 | /* | 27 | /* |
22 | * This function will modify certain transmit queue properties depending on | 28 | * This function will modify certain transmit queue properties depending on |
23 | * the operating mode of the station (AP or AdHoc). Parameters are AIFS | 29 | * the operating mode of the station (AP or AdHoc). Parameters are AIFS |
@@ -28,7 +34,7 @@ int ath_beaconq_config(struct ath_softc *sc) | |||
28 | struct ath_hw *ah = sc->sc_ah; | 34 | struct ath_hw *ah = sc->sc_ah; |
29 | struct ath_common *common = ath9k_hw_common(ah); | 35 | struct ath_common *common = ath9k_hw_common(ah); |
30 | struct ath9k_tx_queue_info qi, qi_be; | 36 | struct ath9k_tx_queue_info qi, qi_be; |
31 | int qnum; | 37 | struct ath_txq *txq; |
32 | 38 | ||
33 | ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); | 39 | ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); |
34 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { | 40 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { |
@@ -38,16 +44,16 @@ int ath_beaconq_config(struct ath_softc *sc) | |||
38 | qi.tqi_cwmax = 0; | 44 | qi.tqi_cwmax = 0; |
39 | } else { | 45 | } else { |
40 | /* Adhoc mode; important thing is to use 2x cwmin. */ | 46 | /* Adhoc mode; important thing is to use 2x cwmin. */ |
41 | qnum = sc->tx.hwq_map[WME_AC_BE]; | 47 | txq = sc->tx.txq_map[WME_AC_BE]; |
42 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); | 48 | ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be); |
43 | qi.tqi_aifs = qi_be.tqi_aifs; | 49 | qi.tqi_aifs = qi_be.tqi_aifs; |
44 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | 50 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; |
45 | qi.tqi_cwmax = qi_be.tqi_cwmax; | 51 | qi.tqi_cwmax = qi_be.tqi_cwmax; |
46 | } | 52 | } |
47 | 53 | ||
48 | if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { | 54 | if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { |
49 | ath_print(common, ATH_DBG_FATAL, | 55 | ath_err(common, |
50 | "Unable to update h/w beacon queue parameters\n"); | 56 | "Unable to update h/w beacon queue parameters\n"); |
51 | return 0; | 57 | return 0; |
52 | } else { | 58 | } else { |
53 | ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); | 59 | ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); |
@@ -57,8 +63,8 @@ int ath_beaconq_config(struct ath_softc *sc) | |||
57 | 63 | ||
58 | /* | 64 | /* |
59 | * Associates the beacon frame buffer with a transmit descriptor. Will set | 65 | * Associates the beacon frame buffer with a transmit descriptor. Will set |
60 | * up all required antenna switch parameters, rate codes, and channel flags. | 66 | * up rate codes, and channel flags. Beacons are always sent out at the |
61 | * Beacons are always sent out at the lowest rate, and are not retried. | 67 | * lowest rate, and are not retried. |
62 | */ | 68 | */ |
63 | static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | 69 | static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, |
64 | struct ath_buf *bf, int rateidx) | 70 | struct ath_buf *bf, int rateidx) |
@@ -68,20 +74,16 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
68 | struct ath_common *common = ath9k_hw_common(ah); | 74 | struct ath_common *common = ath9k_hw_common(ah); |
69 | struct ath_desc *ds; | 75 | struct ath_desc *ds; |
70 | struct ath9k_11n_rate_series series[4]; | 76 | struct ath9k_11n_rate_series series[4]; |
71 | int flags, antenna, ctsrate = 0, ctsduration = 0; | 77 | int flags, ctsrate = 0, ctsduration = 0; |
72 | struct ieee80211_supported_band *sband; | 78 | struct ieee80211_supported_band *sband; |
73 | u8 rate = 0; | 79 | u8 rate = 0; |
74 | 80 | ||
81 | ath9k_reset_beacon_status(sc); | ||
82 | |||
75 | ds = bf->bf_desc; | 83 | ds = bf->bf_desc; |
76 | flags = ATH9K_TXDESC_NOACK; | 84 | flags = ATH9K_TXDESC_NOACK; |
77 | 85 | ||
78 | ds->ds_link = 0; | 86 | ds->ds_link = 0; |
79 | /* | ||
80 | * Switch antenna every beacon. | ||
81 | * Should only switch every beacon period, not for every SWBA | ||
82 | * XXX assumes two antennae | ||
83 | */ | ||
84 | antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); | ||
85 | 87 | ||
86 | sband = &sc->sbands[common->hw->conf.channel->band]; | 88 | sband = &sc->sbands[common->hw->conf.channel->band]; |
87 | rate = sband->bitrates[rateidx].hw_value; | 89 | rate = sband->bitrates[rateidx].hw_value; |
@@ -103,17 +105,35 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
103 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); | 105 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); |
104 | series[0].Tries = 1; | 106 | series[0].Tries = 1; |
105 | series[0].Rate = rate; | 107 | series[0].Rate = rate; |
106 | series[0].ChSel = common->tx_chainmask; | 108 | series[0].ChSel = ath_txchainmask_reduction(sc, |
109 | common->tx_chainmask, series[0].Rate); | ||
107 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; | 110 | series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; |
108 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, | 111 | ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, |
109 | series, 4, 0); | 112 | series, 4, 0); |
110 | } | 113 | } |
111 | 114 | ||
115 | static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
116 | { | ||
117 | struct ath_softc *sc = hw->priv; | ||
118 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
119 | struct ath_tx_control txctl; | ||
120 | |||
121 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | ||
122 | txctl.txq = sc->beacon.cabq; | ||
123 | |||
124 | ath_dbg(common, ATH_DBG_XMIT, | ||
125 | "transmitting CABQ packet, skb: %p\n", skb); | ||
126 | |||
127 | if (ath_tx_start(hw, skb, &txctl) != 0) { | ||
128 | ath_dbg(common, ATH_DBG_XMIT, "CABQ TX failed\n"); | ||
129 | dev_kfree_skb_any(skb); | ||
130 | } | ||
131 | } | ||
132 | |||
112 | static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | 133 | static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, |
113 | struct ieee80211_vif *vif) | 134 | struct ieee80211_vif *vif) |
114 | { | 135 | { |
115 | struct ath_wiphy *aphy = hw->priv; | 136 | struct ath_softc *sc = hw->priv; |
116 | struct ath_softc *sc = aphy->sc; | ||
117 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 137 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
118 | struct ath_buf *bf; | 138 | struct ath_buf *bf; |
119 | struct ath_vif *avp; | 139 | struct ath_vif *avp; |
@@ -122,13 +142,12 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
122 | struct ieee80211_tx_info *info; | 142 | struct ieee80211_tx_info *info; |
123 | int cabq_depth; | 143 | int cabq_depth; |
124 | 144 | ||
125 | if (aphy->state != ATH_WIPHY_ACTIVE) | 145 | ath9k_reset_beacon_status(sc); |
126 | return NULL; | ||
127 | 146 | ||
128 | avp = (void *)vif->drv_priv; | 147 | avp = (void *)vif->drv_priv; |
129 | cabq = sc->beacon.cabq; | 148 | cabq = sc->beacon.cabq; |
130 | 149 | ||
131 | if (avp->av_bcbuf == NULL) | 150 | if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active) |
132 | return NULL; | 151 | return NULL; |
133 | 152 | ||
134 | /* Release the old beacon first */ | 153 | /* Release the old beacon first */ |
@@ -136,9 +155,10 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
136 | bf = avp->av_bcbuf; | 155 | bf = avp->av_bcbuf; |
137 | skb = bf->bf_mpdu; | 156 | skb = bf->bf_mpdu; |
138 | if (skb) { | 157 | if (skb) { |
139 | dma_unmap_single(sc->dev, bf->bf_dmacontext, | 158 | dma_unmap_single(sc->dev, bf->bf_buf_addr, |
140 | skb->len, DMA_TO_DEVICE); | 159 | skb->len, DMA_TO_DEVICE); |
141 | dev_kfree_skb_any(skb); | 160 | dev_kfree_skb_any(skb); |
161 | bf->bf_buf_addr = 0; | ||
142 | } | 162 | } |
143 | 163 | ||
144 | /* Get a new beacon from mac80211 */ | 164 | /* Get a new beacon from mac80211 */ |
@@ -162,14 +182,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
162 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | 182 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); |
163 | } | 183 | } |
164 | 184 | ||
165 | bf->bf_buf_addr = bf->bf_dmacontext = | 185 | bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, |
166 | dma_map_single(sc->dev, skb->data, | 186 | skb->len, DMA_TO_DEVICE); |
167 | skb->len, DMA_TO_DEVICE); | ||
168 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { | 187 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { |
169 | dev_kfree_skb_any(skb); | 188 | dev_kfree_skb_any(skb); |
170 | bf->bf_mpdu = NULL; | 189 | bf->bf_mpdu = NULL; |
171 | ath_print(common, ATH_DBG_FATAL, | 190 | bf->bf_buf_addr = 0; |
172 | "dma_mapping_error on beaconing\n"); | 191 | ath_err(common, "dma_mapping_error on beaconing\n"); |
173 | return NULL; | 192 | return NULL; |
174 | } | 193 | } |
175 | 194 | ||
@@ -189,8 +208,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
189 | 208 | ||
190 | if (skb && cabq_depth) { | 209 | if (skb && cabq_depth) { |
191 | if (sc->nvifs > 1) { | 210 | if (sc->nvifs > 1) { |
192 | ath_print(common, ATH_DBG_BEACON, | 211 | ath_dbg(common, ATH_DBG_BEACON, |
193 | "Flushing previous cabq traffic\n"); | 212 | "Flushing previous cabq traffic\n"); |
194 | ath_draintxq(sc, cabq, false); | 213 | ath_draintxq(sc, cabq, false); |
195 | } | 214 | } |
196 | } | 215 | } |
@@ -205,13 +224,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
205 | return bf; | 224 | return bf; |
206 | } | 225 | } |
207 | 226 | ||
208 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | 227 | int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif) |
209 | { | 228 | { |
210 | struct ath_softc *sc = aphy->sc; | ||
211 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 229 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
212 | struct ath_vif *avp; | 230 | struct ath_vif *avp; |
213 | struct ath_buf *bf; | 231 | struct ath_buf *bf; |
214 | struct sk_buff *skb; | 232 | struct sk_buff *skb; |
233 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | ||
215 | __le64 tstamp; | 234 | __le64 tstamp; |
216 | 235 | ||
217 | avp = (void *)vif->drv_priv; | 236 | avp = (void *)vif->drv_priv; |
@@ -224,9 +243,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
224 | struct ath_buf, list); | 243 | struct ath_buf, list); |
225 | list_del(&avp->av_bcbuf->list); | 244 | list_del(&avp->av_bcbuf->list); |
226 | 245 | ||
227 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || | 246 | if (ath9k_uses_beacons(vif->type)) { |
228 | sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC || | ||
229 | sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
230 | int slot; | 247 | int slot; |
231 | /* | 248 | /* |
232 | * Assign the vif to a beacon xmit slot. As | 249 | * Assign the vif to a beacon xmit slot. As |
@@ -236,6 +253,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
236 | for (slot = 0; slot < ATH_BCBUF; slot++) | 253 | for (slot = 0; slot < ATH_BCBUF; slot++) |
237 | if (sc->beacon.bslot[slot] == NULL) { | 254 | if (sc->beacon.bslot[slot] == NULL) { |
238 | avp->av_bslot = slot; | 255 | avp->av_bslot = slot; |
256 | avp->is_bslot_active = false; | ||
239 | 257 | ||
240 | /* NB: keep looking for a double slot */ | 258 | /* NB: keep looking for a double slot */ |
241 | if (slot == 0 || !sc->beacon.bslot[slot-1]) | 259 | if (slot == 0 || !sc->beacon.bslot[slot-1]) |
@@ -243,7 +261,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
243 | } | 261 | } |
244 | BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); | 262 | BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); |
245 | sc->beacon.bslot[avp->av_bslot] = vif; | 263 | sc->beacon.bslot[avp->av_bslot] = vif; |
246 | sc->beacon.bslot_aphy[avp->av_bslot] = aphy; | ||
247 | sc->nbcnvifs++; | 264 | sc->nbcnvifs++; |
248 | } | 265 | } |
249 | } | 266 | } |
@@ -252,27 +269,26 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
252 | bf = avp->av_bcbuf; | 269 | bf = avp->av_bcbuf; |
253 | if (bf->bf_mpdu != NULL) { | 270 | if (bf->bf_mpdu != NULL) { |
254 | skb = bf->bf_mpdu; | 271 | skb = bf->bf_mpdu; |
255 | dma_unmap_single(sc->dev, bf->bf_dmacontext, | 272 | dma_unmap_single(sc->dev, bf->bf_buf_addr, |
256 | skb->len, DMA_TO_DEVICE); | 273 | skb->len, DMA_TO_DEVICE); |
257 | dev_kfree_skb_any(skb); | 274 | dev_kfree_skb_any(skb); |
258 | bf->bf_mpdu = NULL; | 275 | bf->bf_mpdu = NULL; |
276 | bf->bf_buf_addr = 0; | ||
259 | } | 277 | } |
260 | 278 | ||
261 | /* NB: the beacon data buffer must be 32-bit aligned. */ | 279 | /* NB: the beacon data buffer must be 32-bit aligned. */ |
262 | skb = ieee80211_beacon_get(sc->hw, vif); | 280 | skb = ieee80211_beacon_get(sc->hw, vif); |
263 | if (skb == NULL) { | 281 | if (skb == NULL) |
264 | ath_print(common, ATH_DBG_BEACON, "cannot get skb\n"); | ||
265 | return -ENOMEM; | 282 | return -ENOMEM; |
266 | } | ||
267 | 283 | ||
268 | tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; | 284 | tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; |
269 | sc->beacon.bc_tstamp = le64_to_cpu(tstamp); | 285 | sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp); |
270 | /* Calculate a TSF adjustment factor required for staggered beacons. */ | 286 | /* Calculate a TSF adjustment factor required for staggered beacons. */ |
271 | if (avp->av_bslot > 0) { | 287 | if (avp->av_bslot > 0) { |
272 | u64 tsfadjust; | 288 | u64 tsfadjust; |
273 | int intval; | 289 | int intval; |
274 | 290 | ||
275 | intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; | 291 | intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; |
276 | 292 | ||
277 | /* | 293 | /* |
278 | * Calculate the TSF offset for this beacon slot, i.e., the | 294 | * Calculate the TSF offset for this beacon slot, i.e., the |
@@ -282,13 +298,12 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
282 | * adjustment. Other slots are adjusted to get the timestamp | 298 | * adjustment. Other slots are adjusted to get the timestamp |
283 | * close to the TBTT for the BSS. | 299 | * close to the TBTT for the BSS. |
284 | */ | 300 | */ |
285 | tsfadjust = intval * avp->av_bslot / ATH_BCBUF; | 301 | tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF; |
286 | avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); | 302 | avp->tsf_adjust = cpu_to_le64(tsfadjust); |
287 | 303 | ||
288 | ath_print(common, ATH_DBG_BEACON, | 304 | ath_dbg(common, ATH_DBG_BEACON, |
289 | "stagger beacons, bslot %d intval " | 305 | "stagger beacons, bslot %d intval %u tsfadjust %llu\n", |
290 | "%u tsfadjust %llu\n", | 306 | avp->av_bslot, intval, (unsigned long long)tsfadjust); |
291 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | ||
292 | 307 | ||
293 | ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = | 308 | ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = |
294 | avp->tsf_adjust; | 309 | avp->tsf_adjust; |
@@ -296,16 +311,16 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
296 | avp->tsf_adjust = cpu_to_le64(0); | 311 | avp->tsf_adjust = cpu_to_le64(0); |
297 | 312 | ||
298 | bf->bf_mpdu = skb; | 313 | bf->bf_mpdu = skb; |
299 | bf->bf_buf_addr = bf->bf_dmacontext = | 314 | bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, |
300 | dma_map_single(sc->dev, skb->data, | 315 | skb->len, DMA_TO_DEVICE); |
301 | skb->len, DMA_TO_DEVICE); | ||
302 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { | 316 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { |
303 | dev_kfree_skb_any(skb); | 317 | dev_kfree_skb_any(skb); |
304 | bf->bf_mpdu = NULL; | 318 | bf->bf_mpdu = NULL; |
305 | ath_print(common, ATH_DBG_FATAL, | 319 | bf->bf_buf_addr = 0; |
306 | "dma_mapping_error on beacon alloc\n"); | 320 | ath_err(common, "dma_mapping_error on beacon alloc\n"); |
307 | return -ENOMEM; | 321 | return -ENOMEM; |
308 | } | 322 | } |
323 | avp->is_bslot_active = true; | ||
309 | 324 | ||
310 | return 0; | 325 | return 0; |
311 | } | 326 | } |
@@ -315,19 +330,21 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) | |||
315 | if (avp->av_bcbuf != NULL) { | 330 | if (avp->av_bcbuf != NULL) { |
316 | struct ath_buf *bf; | 331 | struct ath_buf *bf; |
317 | 332 | ||
333 | avp->is_bslot_active = false; | ||
318 | if (avp->av_bslot != -1) { | 334 | if (avp->av_bslot != -1) { |
319 | sc->beacon.bslot[avp->av_bslot] = NULL; | 335 | sc->beacon.bslot[avp->av_bslot] = NULL; |
320 | sc->beacon.bslot_aphy[avp->av_bslot] = NULL; | ||
321 | sc->nbcnvifs--; | 336 | sc->nbcnvifs--; |
337 | avp->av_bslot = -1; | ||
322 | } | 338 | } |
323 | 339 | ||
324 | bf = avp->av_bcbuf; | 340 | bf = avp->av_bcbuf; |
325 | if (bf->bf_mpdu != NULL) { | 341 | if (bf->bf_mpdu != NULL) { |
326 | struct sk_buff *skb = bf->bf_mpdu; | 342 | struct sk_buff *skb = bf->bf_mpdu; |
327 | dma_unmap_single(sc->dev, bf->bf_dmacontext, | 343 | dma_unmap_single(sc->dev, bf->bf_buf_addr, |
328 | skb->len, DMA_TO_DEVICE); | 344 | skb->len, DMA_TO_DEVICE); |
329 | dev_kfree_skb_any(skb); | 345 | dev_kfree_skb_any(skb); |
330 | bf->bf_mpdu = NULL; | 346 | bf->bf_mpdu = NULL; |
347 | bf->bf_buf_addr = 0; | ||
331 | } | 348 | } |
332 | list_add_tail(&bf->list, &sc->beacon.bbuf); | 349 | list_add_tail(&bf->list, &sc->beacon.bbuf); |
333 | 350 | ||
@@ -338,15 +355,13 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) | |||
338 | void ath_beacon_tasklet(unsigned long data) | 355 | void ath_beacon_tasklet(unsigned long data) |
339 | { | 356 | { |
340 | struct ath_softc *sc = (struct ath_softc *)data; | 357 | struct ath_softc *sc = (struct ath_softc *)data; |
358 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | ||
341 | struct ath_hw *ah = sc->sc_ah; | 359 | struct ath_hw *ah = sc->sc_ah; |
342 | struct ath_common *common = ath9k_hw_common(ah); | 360 | struct ath_common *common = ath9k_hw_common(ah); |
343 | struct ath_buf *bf = NULL; | 361 | struct ath_buf *bf = NULL; |
344 | struct ieee80211_vif *vif; | 362 | struct ieee80211_vif *vif; |
345 | struct ath_wiphy *aphy; | ||
346 | int slot; | 363 | int slot; |
347 | u32 bfaddr, bc = 0, tsftu; | 364 | u32 bfaddr, bc = 0; |
348 | u64 tsf; | ||
349 | u16 intval; | ||
350 | 365 | ||
351 | /* | 366 | /* |
352 | * Check if the previous beacon has gone out. If | 367 | * Check if the previous beacon has gone out. If |
@@ -358,60 +373,65 @@ void ath_beacon_tasklet(unsigned long data) | |||
358 | if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { | 373 | if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { |
359 | sc->beacon.bmisscnt++; | 374 | sc->beacon.bmisscnt++; |
360 | 375 | ||
361 | if (sc->beacon.bmisscnt < BSTUCK_THRESH) { | 376 | if (sc->beacon.bmisscnt < BSTUCK_THRESH * sc->nbcnvifs) { |
362 | ath_print(common, ATH_DBG_BEACON, | 377 | ath_dbg(common, ATH_DBG_BSTUCK, |
363 | "missed %u consecutive beacons\n", | 378 | "missed %u consecutive beacons\n", |
364 | sc->beacon.bmisscnt); | 379 | sc->beacon.bmisscnt); |
380 | ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq); | ||
381 | if (sc->beacon.bmisscnt > 3) | ||
382 | ath9k_hw_bstuck_nfcal(ah); | ||
365 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { | 383 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { |
366 | ath_print(common, ATH_DBG_BEACON, | 384 | ath_dbg(common, ATH_DBG_BSTUCK, |
367 | "beacon is officially stuck\n"); | 385 | "beacon is officially stuck\n"); |
368 | sc->sc_flags |= SC_OP_TSF_RESET; | 386 | sc->sc_flags |= SC_OP_TSF_RESET; |
369 | ath_reset(sc, false); | 387 | ath_reset(sc, true); |
370 | } | 388 | } |
371 | 389 | ||
372 | return; | 390 | return; |
373 | } | 391 | } |
374 | 392 | ||
375 | if (sc->beacon.bmisscnt != 0) { | ||
376 | ath_print(common, ATH_DBG_BEACON, | ||
377 | "resume beacon xmit after %u misses\n", | ||
378 | sc->beacon.bmisscnt); | ||
379 | sc->beacon.bmisscnt = 0; | ||
380 | } | ||
381 | |||
382 | /* | 393 | /* |
383 | * Generate beacon frames. we are sending frames | 394 | * Generate beacon frames. we are sending frames |
384 | * staggered so calculate the slot for this frame based | 395 | * staggered so calculate the slot for this frame based |
385 | * on the tsf to safeguard against missing an swba. | 396 | * on the tsf to safeguard against missing an swba. |
386 | */ | 397 | */ |
387 | 398 | ||
388 | intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; | ||
389 | 399 | ||
390 | tsf = ath9k_hw_gettsf64(ah); | 400 | if (ah->opmode == NL80211_IFTYPE_AP) { |
391 | tsftu = TSF_TO_TU(tsf>>32, tsf); | 401 | u16 intval; |
392 | slot = ((tsftu % intval) * ATH_BCBUF) / intval; | 402 | u32 tsftu; |
393 | /* | 403 | u64 tsf; |
394 | * Reverse the slot order to get slot 0 on the TBTT offset that does | 404 | |
395 | * not require TSF adjustment and other slots adding | 405 | intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL; |
396 | * slot/ATH_BCBUF * beacon_int to timestamp. For example, with | 406 | tsf = ath9k_hw_gettsf64(ah); |
397 | * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. | 407 | tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); |
398 | * and slot 0 is at correct offset to TBTT. | 408 | tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); |
399 | */ | 409 | slot = (tsftu % (intval * ATH_BCBUF)) / intval; |
400 | slot = ATH_BCBUF - slot - 1; | 410 | vif = sc->beacon.bslot[slot]; |
401 | vif = sc->beacon.bslot[slot]; | 411 | |
402 | aphy = sc->beacon.bslot_aphy[slot]; | 412 | ath_dbg(common, ATH_DBG_BEACON, |
413 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", | ||
414 | slot, tsf, tsftu / ATH_BCBUF, intval, vif); | ||
415 | } else { | ||
416 | slot = 0; | ||
417 | vif = sc->beacon.bslot[slot]; | ||
418 | } | ||
403 | 419 | ||
404 | ath_print(common, ATH_DBG_BEACON, | ||
405 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", | ||
406 | slot, tsf, tsftu, intval, vif); | ||
407 | 420 | ||
408 | bfaddr = 0; | 421 | bfaddr = 0; |
409 | if (vif) { | 422 | if (vif) { |
410 | bf = ath_beacon_generate(aphy->hw, vif); | 423 | bf = ath_beacon_generate(sc->hw, vif); |
411 | if (bf != NULL) { | 424 | if (bf != NULL) { |
412 | bfaddr = bf->bf_daddr; | 425 | bfaddr = bf->bf_daddr; |
413 | bc = 1; | 426 | bc = 1; |
414 | } | 427 | } |
428 | |||
429 | if (sc->beacon.bmisscnt != 0) { | ||
430 | ath_dbg(common, ATH_DBG_BSTUCK, | ||
431 | "resume beacon xmit after %u misses\n", | ||
432 | sc->beacon.bmisscnt); | ||
433 | sc->beacon.bmisscnt = 0; | ||
434 | } | ||
415 | } | 435 | } |
416 | 436 | ||
417 | /* | 437 | /* |
@@ -439,16 +459,6 @@ void ath_beacon_tasklet(unsigned long data) | |||
439 | sc->beacon.updateslot = OK; | 459 | sc->beacon.updateslot = OK; |
440 | } | 460 | } |
441 | if (bfaddr != 0) { | 461 | if (bfaddr != 0) { |
442 | /* | ||
443 | * Stop any current dma and put the new frame(s) on the queue. | ||
444 | * This should never fail since we check above that no frames | ||
445 | * are still pending on the queue. | ||
446 | */ | ||
447 | if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { | ||
448 | ath_print(common, ATH_DBG_FATAL, | ||
449 | "beacon queue %u did not stop?\n", sc->beacon.beaconq); | ||
450 | } | ||
451 | |||
452 | /* NB: cabq traffic should already be queued and primed */ | 462 | /* NB: cabq traffic should already be queued and primed */ |
453 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); | 463 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); |
454 | ath9k_hw_txstart(ah, sc->beacon.beaconq); | 464 | ath9k_hw_txstart(ah, sc->beacon.beaconq); |
@@ -461,13 +471,17 @@ static void ath9k_beacon_init(struct ath_softc *sc, | |||
461 | u32 next_beacon, | 471 | u32 next_beacon, |
462 | u32 beacon_period) | 472 | u32 beacon_period) |
463 | { | 473 | { |
464 | if (beacon_period & ATH9K_BEACON_RESET_TSF) | 474 | if (sc->sc_flags & SC_OP_TSF_RESET) { |
465 | ath9k_ps_wakeup(sc); | 475 | ath9k_ps_wakeup(sc); |
476 | ath9k_hw_reset_tsf(sc->sc_ah); | ||
477 | } | ||
466 | 478 | ||
467 | ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); | 479 | ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period); |
468 | 480 | ||
469 | if (beacon_period & ATH9K_BEACON_RESET_TSF) | 481 | if (sc->sc_flags & SC_OP_TSF_RESET) { |
470 | ath9k_ps_restore(sc); | 482 | ath9k_ps_restore(sc); |
483 | sc->sc_flags &= ~SC_OP_TSF_RESET; | ||
484 | } | ||
471 | } | 485 | } |
472 | 486 | ||
473 | /* | 487 | /* |
@@ -482,32 +496,23 @@ static void ath_beacon_config_ap(struct ath_softc *sc, | |||
482 | u32 nexttbtt, intval; | 496 | u32 nexttbtt, intval; |
483 | 497 | ||
484 | /* NB: the beacon interval is kept internally in TU's */ | 498 | /* NB: the beacon interval is kept internally in TU's */ |
485 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; | 499 | intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); |
486 | intval /= ATH_BCBUF; /* for staggered beacons */ | 500 | intval /= ATH_BCBUF; /* for staggered beacons */ |
487 | nexttbtt = intval; | 501 | nexttbtt = intval; |
488 | 502 | ||
489 | if (sc->sc_flags & SC_OP_TSF_RESET) | ||
490 | intval |= ATH9K_BEACON_RESET_TSF; | ||
491 | |||
492 | /* | 503 | /* |
493 | * In AP mode we enable the beacon timers and SWBA interrupts to | 504 | * In AP mode we enable the beacon timers and SWBA interrupts to |
494 | * prepare beacon frames. | 505 | * prepare beacon frames. |
495 | */ | 506 | */ |
496 | intval |= ATH9K_BEACON_ENA; | ||
497 | ah->imask |= ATH9K_INT_SWBA; | 507 | ah->imask |= ATH9K_INT_SWBA; |
498 | ath_beaconq_config(sc); | 508 | ath_beaconq_config(sc); |
499 | 509 | ||
500 | /* Set the computed AP beacon timers */ | 510 | /* Set the computed AP beacon timers */ |
501 | 511 | ||
502 | ath9k_hw_set_interrupts(ah, 0); | 512 | ath9k_hw_disable_interrupts(ah); |
503 | ath9k_beacon_init(sc, nexttbtt, intval); | 513 | ath9k_beacon_init(sc, nexttbtt, intval); |
504 | sc->beacon.bmisscnt = 0; | 514 | sc->beacon.bmisscnt = 0; |
505 | ath9k_hw_set_interrupts(ah, ah->imask); | 515 | ath9k_hw_set_interrupts(ah, ah->imask); |
506 | |||
507 | /* Clear the reset TSF flag, so that subsequent beacon updation | ||
508 | will not reset the HW TSF. */ | ||
509 | |||
510 | sc->sc_flags &= ~SC_OP_TSF_RESET; | ||
511 | } | 516 | } |
512 | 517 | ||
513 | /* | 518 | /* |
@@ -532,8 +537,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
532 | 537 | ||
533 | /* No need to configure beacon if we are not associated */ | 538 | /* No need to configure beacon if we are not associated */ |
534 | if (!common->curaid) { | 539 | if (!common->curaid) { |
535 | ath_print(common, ATH_DBG_BEACON, | 540 | ath_dbg(common, ATH_DBG_BEACON, |
536 | "STA is not yet associated..skipping beacon config\n"); | 541 | "STA is not yet associated..skipping beacon config\n"); |
537 | return; | 542 | return; |
538 | } | 543 | } |
539 | 544 | ||
@@ -545,8 +550,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
545 | * last beacon we received (which may be none). | 550 | * last beacon we received (which may be none). |
546 | */ | 551 | */ |
547 | dtimperiod = conf->dtim_period; | 552 | dtimperiod = conf->dtim_period; |
548 | if (dtimperiod <= 0) /* NB: 0 if not known */ | ||
549 | dtimperiod = 1; | ||
550 | dtimcount = conf->dtim_count; | 553 | dtimcount = conf->dtim_count; |
551 | if (dtimcount >= dtimperiod) /* NB: sanity check */ | 554 | if (dtimcount >= dtimperiod) /* NB: sanity check */ |
552 | dtimcount = 0; | 555 | dtimcount = 0; |
@@ -554,8 +557,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
554 | cfpcount = 0; | 557 | cfpcount = 0; |
555 | 558 | ||
556 | sleepduration = conf->listen_interval * intval; | 559 | sleepduration = conf->listen_interval * intval; |
557 | if (sleepduration <= 0) | ||
558 | sleepduration = intval; | ||
559 | 560 | ||
560 | /* | 561 | /* |
561 | * Pull nexttbtt forward to reflect the current | 562 | * Pull nexttbtt forward to reflect the current |
@@ -626,89 +627,135 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
626 | /* TSF out of range threshold fixed at 1 second */ | 627 | /* TSF out of range threshold fixed at 1 second */ |
627 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | 628 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; |
628 | 629 | ||
629 | ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); | 630 | ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); |
630 | ath_print(common, ATH_DBG_BEACON, | 631 | ath_dbg(common, ATH_DBG_BEACON, |
631 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", | 632 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", |
632 | bs.bs_bmissthreshold, bs.bs_sleepduration, | 633 | bs.bs_bmissthreshold, bs.bs_sleepduration, |
633 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | 634 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); |
634 | 635 | ||
635 | /* Set the computed STA beacon timers */ | 636 | /* Set the computed STA beacon timers */ |
636 | 637 | ||
637 | ath9k_hw_set_interrupts(ah, 0); | 638 | ath9k_hw_disable_interrupts(ah); |
638 | ath9k_hw_set_sta_beacon_timers(ah, &bs); | 639 | ath9k_hw_set_sta_beacon_timers(ah, &bs); |
639 | ah->imask |= ATH9K_INT_BMISS; | 640 | ah->imask |= ATH9K_INT_BMISS; |
640 | ath9k_hw_set_interrupts(ah, ah->imask); | 641 | |
642 | /* | ||
643 | * If the beacon config is called beacause of TSFOOR, | ||
644 | * Interrupts will be enabled back at the end of ath9k_tasklet | ||
645 | */ | ||
646 | if (!(sc->ps_flags & PS_TSFOOR_SYNC)) | ||
647 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
641 | } | 648 | } |
642 | 649 | ||
643 | static void ath_beacon_config_adhoc(struct ath_softc *sc, | 650 | static void ath_beacon_config_adhoc(struct ath_softc *sc, |
644 | struct ath_beacon_config *conf, | 651 | struct ath_beacon_config *conf) |
645 | struct ieee80211_vif *vif) | ||
646 | { | 652 | { |
647 | struct ath_hw *ah = sc->sc_ah; | 653 | struct ath_hw *ah = sc->sc_ah; |
648 | struct ath_common *common = ath9k_hw_common(ah); | 654 | struct ath_common *common = ath9k_hw_common(ah); |
649 | u64 tsf; | 655 | u32 tsf, delta, intval, nexttbtt; |
650 | u32 tsftu, intval, nexttbtt; | ||
651 | |||
652 | intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; | ||
653 | |||
654 | 656 | ||
655 | /* Pull nexttbtt forward to reflect the current TSF */ | 657 | ath9k_reset_beacon_status(sc); |
656 | 658 | ||
657 | nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); | 659 | tsf = ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE); |
658 | if (nexttbtt == 0) | 660 | intval = TU_TO_USEC(conf->beacon_interval & ATH9K_BEACON_PERIOD); |
659 | nexttbtt = intval; | ||
660 | else if (intval) | ||
661 | nexttbtt = roundup(nexttbtt, intval); | ||
662 | 661 | ||
663 | tsf = ath9k_hw_gettsf64(ah); | 662 | if (!sc->beacon.bc_tstamp) |
664 | tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; | 663 | nexttbtt = tsf + intval; |
665 | do { | 664 | else { |
666 | nexttbtt += intval; | 665 | if (tsf > sc->beacon.bc_tstamp) |
667 | } while (nexttbtt < tsftu); | 666 | delta = (tsf - sc->beacon.bc_tstamp); |
667 | else | ||
668 | delta = (tsf + 1 + (~0U - sc->beacon.bc_tstamp)); | ||
669 | nexttbtt = tsf + intval - (delta % intval); | ||
670 | } | ||
668 | 671 | ||
669 | ath_print(common, ATH_DBG_BEACON, | 672 | ath_dbg(common, ATH_DBG_BEACON, |
670 | "IBSS nexttbtt %u intval %u (%u)\n", | 673 | "IBSS nexttbtt %u intval %u (%u)\n", |
671 | nexttbtt, intval, conf->beacon_interval); | 674 | nexttbtt, intval, conf->beacon_interval); |
672 | 675 | ||
673 | /* | 676 | /* |
674 | * In IBSS mode enable the beacon timers but only enable SWBA interrupts | 677 | * In IBSS mode enable the beacon timers but only enable SWBA interrupts |
675 | * if we need to manually prepare beacon frames. Otherwise we use a | 678 | * if we need to manually prepare beacon frames. Otherwise we use a |
676 | * self-linked tx descriptor and let the hardware deal with things. | 679 | * self-linked tx descriptor and let the hardware deal with things. |
677 | */ | 680 | */ |
678 | intval |= ATH9K_BEACON_ENA; | ||
679 | ah->imask |= ATH9K_INT_SWBA; | 681 | ah->imask |= ATH9K_INT_SWBA; |
680 | 682 | ||
681 | ath_beaconq_config(sc); | 683 | ath_beaconq_config(sc); |
682 | 684 | ||
683 | /* Set the computed ADHOC beacon timers */ | 685 | /* Set the computed ADHOC beacon timers */ |
684 | 686 | ||
685 | ath9k_hw_set_interrupts(ah, 0); | 687 | ath9k_hw_disable_interrupts(ah); |
686 | ath9k_beacon_init(sc, nexttbtt, intval); | 688 | ath9k_beacon_init(sc, nexttbtt, intval); |
687 | sc->beacon.bmisscnt = 0; | 689 | sc->beacon.bmisscnt = 0; |
688 | ath9k_hw_set_interrupts(ah, ah->imask); | 690 | /* |
691 | * If the beacon config is called beacause of TSFOOR, | ||
692 | * Interrupts will be enabled back at the end of ath9k_tasklet | ||
693 | */ | ||
694 | if (!(sc->ps_flags & PS_TSFOOR_SYNC)) | ||
695 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
689 | } | 696 | } |
690 | 697 | ||
691 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | 698 | static bool ath9k_allow_beacon_config(struct ath_softc *sc, |
699 | struct ieee80211_vif *vif) | ||
692 | { | 700 | { |
693 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | 701 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; |
694 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 702 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
695 | enum nl80211_iftype iftype; | 703 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
704 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
696 | 705 | ||
697 | /* Setup the beacon configuration parameters */ | 706 | /* |
698 | if (vif) { | 707 | * Can not have different beacon interval on multiple |
699 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 708 | * AP interface case |
709 | */ | ||
710 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && | ||
711 | (sc->nbcnvifs > 1) && | ||
712 | (vif->type == NL80211_IFTYPE_AP) && | ||
713 | (cur_conf->beacon_interval != bss_conf->beacon_int)) { | ||
714 | ath_dbg(common, ATH_DBG_CONFIG, | ||
715 | "Changing beacon interval of multiple \ | ||
716 | AP interfaces !\n"); | ||
717 | return false; | ||
718 | } | ||
719 | /* | ||
720 | * Can not configure station vif's beacon config | ||
721 | * while on AP opmode | ||
722 | */ | ||
723 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) && | ||
724 | (vif->type != NL80211_IFTYPE_AP)) { | ||
725 | ath_dbg(common, ATH_DBG_CONFIG, | ||
726 | "STA vif's beacon not allowed on AP mode\n"); | ||
727 | return false; | ||
728 | } | ||
729 | /* | ||
730 | * Do not allow beacon config if HW was already configured | ||
731 | * with another STA vif | ||
732 | */ | ||
733 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && | ||
734 | (vif->type == NL80211_IFTYPE_STATION) && | ||
735 | (sc->sc_flags & SC_OP_BEACONS) && | ||
736 | !avp->primary_sta_vif) { | ||
737 | ath_dbg(common, ATH_DBG_CONFIG, | ||
738 | "Beacon already configured for a station interface\n"); | ||
739 | return false; | ||
740 | } | ||
741 | return true; | ||
742 | } | ||
700 | 743 | ||
701 | iftype = vif->type; | 744 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) |
745 | { | ||
746 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | ||
747 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
702 | 748 | ||
703 | cur_conf->beacon_interval = bss_conf->beacon_int; | 749 | if (!ath9k_allow_beacon_config(sc, vif)) |
704 | cur_conf->dtim_period = bss_conf->dtim_period; | 750 | return; |
705 | cur_conf->listen_interval = 1; | 751 | |
706 | cur_conf->dtim_count = 1; | 752 | /* Setup the beacon configuration parameters */ |
707 | cur_conf->bmiss_timeout = | 753 | cur_conf->beacon_interval = bss_conf->beacon_int; |
708 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; | 754 | cur_conf->dtim_period = bss_conf->dtim_period; |
709 | } else { | 755 | cur_conf->listen_interval = 1; |
710 | iftype = sc->sc_ah->opmode; | 756 | cur_conf->dtim_count = 1; |
711 | } | 757 | cur_conf->bmiss_timeout = |
758 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; | ||
712 | 759 | ||
713 | /* | 760 | /* |
714 | * It looks like mac80211 may end up using beacon interval of zero in | 761 | * It looks like mac80211 may end up using beacon interval of zero in |
@@ -719,22 +766,80 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
719 | if (cur_conf->beacon_interval == 0) | 766 | if (cur_conf->beacon_interval == 0) |
720 | cur_conf->beacon_interval = 100; | 767 | cur_conf->beacon_interval = 100; |
721 | 768 | ||
722 | switch (iftype) { | 769 | /* |
770 | * We don't parse dtim period from mac80211 during the driver | ||
771 | * initialization as it breaks association with hidden-ssid | ||
772 | * AP and it causes latency in roaming | ||
773 | */ | ||
774 | if (cur_conf->dtim_period == 0) | ||
775 | cur_conf->dtim_period = 1; | ||
776 | |||
777 | ath_set_beacon(sc); | ||
778 | } | ||
779 | |||
780 | static bool ath_has_valid_bslot(struct ath_softc *sc) | ||
781 | { | ||
782 | struct ath_vif *avp; | ||
783 | int slot; | ||
784 | bool found = false; | ||
785 | |||
786 | for (slot = 0; slot < ATH_BCBUF; slot++) { | ||
787 | if (sc->beacon.bslot[slot]) { | ||
788 | avp = (void *)sc->beacon.bslot[slot]->drv_priv; | ||
789 | if (avp->is_bslot_active) { | ||
790 | found = true; | ||
791 | break; | ||
792 | } | ||
793 | } | ||
794 | } | ||
795 | return found; | ||
796 | } | ||
797 | |||
798 | |||
799 | void ath_set_beacon(struct ath_softc *sc) | ||
800 | { | ||
801 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
802 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | ||
803 | |||
804 | switch (sc->sc_ah->opmode) { | ||
723 | case NL80211_IFTYPE_AP: | 805 | case NL80211_IFTYPE_AP: |
724 | ath_beacon_config_ap(sc, cur_conf); | 806 | if (ath_has_valid_bslot(sc)) |
807 | ath_beacon_config_ap(sc, cur_conf); | ||
725 | break; | 808 | break; |
726 | case NL80211_IFTYPE_ADHOC: | 809 | case NL80211_IFTYPE_ADHOC: |
727 | case NL80211_IFTYPE_MESH_POINT: | 810 | case NL80211_IFTYPE_MESH_POINT: |
728 | ath_beacon_config_adhoc(sc, cur_conf, vif); | 811 | ath_beacon_config_adhoc(sc, cur_conf); |
729 | break; | 812 | break; |
730 | case NL80211_IFTYPE_STATION: | 813 | case NL80211_IFTYPE_STATION: |
731 | ath_beacon_config_sta(sc, cur_conf); | 814 | ath_beacon_config_sta(sc, cur_conf); |
732 | break; | 815 | break; |
733 | default: | 816 | default: |
734 | ath_print(common, ATH_DBG_CONFIG, | 817 | ath_dbg(common, ATH_DBG_CONFIG, |
735 | "Unsupported beaconing mode\n"); | 818 | "Unsupported beaconing mode\n"); |
736 | return; | 819 | return; |
737 | } | 820 | } |
738 | 821 | ||
739 | sc->sc_flags |= SC_OP_BEACONS; | 822 | sc->sc_flags |= SC_OP_BEACONS; |
740 | } | 823 | } |
824 | |||
825 | void ath9k_set_beaconing_status(struct ath_softc *sc, bool status) | ||
826 | { | ||
827 | struct ath_hw *ah = sc->sc_ah; | ||
828 | |||
829 | if (!ath_has_valid_bslot(sc)) | ||
830 | return; | ||
831 | |||
832 | ath9k_ps_wakeup(sc); | ||
833 | if (status) { | ||
834 | /* Re-enable beaconing */ | ||
835 | ah->imask |= ATH9K_INT_SWBA; | ||
836 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
837 | } else { | ||
838 | /* Disable SWBA interrupt */ | ||
839 | ah->imask &= ~ATH9K_INT_SWBA; | ||
840 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
841 | tasklet_kill(&sc->bcon_tasklet); | ||
842 | ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq); | ||
843 | } | ||
844 | ath9k_ps_restore(sc); | ||
845 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index fb4ac15f3b93..41ce0b139886 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2009 Atheros Communications Inc. | 2 | * Copyright (c) 2009-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -35,29 +35,6 @@ struct ath_btcoex_config { | |||
35 | bool bt_hold_rx_clear; | 35 | bool bt_hold_rx_clear; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static const u16 ath_subsysid_tbl[] = { | ||
39 | AR9280_COEX2WIRE_SUBSYSID, | ||
40 | AT9285_COEX3WIRE_SA_SUBSYSID, | ||
41 | AT9285_COEX3WIRE_DA_SUBSYSID | ||
42 | }; | ||
43 | |||
44 | /* | ||
45 | * Checks the subsystem id of the device to see if it | ||
46 | * supports btcoex | ||
47 | */ | ||
48 | bool ath9k_hw_btcoex_supported(struct ath_hw *ah) | ||
49 | { | ||
50 | int i; | ||
51 | |||
52 | if (!ah->hw_version.subsysid) | ||
53 | return false; | ||
54 | |||
55 | for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++) | ||
56 | if (ah->hw_version.subsysid == ath_subsysid_tbl[i]) | ||
57 | return true; | ||
58 | |||
59 | return false; | ||
60 | } | ||
61 | 38 | ||
62 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) | 39 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) |
63 | { | 40 | { |
@@ -74,6 +51,10 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) | |||
74 | .bt_hold_rx_clear = true, | 51 | .bt_hold_rx_clear = true, |
75 | }; | 52 | }; |
76 | u32 i; | 53 | u32 i; |
54 | bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity; | ||
55 | |||
56 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
57 | rxclear_polarity = !ath_bt_config.bt_rxclear_polarity; | ||
77 | 58 | ||
78 | btcoex_hw->bt_coex_mode = | 59 | btcoex_hw->bt_coex_mode = |
79 | (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) | | 60 | (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) | |
@@ -82,7 +63,7 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) | |||
82 | SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | | 63 | SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | |
83 | SM(ath_bt_config.bt_mode, AR_BT_MODE) | | 64 | SM(ath_bt_config.bt_mode, AR_BT_MODE) | |
84 | SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | | 65 | SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | |
85 | SM(ath_bt_config.bt_rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | | 66 | SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | |
86 | SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | | 67 | SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | |
87 | SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | | 68 | SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | |
88 | SM(qnum, AR_BT_QCU_THRESH); | 69 | SM(qnum, AR_BT_QCU_THRESH); |
@@ -165,18 +146,39 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, | |||
165 | } | 146 | } |
166 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); | 147 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); |
167 | 148 | ||
149 | |||
168 | static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) | 150 | static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) |
169 | { | 151 | { |
170 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | 152 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
153 | u32 val; | ||
171 | 154 | ||
172 | /* | 155 | /* |
173 | * Program coex mode and weight registers to | 156 | * Program coex mode and weight registers to |
174 | * enable coex 3-wire | 157 | * enable coex 3-wire |
175 | */ | 158 | */ |
176 | REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode); | 159 | REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_hw->bt_coex_mode); |
177 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); | ||
178 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); | 160 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); |
179 | 161 | ||
162 | |||
163 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
164 | REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, ah->bt_coex_wlan_weight[0]); | ||
165 | REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, ah->bt_coex_wlan_weight[1]); | ||
166 | REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, ah->bt_coex_bt_weight[0]); | ||
167 | REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, ah->bt_coex_bt_weight[1]); | ||
168 | REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, ah->bt_coex_bt_weight[2]); | ||
169 | REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, ah->bt_coex_bt_weight[3]); | ||
170 | |||
171 | } else | ||
172 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); | ||
173 | |||
174 | |||
175 | |||
176 | if (AR_SREV_9271(ah)) { | ||
177 | val = REG_READ(ah, 0x50040); | ||
178 | val &= 0xFFFFFEFF; | ||
179 | REG_WRITE(ah, 0x50040, val); | ||
180 | } | ||
181 | |||
180 | REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); | 182 | REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); |
181 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); | 183 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); |
182 | 184 | ||
@@ -218,10 +220,86 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) | |||
218 | 220 | ||
219 | if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) { | 221 | if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) { |
220 | REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); | 222 | REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); |
221 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); | ||
222 | REG_WRITE(ah, AR_BT_COEX_MODE2, 0); | 223 | REG_WRITE(ah, AR_BT_COEX_MODE2, 0); |
224 | |||
225 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
226 | REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, 0); | ||
227 | REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS1, 0); | ||
228 | REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS0, 0); | ||
229 | REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS1, 0); | ||
230 | REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS2, 0); | ||
231 | REG_WRITE(ah, AR_BT_COEX_BT_WEIGHTS3, 0); | ||
232 | } else | ||
233 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); | ||
234 | |||
223 | } | 235 | } |
224 | 236 | ||
225 | ah->btcoex_hw.enabled = false; | 237 | ah->btcoex_hw.enabled = false; |
226 | } | 238 | } |
227 | EXPORT_SYMBOL(ath9k_hw_btcoex_disable); | 239 | EXPORT_SYMBOL(ath9k_hw_btcoex_disable); |
240 | |||
241 | static void ar9003_btcoex_bt_stomp(struct ath_hw *ah, | ||
242 | enum ath_stomp_type stomp_type) | ||
243 | { | ||
244 | ah->bt_coex_bt_weight[0] = AR9300_BT_WGHT; | ||
245 | ah->bt_coex_bt_weight[1] = AR9300_BT_WGHT; | ||
246 | ah->bt_coex_bt_weight[2] = AR9300_BT_WGHT; | ||
247 | ah->bt_coex_bt_weight[3] = AR9300_BT_WGHT; | ||
248 | |||
249 | |||
250 | switch (stomp_type) { | ||
251 | case ATH_BTCOEX_STOMP_ALL: | ||
252 | ah->bt_coex_wlan_weight[0] = AR9300_STOMP_ALL_WLAN_WGHT0; | ||
253 | ah->bt_coex_wlan_weight[1] = AR9300_STOMP_ALL_WLAN_WGHT1; | ||
254 | break; | ||
255 | case ATH_BTCOEX_STOMP_LOW: | ||
256 | ah->bt_coex_wlan_weight[0] = AR9300_STOMP_LOW_WLAN_WGHT0; | ||
257 | ah->bt_coex_wlan_weight[1] = AR9300_STOMP_LOW_WLAN_WGHT1; | ||
258 | break; | ||
259 | case ATH_BTCOEX_STOMP_NONE: | ||
260 | ah->bt_coex_wlan_weight[0] = AR9300_STOMP_NONE_WLAN_WGHT0; | ||
261 | ah->bt_coex_wlan_weight[1] = AR9300_STOMP_NONE_WLAN_WGHT1; | ||
262 | break; | ||
263 | |||
264 | default: | ||
265 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
266 | "Invalid Stomptype\n"); | ||
267 | break; | ||
268 | } | ||
269 | |||
270 | ath9k_hw_btcoex_enable(ah); | ||
271 | } | ||
272 | |||
273 | /* | ||
274 | * Configures appropriate weight based on stomp type. | ||
275 | */ | ||
276 | void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, | ||
277 | enum ath_stomp_type stomp_type) | ||
278 | { | ||
279 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
280 | ar9003_btcoex_bt_stomp(ah, stomp_type); | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | switch (stomp_type) { | ||
285 | case ATH_BTCOEX_STOMP_ALL: | ||
286 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
287 | AR_STOMP_ALL_WLAN_WGHT); | ||
288 | break; | ||
289 | case ATH_BTCOEX_STOMP_LOW: | ||
290 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
291 | AR_STOMP_LOW_WLAN_WGHT); | ||
292 | break; | ||
293 | case ATH_BTCOEX_STOMP_NONE: | ||
294 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
295 | AR_STOMP_NONE_WLAN_WGHT); | ||
296 | break; | ||
297 | default: | ||
298 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
299 | "Invalid Stomptype\n"); | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | ath9k_hw_btcoex_enable(ah); | ||
304 | } | ||
305 | EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp); | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 1ee5a15ccbb1..234f77689b14 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2009 Atheros Communications Inc. | 2 | * Copyright (c) 2009-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -19,9 +19,13 @@ | |||
19 | 19 | ||
20 | #include "hw.h" | 20 | #include "hw.h" |
21 | 21 | ||
22 | #define ATH_WLANACTIVE_GPIO 5 | 22 | #define ATH_WLANACTIVE_GPIO_9280 5 |
23 | #define ATH_BTACTIVE_GPIO 6 | 23 | #define ATH_BTACTIVE_GPIO_9280 6 |
24 | #define ATH_BTPRIORITY_GPIO 7 | 24 | #define ATH_BTPRIORITY_GPIO_9285 7 |
25 | |||
26 | #define ATH_WLANACTIVE_GPIO_9300 5 | ||
27 | #define ATH_BTACTIVE_GPIO_9300 4 | ||
28 | #define ATH_BTPRIORITY_GPIO_9300 8 | ||
25 | 29 | ||
26 | #define ATH_BTCOEX_DEF_BT_PERIOD 45 | 30 | #define ATH_BTCOEX_DEF_BT_PERIOD 45 |
27 | #define ATH_BTCOEX_DEF_DUTY_CYCLE 55 | 31 | #define ATH_BTCOEX_DEF_DUTY_CYCLE 55 |
@@ -32,6 +36,14 @@ | |||
32 | #define ATH_BT_CNT_THRESHOLD 3 | 36 | #define ATH_BT_CNT_THRESHOLD 3 |
33 | #define ATH_BT_CNT_SCAN_THRESHOLD 15 | 37 | #define ATH_BT_CNT_SCAN_THRESHOLD 15 |
34 | 38 | ||
39 | /* Defines the BT AR_BT_COEX_WGHT used */ | ||
40 | enum ath_stomp_type { | ||
41 | ATH_BTCOEX_NO_STOMP, | ||
42 | ATH_BTCOEX_STOMP_ALL, | ||
43 | ATH_BTCOEX_STOMP_LOW, | ||
44 | ATH_BTCOEX_STOMP_NONE | ||
45 | }; | ||
46 | |||
35 | enum ath_btcoex_scheme { | 47 | enum ath_btcoex_scheme { |
36 | ATH_BTCOEX_CFG_NONE, | 48 | ATH_BTCOEX_CFG_NONE, |
37 | ATH_BTCOEX_CFG_2WIRE, | 49 | ATH_BTCOEX_CFG_2WIRE, |
@@ -49,7 +61,6 @@ struct ath_btcoex_hw { | |||
49 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ | 61 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ |
50 | }; | 62 | }; |
51 | 63 | ||
52 | bool ath9k_hw_btcoex_supported(struct ath_hw *ah); | ||
53 | void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); | 64 | void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); |
54 | void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah); | 65 | void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah); |
55 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); | 66 | void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); |
@@ -58,5 +69,7 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, | |||
58 | u32 wlan_weight); | 69 | u32 wlan_weight); |
59 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); | 70 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); |
60 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); | 71 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); |
72 | void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, | ||
73 | enum ath_stomp_type stomp_type); | ||
61 | 74 | ||
62 | #endif | 75 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 45208690c0ec..a1250c586e40 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -19,8 +19,7 @@ | |||
19 | 19 | ||
20 | /* Common calibration code */ | 20 | /* Common calibration code */ |
21 | 21 | ||
22 | /* We can tune this as we go by monitoring really low values */ | 22 | #define ATH9K_NF_TOO_HIGH -60 |
23 | #define ATH9K_NF_TOO_LOW -60 | ||
24 | 23 | ||
25 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | 24 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) |
26 | { | 25 | { |
@@ -45,12 +44,46 @@ static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | |||
45 | return nfval; | 44 | return nfval; |
46 | } | 45 | } |
47 | 46 | ||
48 | static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | 47 | static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah, |
48 | struct ath9k_channel *chan) | ||
49 | { | ||
50 | struct ath_nf_limits *limit; | ||
51 | |||
52 | if (!chan || IS_CHAN_2GHZ(chan)) | ||
53 | limit = &ah->nf_2g; | ||
54 | else | ||
55 | limit = &ah->nf_5g; | ||
56 | |||
57 | return limit; | ||
58 | } | ||
59 | |||
60 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | ||
61 | struct ath9k_channel *chan) | ||
62 | { | ||
63 | return ath9k_hw_get_nf_limits(ah, chan)->nominal; | ||
64 | } | ||
65 | |||
66 | |||
67 | static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, | ||
68 | struct ath9k_hw_cal_data *cal, | ||
49 | int16_t *nfarray) | 69 | int16_t *nfarray) |
50 | { | 70 | { |
71 | struct ath_common *common = ath9k_hw_common(ah); | ||
72 | struct ieee80211_conf *conf = &common->hw->conf; | ||
73 | struct ath_nf_limits *limit; | ||
74 | struct ath9k_nfcal_hist *h; | ||
75 | bool high_nf_mid = false; | ||
76 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | ||
51 | int i; | 77 | int i; |
52 | 78 | ||
79 | h = cal->nfCalHist; | ||
80 | limit = ath9k_hw_get_nf_limits(ah, ah->curchan); | ||
81 | |||
53 | for (i = 0; i < NUM_NF_READINGS; i++) { | 82 | for (i = 0; i < NUM_NF_READINGS; i++) { |
83 | if (!(chainmask & (1 << i)) || | ||
84 | ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) | ||
85 | continue; | ||
86 | |||
54 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; | 87 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; |
55 | 88 | ||
56 | if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) | 89 | if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) |
@@ -63,7 +96,39 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | |||
63 | h[i].privNF = | 96 | h[i].privNF = |
64 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); | 97 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); |
65 | } | 98 | } |
99 | |||
100 | if (!h[i].privNF) | ||
101 | continue; | ||
102 | |||
103 | if (h[i].privNF > limit->max) { | ||
104 | high_nf_mid = true; | ||
105 | |||
106 | ath_dbg(common, ATH_DBG_CALIBRATE, | ||
107 | "NFmid[%d] (%d) > MAX (%d), %s\n", | ||
108 | i, h[i].privNF, limit->max, | ||
109 | (cal->nfcal_interference ? | ||
110 | "not corrected (due to interference)" : | ||
111 | "correcting to MAX")); | ||
112 | |||
113 | /* | ||
114 | * Normally we limit the average noise floor by the | ||
115 | * hardware specific maximum here. However if we have | ||
116 | * encountered stuck beacons because of interference, | ||
117 | * we bypass this limit here in order to better deal | ||
118 | * with our environment. | ||
119 | */ | ||
120 | if (!cal->nfcal_interference) | ||
121 | h[i].privNF = limit->max; | ||
122 | } | ||
66 | } | 123 | } |
124 | |||
125 | /* | ||
126 | * If the noise floor seems normal for all chains, assume that | ||
127 | * there is no significant interference in the environment anymore. | ||
128 | * Re-enable the enforcement of the NF maximum again. | ||
129 | */ | ||
130 | if (!high_nf_mid) | ||
131 | cal->nfcal_interference = false; | ||
67 | } | 132 | } |
68 | 133 | ||
69 | static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, | 134 | static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, |
@@ -104,19 +169,6 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah, | |||
104 | ah->cal_samples = 0; | 169 | ah->cal_samples = 0; |
105 | } | 170 | } |
106 | 171 | ||
107 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | ||
108 | struct ath9k_channel *chan) | ||
109 | { | ||
110 | struct ath_nf_limits *limit; | ||
111 | |||
112 | if (!chan || IS_CHAN_2GHZ(chan)) | ||
113 | limit = &ah->nf_2g; | ||
114 | else | ||
115 | limit = &ah->nf_5g; | ||
116 | |||
117 | return limit->nominal; | ||
118 | } | ||
119 | |||
120 | /* This is done for the currently configured channel */ | 172 | /* This is done for the currently configured channel */ |
121 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | 173 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
122 | { | 174 | { |
@@ -134,18 +186,18 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | |||
134 | return true; | 186 | return true; |
135 | 187 | ||
136 | if (currCal->calState != CAL_DONE) { | 188 | if (currCal->calState != CAL_DONE) { |
137 | ath_print(common, ATH_DBG_CALIBRATE, | 189 | ath_dbg(common, ATH_DBG_CALIBRATE, |
138 | "Calibration state incorrect, %d\n", | 190 | "Calibration state incorrect, %d\n", |
139 | currCal->calState); | 191 | currCal->calState); |
140 | return true; | 192 | return true; |
141 | } | 193 | } |
142 | 194 | ||
143 | if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) | 195 | if (!(ah->supp_cals & currCal->calData->calType)) |
144 | return true; | 196 | return true; |
145 | 197 | ||
146 | ath_print(common, ATH_DBG_CALIBRATE, | 198 | ath_dbg(common, ATH_DBG_CALIBRATE, |
147 | "Resetting Cal %d state for channel %u\n", | 199 | "Resetting Cal %d state for channel %u\n", |
148 | currCal->calData->calType, conf->channel->center_freq); | 200 | currCal->calData->calType, conf->channel->center_freq); |
149 | 201 | ||
150 | ah->caldata->CalValid &= ~currCal->calData->calType; | 202 | ah->caldata->CalValid &= ~currCal->calData->calType; |
151 | currCal->calState = CAL_WAITING; | 203 | currCal->calState = CAL_WAITING; |
@@ -179,6 +231,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
179 | int32_t val; | 231 | int32_t val; |
180 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 232 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
181 | struct ath_common *common = ath9k_hw_common(ah); | 233 | struct ath_common *common = ath9k_hw_common(ah); |
234 | struct ieee80211_conf *conf = &common->hw->conf; | ||
182 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); | 235 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); |
183 | 236 | ||
184 | if (ah->caldata) | 237 | if (ah->caldata) |
@@ -188,6 +241,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
188 | if (chainmask & (1 << i)) { | 241 | if (chainmask & (1 << i)) { |
189 | s16 nfval; | 242 | s16 nfval; |
190 | 243 | ||
244 | if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) | ||
245 | continue; | ||
246 | |||
191 | if (h) | 247 | if (h) |
192 | nfval = h[i].privNF; | 248 | nfval = h[i].privNF; |
193 | else | 249 | else |
@@ -216,7 +272,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
216 | * since 250us often results in NF load timeout and causes deaf | 272 | * since 250us often results in NF load timeout and causes deaf |
217 | * condition during stress testing 12/12/2009 | 273 | * condition during stress testing 12/12/2009 |
218 | */ | 274 | */ |
219 | for (j = 0; j < 1000; j++) { | 275 | for (j = 0; j < 10000; j++) { |
220 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & | 276 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & |
221 | AR_PHY_AGC_CONTROL_NF) == 0) | 277 | AR_PHY_AGC_CONTROL_NF) == 0) |
222 | break; | 278 | break; |
@@ -232,10 +288,10 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
232 | * here, the baseband nf cal will just be capped by our present | 288 | * here, the baseband nf cal will just be capped by our present |
233 | * noisefloor until the next calibration timer. | 289 | * noisefloor until the next calibration timer. |
234 | */ | 290 | */ |
235 | if (j == 1000) { | 291 | if (j == 10000) { |
236 | ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf " | 292 | ath_dbg(common, ATH_DBG_ANY, |
237 | "to load: AR_PHY_AGC_CONTROL=0x%x\n", | 293 | "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", |
238 | REG_READ(ah, AR_PHY_AGC_CONTROL)); | 294 | REG_READ(ah, AR_PHY_AGC_CONTROL)); |
239 | return; | 295 | return; |
240 | } | 296 | } |
241 | 297 | ||
@@ -247,6 +303,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
247 | ENABLE_REGWRITE_BUFFER(ah); | 303 | ENABLE_REGWRITE_BUFFER(ah); |
248 | for (i = 0; i < NUM_NF_READINGS; i++) { | 304 | for (i = 0; i < NUM_NF_READINGS; i++) { |
249 | if (chainmask & (1 << i)) { | 305 | if (chainmask & (1 << i)) { |
306 | if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) | ||
307 | continue; | ||
308 | |||
250 | val = REG_READ(ah, ah->nf_regs[i]); | 309 | val = REG_READ(ah, ah->nf_regs[i]); |
251 | val &= 0xFFFFFE00; | 310 | val &= 0xFFFFFE00; |
252 | val |= (((u32) (-50) << 1) & 0x1ff); | 311 | val |= (((u32) (-50) << 1) & 0x1ff); |
@@ -254,7 +313,6 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
254 | } | 313 | } |
255 | } | 314 | } |
256 | REGWRITE_BUFFER_FLUSH(ah); | 315 | REGWRITE_BUFFER_FLUSH(ah); |
257 | DISABLE_REGWRITE_BUFFER(ah); | ||
258 | } | 316 | } |
259 | 317 | ||
260 | 318 | ||
@@ -273,19 +331,19 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) | |||
273 | if (!nf[i]) | 331 | if (!nf[i]) |
274 | continue; | 332 | continue; |
275 | 333 | ||
276 | ath_print(common, ATH_DBG_CALIBRATE, | 334 | ath_dbg(common, ATH_DBG_CALIBRATE, |
277 | "NF calibrated [%s] [chain %d] is %d\n", | 335 | "NF calibrated [%s] [chain %d] is %d\n", |
278 | (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); | 336 | (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); |
279 | 337 | ||
280 | if (nf[i] > limit->max) { | 338 | if (nf[i] > ATH9K_NF_TOO_HIGH) { |
281 | ath_print(common, ATH_DBG_CALIBRATE, | 339 | ath_dbg(common, ATH_DBG_CALIBRATE, |
282 | "NF[%d] (%d) > MAX (%d), correcting to MAX", | 340 | "NF[%d] (%d) > MAX (%d), correcting to MAX\n", |
283 | i, nf[i], limit->max); | 341 | i, nf[i], ATH9K_NF_TOO_HIGH); |
284 | nf[i] = limit->max; | 342 | nf[i] = limit->max; |
285 | } else if (nf[i] < limit->min) { | 343 | } else if (nf[i] < limit->min) { |
286 | ath_print(common, ATH_DBG_CALIBRATE, | 344 | ath_dbg(common, ATH_DBG_CALIBRATE, |
287 | "NF[%d] (%d) < MIN (%d), correcting to NOM", | 345 | "NF[%d] (%d) < MIN (%d), correcting to NOM\n", |
288 | i, nf[i], limit->min); | 346 | i, nf[i], limit->min); |
289 | nf[i] = limit->nominal; | 347 | nf[i] = limit->nominal; |
290 | } | 348 | } |
291 | } | 349 | } |
@@ -300,34 +358,33 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
300 | struct ieee80211_channel *c = chan->chan; | 358 | struct ieee80211_channel *c = chan->chan; |
301 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 359 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
302 | 360 | ||
303 | if (!caldata) | ||
304 | return false; | ||
305 | |||
306 | chan->channelFlags &= (~CHANNEL_CW_INT); | 361 | chan->channelFlags &= (~CHANNEL_CW_INT); |
307 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { | 362 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { |
308 | ath_print(common, ATH_DBG_CALIBRATE, | 363 | ath_dbg(common, ATH_DBG_CALIBRATE, |
309 | "NF did not complete in calibration window\n"); | 364 | "NF did not complete in calibration window\n"); |
310 | nf = 0; | 365 | return false; |
311 | caldata->rawNoiseFloor = nf; | 366 | } |
367 | |||
368 | ath9k_hw_do_getnf(ah, nfarray); | ||
369 | ath9k_hw_nf_sanitize(ah, nfarray); | ||
370 | nf = nfarray[0]; | ||
371 | if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh) | ||
372 | && nf > nfThresh) { | ||
373 | ath_dbg(common, ATH_DBG_CALIBRATE, | ||
374 | "noise floor failed detected; detected %d, threshold %d\n", | ||
375 | nf, nfThresh); | ||
376 | chan->channelFlags |= CHANNEL_CW_INT; | ||
377 | } | ||
378 | |||
379 | if (!caldata) { | ||
380 | chan->noisefloor = nf; | ||
312 | return false; | 381 | return false; |
313 | } else { | ||
314 | ath9k_hw_do_getnf(ah, nfarray); | ||
315 | ath9k_hw_nf_sanitize(ah, nfarray); | ||
316 | nf = nfarray[0]; | ||
317 | if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh) | ||
318 | && nf > nfThresh) { | ||
319 | ath_print(common, ATH_DBG_CALIBRATE, | ||
320 | "noise floor failed detected; " | ||
321 | "detected %d, threshold %d\n", | ||
322 | nf, nfThresh); | ||
323 | chan->channelFlags |= CHANNEL_CW_INT; | ||
324 | } | ||
325 | } | 382 | } |
326 | 383 | ||
327 | h = caldata->nfCalHist; | 384 | h = caldata->nfCalHist; |
328 | caldata->nfcal_pending = false; | 385 | caldata->nfcal_pending = false; |
329 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); | 386 | ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); |
330 | caldata->rawNoiseFloor = h[0].privNF; | 387 | chan->noisefloor = h[0].privNF; |
331 | return true; | 388 | return true; |
332 | } | 389 | } |
333 | 390 | ||
@@ -338,9 +395,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
338 | s16 default_nf; | 395 | s16 default_nf; |
339 | int i, j; | 396 | int i, j; |
340 | 397 | ||
341 | if (!ah->caldata) | 398 | ah->caldata->channel = chan->channel; |
342 | return; | 399 | ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT; |
343 | |||
344 | h = ah->caldata->nfCalHist; | 400 | h = ah->caldata->nfCalHist; |
345 | default_nf = ath9k_hw_get_default_nf(ah, chan); | 401 | default_nf = ath9k_hw_get_default_nf(ah, chan); |
346 | for (i = 0; i < NUM_NF_READINGS; i++) { | 402 | for (i = 0; i < NUM_NF_READINGS; i++) { |
@@ -353,11 +409,28 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
353 | } | 409 | } |
354 | } | 410 | } |
355 | 411 | ||
356 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | 412 | |
413 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) | ||
357 | { | 414 | { |
358 | if (!ah->caldata || !ah->caldata->rawNoiseFloor) | 415 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
359 | return ath9k_hw_get_default_nf(ah, chan); | 416 | |
417 | if (unlikely(!caldata)) | ||
418 | return; | ||
360 | 419 | ||
361 | return ah->caldata->rawNoiseFloor; | 420 | /* |
421 | * If beacons are stuck, the most likely cause is interference. | ||
422 | * Triggering a noise floor calibration at this point helps the | ||
423 | * hardware adapt to a noisy environment much faster. | ||
424 | * To ensure that we recover from stuck beacons quickly, let | ||
425 | * the baseband update the internal NF value itself, similar to | ||
426 | * what is being done after a full reset. | ||
427 | */ | ||
428 | if (!caldata->nfcal_pending) | ||
429 | ath9k_hw_start_nfcal(ah, true); | ||
430 | else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)) | ||
431 | ath9k_hw_getnf(ah, ah->curchan); | ||
432 | |||
433 | caldata->nfcal_interference = true; | ||
362 | } | 434 | } |
363 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); | 435 | EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal); |
436 | |||
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 0a304b3eeeb6..1bef41d1b1ff 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -58,14 +58,6 @@ struct ar5416IniArray { | |||
58 | } \ | 58 | } \ |
59 | } while (0) | 59 | } while (0) |
60 | 60 | ||
61 | enum ath9k_cal_types { | ||
62 | ADC_DC_INIT_CAL = 0x1, | ||
63 | ADC_GAIN_CAL = 0x2, | ||
64 | ADC_DC_CAL = 0x4, | ||
65 | IQ_MISMATCH_CAL = 0x8, | ||
66 | TEMP_COMP_CAL = 0x10, | ||
67 | }; | ||
68 | |||
69 | enum ath9k_cal_state { | 61 | enum ath9k_cal_state { |
70 | CAL_INACTIVE, | 62 | CAL_INACTIVE, |
71 | CAL_WAITING, | 63 | CAL_WAITING, |
@@ -80,7 +72,7 @@ enum ath9k_cal_state { | |||
80 | #define PER_MAX_LOG_COUNT 10 | 72 | #define PER_MAX_LOG_COUNT 10 |
81 | 73 | ||
82 | struct ath9k_percal_data { | 74 | struct ath9k_percal_data { |
83 | enum ath9k_cal_types calType; | 75 | u32 calType; |
84 | u32 calNumSamples; | 76 | u32 calNumSamples; |
85 | u32 calCountMax; | 77 | u32 calCountMax; |
86 | void (*calCollect) (struct ath_hw *); | 78 | void (*calCollect) (struct ath_hw *); |
@@ -113,7 +105,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); | |||
113 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); | 105 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); |
114 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | 106 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
115 | struct ath9k_channel *chan); | 107 | struct ath9k_channel *chan); |
116 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); | 108 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); |
117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, | 109 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
118 | struct ath9k_cal_list *currCal); | 110 | struct ath9k_cal_list *currCal); |
119 | 111 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index c86f7d3593ab..fa6bd2d189e5 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2009 Atheros Communications Inc. | 2 | * Copyright (c) 2009-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -46,12 +46,17 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) | |||
46 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 46 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
47 | 47 | ||
48 | if (tx_info->control.hw_key) { | 48 | if (tx_info->control.hw_key) { |
49 | if (tx_info->control.hw_key->alg == ALG_WEP) | 49 | switch (tx_info->control.hw_key->cipher) { |
50 | case WLAN_CIPHER_SUITE_WEP40: | ||
51 | case WLAN_CIPHER_SUITE_WEP104: | ||
50 | return ATH9K_KEY_TYPE_WEP; | 52 | return ATH9K_KEY_TYPE_WEP; |
51 | else if (tx_info->control.hw_key->alg == ALG_TKIP) | 53 | case WLAN_CIPHER_SUITE_TKIP: |
52 | return ATH9K_KEY_TYPE_TKIP; | 54 | return ATH9K_KEY_TYPE_TKIP; |
53 | else if (tx_info->control.hw_key->alg == ALG_CCMP) | 55 | case WLAN_CIPHER_SUITE_CCMP: |
54 | return ATH9K_KEY_TYPE_AES; | 56 | return ATH9K_KEY_TYPE_AES; |
57 | default: | ||
58 | break; | ||
59 | } | ||
55 | } | 60 | } |
56 | 61 | ||
57 | return ATH9K_KEY_TYPE_CLEAR; | 62 | return ATH9K_KEY_TYPE_CLEAR; |
@@ -102,26 +107,23 @@ static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, | |||
102 | /* | 107 | /* |
103 | * Update internal channel flags. | 108 | * Update internal channel flags. |
104 | */ | 109 | */ |
105 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | 110 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, |
106 | struct ath9k_channel *ichan) | 111 | struct ieee80211_channel *chan, |
112 | enum nl80211_channel_type channel_type) | ||
107 | { | 113 | { |
108 | struct ieee80211_channel *chan = hw->conf.channel; | ||
109 | struct ieee80211_conf *conf = &hw->conf; | ||
110 | |||
111 | ichan->channel = chan->center_freq; | 114 | ichan->channel = chan->center_freq; |
112 | ichan->chan = chan; | 115 | ichan->chan = chan; |
113 | 116 | ||
114 | if (chan->band == IEEE80211_BAND_2GHZ) { | 117 | if (chan->band == IEEE80211_BAND_2GHZ) { |
115 | ichan->chanmode = CHANNEL_G; | 118 | ichan->chanmode = CHANNEL_G; |
116 | ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; | 119 | ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; |
117 | } else { | 120 | } else { |
118 | ichan->chanmode = CHANNEL_A; | 121 | ichan->chanmode = CHANNEL_A; |
119 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; | 122 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; |
120 | } | 123 | } |
121 | 124 | ||
122 | if (conf_is_ht(conf)) | 125 | if (channel_type != NL80211_CHAN_NO_HT) |
123 | ichan->chanmode = ath9k_get_extchanmode(chan, | 126 | ichan->chanmode = ath9k_get_extchanmode(chan, channel_type); |
124 | conf->channel_type); | ||
125 | } | 127 | } |
126 | EXPORT_SYMBOL(ath9k_cmn_update_ichannel); | 128 | EXPORT_SYMBOL(ath9k_cmn_update_ichannel); |
127 | 129 | ||
@@ -137,270 +139,12 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | |||
137 | 139 | ||
138 | chan_idx = curchan->hw_value; | 140 | chan_idx = curchan->hw_value; |
139 | channel = &ah->channels[chan_idx]; | 141 | channel = &ah->channels[chan_idx]; |
140 | ath9k_cmn_update_ichannel(hw, channel); | 142 | ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type); |
141 | 143 | ||
142 | return channel; | 144 | return channel; |
143 | } | 145 | } |
144 | EXPORT_SYMBOL(ath9k_cmn_get_curchannel); | 146 | EXPORT_SYMBOL(ath9k_cmn_get_curchannel); |
145 | 147 | ||
146 | static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, | ||
147 | struct ath9k_keyval *hk, const u8 *addr, | ||
148 | bool authenticator) | ||
149 | { | ||
150 | struct ath_hw *ah = common->ah; | ||
151 | const u8 *key_rxmic; | ||
152 | const u8 *key_txmic; | ||
153 | |||
154 | key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
155 | key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
156 | |||
157 | if (addr == NULL) { | ||
158 | /* | ||
159 | * Group key installation - only two key cache entries are used | ||
160 | * regardless of splitmic capability since group key is only | ||
161 | * used either for TX or RX. | ||
162 | */ | ||
163 | if (authenticator) { | ||
164 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
165 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); | ||
166 | } else { | ||
167 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
168 | memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); | ||
169 | } | ||
170 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
171 | } | ||
172 | if (!common->splitmic) { | ||
173 | /* TX and RX keys share the same key cache entry. */ | ||
174 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
175 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); | ||
176 | return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); | ||
177 | } | ||
178 | |||
179 | /* Separate key cache entries for TX and RX */ | ||
180 | |||
181 | /* TX key goes at first index, RX key at +32. */ | ||
182 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | ||
183 | if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { | ||
184 | /* TX MIC entry failed. No need to proceed further */ | ||
185 | ath_print(common, ATH_DBG_FATAL, | ||
186 | "Setting TX MIC Key Failed\n"); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | ||
191 | /* XXX delete tx key on failure? */ | ||
192 | return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); | ||
193 | } | ||
194 | |||
195 | static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | ||
196 | { | ||
197 | int i; | ||
198 | |||
199 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
200 | if (test_bit(i, common->keymap) || | ||
201 | test_bit(i + 64, common->keymap)) | ||
202 | continue; /* At least one part of TKIP key allocated */ | ||
203 | if (common->splitmic && | ||
204 | (test_bit(i + 32, common->keymap) || | ||
205 | test_bit(i + 64 + 32, common->keymap))) | ||
206 | continue; /* At least one part of TKIP key allocated */ | ||
207 | |||
208 | /* Found a free slot for a TKIP key */ | ||
209 | return i; | ||
210 | } | ||
211 | return -1; | ||
212 | } | ||
213 | |||
214 | static int ath_reserve_key_cache_slot(struct ath_common *common, | ||
215 | enum ieee80211_key_alg alg) | ||
216 | { | ||
217 | int i; | ||
218 | |||
219 | if (alg == ALG_TKIP) | ||
220 | return ath_reserve_key_cache_slot_tkip(common); | ||
221 | |||
222 | /* First, try to find slots that would not be available for TKIP. */ | ||
223 | if (common->splitmic) { | ||
224 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { | ||
225 | if (!test_bit(i, common->keymap) && | ||
226 | (test_bit(i + 32, common->keymap) || | ||
227 | test_bit(i + 64, common->keymap) || | ||
228 | test_bit(i + 64 + 32, common->keymap))) | ||
229 | return i; | ||
230 | if (!test_bit(i + 32, common->keymap) && | ||
231 | (test_bit(i, common->keymap) || | ||
232 | test_bit(i + 64, common->keymap) || | ||
233 | test_bit(i + 64 + 32, common->keymap))) | ||
234 | return i + 32; | ||
235 | if (!test_bit(i + 64, common->keymap) && | ||
236 | (test_bit(i , common->keymap) || | ||
237 | test_bit(i + 32, common->keymap) || | ||
238 | test_bit(i + 64 + 32, common->keymap))) | ||
239 | return i + 64; | ||
240 | if (!test_bit(i + 64 + 32, common->keymap) && | ||
241 | (test_bit(i, common->keymap) || | ||
242 | test_bit(i + 32, common->keymap) || | ||
243 | test_bit(i + 64, common->keymap))) | ||
244 | return i + 64 + 32; | ||
245 | } | ||
246 | } else { | ||
247 | for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { | ||
248 | if (!test_bit(i, common->keymap) && | ||
249 | test_bit(i + 64, common->keymap)) | ||
250 | return i; | ||
251 | if (test_bit(i, common->keymap) && | ||
252 | !test_bit(i + 64, common->keymap)) | ||
253 | return i + 64; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | /* No partially used TKIP slots, pick any available slot */ | ||
258 | for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { | ||
259 | /* Do not allow slots that could be needed for TKIP group keys | ||
260 | * to be used. This limitation could be removed if we know that | ||
261 | * TKIP will not be used. */ | ||
262 | if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) | ||
263 | continue; | ||
264 | if (common->splitmic) { | ||
265 | if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) | ||
266 | continue; | ||
267 | if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) | ||
268 | continue; | ||
269 | } | ||
270 | |||
271 | if (!test_bit(i, common->keymap)) | ||
272 | return i; /* Found a free slot for a key */ | ||
273 | } | ||
274 | |||
275 | /* No free slot found */ | ||
276 | return -1; | ||
277 | } | ||
278 | |||
279 | /* | ||
280 | * Configure encryption in the HW. | ||
281 | */ | ||
282 | int ath9k_cmn_key_config(struct ath_common *common, | ||
283 | struct ieee80211_vif *vif, | ||
284 | struct ieee80211_sta *sta, | ||
285 | struct ieee80211_key_conf *key) | ||
286 | { | ||
287 | struct ath_hw *ah = common->ah; | ||
288 | struct ath9k_keyval hk; | ||
289 | const u8 *mac = NULL; | ||
290 | u8 gmac[ETH_ALEN]; | ||
291 | int ret = 0; | ||
292 | int idx; | ||
293 | |||
294 | memset(&hk, 0, sizeof(hk)); | ||
295 | |||
296 | switch (key->alg) { | ||
297 | case ALG_WEP: | ||
298 | hk.kv_type = ATH9K_CIPHER_WEP; | ||
299 | break; | ||
300 | case ALG_TKIP: | ||
301 | hk.kv_type = ATH9K_CIPHER_TKIP; | ||
302 | break; | ||
303 | case ALG_CCMP: | ||
304 | hk.kv_type = ATH9K_CIPHER_AES_CCM; | ||
305 | break; | ||
306 | default: | ||
307 | return -EOPNOTSUPP; | ||
308 | } | ||
309 | |||
310 | hk.kv_len = key->keylen; | ||
311 | memcpy(hk.kv_val, key->key, key->keylen); | ||
312 | |||
313 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
314 | switch (vif->type) { | ||
315 | case NL80211_IFTYPE_AP: | ||
316 | memcpy(gmac, vif->addr, ETH_ALEN); | ||
317 | gmac[0] |= 0x01; | ||
318 | mac = gmac; | ||
319 | idx = ath_reserve_key_cache_slot(common, key->alg); | ||
320 | break; | ||
321 | case NL80211_IFTYPE_ADHOC: | ||
322 | if (!sta) { | ||
323 | idx = key->keyidx; | ||
324 | break; | ||
325 | } | ||
326 | memcpy(gmac, sta->addr, ETH_ALEN); | ||
327 | gmac[0] |= 0x01; | ||
328 | mac = gmac; | ||
329 | idx = ath_reserve_key_cache_slot(common, key->alg); | ||
330 | break; | ||
331 | default: | ||
332 | idx = key->keyidx; | ||
333 | break; | ||
334 | } | ||
335 | } else if (key->keyidx) { | ||
336 | if (WARN_ON(!sta)) | ||
337 | return -EOPNOTSUPP; | ||
338 | mac = sta->addr; | ||
339 | |||
340 | if (vif->type != NL80211_IFTYPE_AP) { | ||
341 | /* Only keyidx 0 should be used with unicast key, but | ||
342 | * allow this for client mode for now. */ | ||
343 | idx = key->keyidx; | ||
344 | } else | ||
345 | return -EIO; | ||
346 | } else { | ||
347 | if (WARN_ON(!sta)) | ||
348 | return -EOPNOTSUPP; | ||
349 | mac = sta->addr; | ||
350 | |||
351 | idx = ath_reserve_key_cache_slot(common, key->alg); | ||
352 | } | ||
353 | |||
354 | if (idx < 0) | ||
355 | return -ENOSPC; /* no free key cache entries */ | ||
356 | |||
357 | if (key->alg == ALG_TKIP) | ||
358 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | ||
359 | vif->type == NL80211_IFTYPE_AP); | ||
360 | else | ||
361 | ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); | ||
362 | |||
363 | if (!ret) | ||
364 | return -EIO; | ||
365 | |||
366 | set_bit(idx, common->keymap); | ||
367 | if (key->alg == ALG_TKIP) { | ||
368 | set_bit(idx + 64, common->keymap); | ||
369 | if (common->splitmic) { | ||
370 | set_bit(idx + 32, common->keymap); | ||
371 | set_bit(idx + 64 + 32, common->keymap); | ||
372 | } | ||
373 | } | ||
374 | |||
375 | return idx; | ||
376 | } | ||
377 | EXPORT_SYMBOL(ath9k_cmn_key_config); | ||
378 | |||
379 | /* | ||
380 | * Delete Key. | ||
381 | */ | ||
382 | void ath9k_cmn_key_delete(struct ath_common *common, | ||
383 | struct ieee80211_key_conf *key) | ||
384 | { | ||
385 | struct ath_hw *ah = common->ah; | ||
386 | |||
387 | ath9k_hw_keyreset(ah, key->hw_key_idx); | ||
388 | if (key->hw_key_idx < IEEE80211_WEP_NKID) | ||
389 | return; | ||
390 | |||
391 | clear_bit(key->hw_key_idx, common->keymap); | ||
392 | if (key->alg != ALG_TKIP) | ||
393 | return; | ||
394 | |||
395 | clear_bit(key->hw_key_idx + 64, common->keymap); | ||
396 | if (common->splitmic) { | ||
397 | ath9k_hw_keyreset(ah, key->hw_key_idx + 32); | ||
398 | clear_bit(key->hw_key_idx + 32, common->keymap); | ||
399 | clear_bit(key->hw_key_idx + 64 + 32, common->keymap); | ||
400 | } | ||
401 | } | ||
402 | EXPORT_SYMBOL(ath9k_cmn_key_delete); | ||
403 | |||
404 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) | 148 | int ath9k_cmn_count_streams(unsigned int chainmask, int max) |
405 | { | 149 | { |
406 | int streams = 0; | 150 | int streams = 0; |
@@ -414,6 +158,17 @@ int ath9k_cmn_count_streams(unsigned int chainmask, int max) | |||
414 | } | 158 | } |
415 | EXPORT_SYMBOL(ath9k_cmn_count_streams); | 159 | EXPORT_SYMBOL(ath9k_cmn_count_streams); |
416 | 160 | ||
161 | void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, | ||
162 | u16 new_txpow, u16 *txpower) | ||
163 | { | ||
164 | if (cur_txpow != new_txpow) { | ||
165 | ath9k_hw_set_txpowerlimit(ah, new_txpow, false); | ||
166 | /* read back in case value is clamped */ | ||
167 | *txpower = ath9k_hw_regulatory(ah)->power_limit; | ||
168 | } | ||
169 | } | ||
170 | EXPORT_SYMBOL(ath9k_cmn_update_txpow); | ||
171 | |||
417 | static int __init ath9k_cmn_init(void) | 172 | static int __init ath9k_cmn_init(void) |
418 | { | 173 | { |
419 | return 0; | 174 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 97809d39c73f..77ec288b5a70 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2009 Atheros Communications Inc. | 2 | * Copyright (c) 2009-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,24 +17,22 @@ | |||
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | 18 | ||
19 | #include "../ath.h" | 19 | #include "../ath.h" |
20 | #include "../debug.h" | ||
21 | 20 | ||
22 | #include "hw.h" | 21 | #include "hw.h" |
23 | #include "hw-ops.h" | 22 | #include "hw-ops.h" |
24 | 23 | ||
25 | /* Common header for Atheros 802.11n base driver cores */ | 24 | /* Common header for Atheros 802.11n base driver cores */ |
26 | 25 | ||
27 | #define IEEE80211_WEP_NKID 4 | ||
28 | |||
29 | #define WME_NUM_TID 16 | 26 | #define WME_NUM_TID 16 |
30 | #define WME_BA_BMP_SIZE 64 | 27 | #define WME_BA_BMP_SIZE 64 |
31 | #define WME_MAX_BA WME_BA_BMP_SIZE | 28 | #define WME_MAX_BA WME_BA_BMP_SIZE |
32 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) | 29 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) |
33 | 30 | ||
34 | #define WME_AC_BE 0 | 31 | /* These must match mac80211 skb queue mapping numbers */ |
35 | #define WME_AC_BK 1 | 32 | #define WME_AC_VO 0 |
36 | #define WME_AC_VI 2 | 33 | #define WME_AC_VI 1 |
37 | #define WME_AC_VO 3 | 34 | #define WME_AC_BE 2 |
35 | #define WME_AC_BK 3 | ||
38 | #define WME_NUM_AC 4 | 36 | #define WME_NUM_AC 4 |
39 | 37 | ||
40 | #define ATH_RSSI_DUMMY_MARKER 0x127 | 38 | #define ATH_RSSI_DUMMY_MARKER 0x127 |
@@ -54,14 +52,13 @@ | |||
54 | 52 | ||
55 | int ath9k_cmn_padpos(__le16 frame_control); | 53 | int ath9k_cmn_padpos(__le16 frame_control); |
56 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 54 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
57 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | 55 | void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, |
58 | struct ath9k_channel *ichan); | 56 | struct ieee80211_channel *chan, |
57 | enum nl80211_channel_type channel_type); | ||
59 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, | 58 | struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, |
60 | struct ath_hw *ah); | 59 | struct ath_hw *ah); |
61 | int ath9k_cmn_key_config(struct ath_common *common, | ||
62 | struct ieee80211_vif *vif, | ||
63 | struct ieee80211_sta *sta, | ||
64 | struct ieee80211_key_conf *key); | ||
65 | void ath9k_cmn_key_delete(struct ath_common *common, | ||
66 | struct ieee80211_key_conf *key); | ||
67 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | 60 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); |
61 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | ||
62 | enum ath_stomp_type stomp_type); | ||
63 | void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, | ||
64 | u16 new_txpow, u16 *txpower); | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 54aae931424e..d55ffd7d4bd2 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/vmalloc.h> | ||
18 | #include <asm/unaligned.h> | 19 | #include <asm/unaligned.h> |
19 | 20 | ||
20 | #include "ath9k.h" | 21 | #include "ath9k.h" |
@@ -24,14 +25,25 @@ | |||
24 | #define REG_READ_D(_ah, _reg) \ | 25 | #define REG_READ_D(_ah, _reg) \ |
25 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) | 26 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) |
26 | 27 | ||
27 | static struct dentry *ath9k_debugfs_root; | ||
28 | |||
29 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | 28 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) |
30 | { | 29 | { |
31 | file->private_data = inode->i_private; | 30 | file->private_data = inode->i_private; |
32 | return 0; | 31 | return 0; |
33 | } | 32 | } |
34 | 33 | ||
34 | static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf, | ||
35 | size_t count, loff_t *ppos) | ||
36 | { | ||
37 | u8 *buf = file->private_data; | ||
38 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | ||
39 | } | ||
40 | |||
41 | static int ath9k_debugfs_release_buf(struct inode *inode, struct file *file) | ||
42 | { | ||
43 | vfree(file->private_data); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
35 | #ifdef CONFIG_ATH_DEBUG | 47 | #ifdef CONFIG_ATH_DEBUG |
36 | 48 | ||
37 | static ssize_t read_file_debug(struct file *file, char __user *user_buf, | 49 | static ssize_t read_file_debug(struct file *file, char __user *user_buf, |
@@ -71,7 +83,8 @@ static const struct file_operations fops_debug = { | |||
71 | .read = read_file_debug, | 83 | .read = read_file_debug, |
72 | .write = write_file_debug, | 84 | .write = write_file_debug, |
73 | .open = ath9k_debugfs_open, | 85 | .open = ath9k_debugfs_open, |
74 | .owner = THIS_MODULE | 86 | .owner = THIS_MODULE, |
87 | .llseek = default_llseek, | ||
75 | }; | 88 | }; |
76 | 89 | ||
77 | #endif | 90 | #endif |
@@ -116,7 +129,8 @@ static const struct file_operations fops_tx_chainmask = { | |||
116 | .read = read_file_tx_chainmask, | 129 | .read = read_file_tx_chainmask, |
117 | .write = write_file_tx_chainmask, | 130 | .write = write_file_tx_chainmask, |
118 | .open = ath9k_debugfs_open, | 131 | .open = ath9k_debugfs_open, |
119 | .owner = THIS_MODULE | 132 | .owner = THIS_MODULE, |
133 | .llseek = default_llseek, | ||
120 | }; | 134 | }; |
121 | 135 | ||
122 | 136 | ||
@@ -158,7 +172,8 @@ static const struct file_operations fops_rx_chainmask = { | |||
158 | .read = read_file_rx_chainmask, | 172 | .read = read_file_rx_chainmask, |
159 | .write = write_file_rx_chainmask, | 173 | .write = write_file_rx_chainmask, |
160 | .open = ath9k_debugfs_open, | 174 | .open = ath9k_debugfs_open, |
161 | .owner = THIS_MODULE | 175 | .owner = THIS_MODULE, |
176 | .llseek = default_llseek, | ||
162 | }; | 177 | }; |
163 | 178 | ||
164 | 179 | ||
@@ -259,7 +274,8 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
259 | static const struct file_operations fops_dma = { | 274 | static const struct file_operations fops_dma = { |
260 | .read = read_file_dma, | 275 | .read = read_file_dma, |
261 | .open = ath9k_debugfs_open, | 276 | .open = ath9k_debugfs_open, |
262 | .owner = THIS_MODULE | 277 | .owner = THIS_MODULE, |
278 | .llseek = default_llseek, | ||
263 | }; | 279 | }; |
264 | 280 | ||
265 | 281 | ||
@@ -310,6 +326,8 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) | |||
310 | sc->debug.stats.istats.dtimsync++; | 326 | sc->debug.stats.istats.dtimsync++; |
311 | if (status & ATH9K_INT_DTIM) | 327 | if (status & ATH9K_INT_DTIM) |
312 | sc->debug.stats.istats.dtim++; | 328 | sc->debug.stats.istats.dtim++; |
329 | if (status & ATH9K_INT_TSFOOR) | ||
330 | sc->debug.stats.istats.tsfoor++; | ||
313 | } | 331 | } |
314 | 332 | ||
315 | static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | 333 | static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, |
@@ -364,8 +382,11 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | |||
364 | len += snprintf(buf + len, sizeof(buf) - len, | 382 | len += snprintf(buf + len, sizeof(buf) - len, |
365 | "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); | 383 | "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); |
366 | len += snprintf(buf + len, sizeof(buf) - len, | 384 | len += snprintf(buf + len, sizeof(buf) - len, |
385 | "%8s: %10u\n", "TSFOOR", sc->debug.stats.istats.tsfoor); | ||
386 | len += snprintf(buf + len, sizeof(buf) - len, | ||
367 | "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); | 387 | "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); |
368 | 388 | ||
389 | |||
369 | if (len > sizeof(buf)) | 390 | if (len > sizeof(buf)) |
370 | len = sizeof(buf); | 391 | len = sizeof(buf); |
371 | 392 | ||
@@ -375,140 +396,46 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, | |||
375 | static const struct file_operations fops_interrupt = { | 396 | static const struct file_operations fops_interrupt = { |
376 | .read = read_file_interrupt, | 397 | .read = read_file_interrupt, |
377 | .open = ath9k_debugfs_open, | 398 | .open = ath9k_debugfs_open, |
378 | .owner = THIS_MODULE | 399 | .owner = THIS_MODULE, |
400 | .llseek = default_llseek, | ||
379 | }; | 401 | }; |
380 | 402 | ||
381 | void ath_debug_stat_rc(struct ath_softc *sc, int final_rate) | 403 | static const char *channel_type_str(enum nl80211_channel_type t) |
382 | { | ||
383 | struct ath_rc_stats *stats; | ||
384 | |||
385 | stats = &sc->debug.stats.rcstats[final_rate]; | ||
386 | stats->success++; | ||
387 | } | ||
388 | |||
389 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, | ||
390 | int xretries, int retries, u8 per) | ||
391 | { | 404 | { |
392 | struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix]; | 405 | switch (t) { |
393 | 406 | case NL80211_CHAN_NO_HT: | |
394 | stats->xretries += xretries; | 407 | return "no ht"; |
395 | stats->retries += retries; | 408 | case NL80211_CHAN_HT20: |
396 | stats->per = per; | 409 | return "ht20"; |
397 | } | 410 | case NL80211_CHAN_HT40MINUS: |
398 | 411 | return "ht40-"; | |
399 | static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | 412 | case NL80211_CHAN_HT40PLUS: |
400 | size_t count, loff_t *ppos) | 413 | return "ht40+"; |
401 | { | 414 | default: |
402 | struct ath_softc *sc = file->private_data; | 415 | return "???"; |
403 | char *buf; | ||
404 | unsigned int len = 0, max; | ||
405 | int i = 0; | ||
406 | ssize_t retval; | ||
407 | |||
408 | if (sc->cur_rate_table == NULL) | ||
409 | return 0; | ||
410 | |||
411 | max = 80 + sc->cur_rate_table->rate_cnt * 1024 + 1; | ||
412 | buf = kmalloc(max, GFP_KERNEL); | ||
413 | if (buf == NULL) | ||
414 | return -ENOMEM; | ||
415 | |||
416 | len += sprintf(buf, "%6s %6s %6s " | ||
417 | "%10s %10s %10s %10s\n", | ||
418 | "HT", "MCS", "Rate", | ||
419 | "Success", "Retries", "XRetries", "PER"); | ||
420 | |||
421 | for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { | ||
422 | u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; | ||
423 | struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; | ||
424 | char mcs[5]; | ||
425 | char htmode[5]; | ||
426 | int used_mcs = 0, used_htmode = 0; | ||
427 | |||
428 | if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) { | ||
429 | used_mcs = snprintf(mcs, 5, "%d", | ||
430 | sc->cur_rate_table->info[i].ratecode); | ||
431 | |||
432 | if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy)) | ||
433 | used_htmode = snprintf(htmode, 5, "HT40"); | ||
434 | else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy)) | ||
435 | used_htmode = snprintf(htmode, 5, "HT20"); | ||
436 | else | ||
437 | used_htmode = snprintf(htmode, 5, "????"); | ||
438 | } | ||
439 | |||
440 | mcs[used_mcs] = '\0'; | ||
441 | htmode[used_htmode] = '\0'; | ||
442 | |||
443 | len += snprintf(buf + len, max - len, | ||
444 | "%6s %6s %3u.%d: " | ||
445 | "%10u %10u %10u %10u\n", | ||
446 | htmode, | ||
447 | mcs, | ||
448 | ratekbps / 1000, | ||
449 | (ratekbps % 1000) / 100, | ||
450 | stats->success, | ||
451 | stats->retries, | ||
452 | stats->xretries, | ||
453 | stats->per); | ||
454 | } | 416 | } |
455 | |||
456 | if (len > max) | ||
457 | len = max; | ||
458 | |||
459 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
460 | kfree(buf); | ||
461 | return retval; | ||
462 | } | ||
463 | |||
464 | static const struct file_operations fops_rcstat = { | ||
465 | .read = read_file_rcstat, | ||
466 | .open = ath9k_debugfs_open, | ||
467 | .owner = THIS_MODULE | ||
468 | }; | ||
469 | |||
470 | static const char * ath_wiphy_state_str(enum ath_wiphy_state state) | ||
471 | { | ||
472 | switch (state) { | ||
473 | case ATH_WIPHY_INACTIVE: | ||
474 | return "INACTIVE"; | ||
475 | case ATH_WIPHY_ACTIVE: | ||
476 | return "ACTIVE"; | ||
477 | case ATH_WIPHY_PAUSING: | ||
478 | return "PAUSING"; | ||
479 | case ATH_WIPHY_PAUSED: | ||
480 | return "PAUSED"; | ||
481 | case ATH_WIPHY_SCAN: | ||
482 | return "SCAN"; | ||
483 | } | ||
484 | return "?"; | ||
485 | } | 417 | } |
486 | 418 | ||
487 | static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | 419 | static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, |
488 | size_t count, loff_t *ppos) | 420 | size_t count, loff_t *ppos) |
489 | { | 421 | { |
490 | struct ath_softc *sc = file->private_data; | 422 | struct ath_softc *sc = file->private_data; |
423 | struct ieee80211_channel *chan = sc->hw->conf.channel; | ||
424 | struct ieee80211_conf *conf = &(sc->hw->conf); | ||
491 | char buf[512]; | 425 | char buf[512]; |
492 | unsigned int len = 0; | 426 | unsigned int len = 0; |
493 | int i; | ||
494 | u8 addr[ETH_ALEN]; | 427 | u8 addr[ETH_ALEN]; |
428 | u32 tmp; | ||
495 | 429 | ||
496 | len += snprintf(buf + len, sizeof(buf) - len, | 430 | len += snprintf(buf + len, sizeof(buf) - len, |
497 | "primary: %s (%s chan=%d ht=%d)\n", | 431 | "%s (chan=%d center-freq: %d MHz channel-type: %d (%s))\n", |
498 | wiphy_name(sc->pri_wiphy->hw->wiphy), | 432 | wiphy_name(sc->hw->wiphy), |
499 | ath_wiphy_state_str(sc->pri_wiphy->state), | 433 | ieee80211_frequency_to_channel(chan->center_freq), |
500 | sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); | 434 | chan->center_freq, |
501 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 435 | conf->channel_type, |
502 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 436 | channel_type_str(conf->channel_type)); |
503 | if (aphy == NULL) | ||
504 | continue; | ||
505 | len += snprintf(buf + len, sizeof(buf) - len, | ||
506 | "secondary: %s (%s chan=%d ht=%d)\n", | ||
507 | wiphy_name(aphy->hw->wiphy), | ||
508 | ath_wiphy_state_str(aphy->state), | ||
509 | aphy->chan_idx, aphy->chan_is_ht); | ||
510 | } | ||
511 | 437 | ||
438 | ath9k_ps_wakeup(sc); | ||
512 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); | 439 | put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr); |
513 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); | 440 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); |
514 | len += snprintf(buf + len, sizeof(buf) - len, | 441 | len += snprintf(buf + len, sizeof(buf) - len, |
@@ -517,6 +444,38 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
517 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); | 444 | put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); |
518 | len += snprintf(buf + len, sizeof(buf) - len, | 445 | len += snprintf(buf + len, sizeof(buf) - len, |
519 | "addrmask: %pM\n", addr); | 446 | "addrmask: %pM\n", addr); |
447 | tmp = ath9k_hw_getrxfilter(sc->sc_ah); | ||
448 | ath9k_ps_restore(sc); | ||
449 | len += snprintf(buf + len, sizeof(buf) - len, | ||
450 | "rfilt: 0x%x", tmp); | ||
451 | if (tmp & ATH9K_RX_FILTER_UCAST) | ||
452 | len += snprintf(buf + len, sizeof(buf) - len, " UCAST"); | ||
453 | if (tmp & ATH9K_RX_FILTER_MCAST) | ||
454 | len += snprintf(buf + len, sizeof(buf) - len, " MCAST"); | ||
455 | if (tmp & ATH9K_RX_FILTER_BCAST) | ||
456 | len += snprintf(buf + len, sizeof(buf) - len, " BCAST"); | ||
457 | if (tmp & ATH9K_RX_FILTER_CONTROL) | ||
458 | len += snprintf(buf + len, sizeof(buf) - len, " CONTROL"); | ||
459 | if (tmp & ATH9K_RX_FILTER_BEACON) | ||
460 | len += snprintf(buf + len, sizeof(buf) - len, " BEACON"); | ||
461 | if (tmp & ATH9K_RX_FILTER_PROM) | ||
462 | len += snprintf(buf + len, sizeof(buf) - len, " PROM"); | ||
463 | if (tmp & ATH9K_RX_FILTER_PROBEREQ) | ||
464 | len += snprintf(buf + len, sizeof(buf) - len, " PROBEREQ"); | ||
465 | if (tmp & ATH9K_RX_FILTER_PHYERR) | ||
466 | len += snprintf(buf + len, sizeof(buf) - len, " PHYERR"); | ||
467 | if (tmp & ATH9K_RX_FILTER_MYBEACON) | ||
468 | len += snprintf(buf + len, sizeof(buf) - len, " MYBEACON"); | ||
469 | if (tmp & ATH9K_RX_FILTER_COMP_BAR) | ||
470 | len += snprintf(buf + len, sizeof(buf) - len, " COMP_BAR"); | ||
471 | if (tmp & ATH9K_RX_FILTER_PSPOLL) | ||
472 | len += snprintf(buf + len, sizeof(buf) - len, " PSPOLL"); | ||
473 | if (tmp & ATH9K_RX_FILTER_PHYRADAR) | ||
474 | len += snprintf(buf + len, sizeof(buf) - len, " PHYRADAR"); | ||
475 | if (tmp & ATH9K_RX_FILTER_MCAST_BCAST_ALL) | ||
476 | len += snprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL\n"); | ||
477 | else | ||
478 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | ||
520 | 479 | ||
521 | if (len > sizeof(buf)) | 480 | if (len > sizeof(buf)) |
522 | len = sizeof(buf); | 481 | len = sizeof(buf); |
@@ -524,136 +483,76 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, | |||
524 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 483 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
525 | } | 484 | } |
526 | 485 | ||
527 | static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name) | ||
528 | { | ||
529 | int i; | ||
530 | if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0) | ||
531 | return sc->pri_wiphy; | ||
532 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
533 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
534 | if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0) | ||
535 | return aphy; | ||
536 | } | ||
537 | return NULL; | ||
538 | } | ||
539 | |||
540 | static int del_wiphy(struct ath_softc *sc, const char *name) | ||
541 | { | ||
542 | struct ath_wiphy *aphy = get_wiphy(sc, name); | ||
543 | if (!aphy) | ||
544 | return -ENOENT; | ||
545 | return ath9k_wiphy_del(aphy); | ||
546 | } | ||
547 | |||
548 | static int pause_wiphy(struct ath_softc *sc, const char *name) | ||
549 | { | ||
550 | struct ath_wiphy *aphy = get_wiphy(sc, name); | ||
551 | if (!aphy) | ||
552 | return -ENOENT; | ||
553 | return ath9k_wiphy_pause(aphy); | ||
554 | } | ||
555 | |||
556 | static int unpause_wiphy(struct ath_softc *sc, const char *name) | ||
557 | { | ||
558 | struct ath_wiphy *aphy = get_wiphy(sc, name); | ||
559 | if (!aphy) | ||
560 | return -ENOENT; | ||
561 | return ath9k_wiphy_unpause(aphy); | ||
562 | } | ||
563 | |||
564 | static int select_wiphy(struct ath_softc *sc, const char *name) | ||
565 | { | ||
566 | struct ath_wiphy *aphy = get_wiphy(sc, name); | ||
567 | if (!aphy) | ||
568 | return -ENOENT; | ||
569 | return ath9k_wiphy_select(aphy); | ||
570 | } | ||
571 | |||
572 | static int schedule_wiphy(struct ath_softc *sc, const char *msec) | ||
573 | { | ||
574 | ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0)); | ||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf, | ||
579 | size_t count, loff_t *ppos) | ||
580 | { | ||
581 | struct ath_softc *sc = file->private_data; | ||
582 | char buf[50]; | ||
583 | size_t len; | ||
584 | |||
585 | len = min(count, sizeof(buf) - 1); | ||
586 | if (copy_from_user(buf, user_buf, len)) | ||
587 | return -EFAULT; | ||
588 | buf[len] = '\0'; | ||
589 | if (len > 0 && buf[len - 1] == '\n') | ||
590 | buf[len - 1] = '\0'; | ||
591 | |||
592 | if (strncmp(buf, "add", 3) == 0) { | ||
593 | int res = ath9k_wiphy_add(sc); | ||
594 | if (res < 0) | ||
595 | return res; | ||
596 | } else if (strncmp(buf, "del=", 4) == 0) { | ||
597 | int res = del_wiphy(sc, buf + 4); | ||
598 | if (res < 0) | ||
599 | return res; | ||
600 | } else if (strncmp(buf, "pause=", 6) == 0) { | ||
601 | int res = pause_wiphy(sc, buf + 6); | ||
602 | if (res < 0) | ||
603 | return res; | ||
604 | } else if (strncmp(buf, "unpause=", 8) == 0) { | ||
605 | int res = unpause_wiphy(sc, buf + 8); | ||
606 | if (res < 0) | ||
607 | return res; | ||
608 | } else if (strncmp(buf, "select=", 7) == 0) { | ||
609 | int res = select_wiphy(sc, buf + 7); | ||
610 | if (res < 0) | ||
611 | return res; | ||
612 | } else if (strncmp(buf, "schedule=", 9) == 0) { | ||
613 | int res = schedule_wiphy(sc, buf + 9); | ||
614 | if (res < 0) | ||
615 | return res; | ||
616 | } else | ||
617 | return -EOPNOTSUPP; | ||
618 | |||
619 | return count; | ||
620 | } | ||
621 | |||
622 | static const struct file_operations fops_wiphy = { | 486 | static const struct file_operations fops_wiphy = { |
623 | .read = read_file_wiphy, | 487 | .read = read_file_wiphy, |
624 | .write = write_file_wiphy, | ||
625 | .open = ath9k_debugfs_open, | 488 | .open = ath9k_debugfs_open, |
626 | .owner = THIS_MODULE | 489 | .owner = THIS_MODULE, |
490 | .llseek = default_llseek, | ||
627 | }; | 491 | }; |
628 | 492 | ||
493 | #define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum | ||
629 | #define PR(str, elem) \ | 494 | #define PR(str, elem) \ |
630 | do { \ | 495 | do { \ |
631 | len += snprintf(buf + len, size - len, \ | 496 | len += snprintf(buf + len, size - len, \ |
632 | "%s%13u%11u%10u%10u\n", str, \ | 497 | "%s%13u%11u%10u%10u\n", str, \ |
633 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \ | 498 | sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \ |
634 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \ | 499 | sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \ |
635 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \ | 500 | sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \ |
636 | sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \ | 501 | sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \ |
502 | if (len >= size) \ | ||
503 | goto done; \ | ||
637 | } while(0) | 504 | } while(0) |
638 | 505 | ||
506 | #define PRX(str, elem) \ | ||
507 | do { \ | ||
508 | len += snprintf(buf + len, size - len, \ | ||
509 | "%s%13u%11u%10u%10u\n", str, \ | ||
510 | (unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem), \ | ||
511 | (unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem), \ | ||
512 | (unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem), \ | ||
513 | (unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem)); \ | ||
514 | if (len >= size) \ | ||
515 | goto done; \ | ||
516 | } while(0) | ||
517 | |||
518 | #define PRQLE(str, elem) \ | ||
519 | do { \ | ||
520 | len += snprintf(buf + len, size - len, \ | ||
521 | "%s%13i%11i%10i%10i\n", str, \ | ||
522 | list_empty(&sc->tx.txq_map[WME_AC_BE]->elem), \ | ||
523 | list_empty(&sc->tx.txq_map[WME_AC_BK]->elem), \ | ||
524 | list_empty(&sc->tx.txq_map[WME_AC_VI]->elem), \ | ||
525 | list_empty(&sc->tx.txq_map[WME_AC_VO]->elem)); \ | ||
526 | if (len >= size) \ | ||
527 | goto done; \ | ||
528 | } while (0) | ||
529 | |||
639 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | 530 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, |
640 | size_t count, loff_t *ppos) | 531 | size_t count, loff_t *ppos) |
641 | { | 532 | { |
642 | struct ath_softc *sc = file->private_data; | 533 | struct ath_softc *sc = file->private_data; |
643 | char *buf; | 534 | char *buf; |
644 | unsigned int len = 0, size = 2048; | 535 | unsigned int len = 0, size = 8000; |
536 | int i; | ||
645 | ssize_t retval = 0; | 537 | ssize_t retval = 0; |
538 | char tmp[32]; | ||
646 | 539 | ||
647 | buf = kzalloc(size, GFP_KERNEL); | 540 | buf = kzalloc(size, GFP_KERNEL); |
648 | if (buf == NULL) | 541 | if (buf == NULL) |
649 | return -ENOMEM; | 542 | return -ENOMEM; |
650 | 543 | ||
651 | len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); | 544 | len += sprintf(buf, "Num-Tx-Queues: %i tx-queues-setup: 0x%x" |
545 | " poll-work-seen: %u\n" | ||
546 | "%30s %10s%10s%10s\n\n", | ||
547 | ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup, | ||
548 | sc->tx_complete_poll_work_seen, | ||
549 | "BE", "BK", "VI", "VO"); | ||
652 | 550 | ||
653 | PR("MPDUs Queued: ", queued); | 551 | PR("MPDUs Queued: ", queued); |
654 | PR("MPDUs Completed: ", completed); | 552 | PR("MPDUs Completed: ", completed); |
655 | PR("Aggregates: ", a_aggr); | 553 | PR("Aggregates: ", a_aggr); |
656 | PR("AMPDUs Queued: ", a_queued); | 554 | PR("AMPDUs Queued HW:", a_queued_hw); |
555 | PR("AMPDUs Queued SW:", a_queued_sw); | ||
657 | PR("AMPDUs Completed:", a_completed); | 556 | PR("AMPDUs Completed:", a_completed); |
658 | PR("AMPDUs Retried: ", a_retries); | 557 | PR("AMPDUs Retried: ", a_retries); |
659 | PR("AMPDUs XRetried: ", a_xretries); | 558 | PR("AMPDUs XRetried: ", a_xretries); |
@@ -663,7 +562,64 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
663 | PR("DESC CFG Error: ", desc_cfg_err); | 562 | PR("DESC CFG Error: ", desc_cfg_err); |
664 | PR("DATA Underrun: ", data_underrun); | 563 | PR("DATA Underrun: ", data_underrun); |
665 | PR("DELIM Underrun: ", delim_underrun); | 564 | PR("DELIM Underrun: ", delim_underrun); |
565 | PR("TX-Pkts-All: ", tx_pkts_all); | ||
566 | PR("TX-Bytes-All: ", tx_bytes_all); | ||
567 | PR("hw-put-tx-buf: ", puttxbuf); | ||
568 | PR("hw-tx-start: ", txstart); | ||
569 | PR("hw-tx-proc-desc: ", txprocdesc); | ||
570 | len += snprintf(buf + len, size - len, | ||
571 | "%s%11p%11p%10p%10p\n", "txq-memory-address:", | ||
572 | sc->tx.txq_map[WME_AC_BE], | ||
573 | sc->tx.txq_map[WME_AC_BK], | ||
574 | sc->tx.txq_map[WME_AC_VI], | ||
575 | sc->tx.txq_map[WME_AC_VO]); | ||
576 | if (len >= size) | ||
577 | goto done; | ||
578 | |||
579 | PRX("axq-qnum: ", axq_qnum); | ||
580 | PRX("axq-depth: ", axq_depth); | ||
581 | PRX("axq-ampdu_depth: ", axq_ampdu_depth); | ||
582 | PRX("axq-stopped ", stopped); | ||
583 | PRX("tx-in-progress ", axq_tx_inprogress); | ||
584 | PRX("pending-frames ", pending_frames); | ||
585 | PRX("txq_headidx: ", txq_headidx); | ||
586 | PRX("txq_tailidx: ", txq_headidx); | ||
587 | |||
588 | PRQLE("axq_q empty: ", axq_q); | ||
589 | PRQLE("axq_acq empty: ", axq_acq); | ||
590 | PRQLE("txq_fifo_pending: ", txq_fifo_pending); | ||
591 | for (i = 0; i < ATH_TXFIFO_DEPTH; i++) { | ||
592 | snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i); | ||
593 | PRQLE(tmp, txq_fifo[i]); | ||
594 | } | ||
666 | 595 | ||
596 | /* Print out more detailed queue-info */ | ||
597 | for (i = 0; i <= WME_AC_BK; i++) { | ||
598 | struct ath_txq *txq = &(sc->tx.txq[i]); | ||
599 | struct ath_atx_ac *ac; | ||
600 | struct ath_atx_tid *tid; | ||
601 | if (len >= size) | ||
602 | goto done; | ||
603 | spin_lock_bh(&txq->axq_lock); | ||
604 | if (!list_empty(&txq->axq_acq)) { | ||
605 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, | ||
606 | list); | ||
607 | len += snprintf(buf + len, size - len, | ||
608 | "txq[%i] first-ac: %p sched: %i\n", | ||
609 | i, ac, ac->sched); | ||
610 | if (list_empty(&ac->tid_q) || (len >= size)) | ||
611 | goto done_for; | ||
612 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, | ||
613 | list); | ||
614 | len += snprintf(buf + len, size - len, | ||
615 | " first-tid: %p sched: %i paused: %i\n", | ||
616 | tid, tid->sched, tid->paused); | ||
617 | } | ||
618 | done_for: | ||
619 | spin_unlock_bh(&txq->axq_lock); | ||
620 | } | ||
621 | |||
622 | done: | ||
667 | if (len > size) | 623 | if (len > size) |
668 | len = size; | 624 | len = size; |
669 | 625 | ||
@@ -673,36 +629,220 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | |||
673 | return retval; | 629 | return retval; |
674 | } | 630 | } |
675 | 631 | ||
676 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | 632 | static ssize_t read_file_stations(struct file *file, char __user *user_buf, |
677 | struct ath_buf *bf, struct ath_tx_status *ts) | 633 | size_t count, loff_t *ppos) |
678 | { | 634 | { |
635 | struct ath_softc *sc = file->private_data; | ||
636 | char *buf; | ||
637 | unsigned int len = 0, size = 64000; | ||
638 | struct ath_node *an = NULL; | ||
639 | ssize_t retval = 0; | ||
640 | int q; | ||
641 | |||
642 | buf = kzalloc(size, GFP_KERNEL); | ||
643 | if (buf == NULL) | ||
644 | return -ENOMEM; | ||
645 | |||
646 | len += snprintf(buf + len, size - len, | ||
647 | "Stations:\n" | ||
648 | " tid: addr sched paused buf_q-empty an ac\n" | ||
649 | " ac: addr sched tid_q-empty txq\n"); | ||
650 | |||
651 | spin_lock(&sc->nodes_lock); | ||
652 | list_for_each_entry(an, &sc->nodes, list) { | ||
653 | len += snprintf(buf + len, size - len, | ||
654 | "%pM\n", an->sta->addr); | ||
655 | if (len >= size) | ||
656 | goto done; | ||
657 | |||
658 | for (q = 0; q < WME_NUM_TID; q++) { | ||
659 | struct ath_atx_tid *tid = &(an->tid[q]); | ||
660 | len += snprintf(buf + len, size - len, | ||
661 | " tid: %p %s %s %i %p %p\n", | ||
662 | tid, tid->sched ? "sched" : "idle", | ||
663 | tid->paused ? "paused" : "running", | ||
664 | list_empty(&tid->buf_q), | ||
665 | tid->an, tid->ac); | ||
666 | if (len >= size) | ||
667 | goto done; | ||
668 | } | ||
669 | |||
670 | for (q = 0; q < WME_NUM_AC; q++) { | ||
671 | struct ath_atx_ac *ac = &(an->ac[q]); | ||
672 | len += snprintf(buf + len, size - len, | ||
673 | " ac: %p %s %i %p\n", | ||
674 | ac, ac->sched ? "sched" : "idle", | ||
675 | list_empty(&ac->tid_q), ac->txq); | ||
676 | if (len >= size) | ||
677 | goto done; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | done: | ||
682 | spin_unlock(&sc->nodes_lock); | ||
683 | if (len > size) | ||
684 | len = size; | ||
685 | |||
686 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
687 | kfree(buf); | ||
688 | |||
689 | return retval; | ||
690 | } | ||
691 | |||
692 | static ssize_t read_file_misc(struct file *file, char __user *user_buf, | ||
693 | size_t count, loff_t *ppos) | ||
694 | { | ||
695 | struct ath_softc *sc = file->private_data; | ||
696 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
697 | struct ath_hw *ah = sc->sc_ah; | ||
698 | struct ieee80211_hw *hw = sc->hw; | ||
699 | char *buf; | ||
700 | unsigned int len = 0, size = 8000; | ||
701 | ssize_t retval = 0; | ||
702 | const char *tmp; | ||
703 | unsigned int reg; | ||
704 | struct ath9k_vif_iter_data iter_data; | ||
705 | |||
706 | ath9k_calculate_iter_data(hw, NULL, &iter_data); | ||
707 | |||
708 | buf = kzalloc(size, GFP_KERNEL); | ||
709 | if (buf == NULL) | ||
710 | return -ENOMEM; | ||
711 | |||
712 | switch (sc->sc_ah->opmode) { | ||
713 | case NL80211_IFTYPE_ADHOC: | ||
714 | tmp = "ADHOC"; | ||
715 | break; | ||
716 | case NL80211_IFTYPE_MESH_POINT: | ||
717 | tmp = "MESH"; | ||
718 | break; | ||
719 | case NL80211_IFTYPE_AP: | ||
720 | tmp = "AP"; | ||
721 | break; | ||
722 | case NL80211_IFTYPE_STATION: | ||
723 | tmp = "STATION"; | ||
724 | break; | ||
725 | default: | ||
726 | tmp = "???"; | ||
727 | break; | ||
728 | } | ||
729 | |||
730 | ath9k_ps_wakeup(sc); | ||
731 | len += snprintf(buf + len, size - len, | ||
732 | "curbssid: %pM\n" | ||
733 | "OP-Mode: %s(%i)\n" | ||
734 | "Beacon-Timer-Register: 0x%x\n", | ||
735 | common->curbssid, | ||
736 | tmp, (int)(sc->sc_ah->opmode), | ||
737 | REG_READ(ah, AR_BEACON_PERIOD)); | ||
738 | |||
739 | reg = REG_READ(ah, AR_TIMER_MODE); | ||
740 | ath9k_ps_restore(sc); | ||
741 | len += snprintf(buf + len, size - len, "Timer-Mode-Register: 0x%x (", | ||
742 | reg); | ||
743 | if (reg & AR_TBTT_TIMER_EN) | ||
744 | len += snprintf(buf + len, size - len, "TBTT "); | ||
745 | if (reg & AR_DBA_TIMER_EN) | ||
746 | len += snprintf(buf + len, size - len, "DBA "); | ||
747 | if (reg & AR_SWBA_TIMER_EN) | ||
748 | len += snprintf(buf + len, size - len, "SWBA "); | ||
749 | if (reg & AR_HCF_TIMER_EN) | ||
750 | len += snprintf(buf + len, size - len, "HCF "); | ||
751 | if (reg & AR_TIM_TIMER_EN) | ||
752 | len += snprintf(buf + len, size - len, "TIM "); | ||
753 | if (reg & AR_DTIM_TIMER_EN) | ||
754 | len += snprintf(buf + len, size - len, "DTIM "); | ||
755 | len += snprintf(buf + len, size - len, ")\n"); | ||
756 | |||
757 | reg = sc->sc_ah->imask; | ||
758 | len += snprintf(buf + len, size - len, "imask: 0x%x (", reg); | ||
759 | if (reg & ATH9K_INT_SWBA) | ||
760 | len += snprintf(buf + len, size - len, "SWBA "); | ||
761 | if (reg & ATH9K_INT_BMISS) | ||
762 | len += snprintf(buf + len, size - len, "BMISS "); | ||
763 | if (reg & ATH9K_INT_CST) | ||
764 | len += snprintf(buf + len, size - len, "CST "); | ||
765 | if (reg & ATH9K_INT_RX) | ||
766 | len += snprintf(buf + len, size - len, "RX "); | ||
767 | if (reg & ATH9K_INT_RXHP) | ||
768 | len += snprintf(buf + len, size - len, "RXHP "); | ||
769 | if (reg & ATH9K_INT_RXLP) | ||
770 | len += snprintf(buf + len, size - len, "RXLP "); | ||
771 | if (reg & ATH9K_INT_BB_WATCHDOG) | ||
772 | len += snprintf(buf + len, size - len, "BB_WATCHDOG "); | ||
773 | /* there are other IRQs if one wanted to add them. */ | ||
774 | len += snprintf(buf + len, size - len, ")\n"); | ||
775 | |||
776 | len += snprintf(buf + len, size - len, | ||
777 | "VIF Counts: AP: %i STA: %i MESH: %i WDS: %i" | ||
778 | " ADHOC: %i OTHER: %i nvifs: %hi beacon-vifs: %hi\n", | ||
779 | iter_data.naps, iter_data.nstations, iter_data.nmeshes, | ||
780 | iter_data.nwds, iter_data.nadhocs, iter_data.nothers, | ||
781 | sc->nvifs, sc->nbcnvifs); | ||
782 | |||
783 | len += snprintf(buf + len, size - len, | ||
784 | "Calculated-BSSID-Mask: %pM\n", | ||
785 | iter_data.mask); | ||
786 | |||
787 | if (len > size) | ||
788 | len = size; | ||
789 | |||
790 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
791 | kfree(buf); | ||
792 | |||
793 | return retval; | ||
794 | } | ||
795 | |||
796 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, | ||
797 | struct ath_tx_status *ts, struct ath_txq *txq) | ||
798 | { | ||
799 | int qnum = txq->axq_qnum; | ||
800 | |||
801 | TX_STAT_INC(qnum, tx_pkts_all); | ||
802 | sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len; | ||
803 | |||
679 | if (bf_isampdu(bf)) { | 804 | if (bf_isampdu(bf)) { |
680 | if (bf_isxretried(bf)) | 805 | if (bf_isxretried(bf)) |
681 | TX_STAT_INC(txq->axq_qnum, a_xretries); | 806 | TX_STAT_INC(qnum, a_xretries); |
682 | else | 807 | else |
683 | TX_STAT_INC(txq->axq_qnum, a_completed); | 808 | TX_STAT_INC(qnum, a_completed); |
684 | } else { | 809 | } else { |
685 | TX_STAT_INC(txq->axq_qnum, completed); | 810 | TX_STAT_INC(qnum, completed); |
686 | } | 811 | } |
687 | 812 | ||
688 | if (ts->ts_status & ATH9K_TXERR_FIFO) | 813 | if (ts->ts_status & ATH9K_TXERR_FIFO) |
689 | TX_STAT_INC(txq->axq_qnum, fifo_underrun); | 814 | TX_STAT_INC(qnum, fifo_underrun); |
690 | if (ts->ts_status & ATH9K_TXERR_XTXOP) | 815 | if (ts->ts_status & ATH9K_TXERR_XTXOP) |
691 | TX_STAT_INC(txq->axq_qnum, xtxop); | 816 | TX_STAT_INC(qnum, xtxop); |
692 | if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) | 817 | if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED) |
693 | TX_STAT_INC(txq->axq_qnum, timer_exp); | 818 | TX_STAT_INC(qnum, timer_exp); |
694 | if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) | 819 | if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR) |
695 | TX_STAT_INC(txq->axq_qnum, desc_cfg_err); | 820 | TX_STAT_INC(qnum, desc_cfg_err); |
696 | if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) | 821 | if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN) |
697 | TX_STAT_INC(txq->axq_qnum, data_underrun); | 822 | TX_STAT_INC(qnum, data_underrun); |
698 | if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) | 823 | if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN) |
699 | TX_STAT_INC(txq->axq_qnum, delim_underrun); | 824 | TX_STAT_INC(qnum, delim_underrun); |
700 | } | 825 | } |
701 | 826 | ||
702 | static const struct file_operations fops_xmit = { | 827 | static const struct file_operations fops_xmit = { |
703 | .read = read_file_xmit, | 828 | .read = read_file_xmit, |
704 | .open = ath9k_debugfs_open, | 829 | .open = ath9k_debugfs_open, |
705 | .owner = THIS_MODULE | 830 | .owner = THIS_MODULE, |
831 | .llseek = default_llseek, | ||
832 | }; | ||
833 | |||
834 | static const struct file_operations fops_stations = { | ||
835 | .read = read_file_stations, | ||
836 | .open = ath9k_debugfs_open, | ||
837 | .owner = THIS_MODULE, | ||
838 | .llseek = default_llseek, | ||
839 | }; | ||
840 | |||
841 | static const struct file_operations fops_misc = { | ||
842 | .read = read_file_misc, | ||
843 | .open = ath9k_debugfs_open, | ||
844 | .owner = THIS_MODULE, | ||
845 | .llseek = default_llseek, | ||
706 | }; | 846 | }; |
707 | 847 | ||
708 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | 848 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, |
@@ -714,7 +854,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
714 | 854 | ||
715 | struct ath_softc *sc = file->private_data; | 855 | struct ath_softc *sc = file->private_data; |
716 | char *buf; | 856 | char *buf; |
717 | unsigned int len = 0, size = 1152; | 857 | unsigned int len = 0, size = 1400; |
718 | ssize_t retval = 0; | 858 | ssize_t retval = 0; |
719 | 859 | ||
720 | buf = kzalloc(size, GFP_KERNEL); | 860 | buf = kzalloc(size, GFP_KERNEL); |
@@ -743,6 +883,34 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
743 | "%18s : %10u\n", "DECRYPT BUSY ERR", | 883 | "%18s : %10u\n", "DECRYPT BUSY ERR", |
744 | sc->debug.stats.rxstats.decrypt_busy_err); | 884 | sc->debug.stats.rxstats.decrypt_busy_err); |
745 | 885 | ||
886 | len += snprintf(buf + len, size - len, | ||
887 | "%18s : %10d\n", "RSSI-CTL0", | ||
888 | sc->debug.stats.rxstats.rs_rssi_ctl0); | ||
889 | |||
890 | len += snprintf(buf + len, size - len, | ||
891 | "%18s : %10d\n", "RSSI-CTL1", | ||
892 | sc->debug.stats.rxstats.rs_rssi_ctl1); | ||
893 | |||
894 | len += snprintf(buf + len, size - len, | ||
895 | "%18s : %10d\n", "RSSI-CTL2", | ||
896 | sc->debug.stats.rxstats.rs_rssi_ctl2); | ||
897 | |||
898 | len += snprintf(buf + len, size - len, | ||
899 | "%18s : %10d\n", "RSSI-EXT0", | ||
900 | sc->debug.stats.rxstats.rs_rssi_ext0); | ||
901 | |||
902 | len += snprintf(buf + len, size - len, | ||
903 | "%18s : %10d\n", "RSSI-EXT1", | ||
904 | sc->debug.stats.rxstats.rs_rssi_ext1); | ||
905 | |||
906 | len += snprintf(buf + len, size - len, | ||
907 | "%18s : %10d\n", "RSSI-EXT2", | ||
908 | sc->debug.stats.rxstats.rs_rssi_ext2); | ||
909 | |||
910 | len += snprintf(buf + len, size - len, | ||
911 | "%18s : %10d\n", "Rx Antenna", | ||
912 | sc->debug.stats.rxstats.rs_antenna); | ||
913 | |||
746 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); | 914 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); |
747 | PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); | 915 | PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); |
748 | PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); | 916 | PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); |
@@ -770,6 +938,13 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
770 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | 938 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); |
771 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); | 939 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); |
772 | 940 | ||
941 | len += snprintf(buf + len, size - len, | ||
942 | "%18s : %10u\n", "RX-Pkts-All", | ||
943 | sc->debug.stats.rxstats.rx_pkts_all); | ||
944 | len += snprintf(buf + len, size - len, | ||
945 | "%18s : %10u\n", "RX-Bytes-All", | ||
946 | sc->debug.stats.rxstats.rx_bytes_all); | ||
947 | |||
773 | if (len > size) | 948 | if (len > size) |
774 | len = size; | 949 | len = size; |
775 | 950 | ||
@@ -788,6 +963,9 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | |||
788 | 963 | ||
789 | u32 phyerr; | 964 | u32 phyerr; |
790 | 965 | ||
966 | RX_STAT_INC(rx_pkts_all); | ||
967 | sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen; | ||
968 | |||
791 | if (rs->rs_status & ATH9K_RXERR_CRC) | 969 | if (rs->rs_status & ATH9K_RXERR_CRC) |
792 | RX_STAT_INC(crc_err); | 970 | RX_STAT_INC(crc_err); |
793 | if (rs->rs_status & ATH9K_RXERR_DECRYPT) | 971 | if (rs->rs_status & ATH9K_RXERR_DECRYPT) |
@@ -807,6 +985,16 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | |||
807 | RX_PHY_ERR_INC(phyerr); | 985 | RX_PHY_ERR_INC(phyerr); |
808 | } | 986 | } |
809 | 987 | ||
988 | sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0; | ||
989 | sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1; | ||
990 | sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2; | ||
991 | |||
992 | sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0; | ||
993 | sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1; | ||
994 | sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2; | ||
995 | |||
996 | sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna; | ||
997 | |||
810 | #undef RX_STAT_INC | 998 | #undef RX_STAT_INC |
811 | #undef RX_PHY_ERR_INC | 999 | #undef RX_PHY_ERR_INC |
812 | } | 1000 | } |
@@ -814,7 +1002,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs) | |||
814 | static const struct file_operations fops_recv = { | 1002 | static const struct file_operations fops_recv = { |
815 | .read = read_file_recv, | 1003 | .read = read_file_recv, |
816 | .open = ath9k_debugfs_open, | 1004 | .open = ath9k_debugfs_open, |
817 | .owner = THIS_MODULE | 1005 | .owner = THIS_MODULE, |
1006 | .llseek = default_llseek, | ||
818 | }; | 1007 | }; |
819 | 1008 | ||
820 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, | 1009 | static ssize_t read_file_regidx(struct file *file, char __user *user_buf, |
@@ -852,7 +1041,8 @@ static const struct file_operations fops_regidx = { | |||
852 | .read = read_file_regidx, | 1041 | .read = read_file_regidx, |
853 | .write = write_file_regidx, | 1042 | .write = write_file_regidx, |
854 | .open = ath9k_debugfs_open, | 1043 | .open = ath9k_debugfs_open, |
855 | .owner = THIS_MODULE | 1044 | .owner = THIS_MODULE, |
1045 | .llseek = default_llseek, | ||
856 | }; | 1046 | }; |
857 | 1047 | ||
858 | static ssize_t read_file_regval(struct file *file, char __user *user_buf, | 1048 | static ssize_t read_file_regval(struct file *file, char __user *user_buf, |
@@ -864,7 +1054,9 @@ static ssize_t read_file_regval(struct file *file, char __user *user_buf, | |||
864 | unsigned int len; | 1054 | unsigned int len; |
865 | u32 regval; | 1055 | u32 regval; |
866 | 1056 | ||
1057 | ath9k_ps_wakeup(sc); | ||
867 | regval = REG_READ_D(ah, sc->debug.regidx); | 1058 | regval = REG_READ_D(ah, sc->debug.regidx); |
1059 | ath9k_ps_restore(sc); | ||
868 | len = sprintf(buf, "0x%08x\n", regval); | 1060 | len = sprintf(buf, "0x%08x\n", regval); |
869 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 1061 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
870 | } | 1062 | } |
@@ -886,7 +1078,9 @@ static ssize_t write_file_regval(struct file *file, const char __user *user_buf, | |||
886 | if (strict_strtoul(buf, 0, ®val)) | 1078 | if (strict_strtoul(buf, 0, ®val)) |
887 | return -EINVAL; | 1079 | return -EINVAL; |
888 | 1080 | ||
1081 | ath9k_ps_wakeup(sc); | ||
889 | REG_WRITE_D(ah, sc->debug.regidx, regval); | 1082 | REG_WRITE_D(ah, sc->debug.regidx, regval); |
1083 | ath9k_ps_restore(sc); | ||
890 | return count; | 1084 | return count; |
891 | } | 1085 | } |
892 | 1086 | ||
@@ -894,98 +1088,94 @@ static const struct file_operations fops_regval = { | |||
894 | .read = read_file_regval, | 1088 | .read = read_file_regval, |
895 | .write = write_file_regval, | 1089 | .write = write_file_regval, |
896 | .open = ath9k_debugfs_open, | 1090 | .open = ath9k_debugfs_open, |
897 | .owner = THIS_MODULE | 1091 | .owner = THIS_MODULE, |
1092 | .llseek = default_llseek, | ||
898 | }; | 1093 | }; |
899 | 1094 | ||
900 | int ath9k_init_debug(struct ath_hw *ah) | 1095 | #define REGDUMP_LINE_SIZE 20 |
901 | { | ||
902 | struct ath_common *common = ath9k_hw_common(ah); | ||
903 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
904 | 1096 | ||
905 | if (!ath9k_debugfs_root) | 1097 | static int open_file_regdump(struct inode *inode, struct file *file) |
906 | return -ENOENT; | 1098 | { |
1099 | struct ath_softc *sc = inode->i_private; | ||
1100 | unsigned int len = 0; | ||
1101 | u8 *buf; | ||
1102 | int i; | ||
1103 | unsigned long num_regs, regdump_len, max_reg_offset; | ||
907 | 1104 | ||
908 | sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), | 1105 | max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x16bd4 : 0xb500; |
909 | ath9k_debugfs_root); | 1106 | num_regs = max_reg_offset / 4 + 1; |
910 | if (!sc->debug.debugfs_phy) | 1107 | regdump_len = num_regs * REGDUMP_LINE_SIZE + 1; |
1108 | buf = vmalloc(regdump_len); | ||
1109 | if (!buf) | ||
911 | return -ENOMEM; | 1110 | return -ENOMEM; |
912 | 1111 | ||
913 | #ifdef CONFIG_ATH_DEBUG | 1112 | ath9k_ps_wakeup(sc); |
914 | if (!debugfs_create_file("debug", S_IRUSR | S_IWUSR, | 1113 | for (i = 0; i < num_regs; i++) |
915 | sc->debug.debugfs_phy, sc, &fops_debug)) | 1114 | len += scnprintf(buf + len, regdump_len - len, |
916 | goto err; | 1115 | "0x%06x 0x%08x\n", i << 2, REG_READ(sc->sc_ah, i << 2)); |
917 | #endif | 1116 | ath9k_ps_restore(sc); |
918 | |||
919 | if (!debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, | ||
920 | sc, &fops_dma)) | ||
921 | goto err; | ||
922 | |||
923 | if (!debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, | ||
924 | sc, &fops_interrupt)) | ||
925 | goto err; | ||
926 | |||
927 | if (!debugfs_create_file("rcstat", S_IRUSR, sc->debug.debugfs_phy, | ||
928 | sc, &fops_rcstat)) | ||
929 | goto err; | ||
930 | |||
931 | if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, | ||
932 | sc->debug.debugfs_phy, sc, &fops_wiphy)) | ||
933 | goto err; | ||
934 | |||
935 | if (!debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, | ||
936 | sc, &fops_xmit)) | ||
937 | goto err; | ||
938 | |||
939 | if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, | ||
940 | sc, &fops_recv)) | ||
941 | goto err; | ||
942 | |||
943 | if (!debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, | ||
944 | sc->debug.debugfs_phy, sc, &fops_rx_chainmask)) | ||
945 | goto err; | ||
946 | |||
947 | if (!debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, | ||
948 | sc->debug.debugfs_phy, sc, &fops_tx_chainmask)) | ||
949 | goto err; | ||
950 | |||
951 | if (!debugfs_create_file("regidx", S_IRUSR | S_IWUSR, | ||
952 | sc->debug.debugfs_phy, sc, &fops_regidx)) | ||
953 | goto err; | ||
954 | |||
955 | if (!debugfs_create_file("regval", S_IRUSR | S_IWUSR, | ||
956 | sc->debug.debugfs_phy, sc, &fops_regval)) | ||
957 | goto err; | ||
958 | 1117 | ||
959 | if (!debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, | 1118 | file->private_data = buf; |
960 | sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca)) | ||
961 | goto err; | ||
962 | 1119 | ||
963 | sc->debug.regidx = 0; | ||
964 | return 0; | 1120 | return 0; |
965 | err: | ||
966 | ath9k_exit_debug(ah); | ||
967 | return -ENOMEM; | ||
968 | } | 1121 | } |
969 | 1122 | ||
970 | void ath9k_exit_debug(struct ath_hw *ah) | 1123 | static const struct file_operations fops_regdump = { |
1124 | .open = open_file_regdump, | ||
1125 | .read = ath9k_debugfs_read_buf, | ||
1126 | .release = ath9k_debugfs_release_buf, | ||
1127 | .owner = THIS_MODULE, | ||
1128 | .llseek = default_llseek,/* read accesses f_pos */ | ||
1129 | }; | ||
1130 | |||
1131 | int ath9k_init_debug(struct ath_hw *ah) | ||
971 | { | 1132 | { |
972 | struct ath_common *common = ath9k_hw_common(ah); | 1133 | struct ath_common *common = ath9k_hw_common(ah); |
973 | struct ath_softc *sc = (struct ath_softc *) common->priv; | 1134 | struct ath_softc *sc = (struct ath_softc *) common->priv; |
974 | 1135 | ||
975 | debugfs_remove_recursive(sc->debug.debugfs_phy); | 1136 | sc->debug.debugfs_phy = debugfs_create_dir("ath9k", |
976 | } | 1137 | sc->hw->wiphy->debugfsdir); |
1138 | if (!sc->debug.debugfs_phy) | ||
1139 | return -ENOMEM; | ||
977 | 1140 | ||
978 | int ath9k_debug_create_root(void) | 1141 | #ifdef CONFIG_ATH_DEBUG |
979 | { | 1142 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
980 | ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); | 1143 | sc, &fops_debug); |
981 | if (!ath9k_debugfs_root) | 1144 | #endif |
982 | return -ENOENT; | 1145 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, |
1146 | &fops_dma); | ||
1147 | debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc, | ||
1148 | &fops_interrupt); | ||
1149 | debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | ||
1150 | sc, &fops_wiphy); | ||
1151 | debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc, | ||
1152 | &fops_xmit); | ||
1153 | debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc, | ||
1154 | &fops_stations); | ||
1155 | debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc, | ||
1156 | &fops_misc); | ||
1157 | debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc, | ||
1158 | &fops_recv); | ||
1159 | debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR, | ||
1160 | sc->debug.debugfs_phy, sc, &fops_rx_chainmask); | ||
1161 | debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR, | ||
1162 | sc->debug.debugfs_phy, sc, &fops_tx_chainmask); | ||
1163 | debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | ||
1164 | sc, &fops_regidx); | ||
1165 | debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, | ||
1166 | sc, &fops_regval); | ||
1167 | debugfs_create_bool("ignore_extcca", S_IRUSR | S_IWUSR, | ||
1168 | sc->debug.debugfs_phy, | ||
1169 | &ah->config.cwm_ignore_extcca); | ||
1170 | debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, | ||
1171 | &fops_regdump); | ||
1172 | |||
1173 | debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, | ||
1174 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); | ||
1175 | |||
1176 | debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, | ||
1177 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); | ||
983 | 1178 | ||
1179 | sc->debug.regidx = 0; | ||
984 | return 0; | 1180 | return 0; |
985 | } | 1181 | } |
986 | |||
987 | void ath9k_debug_remove_root(void) | ||
988 | { | ||
989 | debugfs_remove(ath9k_debugfs_root); | ||
990 | ath9k_debugfs_root = NULL; | ||
991 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 5d21704e87ff..8ce6ad80f4e2 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -54,6 +54,9 @@ struct ath_buf; | |||
54 | * @dtimsync: DTIM sync lossage | 54 | * @dtimsync: DTIM sync lossage |
55 | * @dtim: RX Beacon with DTIM | 55 | * @dtim: RX Beacon with DTIM |
56 | * @bb_watchdog: Baseband watchdog | 56 | * @bb_watchdog: Baseband watchdog |
57 | * @tsfoor: TSF out of range, indicates that the corrected TSF received | ||
58 | * from a beacon differs from the PCU's internal TSF by more than a | ||
59 | * (programmable) threshold | ||
57 | */ | 60 | */ |
58 | struct ath_interrupt_stats { | 61 | struct ath_interrupt_stats { |
59 | u32 total; | 62 | u32 total; |
@@ -78,21 +81,20 @@ struct ath_interrupt_stats { | |||
78 | u32 dtimsync; | 81 | u32 dtimsync; |
79 | u32 dtim; | 82 | u32 dtim; |
80 | u32 bb_watchdog; | 83 | u32 bb_watchdog; |
81 | }; | 84 | u32 tsfoor; |
82 | |||
83 | struct ath_rc_stats { | ||
84 | u32 success; | ||
85 | u32 retries; | ||
86 | u32 xretries; | ||
87 | u8 per; | ||
88 | }; | 85 | }; |
89 | 86 | ||
90 | /** | 87 | /** |
91 | * struct ath_tx_stats - Statistics about TX | 88 | * struct ath_tx_stats - Statistics about TX |
89 | * @tx_pkts_all: No. of total frames transmitted, including ones that | ||
90 | may have had errors. | ||
91 | * @tx_bytes_all: No. of total bytes transmitted, including ones that | ||
92 | may have had errors. | ||
92 | * @queued: Total MPDUs (non-aggr) queued | 93 | * @queued: Total MPDUs (non-aggr) queued |
93 | * @completed: Total MPDUs (non-aggr) completed | 94 | * @completed: Total MPDUs (non-aggr) completed |
94 | * @a_aggr: Total no. of aggregates queued | 95 | * @a_aggr: Total no. of aggregates queued |
95 | * @a_queued: Total AMPDUs queued | 96 | * @a_queued_hw: Total AMPDUs queued to hardware |
97 | * @a_queued_sw: Total AMPDUs queued to software queues | ||
96 | * @a_completed: Total AMPDUs completed | 98 | * @a_completed: Total AMPDUs completed |
97 | * @a_retries: No. of AMPDUs retried (SW) | 99 | * @a_retries: No. of AMPDUs retried (SW) |
98 | * @a_xretries: No. of AMPDUs dropped due to xretries | 100 | * @a_xretries: No. of AMPDUs dropped due to xretries |
@@ -105,12 +107,18 @@ struct ath_rc_stats { | |||
105 | * @desc_cfg_err: Descriptor configuration errors | 107 | * @desc_cfg_err: Descriptor configuration errors |
106 | * @data_urn: TX data underrun errors | 108 | * @data_urn: TX data underrun errors |
107 | * @delim_urn: TX delimiter underrun errors | 109 | * @delim_urn: TX delimiter underrun errors |
110 | * @puttxbuf: Number of times hardware was given txbuf to write. | ||
111 | * @txstart: Number of times hardware was told to start tx. | ||
112 | * @txprocdesc: Number of times tx descriptor was processed | ||
108 | */ | 113 | */ |
109 | struct ath_tx_stats { | 114 | struct ath_tx_stats { |
115 | u32 tx_pkts_all; | ||
116 | u32 tx_bytes_all; | ||
110 | u32 queued; | 117 | u32 queued; |
111 | u32 completed; | 118 | u32 completed; |
112 | u32 a_aggr; | 119 | u32 a_aggr; |
113 | u32 a_queued; | 120 | u32 a_queued_hw; |
121 | u32 a_queued_sw; | ||
114 | u32 a_completed; | 122 | u32 a_completed; |
115 | u32 a_retries; | 123 | u32 a_retries; |
116 | u32 a_xretries; | 124 | u32 a_xretries; |
@@ -120,10 +128,17 @@ struct ath_tx_stats { | |||
120 | u32 desc_cfg_err; | 128 | u32 desc_cfg_err; |
121 | u32 data_underrun; | 129 | u32 data_underrun; |
122 | u32 delim_underrun; | 130 | u32 delim_underrun; |
131 | u32 puttxbuf; | ||
132 | u32 txstart; | ||
133 | u32 txprocdesc; | ||
123 | }; | 134 | }; |
124 | 135 | ||
125 | /** | 136 | /** |
126 | * struct ath_rx_stats - RX Statistics | 137 | * struct ath_rx_stats - RX Statistics |
138 | * @rx_pkts_all: No. of total frames received, including ones that | ||
139 | may have had errors. | ||
140 | * @rx_bytes_all: No. of total bytes received, including ones that | ||
141 | may have had errors. | ||
127 | * @crc_err: No. of frames with incorrect CRC value | 142 | * @crc_err: No. of frames with incorrect CRC value |
128 | * @decrypt_crc_err: No. of frames whose CRC check failed after | 143 | * @decrypt_crc_err: No. of frames whose CRC check failed after |
129 | decryption process completed | 144 | decryption process completed |
@@ -136,6 +151,8 @@ struct ath_tx_stats { | |||
136 | * @phy_err_stats: Individual PHY error statistics | 151 | * @phy_err_stats: Individual PHY error statistics |
137 | */ | 152 | */ |
138 | struct ath_rx_stats { | 153 | struct ath_rx_stats { |
154 | u32 rx_pkts_all; | ||
155 | u32 rx_bytes_all; | ||
139 | u32 crc_err; | 156 | u32 crc_err; |
140 | u32 decrypt_crc_err; | 157 | u32 decrypt_crc_err; |
141 | u32 phy_err; | 158 | u32 phy_err; |
@@ -144,11 +161,17 @@ struct ath_rx_stats { | |||
144 | u32 post_delim_crc_err; | 161 | u32 post_delim_crc_err; |
145 | u32 decrypt_busy_err; | 162 | u32 decrypt_busy_err; |
146 | u32 phy_err_stats[ATH9K_PHYERR_MAX]; | 163 | u32 phy_err_stats[ATH9K_PHYERR_MAX]; |
164 | int8_t rs_rssi_ctl0; | ||
165 | int8_t rs_rssi_ctl1; | ||
166 | int8_t rs_rssi_ctl2; | ||
167 | int8_t rs_rssi_ext0; | ||
168 | int8_t rs_rssi_ext1; | ||
169 | int8_t rs_rssi_ext2; | ||
170 | u8 rs_antenna; | ||
147 | }; | 171 | }; |
148 | 172 | ||
149 | struct ath_stats { | 173 | struct ath_stats { |
150 | struct ath_interrupt_stats istats; | 174 | struct ath_interrupt_stats istats; |
151 | struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; | ||
152 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; | 175 | struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; |
153 | struct ath_rx_stats rxstats; | 176 | struct ath_rx_stats rxstats; |
154 | }; | 177 | }; |
@@ -160,17 +183,11 @@ struct ath9k_debug { | |||
160 | }; | 183 | }; |
161 | 184 | ||
162 | int ath9k_init_debug(struct ath_hw *ah); | 185 | int ath9k_init_debug(struct ath_hw *ah); |
163 | void ath9k_exit_debug(struct ath_hw *ah); | ||
164 | 186 | ||
165 | int ath9k_debug_create_root(void); | ||
166 | void ath9k_debug_remove_root(void); | ||
167 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | 187 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); |
168 | void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); | 188 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, |
169 | void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, | 189 | struct ath_tx_status *ts, struct ath_txq *txq); |
170 | struct ath_buf *bf, struct ath_tx_status *ts); | ||
171 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); | 190 | void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); |
172 | void ath_debug_stat_retries(struct ath_softc *sc, int rix, | ||
173 | int xretries, int retries, u8 per); | ||
174 | 191 | ||
175 | #else | 192 | #else |
176 | 193 | ||
@@ -179,33 +196,15 @@ static inline int ath9k_init_debug(struct ath_hw *ah) | |||
179 | return 0; | 196 | return 0; |
180 | } | 197 | } |
181 | 198 | ||
182 | static inline void ath9k_exit_debug(struct ath_hw *ah) | ||
183 | { | ||
184 | } | ||
185 | |||
186 | static inline int ath9k_debug_create_root(void) | ||
187 | { | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static inline void ath9k_debug_remove_root(void) | ||
192 | { | ||
193 | } | ||
194 | |||
195 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, | 199 | static inline void ath_debug_stat_interrupt(struct ath_softc *sc, |
196 | enum ath9k_int status) | 200 | enum ath9k_int status) |
197 | { | 201 | { |
198 | } | 202 | } |
199 | 203 | ||
200 | static inline void ath_debug_stat_rc(struct ath_softc *sc, | ||
201 | int final_rate) | ||
202 | { | ||
203 | } | ||
204 | |||
205 | static inline void ath_debug_stat_tx(struct ath_softc *sc, | 204 | static inline void ath_debug_stat_tx(struct ath_softc *sc, |
206 | struct ath_txq *txq, | ||
207 | struct ath_buf *bf, | 205 | struct ath_buf *bf, |
208 | struct ath_tx_status *ts) | 206 | struct ath_tx_status *ts, |
207 | struct ath_txq *txq) | ||
209 | { | 208 | { |
210 | } | 209 | } |
211 | 210 | ||
@@ -214,11 +213,6 @@ static inline void ath_debug_stat_rx(struct ath_softc *sc, | |||
214 | { | 213 | { |
215 | } | 214 | } |
216 | 215 | ||
217 | static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, | ||
218 | int xretries, int retries, u8 per) | ||
219 | { | ||
220 | } | ||
221 | |||
222 | #endif /* CONFIG_ATH9K_DEBUGFS */ | 216 | #endif /* CONFIG_ATH9K_DEBUGFS */ |
223 | 217 | ||
224 | #endif /* DEBUG_H */ | 218 | #endif /* DEBUG_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index 1266333f586d..e61404dda8c5 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -89,6 +89,38 @@ bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, | |||
89 | return false; | 89 | return false; |
90 | } | 90 | } |
91 | 91 | ||
92 | void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, | ||
93 | int eep_start_loc, int size) | ||
94 | { | ||
95 | int i = 0, j, addr; | ||
96 | u32 addrdata[8]; | ||
97 | u32 data[8]; | ||
98 | |||
99 | for (addr = 0; addr < size; addr++) { | ||
100 | addrdata[i] = AR5416_EEPROM_OFFSET + | ||
101 | ((addr + eep_start_loc) << AR5416_EEPROM_S); | ||
102 | i++; | ||
103 | if (i == 8) { | ||
104 | REG_READ_MULTI(ah, addrdata, data, i); | ||
105 | |||
106 | for (j = 0; j < i; j++) { | ||
107 | *eep_data = data[j]; | ||
108 | eep_data++; | ||
109 | } | ||
110 | i = 0; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | if (i != 0) { | ||
115 | REG_READ_MULTI(ah, addrdata, data, i); | ||
116 | |||
117 | for (j = 0; j < i; j++) { | ||
118 | *eep_data = data[j]; | ||
119 | eep_data++; | ||
120 | } | ||
121 | } | ||
122 | } | ||
123 | |||
92 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data) | 124 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data) |
93 | { | 125 | { |
94 | return common->bus_ops->eeprom_read(common, off, data); | 126 | return common->bus_ops->eeprom_read(common, off, data); |
@@ -234,22 +266,22 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah, | |||
234 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, | 266 | u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, |
235 | bool is2GHz, int num_band_edges) | 267 | bool is2GHz, int num_band_edges) |
236 | { | 268 | { |
237 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 269 | u16 twiceMaxEdgePower = MAX_RATE_POWER; |
238 | int i; | 270 | int i; |
239 | 271 | ||
240 | for (i = 0; (i < num_band_edges) && | 272 | for (i = 0; (i < num_band_edges) && |
241 | (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) { | 273 | (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) { |
242 | if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) { | 274 | if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) { |
243 | twiceMaxEdgePower = pRdEdgesPower[i].tPower; | 275 | twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl); |
244 | break; | 276 | break; |
245 | } else if ((i > 0) && | 277 | } else if ((i > 0) && |
246 | (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, | 278 | (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, |
247 | is2GHz))) { | 279 | is2GHz))) { |
248 | if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel, | 280 | if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel, |
249 | is2GHz) < freq && | 281 | is2GHz) < freq && |
250 | pRdEdgesPower[i - 1].flag) { | 282 | CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) { |
251 | twiceMaxEdgePower = | 283 | twiceMaxEdgePower = |
252 | pRdEdgesPower[i - 1].tPower; | 284 | CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl); |
253 | } | 285 | } |
254 | break; | 286 | break; |
255 | } | 287 | } |
@@ -273,12 +305,225 @@ void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah) | |||
273 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | 305 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; |
274 | break; | 306 | break; |
275 | default: | 307 | default: |
276 | ath_print(common, ATH_DBG_EEPROM, | 308 | ath_dbg(common, ATH_DBG_EEPROM, |
277 | "Invalid chainmask configuration\n"); | 309 | "Invalid chainmask configuration\n"); |
278 | break; | 310 | break; |
279 | } | 311 | } |
280 | } | 312 | } |
281 | 313 | ||
314 | void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
315 | struct ath9k_channel *chan, | ||
316 | void *pRawDataSet, | ||
317 | u8 *bChans, u16 availPiers, | ||
318 | u16 tPdGainOverlap, | ||
319 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
320 | u16 numXpdGains) | ||
321 | { | ||
322 | int i, j, k; | ||
323 | int16_t ss; | ||
324 | u16 idxL = 0, idxR = 0, numPiers; | ||
325 | static u8 vpdTableL[AR5416_NUM_PD_GAINS] | ||
326 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
327 | static u8 vpdTableR[AR5416_NUM_PD_GAINS] | ||
328 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
329 | static u8 vpdTableI[AR5416_NUM_PD_GAINS] | ||
330 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
331 | |||
332 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
333 | u8 minPwrT4[AR5416_NUM_PD_GAINS]; | ||
334 | u8 maxPwrT4[AR5416_NUM_PD_GAINS]; | ||
335 | int16_t vpdStep; | ||
336 | int16_t tmpVal; | ||
337 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
338 | bool match; | ||
339 | int16_t minDelta = 0; | ||
340 | struct chan_centers centers; | ||
341 | int pdgain_boundary_default; | ||
342 | struct cal_data_per_freq *data_def = pRawDataSet; | ||
343 | struct cal_data_per_freq_4k *data_4k = pRawDataSet; | ||
344 | struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet; | ||
345 | bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah); | ||
346 | int intercepts; | ||
347 | |||
348 | if (AR_SREV_9287(ah)) | ||
349 | intercepts = AR9287_PD_GAIN_ICEPTS; | ||
350 | else | ||
351 | intercepts = AR5416_PD_GAIN_ICEPTS; | ||
352 | |||
353 | memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS); | ||
354 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
355 | |||
356 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
357 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center, | ||
362 | IS_CHAN_2GHZ(chan)), | ||
363 | bChans, numPiers, &idxL, &idxR); | ||
364 | |||
365 | if (match) { | ||
366 | if (AR_SREV_9287(ah)) { | ||
367 | /* FIXME: array overrun? */ | ||
368 | for (i = 0; i < numXpdGains; i++) { | ||
369 | minPwrT4[i] = data_9287[idxL].pwrPdg[i][0]; | ||
370 | maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4]; | ||
371 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
372 | data_9287[idxL].pwrPdg[i], | ||
373 | data_9287[idxL].vpdPdg[i], | ||
374 | intercepts, | ||
375 | vpdTableI[i]); | ||
376 | } | ||
377 | } else if (eeprom_4k) { | ||
378 | for (i = 0; i < numXpdGains; i++) { | ||
379 | minPwrT4[i] = data_4k[idxL].pwrPdg[i][0]; | ||
380 | maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4]; | ||
381 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
382 | data_4k[idxL].pwrPdg[i], | ||
383 | data_4k[idxL].vpdPdg[i], | ||
384 | intercepts, | ||
385 | vpdTableI[i]); | ||
386 | } | ||
387 | } else { | ||
388 | for (i = 0; i < numXpdGains; i++) { | ||
389 | minPwrT4[i] = data_def[idxL].pwrPdg[i][0]; | ||
390 | maxPwrT4[i] = data_def[idxL].pwrPdg[i][4]; | ||
391 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
392 | data_def[idxL].pwrPdg[i], | ||
393 | data_def[idxL].vpdPdg[i], | ||
394 | intercepts, | ||
395 | vpdTableI[i]); | ||
396 | } | ||
397 | } | ||
398 | } else { | ||
399 | for (i = 0; i < numXpdGains; i++) { | ||
400 | if (AR_SREV_9287(ah)) { | ||
401 | pVpdL = data_9287[idxL].vpdPdg[i]; | ||
402 | pPwrL = data_9287[idxL].pwrPdg[i]; | ||
403 | pVpdR = data_9287[idxR].vpdPdg[i]; | ||
404 | pPwrR = data_9287[idxR].pwrPdg[i]; | ||
405 | } else if (eeprom_4k) { | ||
406 | pVpdL = data_4k[idxL].vpdPdg[i]; | ||
407 | pPwrL = data_4k[idxL].pwrPdg[i]; | ||
408 | pVpdR = data_4k[idxR].vpdPdg[i]; | ||
409 | pPwrR = data_4k[idxR].pwrPdg[i]; | ||
410 | } else { | ||
411 | pVpdL = data_def[idxL].vpdPdg[i]; | ||
412 | pPwrL = data_def[idxL].pwrPdg[i]; | ||
413 | pVpdR = data_def[idxR].vpdPdg[i]; | ||
414 | pPwrR = data_def[idxR].pwrPdg[i]; | ||
415 | } | ||
416 | |||
417 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
418 | |||
419 | maxPwrT4[i] = | ||
420 | min(pPwrL[intercepts - 1], | ||
421 | pPwrR[intercepts - 1]); | ||
422 | |||
423 | |||
424 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
425 | pPwrL, pVpdL, | ||
426 | intercepts, | ||
427 | vpdTableL[i]); | ||
428 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
429 | pPwrR, pVpdR, | ||
430 | intercepts, | ||
431 | vpdTableR[i]); | ||
432 | |||
433 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
434 | vpdTableI[i][j] = | ||
435 | (u8)(ath9k_hw_interpolate((u16) | ||
436 | FREQ2FBIN(centers. | ||
437 | synth_center, | ||
438 | IS_CHAN_2GHZ | ||
439 | (chan)), | ||
440 | bChans[idxL], bChans[idxR], | ||
441 | vpdTableL[i][j], vpdTableR[i][j])); | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | k = 0; | ||
447 | |||
448 | for (i = 0; i < numXpdGains; i++) { | ||
449 | if (i == (numXpdGains - 1)) | ||
450 | pPdGainBoundaries[i] = | ||
451 | (u16)(maxPwrT4[i] / 2); | ||
452 | else | ||
453 | pPdGainBoundaries[i] = | ||
454 | (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); | ||
455 | |||
456 | pPdGainBoundaries[i] = | ||
457 | min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]); | ||
458 | |||
459 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
460 | minDelta = pPdGainBoundaries[0] - 23; | ||
461 | pPdGainBoundaries[0] = 23; | ||
462 | } else { | ||
463 | minDelta = 0; | ||
464 | } | ||
465 | |||
466 | if (i == 0) { | ||
467 | if (AR_SREV_9280_20_OR_LATER(ah)) | ||
468 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
469 | else | ||
470 | ss = 0; | ||
471 | } else { | ||
472 | ss = (int16_t)((pPdGainBoundaries[i - 1] - | ||
473 | (minPwrT4[i] / 2)) - | ||
474 | tPdGainOverlap + 1 + minDelta); | ||
475 | } | ||
476 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
477 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
478 | |||
479 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
480 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
481 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
482 | ss++; | ||
483 | } | ||
484 | |||
485 | sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
486 | tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - | ||
487 | (minPwrT4[i] / 2)); | ||
488 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
489 | tgtIndex : sizeCurrVpdTable; | ||
490 | |||
491 | while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
492 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
493 | } | ||
494 | |||
495 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
496 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
497 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
498 | |||
499 | if (tgtIndex >= maxIndex) { | ||
500 | while ((ss <= tgtIndex) && | ||
501 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
502 | tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + | ||
503 | (ss - maxIndex + 1) * vpdStep)); | ||
504 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
505 | 255 : tmpVal); | ||
506 | ss++; | ||
507 | } | ||
508 | } | ||
509 | } | ||
510 | |||
511 | if (eeprom_4k) | ||
512 | pdgain_boundary_default = 58; | ||
513 | else | ||
514 | pdgain_boundary_default = pPdGainBoundaries[i - 1]; | ||
515 | |||
516 | while (i < AR5416_PD_GAINS_IN_MASK) { | ||
517 | pPdGainBoundaries[i] = pdgain_boundary_default; | ||
518 | i++; | ||
519 | } | ||
520 | |||
521 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
522 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
523 | k++; | ||
524 | } | ||
525 | } | ||
526 | |||
282 | int ath9k_hw_eeprom_init(struct ath_hw *ah) | 527 | int ath9k_hw_eeprom_init(struct ath_hw *ah) |
283 | { | 528 | { |
284 | int status; | 529 | int status; |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 0b09db0f8e7d..de99c0da52e4 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,12 +17,12 @@ | |||
17 | #ifndef EEPROM_H | 17 | #ifndef EEPROM_H |
18 | #define EEPROM_H | 18 | #define EEPROM_H |
19 | 19 | ||
20 | #define AR_EEPROM_MODAL_SPURS 5 | ||
21 | |||
20 | #include "../ath.h" | 22 | #include "../ath.h" |
21 | #include <net/cfg80211.h> | 23 | #include <net/cfg80211.h> |
22 | #include "ar9003_eeprom.h" | 24 | #include "ar9003_eeprom.h" |
23 | 25 | ||
24 | #define AH_USE_EEPROM 0x1 | ||
25 | |||
26 | #ifdef __BIG_ENDIAN | 26 | #ifdef __BIG_ENDIAN |
27 | #define AR5416_EEPROM_MAGIC 0x5aa5 | 27 | #define AR5416_EEPROM_MAGIC 0x5aa5 |
28 | #else | 28 | #else |
@@ -101,7 +101,7 @@ | |||
101 | #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) | 101 | #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) |
102 | #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ | 102 | #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ |
103 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | 103 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) |
104 | #define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_10_OR_LATER(ah) && \ | 104 | #define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \ |
105 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | 105 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) |
106 | 106 | ||
107 | #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c | 107 | #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c |
@@ -149,8 +149,6 @@ | |||
149 | #define AR5416_NUM_PD_GAINS 4 | 149 | #define AR5416_NUM_PD_GAINS 4 |
150 | #define AR5416_PD_GAINS_IN_MASK 4 | 150 | #define AR5416_PD_GAINS_IN_MASK 4 |
151 | #define AR5416_PD_GAIN_ICEPTS 5 | 151 | #define AR5416_PD_GAIN_ICEPTS 5 |
152 | #define AR5416_EEPROM_MODAL_SPURS 5 | ||
153 | #define AR5416_MAX_RATE_POWER 63 | ||
154 | #define AR5416_NUM_PDADC_VALUES 128 | 152 | #define AR5416_NUM_PDADC_VALUES 128 |
155 | #define AR5416_BCHAN_UNUSED 0xFF | 153 | #define AR5416_BCHAN_UNUSED 0xFF |
156 | #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 | 154 | #define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 |
@@ -175,8 +173,6 @@ | |||
175 | #define AR5416_EEP4K_NUM_CTLS 12 | 173 | #define AR5416_EEP4K_NUM_CTLS 12 |
176 | #define AR5416_EEP4K_NUM_BAND_EDGES 4 | 174 | #define AR5416_EEP4K_NUM_BAND_EDGES 4 |
177 | #define AR5416_EEP4K_NUM_PD_GAINS 2 | 175 | #define AR5416_EEP4K_NUM_PD_GAINS 2 |
178 | #define AR5416_EEP4K_PD_GAINS_IN_MASK 4 | ||
179 | #define AR5416_EEP4K_PD_GAIN_ICEPTS 5 | ||
180 | #define AR5416_EEP4K_MAX_CHAINS 1 | 176 | #define AR5416_EEP4K_MAX_CHAINS 1 |
181 | 177 | ||
182 | #define AR9280_TX_GAIN_TABLE_SIZE 22 | 178 | #define AR9280_TX_GAIN_TABLE_SIZE 22 |
@@ -198,41 +194,30 @@ | |||
198 | #define AR9287_NUM_2G_40_TARGET_POWERS 3 | 194 | #define AR9287_NUM_2G_40_TARGET_POWERS 3 |
199 | #define AR9287_NUM_CTLS 12 | 195 | #define AR9287_NUM_CTLS 12 |
200 | #define AR9287_NUM_BAND_EDGES 4 | 196 | #define AR9287_NUM_BAND_EDGES 4 |
201 | #define AR9287_NUM_PD_GAINS 4 | ||
202 | #define AR9287_PD_GAINS_IN_MASK 4 | ||
203 | #define AR9287_PD_GAIN_ICEPTS 1 | 197 | #define AR9287_PD_GAIN_ICEPTS 1 |
204 | #define AR9287_EEPROM_MODAL_SPURS 5 | ||
205 | #define AR9287_MAX_RATE_POWER 63 | ||
206 | #define AR9287_NUM_PDADC_VALUES 128 | ||
207 | #define AR9287_NUM_RATES 16 | ||
208 | #define AR9287_BCHAN_UNUSED 0xFF | ||
209 | #define AR9287_MAX_PWR_RANGE_IN_HALF_DB 64 | ||
210 | #define AR9287_OPFLAGS_11A 0x01 | ||
211 | #define AR9287_OPFLAGS_11G 0x02 | ||
212 | #define AR9287_OPFLAGS_2G_HT40 0x08 | ||
213 | #define AR9287_OPFLAGS_2G_HT20 0x20 | ||
214 | #define AR9287_OPFLAGS_5G_HT40 0x04 | ||
215 | #define AR9287_OPFLAGS_5G_HT20 0x10 | ||
216 | #define AR9287_EEPMISC_BIG_ENDIAN 0x01 | 198 | #define AR9287_EEPMISC_BIG_ENDIAN 0x01 |
217 | #define AR9287_EEPMISC_WOW 0x02 | 199 | #define AR9287_EEPMISC_WOW 0x02 |
218 | #define AR9287_MAX_CHAINS 2 | 200 | #define AR9287_MAX_CHAINS 2 |
219 | #define AR9287_ANT_16S 32 | 201 | #define AR9287_ANT_16S 32 |
220 | #define AR9287_custdatasize 20 | 202 | |
221 | |||
222 | #define AR9287_NUM_ANT_CHAIN_FIELDS 6 | ||
223 | #define AR9287_NUM_ANT_COMMON_FIELDS 4 | ||
224 | #define AR9287_SIZE_ANT_CHAIN_FIELD 2 | ||
225 | #define AR9287_SIZE_ANT_COMMON_FIELD 4 | ||
226 | #define AR9287_ANT_CHAIN_MASK 0x3 | ||
227 | #define AR9287_ANT_COMMON_MASK 0xf | ||
228 | #define AR9287_CHAIN_0_IDX 0 | ||
229 | #define AR9287_CHAIN_1_IDX 1 | ||
230 | #define AR9287_DATA_SZ 32 | 203 | #define AR9287_DATA_SZ 32 |
231 | 204 | ||
232 | #define AR9287_PWR_TABLE_OFFSET_DB -5 | 205 | #define AR9287_PWR_TABLE_OFFSET_DB -5 |
233 | 206 | ||
234 | #define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1) | 207 | #define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1) |
235 | 208 | ||
209 | #define CTL_EDGE_TPOWER(_ctl) ((_ctl) & 0x3f) | ||
210 | #define CTL_EDGE_FLAGS(_ctl) (((_ctl) >> 6) & 0x03) | ||
211 | |||
212 | #define LNA_CTL_BUF_MODE BIT(0) | ||
213 | #define LNA_CTL_ISEL_LO BIT(1) | ||
214 | #define LNA_CTL_ISEL_HI BIT(2) | ||
215 | #define LNA_CTL_BUF_IN BIT(3) | ||
216 | #define LNA_CTL_FEM_BAND BIT(4) | ||
217 | #define LNA_CTL_LOCAL_BIAS BIT(5) | ||
218 | #define LNA_CTL_FORCE_XPA BIT(6) | ||
219 | #define LNA_CTL_USE_ANT1 BIT(7) | ||
220 | |||
236 | enum eeprom_param { | 221 | enum eeprom_param { |
237 | EEP_NFTHRESH_5, | 222 | EEP_NFTHRESH_5, |
238 | EEP_NFTHRESH_2, | 223 | EEP_NFTHRESH_2, |
@@ -266,6 +251,9 @@ enum eeprom_param { | |||
266 | EEP_INTERNAL_REGULATOR, | 251 | EEP_INTERNAL_REGULATOR, |
267 | EEP_SWREG, | 252 | EEP_SWREG, |
268 | EEP_PAPRD, | 253 | EEP_PAPRD, |
254 | EEP_MODAL_VER, | ||
255 | EEP_ANT_DIV_CTL1, | ||
256 | EEP_CHAIN_MASK_REDUCE | ||
269 | }; | 257 | }; |
270 | 258 | ||
271 | enum ar5416_rates { | 259 | enum ar5416_rates { |
@@ -376,15 +364,12 @@ struct modal_eep_header { | |||
376 | u8 xatten2Margin[AR5416_MAX_CHAINS]; | 364 | u8 xatten2Margin[AR5416_MAX_CHAINS]; |
377 | u8 ob_ch1; | 365 | u8 ob_ch1; |
378 | u8 db_ch1; | 366 | u8 db_ch1; |
379 | u8 useAnt1:1, | 367 | u8 lna_ctl; |
380 | force_xpaon:1, | ||
381 | local_bias:1, | ||
382 | femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1; | ||
383 | u8 miscBits; | 368 | u8 miscBits; |
384 | u16 xpaBiasLvlFreq[3]; | 369 | u16 xpaBiasLvlFreq[3]; |
385 | u8 futureModal[6]; | 370 | u8 futureModal[6]; |
386 | 371 | ||
387 | struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; | 372 | struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; |
388 | } __packed; | 373 | } __packed; |
389 | 374 | ||
390 | struct calDataPerFreqOpLoop { | 375 | struct calDataPerFreqOpLoop { |
@@ -451,8 +436,12 @@ struct modal_eep_4k_header { | |||
451 | u8 db2_2:4, db2_3:4; | 436 | u8 db2_2:4, db2_3:4; |
452 | u8 db2_4:4, reserved:4; | 437 | u8 db2_4:4, reserved:4; |
453 | #endif | 438 | #endif |
454 | u8 futureModal[4]; | 439 | u8 tx_diversity; |
455 | struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; | 440 | u8 flc_pwr_thresh; |
441 | u8 bb_scale_smrt_antenna; | ||
442 | #define EEP_4K_BB_DESIRED_SCALE_MASK 0x1f | ||
443 | u8 futureModal[1]; | ||
444 | struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; | ||
456 | } __packed; | 445 | } __packed; |
457 | 446 | ||
458 | struct base_eep_ar9287_header { | 447 | struct base_eep_ar9287_header { |
@@ -510,7 +499,7 @@ struct modal_eep_ar9287_header { | |||
510 | u8 ob_qam; | 499 | u8 ob_qam; |
511 | u8 ob_pal_off; | 500 | u8 ob_pal_off; |
512 | u8 futureModal[30]; | 501 | u8 futureModal[30]; |
513 | struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS]; | 502 | struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS]; |
514 | } __packed; | 503 | } __packed; |
515 | 504 | ||
516 | struct cal_data_per_freq { | 505 | struct cal_data_per_freq { |
@@ -519,8 +508,8 @@ struct cal_data_per_freq { | |||
519 | } __packed; | 508 | } __packed; |
520 | 509 | ||
521 | struct cal_data_per_freq_4k { | 510 | struct cal_data_per_freq_4k { |
522 | u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; | 511 | u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; |
523 | u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; | 512 | u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; |
524 | } __packed; | 513 | } __packed; |
525 | 514 | ||
526 | struct cal_target_power_leg { | 515 | struct cal_target_power_leg { |
@@ -533,18 +522,10 @@ struct cal_target_power_ht { | |||
533 | u8 tPow2x[8]; | 522 | u8 tPow2x[8]; |
534 | } __packed; | 523 | } __packed; |
535 | 524 | ||
536 | |||
537 | #ifdef __BIG_ENDIAN_BITFIELD | ||
538 | struct cal_ctl_edges { | 525 | struct cal_ctl_edges { |
539 | u8 bChannel; | 526 | u8 bChannel; |
540 | u8 flag:2, tPower:6; | 527 | u8 ctl; |
541 | } __packed; | 528 | } __packed; |
542 | #else | ||
543 | struct cal_ctl_edges { | ||
544 | u8 bChannel; | ||
545 | u8 tPower:6, flag:2; | ||
546 | } __packed; | ||
547 | #endif | ||
548 | 529 | ||
549 | struct cal_data_op_loop_ar9287 { | 530 | struct cal_data_op_loop_ar9287 { |
550 | u8 pwrPdg[2][5]; | 531 | u8 pwrPdg[2][5]; |
@@ -554,8 +535,8 @@ struct cal_data_op_loop_ar9287 { | |||
554 | } __packed; | 535 | } __packed; |
555 | 536 | ||
556 | struct cal_data_per_freq_ar9287 { | 537 | struct cal_data_per_freq_ar9287 { |
557 | u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; | 538 | u8 pwrPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; |
558 | u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; | 539 | u8 vpdPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; |
559 | } __packed; | 540 | } __packed; |
560 | 541 | ||
561 | union cal_data_per_freq_ar9287_u { | 542 | union cal_data_per_freq_ar9287_u { |
@@ -670,14 +651,12 @@ struct eeprom_ops { | |||
670 | bool (*fill_eeprom)(struct ath_hw *hw); | 651 | bool (*fill_eeprom)(struct ath_hw *hw); |
671 | int (*get_eeprom_ver)(struct ath_hw *hw); | 652 | int (*get_eeprom_ver)(struct ath_hw *hw); |
672 | int (*get_eeprom_rev)(struct ath_hw *hw); | 653 | int (*get_eeprom_rev)(struct ath_hw *hw); |
673 | u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); | ||
674 | u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, | ||
675 | struct ath9k_channel *chan); | ||
676 | void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); | 654 | void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); |
677 | void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); | 655 | void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); |
678 | void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, | 656 | void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, |
679 | u16 cfgCtl, u8 twiceAntennaReduction, | 657 | u16 cfgCtl, u8 twiceAntennaReduction, |
680 | u8 twiceMaxRegulatoryPower, u8 powerLimit); | 658 | u8 twiceMaxRegulatoryPower, u8 powerLimit, |
659 | bool test); | ||
681 | u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); | 660 | u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); |
682 | }; | 661 | }; |
683 | 662 | ||
@@ -690,6 +669,8 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, | |||
690 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, | 669 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, |
691 | u16 *indexL, u16 *indexR); | 670 | u16 *indexL, u16 *indexR); |
692 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data); | 671 | bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data); |
672 | void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, | ||
673 | int eep_start_loc, int size); | ||
693 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, | 674 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, |
694 | u8 *pVpdList, u16 numIntercepts, | 675 | u8 *pVpdList, u16 numIntercepts, |
695 | u8 *pRetVpdList); | 676 | u8 *pRetVpdList); |
@@ -710,6 +691,14 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, | |||
710 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah); | 691 | void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah); |
711 | int ath9k_hw_eeprom_init(struct ath_hw *ah); | 692 | int ath9k_hw_eeprom_init(struct ath_hw *ah); |
712 | 693 | ||
694 | void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
695 | struct ath9k_channel *chan, | ||
696 | void *pRawDataSet, | ||
697 | u8 *bChans, u16 availPiers, | ||
698 | u16 tPdGainOverlap, | ||
699 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
700 | u16 numXpdGains); | ||
701 | |||
713 | #define ar5416_get_ntxchains(_txchainmask) \ | 702 | #define ar5416_get_ntxchains(_txchainmask) \ |
714 | (((_txchainmask >> 2) & 1) + \ | 703 | (((_txchainmask >> 2) & 1) + \ |
715 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) | 704 | ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 9cccd12e8f21..5b1e894f3d67 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -27,33 +27,52 @@ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) | |||
27 | return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); | 27 | return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); |
28 | } | 28 | } |
29 | 29 | ||
30 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | ||
31 | { | ||
32 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | 30 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) |
31 | |||
32 | static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | ||
33 | { | ||
33 | struct ath_common *common = ath9k_hw_common(ah); | 34 | struct ath_common *common = ath9k_hw_common(ah); |
34 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; | 35 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; |
35 | int addr, eep_start_loc = 0; | 36 | int addr, eep_start_loc = 64; |
36 | |||
37 | eep_start_loc = 64; | ||
38 | |||
39 | if (!ath9k_hw_use_flash(ah)) { | ||
40 | ath_print(common, ATH_DBG_EEPROM, | ||
41 | "Reading from EEPROM, not flash\n"); | ||
42 | } | ||
43 | 37 | ||
44 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { | 38 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { |
45 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { | 39 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) { |
46 | ath_print(common, ATH_DBG_EEPROM, | 40 | ath_dbg(common, ATH_DBG_EEPROM, |
47 | "Unable to read eeprom region\n"); | 41 | "Unable to read eeprom region\n"); |
48 | return false; | 42 | return false; |
49 | } | 43 | } |
50 | eep_data++; | 44 | eep_data++; |
51 | } | 45 | } |
52 | 46 | ||
53 | return true; | 47 | return true; |
54 | #undef SIZE_EEPROM_4K | ||
55 | } | 48 | } |
56 | 49 | ||
50 | static bool __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah) | ||
51 | { | ||
52 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; | ||
53 | |||
54 | ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K); | ||
55 | |||
56 | return true; | ||
57 | } | ||
58 | |||
59 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | ||
60 | { | ||
61 | struct ath_common *common = ath9k_hw_common(ah); | ||
62 | |||
63 | if (!ath9k_hw_use_flash(ah)) { | ||
64 | ath_dbg(common, ATH_DBG_EEPROM, | ||
65 | "Reading from EEPROM, not flash\n"); | ||
66 | } | ||
67 | |||
68 | if (common->bus_ops->ath_bus_type == ATH_USB) | ||
69 | return __ath9k_hw_usb_4k_fill_eeprom(ah); | ||
70 | else | ||
71 | return __ath9k_hw_4k_fill_eeprom(ah); | ||
72 | } | ||
73 | |||
74 | #undef SIZE_EEPROM_4K | ||
75 | |||
57 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | 76 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) |
58 | { | 77 | { |
59 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | 78 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) |
@@ -69,13 +88,12 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
69 | if (!ath9k_hw_use_flash(ah)) { | 88 | if (!ath9k_hw_use_flash(ah)) { |
70 | if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, | 89 | if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, |
71 | &magic)) { | 90 | &magic)) { |
72 | ath_print(common, ATH_DBG_FATAL, | 91 | ath_err(common, "Reading Magic # failed\n"); |
73 | "Reading Magic # failed\n"); | ||
74 | return false; | 92 | return false; |
75 | } | 93 | } |
76 | 94 | ||
77 | ath_print(common, ATH_DBG_EEPROM, | 95 | ath_dbg(common, ATH_DBG_EEPROM, |
78 | "Read Magic = 0x%04X\n", magic); | 96 | "Read Magic = 0x%04X\n", magic); |
79 | 97 | ||
80 | if (magic != AR5416_EEPROM_MAGIC) { | 98 | if (magic != AR5416_EEPROM_MAGIC) { |
81 | magic2 = swab16(magic); | 99 | magic2 = swab16(magic); |
@@ -90,16 +108,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
90 | eepdata++; | 108 | eepdata++; |
91 | } | 109 | } |
92 | } else { | 110 | } else { |
93 | ath_print(common, ATH_DBG_FATAL, | 111 | ath_err(common, |
94 | "Invalid EEPROM Magic. " | 112 | "Invalid EEPROM Magic. Endianness mismatch.\n"); |
95 | "endianness mismatch.\n"); | ||
96 | return -EINVAL; | 113 | return -EINVAL; |
97 | } | 114 | } |
98 | } | 115 | } |
99 | } | 116 | } |
100 | 117 | ||
101 | ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", | 118 | ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n", |
102 | need_swap ? "True" : "False"); | 119 | need_swap ? "True" : "False"); |
103 | 120 | ||
104 | if (need_swap) | 121 | if (need_swap) |
105 | el = swab16(ah->eeprom.map4k.baseEepHeader.length); | 122 | el = swab16(ah->eeprom.map4k.baseEepHeader.length); |
@@ -120,8 +137,8 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
120 | u32 integer; | 137 | u32 integer; |
121 | u16 word; | 138 | u16 word; |
122 | 139 | ||
123 | ath_print(common, ATH_DBG_EEPROM, | 140 | ath_dbg(common, ATH_DBG_EEPROM, |
124 | "EEPROM Endianness is not native.. Changing\n"); | 141 | "EEPROM Endianness is not native.. Changing\n"); |
125 | 142 | ||
126 | word = swab16(eep->baseEepHeader.length); | 143 | word = swab16(eep->baseEepHeader.length); |
127 | eep->baseEepHeader.length = word; | 144 | eep->baseEepHeader.length = word; |
@@ -155,7 +172,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
155 | eep->modalHeader.antCtrlChain[i] = integer; | 172 | eep->modalHeader.antCtrlChain[i] = integer; |
156 | } | 173 | } |
157 | 174 | ||
158 | for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { | 175 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
159 | word = swab16(eep->modalHeader.spurChans[i].spurChan); | 176 | word = swab16(eep->modalHeader.spurChans[i].spurChan); |
160 | eep->modalHeader.spurChans[i].spurChan = word; | 177 | eep->modalHeader.spurChans[i].spurChan = word; |
161 | } | 178 | } |
@@ -163,9 +180,8 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
163 | 180 | ||
164 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | 181 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || |
165 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 182 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { |
166 | ath_print(common, ATH_DBG_FATAL, | 183 | ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", |
167 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | 184 | sum, ah->eep_ops->get_eeprom_ver(ah)); |
168 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
169 | return -EINVAL; | 185 | return -EINVAL; |
170 | } | 186 | } |
171 | 187 | ||
@@ -179,6 +195,9 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | |||
179 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | 195 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; |
180 | struct modal_eep_4k_header *pModal = &eep->modalHeader; | 196 | struct modal_eep_4k_header *pModal = &eep->modalHeader; |
181 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; | 197 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; |
198 | u16 ver_minor; | ||
199 | |||
200 | ver_minor = pBase->version & AR5416_EEP_VER_MINOR_MASK; | ||
182 | 201 | ||
183 | switch (param) { | 202 | switch (param) { |
184 | case EEP_NFTHRESH_2: | 203 | case EEP_NFTHRESH_2: |
@@ -204,7 +223,7 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | |||
204 | case EEP_DB_2: | 223 | case EEP_DB_2: |
205 | return pModal->db1_1; | 224 | return pModal->db1_1; |
206 | case EEP_MINOR_REV: | 225 | case EEP_MINOR_REV: |
207 | return pBase->version & AR5416_EEP_VER_MINOR_MASK; | 226 | return ver_minor; |
208 | case EEP_TX_MASK: | 227 | case EEP_TX_MASK: |
209 | return pBase->txMask; | 228 | return pBase->txMask; |
210 | case EEP_RX_MASK: | 229 | case EEP_RX_MASK: |
@@ -213,178 +232,20 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | |||
213 | return 0; | 232 | return 0; |
214 | case EEP_PWR_TABLE_OFFSET: | 233 | case EEP_PWR_TABLE_OFFSET: |
215 | return AR5416_PWR_TABLE_OFFSET_DB; | 234 | return AR5416_PWR_TABLE_OFFSET_DB; |
235 | case EEP_MODAL_VER: | ||
236 | return pModal->version; | ||
237 | case EEP_ANT_DIV_CTL1: | ||
238 | return pModal->antdiv_ctl1; | ||
239 | case EEP_TXGAIN_TYPE: | ||
240 | if (ver_minor >= AR5416_EEP_MINOR_VER_19) | ||
241 | return pBase->txGainType; | ||
242 | else | ||
243 | return AR5416_EEP_TXGAIN_ORIGINAL; | ||
216 | default: | 244 | default: |
217 | return 0; | 245 | return 0; |
218 | } | 246 | } |
219 | } | 247 | } |
220 | 248 | ||
221 | static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
222 | struct ath9k_channel *chan, | ||
223 | struct cal_data_per_freq_4k *pRawDataSet, | ||
224 | u8 *bChans, u16 availPiers, | ||
225 | u16 tPdGainOverlap, | ||
226 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
227 | u16 numXpdGains) | ||
228 | { | ||
229 | #define TMP_VAL_VPD_TABLE \ | ||
230 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); | ||
231 | int i, j, k; | ||
232 | int16_t ss; | ||
233 | u16 idxL = 0, idxR = 0, numPiers; | ||
234 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] | ||
235 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
236 | static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] | ||
237 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
238 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] | ||
239 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
240 | |||
241 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
242 | u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; | ||
243 | u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; | ||
244 | int16_t vpdStep; | ||
245 | int16_t tmpVal; | ||
246 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
247 | bool match; | ||
248 | int16_t minDelta = 0; | ||
249 | struct chan_centers centers; | ||
250 | #define PD_GAIN_BOUNDARY_DEFAULT 58; | ||
251 | |||
252 | memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); | ||
253 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
254 | |||
255 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
256 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
257 | break; | ||
258 | } | ||
259 | |||
260 | match = ath9k_hw_get_lower_upper_index( | ||
261 | (u8)FREQ2FBIN(centers.synth_center, | ||
262 | IS_CHAN_2GHZ(chan)), bChans, numPiers, | ||
263 | &idxL, &idxR); | ||
264 | |||
265 | if (match) { | ||
266 | for (i = 0; i < numXpdGains; i++) { | ||
267 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
268 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
269 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
270 | pRawDataSet[idxL].pwrPdg[i], | ||
271 | pRawDataSet[idxL].vpdPdg[i], | ||
272 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
273 | vpdTableI[i]); | ||
274 | } | ||
275 | } else { | ||
276 | for (i = 0; i < numXpdGains; i++) { | ||
277 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
278 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
279 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
280 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
281 | |||
282 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
283 | |||
284 | maxPwrT4[i] = | ||
285 | min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1], | ||
286 | pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]); | ||
287 | |||
288 | |||
289 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
290 | pPwrL, pVpdL, | ||
291 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
292 | vpdTableL[i]); | ||
293 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
294 | pPwrR, pVpdR, | ||
295 | AR5416_EEP4K_PD_GAIN_ICEPTS, | ||
296 | vpdTableR[i]); | ||
297 | |||
298 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
299 | vpdTableI[i][j] = | ||
300 | (u8)(ath9k_hw_interpolate((u16) | ||
301 | FREQ2FBIN(centers. | ||
302 | synth_center, | ||
303 | IS_CHAN_2GHZ | ||
304 | (chan)), | ||
305 | bChans[idxL], bChans[idxR], | ||
306 | vpdTableL[i][j], vpdTableR[i][j])); | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | |||
311 | k = 0; | ||
312 | |||
313 | for (i = 0; i < numXpdGains; i++) { | ||
314 | if (i == (numXpdGains - 1)) | ||
315 | pPdGainBoundaries[i] = | ||
316 | (u16)(maxPwrT4[i] / 2); | ||
317 | else | ||
318 | pPdGainBoundaries[i] = | ||
319 | (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); | ||
320 | |||
321 | pPdGainBoundaries[i] = | ||
322 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); | ||
323 | |||
324 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
325 | minDelta = pPdGainBoundaries[0] - 23; | ||
326 | pPdGainBoundaries[0] = 23; | ||
327 | } else { | ||
328 | minDelta = 0; | ||
329 | } | ||
330 | |||
331 | if (i == 0) { | ||
332 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
333 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
334 | else | ||
335 | ss = 0; | ||
336 | } else { | ||
337 | ss = (int16_t)((pPdGainBoundaries[i - 1] - | ||
338 | (minPwrT4[i] / 2)) - | ||
339 | tPdGainOverlap + 1 + minDelta); | ||
340 | } | ||
341 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
342 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
343 | |||
344 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
345 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
346 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
347 | ss++; | ||
348 | } | ||
349 | |||
350 | sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
351 | tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - | ||
352 | (minPwrT4[i] / 2)); | ||
353 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
354 | tgtIndex : sizeCurrVpdTable; | ||
355 | |||
356 | while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) | ||
357 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
358 | |||
359 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
360 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
361 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
362 | |||
363 | if (tgtIndex >= maxIndex) { | ||
364 | while ((ss <= tgtIndex) && | ||
365 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
366 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | ||
367 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
368 | 255 : tmpVal); | ||
369 | ss++; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | |||
374 | while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) { | ||
375 | pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT; | ||
376 | i++; | ||
377 | } | ||
378 | |||
379 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
380 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
381 | k++; | ||
382 | } | ||
383 | |||
384 | return; | ||
385 | #undef TMP_VAL_VPD_TABLE | ||
386 | } | ||
387 | |||
388 | static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | 249 | static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, |
389 | struct ath9k_channel *chan, | 250 | struct ath9k_channel *chan, |
390 | int16_t *pTxPowerIndexOffset) | 251 | int16_t *pTxPowerIndexOffset) |
@@ -395,7 +256,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
395 | u8 *pCalBChans = NULL; | 256 | u8 *pCalBChans = NULL; |
396 | u16 pdGainOverlap_t2; | 257 | u16 pdGainOverlap_t2; |
397 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; | 258 | static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; |
398 | u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; | 259 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; |
399 | u16 numPiers, i, j; | 260 | u16 numPiers, i, j; |
400 | u16 numXpdGain, xpdMask; | 261 | u16 numXpdGain, xpdMask; |
401 | u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; | 262 | u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; |
@@ -417,12 +278,12 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
417 | 278 | ||
418 | numXpdGain = 0; | 279 | numXpdGain = 0; |
419 | 280 | ||
420 | for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { | 281 | for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { |
421 | if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { | 282 | if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { |
422 | if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) | 283 | if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) |
423 | break; | 284 | break; |
424 | xpdGainValues[numXpdGain] = | 285 | xpdGainValues[numXpdGain] = |
425 | (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); | 286 | (u16)(AR5416_PD_GAINS_IN_MASK - i); |
426 | numXpdGain++; | 287 | numXpdGain++; |
427 | } | 288 | } |
428 | } | 289 | } |
@@ -446,7 +307,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
446 | if (pEepData->baseEepHeader.txMask & (1 << i)) { | 307 | if (pEepData->baseEepHeader.txMask & (1 << i)) { |
447 | pRawDataset = pEepData->calPierData2G[i]; | 308 | pRawDataset = pEepData->calPierData2G[i]; |
448 | 309 | ||
449 | ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan, | 310 | ath9k_hw_get_gain_boundaries_pdadcs(ah, chan, |
450 | pRawDataset, pCalBChans, | 311 | pRawDataset, pCalBChans, |
451 | numPiers, pdGainOverlap_t2, | 312 | numPiers, pdGainOverlap_t2, |
452 | gainBoundaries, | 313 | gainBoundaries, |
@@ -476,27 +337,25 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, | |||
476 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); | 337 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); |
477 | REG_WRITE(ah, regOffset, reg32); | 338 | REG_WRITE(ah, regOffset, reg32); |
478 | 339 | ||
479 | ath_print(common, ATH_DBG_EEPROM, | 340 | ath_dbg(common, ATH_DBG_EEPROM, |
480 | "PDADC (%d,%4x): %4.4x %8.8x\n", | 341 | "PDADC (%d,%4x): %4.4x %8.8x\n", |
481 | i, regChainOffset, regOffset, | 342 | i, regChainOffset, regOffset, |
482 | reg32); | 343 | reg32); |
483 | ath_print(common, ATH_DBG_EEPROM, | 344 | ath_dbg(common, ATH_DBG_EEPROM, |
484 | "PDADC: Chain %d | " | 345 | "PDADC: Chain %d | " |
485 | "PDADC %3d Value %3d | " | 346 | "PDADC %3d Value %3d | " |
486 | "PDADC %3d Value %3d | " | 347 | "PDADC %3d Value %3d | " |
487 | "PDADC %3d Value %3d | " | 348 | "PDADC %3d Value %3d | " |
488 | "PDADC %3d Value %3d |\n", | 349 | "PDADC %3d Value %3d |\n", |
489 | i, 4 * j, pdadcValues[4 * j], | 350 | i, 4 * j, pdadcValues[4 * j], |
490 | 4 * j + 1, pdadcValues[4 * j + 1], | 351 | 4 * j + 1, pdadcValues[4 * j + 1], |
491 | 4 * j + 2, pdadcValues[4 * j + 2], | 352 | 4 * j + 2, pdadcValues[4 * j + 2], |
492 | 4 * j + 3, | 353 | 4 * j + 3, pdadcValues[4 * j + 3]); |
493 | pdadcValues[4 * j + 3]); | ||
494 | 354 | ||
495 | regOffset += 4; | 355 | regOffset += 4; |
496 | } | 356 | } |
497 | 357 | ||
498 | REGWRITE_BUFFER_FLUSH(ah); | 358 | REGWRITE_BUFFER_FLUSH(ah); |
499 | DISABLE_REGWRITE_BUFFER(ah); | ||
500 | } | 359 | } |
501 | } | 360 | } |
502 | 361 | ||
@@ -521,14 +380,16 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | |||
521 | int i; | 380 | int i; |
522 | int16_t twiceLargestAntenna; | 381 | int16_t twiceLargestAntenna; |
523 | u16 twiceMinEdgePower; | 382 | u16 twiceMinEdgePower; |
524 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 383 | u16 twiceMaxEdgePower = MAX_RATE_POWER; |
525 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | 384 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; |
526 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | 385 | u16 numCtlModes; |
386 | const u16 *pCtlMode; | ||
387 | u16 ctlMode, freq; | ||
527 | struct chan_centers centers; | 388 | struct chan_centers centers; |
528 | struct cal_ctl_data_4k *rep; | 389 | struct cal_ctl_data_4k *rep; |
529 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | 390 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; |
530 | static const u16 tpScaleReductionTable[5] = | 391 | static const u16 tpScaleReductionTable[5] = |
531 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | 392 | { 0, 3, 6, 9, MAX_RATE_POWER }; |
532 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { | 393 | struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { |
533 | 0, { 0, 0, 0, 0} | 394 | 0, { 0, 0, 0, 0} |
534 | }; | 395 | }; |
@@ -539,10 +400,10 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | |||
539 | struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { | 400 | struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { |
540 | 0, {0, 0, 0, 0} | 401 | 0, {0, 0, 0, 0} |
541 | }; | 402 | }; |
542 | u16 ctlModesFor11g[] = | 403 | static const u16 ctlModesFor11g[] = { |
543 | { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, | 404 | CTL_11B, CTL_11G, CTL_2GHT20, |
544 | CTL_2GHT40 | 405 | CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 |
545 | }; | 406 | }; |
546 | 407 | ||
547 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 408 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
548 | 409 | ||
@@ -604,7 +465,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | |||
604 | 465 | ||
605 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | 466 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && |
606 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | 467 | ah->eep_ops->get_eeprom_rev(ah) <= 2) |
607 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 468 | twiceMaxEdgePower = MAX_RATE_POWER; |
608 | 469 | ||
609 | for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && | 470 | for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && |
610 | pEepData->ctlIndex[i]; i++) { | 471 | pEepData->ctlIndex[i]; i++) { |
@@ -715,7 +576,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
715 | u16 cfgCtl, | 576 | u16 cfgCtl, |
716 | u8 twiceAntennaReduction, | 577 | u8 twiceAntennaReduction, |
717 | u8 twiceMaxRegulatoryPower, | 578 | u8 twiceMaxRegulatoryPower, |
718 | u8 powerLimit) | 579 | u8 powerLimit, bool test) |
719 | { | 580 | { |
720 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 581 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
721 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | 582 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; |
@@ -740,15 +601,20 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
740 | 601 | ||
741 | ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); | 602 | ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); |
742 | 603 | ||
604 | regulatory->max_power_level = 0; | ||
743 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | 605 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { |
744 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | 606 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); |
745 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) | 607 | if (ratesArray[i] > MAX_RATE_POWER) |
746 | ratesArray[i] = AR5416_MAX_RATE_POWER; | 608 | ratesArray[i] = MAX_RATE_POWER; |
609 | |||
610 | if (ratesArray[i] > regulatory->max_power_level) | ||
611 | regulatory->max_power_level = ratesArray[i]; | ||
747 | } | 612 | } |
748 | 613 | ||
614 | if (test) | ||
615 | return; | ||
749 | 616 | ||
750 | /* Update regulatory */ | 617 | /* Update regulatory */ |
751 | |||
752 | i = rate6mb; | 618 | i = rate6mb; |
753 | if (IS_CHAN_HT40(chan)) | 619 | if (IS_CHAN_HT40(chan)) |
754 | i = rateHt40_0; | 620 | i = rateHt40_0; |
@@ -757,7 +623,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
757 | 623 | ||
758 | regulatory->max_power_level = ratesArray[i]; | 624 | regulatory->max_power_level = ratesArray[i]; |
759 | 625 | ||
760 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 626 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
761 | for (i = 0; i < Ar5416RateSize; i++) | 627 | for (i = 0; i < Ar5416RateSize; i++) |
762 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; | 628 | ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; |
763 | } | 629 | } |
@@ -828,7 +694,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
828 | } | 694 | } |
829 | 695 | ||
830 | REGWRITE_BUFFER_FLUSH(ah); | 696 | REGWRITE_BUFFER_FLUSH(ah); |
831 | DISABLE_REGWRITE_BUFFER(ah); | ||
832 | } | 697 | } |
833 | 698 | ||
834 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, | 699 | static void ath9k_hw_4k_set_addac(struct ath_hw *ah, |
@@ -905,9 +770,6 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, | |||
905 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | 770 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); |
906 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, | 771 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, |
907 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | 772 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); |
908 | |||
909 | if (AR_SREV_9285_11(ah)) | ||
910 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | ||
911 | } | 773 | } |
912 | 774 | ||
913 | /* | 775 | /* |
@@ -919,6 +781,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
919 | { | 781 | { |
920 | struct modal_eep_4k_header *pModal; | 782 | struct modal_eep_4k_header *pModal; |
921 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | 783 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; |
784 | struct base_eep_header_4k *pBase = &eep->baseEepHeader; | ||
922 | u8 txRxAttenLocal; | 785 | u8 txRxAttenLocal; |
923 | u8 ob[5], db1[5], db2[5]; | 786 | u8 ob[5], db1[5], db2[5]; |
924 | u8 ant_div_control1, ant_div_control2; | 787 | u8 ant_div_control1, ant_div_control2; |
@@ -927,8 +790,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
927 | pModal = &eep->modalHeader; | 790 | pModal = &eep->modalHeader; |
928 | txRxAttenLocal = 23; | 791 | txRxAttenLocal = 23; |
929 | 792 | ||
930 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | 793 | REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); |
931 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
932 | 794 | ||
933 | /* Single chain for 4K EEPROM*/ | 795 | /* Single chain for 4K EEPROM*/ |
934 | ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal); | 796 | ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal); |
@@ -1105,9 +967,6 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1105 | } | 967 | } |
1106 | 968 | ||
1107 | 969 | ||
1108 | if (AR_SREV_9285_11(ah)) | ||
1109 | REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); | ||
1110 | |||
1111 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, | 970 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, |
1112 | pModal->switchSettling); | 971 | pModal->switchSettling); |
1113 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, | 972 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, |
@@ -1145,21 +1004,31 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1145 | AR_PHY_SETTLING_SWITCH, | 1004 | AR_PHY_SETTLING_SWITCH, |
1146 | pModal->swSettleHt40); | 1005 | pModal->swSettleHt40); |
1147 | } | 1006 | } |
1148 | } | 1007 | if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) { |
1149 | 1008 | u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna & | |
1150 | static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, | 1009 | EEP_4K_BB_DESIRED_SCALE_MASK); |
1151 | struct ath9k_channel *chan) | 1010 | if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) { |
1152 | { | 1011 | u32 pwrctrl, mask, clr; |
1153 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | 1012 | |
1154 | struct modal_eep_4k_header *pModal = &eep->modalHeader; | 1013 | mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25); |
1155 | 1014 | pwrctrl = mask * bb_desired_scale; | |
1156 | return pModal->antCtrlCommon; | 1015 | clr = mask * 0x1f; |
1157 | } | 1016 | REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr); |
1158 | 1017 | REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr); | |
1159 | static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, | 1018 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr); |
1160 | enum ieee80211_band freq_band) | 1019 | |
1161 | { | 1020 | mask = BIT(0)|BIT(5)|BIT(15); |
1162 | return 1; | 1021 | pwrctrl = mask * bb_desired_scale; |
1022 | clr = mask * 0x1f; | ||
1023 | REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr); | ||
1024 | |||
1025 | mask = BIT(0)|BIT(5); | ||
1026 | pwrctrl = mask * bb_desired_scale; | ||
1027 | clr = mask * 0x1f; | ||
1028 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr); | ||
1029 | REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr); | ||
1030 | } | ||
1031 | } | ||
1163 | } | 1032 | } |
1164 | 1033 | ||
1165 | static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | 1034 | static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) |
@@ -1170,17 +1039,17 @@ static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | |||
1170 | 1039 | ||
1171 | u16 spur_val = AR_NO_SPUR; | 1040 | u16 spur_val = AR_NO_SPUR; |
1172 | 1041 | ||
1173 | ath_print(common, ATH_DBG_ANI, | 1042 | ath_dbg(common, ATH_DBG_ANI, |
1174 | "Getting spur idx %d is2Ghz. %d val %x\n", | 1043 | "Getting spur idx:%d is2Ghz:%d val:%x\n", |
1175 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | 1044 | i, is2GHz, ah->config.spurchans[i][is2GHz]); |
1176 | 1045 | ||
1177 | switch (ah->config.spurmode) { | 1046 | switch (ah->config.spurmode) { |
1178 | case SPUR_DISABLE: | 1047 | case SPUR_DISABLE: |
1179 | break; | 1048 | break; |
1180 | case SPUR_ENABLE_IOCTL: | 1049 | case SPUR_ENABLE_IOCTL: |
1181 | spur_val = ah->config.spurchans[i][is2GHz]; | 1050 | spur_val = ah->config.spurchans[i][is2GHz]; |
1182 | ath_print(common, ATH_DBG_ANI, | 1051 | ath_dbg(common, ATH_DBG_ANI, |
1183 | "Getting spur val from new loc. %d\n", spur_val); | 1052 | "Getting spur val from new loc. %d\n", spur_val); |
1184 | break; | 1053 | break; |
1185 | case SPUR_ENABLE_EEPROM: | 1054 | case SPUR_ENABLE_EEPROM: |
1186 | spur_val = EEP_MAP4K_SPURCHAN; | 1055 | spur_val = EEP_MAP4K_SPURCHAN; |
@@ -1198,8 +1067,6 @@ const struct eeprom_ops eep_4k_ops = { | |||
1198 | .fill_eeprom = ath9k_hw_4k_fill_eeprom, | 1067 | .fill_eeprom = ath9k_hw_4k_fill_eeprom, |
1199 | .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, | 1068 | .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, |
1200 | .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, | 1069 | .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, |
1201 | .get_num_ant_config = ath9k_hw_4k_get_num_ant_config, | ||
1202 | .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg, | ||
1203 | .set_board_values = ath9k_hw_4k_set_board_values, | 1070 | .set_board_values = ath9k_hw_4k_set_board_values, |
1204 | .set_addac = ath9k_hw_4k_set_addac, | 1071 | .set_addac = ath9k_hw_4k_set_addac, |
1205 | .set_txpower = ath9k_hw_4k_set_txpower, | 1072 | .set_txpower = ath9k_hw_4k_set_txpower, |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index dff2da777312..343fc9f946db 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,7 +17,7 @@ | |||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "ar9002_phy.h" | 18 | #include "ar9002_phy.h" |
19 | 19 | ||
20 | #define NUM_EEP_WORDS (sizeof(struct ar9287_eeprom) / sizeof(u16)) | 20 | #define SIZE_EEPROM_AR9287 (sizeof(struct ar9287_eeprom) / sizeof(u16)) |
21 | 21 | ||
22 | static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) | 22 | static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah) |
23 | { | 23 | { |
@@ -29,29 +29,19 @@ static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah) | |||
29 | return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; | 29 | return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; |
30 | } | 30 | } |
31 | 31 | ||
32 | static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) | 32 | static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) |
33 | { | 33 | { |
34 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 34 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
35 | struct ath_common *common = ath9k_hw_common(ah); | 35 | struct ath_common *common = ath9k_hw_common(ah); |
36 | u16 *eep_data; | 36 | u16 *eep_data; |
37 | int addr, eep_start_loc; | 37 | int addr, eep_start_loc = AR9287_EEP_START_LOC; |
38 | eep_data = (u16 *)eep; | 38 | eep_data = (u16 *)eep; |
39 | 39 | ||
40 | if (ah->hw_version.devid == 0x7015) | 40 | for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) { |
41 | eep_start_loc = AR9287_HTC_EEP_START_LOC; | ||
42 | else | ||
43 | eep_start_loc = AR9287_EEP_START_LOC; | ||
44 | |||
45 | if (!ath9k_hw_use_flash(ah)) { | ||
46 | ath_print(common, ATH_DBG_EEPROM, | ||
47 | "Reading from EEPROM, not flash\n"); | ||
48 | } | ||
49 | |||
50 | for (addr = 0; addr < NUM_EEP_WORDS; addr++) { | ||
51 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, | 41 | if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, |
52 | eep_data)) { | 42 | eep_data)) { |
53 | ath_print(common, ATH_DBG_EEPROM, | 43 | ath_dbg(common, ATH_DBG_EEPROM, |
54 | "Unable to read eeprom region\n"); | 44 | "Unable to read eeprom region\n"); |
55 | return false; | 45 | return false; |
56 | } | 46 | } |
57 | eep_data++; | 47 | eep_data++; |
@@ -60,6 +50,31 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) | |||
60 | return true; | 50 | return true; |
61 | } | 51 | } |
62 | 52 | ||
53 | static bool __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah) | ||
54 | { | ||
55 | u16 *eep_data = (u16 *)&ah->eeprom.map9287; | ||
56 | |||
57 | ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, | ||
58 | AR9287_HTC_EEP_START_LOC, | ||
59 | SIZE_EEPROM_AR9287); | ||
60 | return true; | ||
61 | } | ||
62 | |||
63 | static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) | ||
64 | { | ||
65 | struct ath_common *common = ath9k_hw_common(ah); | ||
66 | |||
67 | if (!ath9k_hw_use_flash(ah)) { | ||
68 | ath_dbg(common, ATH_DBG_EEPROM, | ||
69 | "Reading from EEPROM, not flash\n"); | ||
70 | } | ||
71 | |||
72 | if (common->bus_ops->ath_bus_type == ATH_USB) | ||
73 | return __ath9k_hw_usb_ar9287_fill_eeprom(ah); | ||
74 | else | ||
75 | return __ath9k_hw_ar9287_fill_eeprom(ah); | ||
76 | } | ||
77 | |||
63 | static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) | 78 | static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) |
64 | { | 79 | { |
65 | u32 sum = 0, el, integer; | 80 | u32 sum = 0, el, integer; |
@@ -72,13 +87,12 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) | |||
72 | if (!ath9k_hw_use_flash(ah)) { | 87 | if (!ath9k_hw_use_flash(ah)) { |
73 | if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, | 88 | if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, |
74 | &magic)) { | 89 | &magic)) { |
75 | ath_print(common, ATH_DBG_FATAL, | 90 | ath_err(common, "Reading Magic # failed\n"); |
76 | "Reading Magic # failed\n"); | ||
77 | return false; | 91 | return false; |
78 | } | 92 | } |
79 | 93 | ||
80 | ath_print(common, ATH_DBG_EEPROM, | 94 | ath_dbg(common, ATH_DBG_EEPROM, |
81 | "Read Magic = 0x%04X\n", magic); | 95 | "Read Magic = 0x%04X\n", magic); |
82 | 96 | ||
83 | if (magic != AR5416_EEPROM_MAGIC) { | 97 | if (magic != AR5416_EEPROM_MAGIC) { |
84 | magic2 = swab16(magic); | 98 | magic2 = swab16(magic); |
@@ -87,22 +101,21 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) | |||
87 | need_swap = true; | 101 | need_swap = true; |
88 | eepdata = (u16 *)(&ah->eeprom); | 102 | eepdata = (u16 *)(&ah->eeprom); |
89 | 103 | ||
90 | for (addr = 0; addr < NUM_EEP_WORDS; addr++) { | 104 | for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) { |
91 | temp = swab16(*eepdata); | 105 | temp = swab16(*eepdata); |
92 | *eepdata = temp; | 106 | *eepdata = temp; |
93 | eepdata++; | 107 | eepdata++; |
94 | } | 108 | } |
95 | } else { | 109 | } else { |
96 | ath_print(common, ATH_DBG_FATAL, | 110 | ath_err(common, |
97 | "Invalid EEPROM Magic. " | 111 | "Invalid EEPROM Magic. Endianness mismatch.\n"); |
98 | "Endianness mismatch.\n"); | ||
99 | return -EINVAL; | 112 | return -EINVAL; |
100 | } | 113 | } |
101 | } | 114 | } |
102 | } | 115 | } |
103 | 116 | ||
104 | ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", | 117 | ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n", |
105 | need_swap ? "True" : "False"); | 118 | need_swap ? "True" : "False"); |
106 | 119 | ||
107 | if (need_swap) | 120 | if (need_swap) |
108 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); | 121 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); |
@@ -152,7 +165,7 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) | |||
152 | eep->modalHeader.antCtrlChain[i] = integer; | 165 | eep->modalHeader.antCtrlChain[i] = integer; |
153 | } | 166 | } |
154 | 167 | ||
155 | for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) { | 168 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
156 | word = swab16(eep->modalHeader.spurChans[i].spurChan); | 169 | word = swab16(eep->modalHeader.spurChans[i].spurChan); |
157 | eep->modalHeader.spurChans[i].spurChan = word; | 170 | eep->modalHeader.spurChans[i].spurChan = word; |
158 | } | 171 | } |
@@ -160,9 +173,8 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) | |||
160 | 173 | ||
161 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER | 174 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER |
162 | || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 175 | || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { |
163 | ath_print(common, ATH_DBG_FATAL, | 176 | ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", |
164 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | 177 | sum, ah->eep_ops->get_eeprom_ver(ah)); |
165 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
166 | return -EINVAL; | 178 | return -EINVAL; |
167 | } | 179 | } |
168 | 180 | ||
@@ -223,163 +235,6 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, | |||
223 | } | 235 | } |
224 | } | 236 | } |
225 | 237 | ||
226 | static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
227 | struct ath9k_channel *chan, | ||
228 | struct cal_data_per_freq_ar9287 *pRawDataSet, | ||
229 | u8 *bChans, u16 availPiers, | ||
230 | u16 tPdGainOverlap, | ||
231 | u16 *pPdGainBoundaries, | ||
232 | u8 *pPDADCValues, | ||
233 | u16 numXpdGains) | ||
234 | { | ||
235 | #define TMP_VAL_VPD_TABLE \ | ||
236 | ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); | ||
237 | |||
238 | int i, j, k; | ||
239 | int16_t ss; | ||
240 | u16 idxL = 0, idxR = 0, numPiers; | ||
241 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
242 | u8 minPwrT4[AR9287_NUM_PD_GAINS]; | ||
243 | u8 maxPwrT4[AR9287_NUM_PD_GAINS]; | ||
244 | int16_t vpdStep; | ||
245 | int16_t tmpVal; | ||
246 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
247 | bool match; | ||
248 | int16_t minDelta = 0; | ||
249 | struct chan_centers centers; | ||
250 | static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] | ||
251 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
252 | static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] | ||
253 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
254 | static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] | ||
255 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
256 | |||
257 | memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); | ||
258 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
259 | |||
260 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
261 | if (bChans[numPiers] == AR9287_BCHAN_UNUSED) | ||
262 | break; | ||
263 | } | ||
264 | |||
265 | match = ath9k_hw_get_lower_upper_index( | ||
266 | (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), | ||
267 | bChans, numPiers, &idxL, &idxR); | ||
268 | |||
269 | if (match) { | ||
270 | for (i = 0; i < numXpdGains; i++) { | ||
271 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
272 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
273 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
274 | pRawDataSet[idxL].pwrPdg[i], | ||
275 | pRawDataSet[idxL].vpdPdg[i], | ||
276 | AR9287_PD_GAIN_ICEPTS, | ||
277 | vpdTableI[i]); | ||
278 | } | ||
279 | } else { | ||
280 | for (i = 0; i < numXpdGains; i++) { | ||
281 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
282 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
283 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
284 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
285 | |||
286 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
287 | |||
288 | maxPwrT4[i] = min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], | ||
289 | pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); | ||
290 | |||
291 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
292 | pPwrL, pVpdL, | ||
293 | AR9287_PD_GAIN_ICEPTS, | ||
294 | vpdTableL[i]); | ||
295 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
296 | pPwrR, pVpdR, | ||
297 | AR9287_PD_GAIN_ICEPTS, | ||
298 | vpdTableR[i]); | ||
299 | |||
300 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
301 | vpdTableI[i][j] = (u8)(ath9k_hw_interpolate( | ||
302 | (u16)FREQ2FBIN(centers. synth_center, | ||
303 | IS_CHAN_2GHZ(chan)), | ||
304 | bChans[idxL], bChans[idxR], | ||
305 | vpdTableL[i][j], vpdTableR[i][j])); | ||
306 | } | ||
307 | } | ||
308 | } | ||
309 | |||
310 | k = 0; | ||
311 | |||
312 | for (i = 0; i < numXpdGains; i++) { | ||
313 | if (i == (numXpdGains - 1)) | ||
314 | pPdGainBoundaries[i] = | ||
315 | (u16)(maxPwrT4[i] / 2); | ||
316 | else | ||
317 | pPdGainBoundaries[i] = | ||
318 | (u16)((maxPwrT4[i] + minPwrT4[i+1]) / 4); | ||
319 | |||
320 | pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, | ||
321 | pPdGainBoundaries[i]); | ||
322 | |||
323 | |||
324 | minDelta = 0; | ||
325 | |||
326 | if (i == 0) { | ||
327 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
328 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
329 | else | ||
330 | ss = 0; | ||
331 | } else { | ||
332 | ss = (int16_t)((pPdGainBoundaries[i-1] - | ||
333 | (minPwrT4[i] / 2)) - | ||
334 | tPdGainOverlap + 1 + minDelta); | ||
335 | } | ||
336 | |||
337 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
338 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
339 | |||
340 | while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { | ||
341 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
342 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
343 | ss++; | ||
344 | } | ||
345 | |||
346 | sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
347 | tgtIndex = (u8)(pPdGainBoundaries[i] + | ||
348 | tPdGainOverlap - (minPwrT4[i] / 2)); | ||
349 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
350 | tgtIndex : sizeCurrVpdTable; | ||
351 | |||
352 | while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1))) | ||
353 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
354 | |||
355 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
356 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
357 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
358 | |||
359 | if (tgtIndex > maxIndex) { | ||
360 | while ((ss <= tgtIndex) && | ||
361 | (k < (AR9287_NUM_PDADC_VALUES - 1))) { | ||
362 | tmpVal = (int16_t) TMP_VAL_VPD_TABLE; | ||
363 | pPDADCValues[k++] = | ||
364 | (u8)((tmpVal > 255) ? 255 : tmpVal); | ||
365 | ss++; | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | |||
370 | while (i < AR9287_PD_GAINS_IN_MASK) { | ||
371 | pPdGainBoundaries[i] = pPdGainBoundaries[i-1]; | ||
372 | i++; | ||
373 | } | ||
374 | |||
375 | while (k < AR9287_NUM_PDADC_VALUES) { | ||
376 | pPDADCValues[k] = pPDADCValues[k-1]; | ||
377 | k++; | ||
378 | } | ||
379 | |||
380 | #undef TMP_VAL_VPD_TABLE | ||
381 | } | ||
382 | |||
383 | static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | 238 | static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, |
384 | struct ath9k_channel *chan, | 239 | struct ath9k_channel *chan, |
385 | struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, | 240 | struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, |
@@ -392,7 +247,7 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | |||
392 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | 247 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); |
393 | 248 | ||
394 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | 249 | for (numPiers = 0; numPiers < availPiers; numPiers++) { |
395 | if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED) | 250 | if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED) |
396 | break; | 251 | break; |
397 | } | 252 | } |
398 | 253 | ||
@@ -458,16 +313,15 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
458 | struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; | 313 | struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; |
459 | u8 *pCalBChans = NULL; | 314 | u8 *pCalBChans = NULL; |
460 | u16 pdGainOverlap_t2; | 315 | u16 pdGainOverlap_t2; |
461 | u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; | 316 | u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; |
462 | u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; | 317 | u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; |
463 | u16 numPiers = 0, i, j; | 318 | u16 numPiers = 0, i, j; |
464 | u16 numXpdGain, xpdMask; | 319 | u16 numXpdGain, xpdMask; |
465 | u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; | 320 | u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0}; |
466 | u32 reg32, regOffset, regChainOffset, regval; | 321 | u32 reg32, regOffset, regChainOffset, regval; |
467 | int16_t modalIdx, diff = 0; | 322 | int16_t diff = 0; |
468 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | 323 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
469 | 324 | ||
470 | modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; | ||
471 | xpdMask = pEepData->modalHeader.xpdGain; | 325 | xpdMask = pEepData->modalHeader.xpdGain; |
472 | 326 | ||
473 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= | 327 | if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= |
@@ -490,12 +344,12 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
490 | numXpdGain = 0; | 344 | numXpdGain = 0; |
491 | 345 | ||
492 | /* Calculate the value of xpdgains from the xpdGain Mask */ | 346 | /* Calculate the value of xpdgains from the xpdGain Mask */ |
493 | for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { | 347 | for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { |
494 | if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { | 348 | if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { |
495 | if (numXpdGain >= AR9287_NUM_PD_GAINS) | 349 | if (numXpdGain >= AR5416_NUM_PD_GAINS) |
496 | break; | 350 | break; |
497 | xpdGainValues[numXpdGain] = | 351 | xpdGainValues[numXpdGain] = |
498 | (u16)(AR9287_PD_GAINS_IN_MASK-i); | 352 | (u16)(AR5416_PD_GAINS_IN_MASK-i); |
499 | numXpdGain++; | 353 | numXpdGain++; |
500 | } | 354 | } |
501 | } | 355 | } |
@@ -528,7 +382,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
528 | (struct cal_data_per_freq_ar9287 *) | 382 | (struct cal_data_per_freq_ar9287 *) |
529 | pEepData->calPierData2G[i]; | 383 | pEepData->calPierData2G[i]; |
530 | 384 | ||
531 | ath9k_hw_get_ar9287_gain_boundaries_pdadcs(ah, chan, | 385 | ath9k_hw_get_gain_boundaries_pdadcs(ah, chan, |
532 | pRawDataset, | 386 | pRawDataset, |
533 | pCalBChans, numPiers, | 387 | pCalBChans, numPiers, |
534 | pdGainOverlap_t2, | 388 | pdGainOverlap_t2, |
@@ -537,6 +391,8 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
537 | numXpdGain); | 391 | numXpdGain); |
538 | } | 392 | } |
539 | 393 | ||
394 | ENABLE_REGWRITE_BUFFER(ah); | ||
395 | |||
540 | if (i == 0) { | 396 | if (i == 0) { |
541 | if (!ath9k_hw_ar9287_get_eeprom(ah, | 397 | if (!ath9k_hw_ar9287_get_eeprom(ah, |
542 | EEP_OL_PWRCTRL)) { | 398 | EEP_OL_PWRCTRL)) { |
@@ -564,13 +420,13 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
564 | (int32_t)AR9287_PWR_TABLE_OFFSET_DB); | 420 | (int32_t)AR9287_PWR_TABLE_OFFSET_DB); |
565 | diff *= 2; | 421 | diff *= 2; |
566 | 422 | ||
567 | for (j = 0; j < ((u16)AR9287_NUM_PDADC_VALUES-diff); j++) | 423 | for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++) |
568 | pdadcValues[j] = pdadcValues[j+diff]; | 424 | pdadcValues[j] = pdadcValues[j+diff]; |
569 | 425 | ||
570 | for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); | 426 | for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff); |
571 | j < AR9287_NUM_PDADC_VALUES; j++) | 427 | j < AR5416_NUM_PDADC_VALUES; j++) |
572 | pdadcValues[j] = | 428 | pdadcValues[j] = |
573 | pdadcValues[AR9287_NUM_PDADC_VALUES-diff]; | 429 | pdadcValues[AR5416_NUM_PDADC_VALUES-diff]; |
574 | } | 430 | } |
575 | 431 | ||
576 | if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { | 432 | if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { |
@@ -587,6 +443,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, | |||
587 | regOffset += 4; | 443 | regOffset += 4; |
588 | } | 444 | } |
589 | } | 445 | } |
446 | REGWRITE_BUFFER_FLUSH(ah); | ||
590 | } | 447 | } |
591 | } | 448 | } |
592 | 449 | ||
@@ -613,9 +470,9 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
613 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 | 470 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 |
614 | 471 | ||
615 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 472 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
616 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 473 | u16 twiceMaxEdgePower = MAX_RATE_POWER; |
617 | static const u16 tpScaleReductionTable[5] = | 474 | static const u16 tpScaleReductionTable[5] = |
618 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | 475 | { 0, 3, 6, 9, MAX_RATE_POWER }; |
619 | int i; | 476 | int i; |
620 | int16_t twiceLargestAntenna; | 477 | int16_t twiceLargestAntenna; |
621 | struct cal_ctl_data_ar9287 *rep; | 478 | struct cal_ctl_data_ar9287 *rep; |
@@ -626,13 +483,13 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
626 | struct cal_target_power_ht targetPowerHt20, | 483 | struct cal_target_power_ht targetPowerHt20, |
627 | targetPowerHt40 = {0, {0, 0, 0, 0} }; | 484 | targetPowerHt40 = {0, {0, 0, 0, 0} }; |
628 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | 485 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; |
629 | u16 ctlModesFor11g[] = {CTL_11B, | 486 | static const u16 ctlModesFor11g[] = { |
630 | CTL_11G, | 487 | CTL_11B, CTL_11G, CTL_2GHT20, |
631 | CTL_2GHT20, | 488 | CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 |
632 | CTL_11B_EXT, | 489 | }; |
633 | CTL_11G_EXT, | 490 | u16 numCtlModes = 0; |
634 | CTL_2GHT40}; | 491 | const u16 *pCtlMode = NULL; |
635 | u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; | 492 | u16 ctlMode, freq; |
636 | struct chan_centers centers; | 493 | struct chan_centers centers; |
637 | int tx_chainmask; | 494 | int tx_chainmask; |
638 | u16 twiceMinEdgePower; | 495 | u16 twiceMinEdgePower; |
@@ -667,10 +524,16 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, | |||
667 | case 1: | 524 | case 1: |
668 | break; | 525 | break; |
669 | case 2: | 526 | case 2: |
670 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | 527 | if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) |
528 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
529 | else | ||
530 | scaledPower = 0; | ||
671 | break; | 531 | break; |
672 | case 3: | 532 | case 3: |
673 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | 533 | if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) |
534 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
535 | else | ||
536 | scaledPower = 0; | ||
674 | break; | 537 | break; |
675 | } | 538 | } |
676 | scaledPower = max((u16)0, scaledPower); | 539 | scaledPower = max((u16)0, scaledPower); |
@@ -853,7 +716,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
853 | struct ath9k_channel *chan, u16 cfgCtl, | 716 | struct ath9k_channel *chan, u16 cfgCtl, |
854 | u8 twiceAntennaReduction, | 717 | u8 twiceAntennaReduction, |
855 | u8 twiceMaxRegulatoryPower, | 718 | u8 twiceMaxRegulatoryPower, |
856 | u8 powerLimit) | 719 | u8 powerLimit, bool test) |
857 | { | 720 | { |
858 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 721 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
859 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | 722 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
@@ -877,17 +740,33 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
877 | 740 | ||
878 | ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); | 741 | ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); |
879 | 742 | ||
743 | regulatory->max_power_level = 0; | ||
880 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | 744 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { |
881 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | 745 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); |
882 | if (ratesArray[i] > AR9287_MAX_RATE_POWER) | 746 | if (ratesArray[i] > MAX_RATE_POWER) |
883 | ratesArray[i] = AR9287_MAX_RATE_POWER; | 747 | ratesArray[i] = MAX_RATE_POWER; |
748 | |||
749 | if (ratesArray[i] > regulatory->max_power_level) | ||
750 | regulatory->max_power_level = ratesArray[i]; | ||
884 | } | 751 | } |
885 | 752 | ||
886 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 753 | if (test) |
754 | return; | ||
755 | |||
756 | if (IS_CHAN_2GHZ(chan)) | ||
757 | i = rate1l; | ||
758 | else | ||
759 | i = rate6mb; | ||
760 | |||
761 | regulatory->max_power_level = ratesArray[i]; | ||
762 | |||
763 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
887 | for (i = 0; i < Ar5416RateSize; i++) | 764 | for (i = 0; i < Ar5416RateSize; i++) |
888 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; | 765 | ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; |
889 | } | 766 | } |
890 | 767 | ||
768 | ENABLE_REGWRITE_BUFFER(ah); | ||
769 | |||
891 | /* OFDM power per rate */ | 770 | /* OFDM power per rate */ |
892 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | 771 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, |
893 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | 772 | ATH9K_POW_SM(ratesArray[rate18mb], 24) |
@@ -971,17 +850,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, | |||
971 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) | 850 | | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) |
972 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); | 851 | | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); |
973 | } | 852 | } |
974 | 853 | REGWRITE_BUFFER_FLUSH(ah); | |
975 | if (IS_CHAN_2GHZ(chan)) | ||
976 | i = rate1l; | ||
977 | else | ||
978 | i = rate6mb; | ||
979 | |||
980 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
981 | regulatory->max_power_level = | ||
982 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; | ||
983 | else | ||
984 | regulatory->max_power_level = ratesArray[i]; | ||
985 | } | 854 | } |
986 | 855 | ||
987 | static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, | 856 | static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah, |
@@ -994,37 +863,13 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, | |||
994 | { | 863 | { |
995 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 864 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
996 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | 865 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; |
997 | u16 antWrites[AR9287_ANT_16S]; | ||
998 | u32 regChainOffset, regval; | 866 | u32 regChainOffset, regval; |
999 | u8 txRxAttenLocal; | 867 | u8 txRxAttenLocal; |
1000 | int i, j, offset_num; | 868 | int i; |
1001 | 869 | ||
1002 | pModal = &eep->modalHeader; | 870 | pModal = &eep->modalHeader; |
1003 | 871 | ||
1004 | antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); | 872 | REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon); |
1005 | antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); | ||
1006 | antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); | ||
1007 | antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); | ||
1008 | antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); | ||
1009 | antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); | ||
1010 | antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF); | ||
1011 | antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); | ||
1012 | |||
1013 | offset_num = 8; | ||
1014 | |||
1015 | for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { | ||
1016 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); | ||
1017 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); | ||
1018 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); | ||
1019 | antWrites[j++] = 0; | ||
1020 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); | ||
1021 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); | ||
1022 | antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); | ||
1023 | antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); | ||
1024 | } | ||
1025 | |||
1026 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
1027 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
1028 | 873 | ||
1029 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { | 874 | for (i = 0; i < AR9287_MAX_CHAINS; i++) { |
1030 | regChainOffset = i * 0x1000; | 875 | regChainOffset = i * 0x1000; |
@@ -1125,21 +970,6 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah, | |||
1125 | pModal->xpaBiasLvl); | 970 | pModal->xpaBiasLvl); |
1126 | } | 971 | } |
1127 | 972 | ||
1128 | static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah, | ||
1129 | enum ieee80211_band freq_band) | ||
1130 | { | ||
1131 | return 1; | ||
1132 | } | ||
1133 | |||
1134 | static u32 ath9k_hw_ar9287_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
1135 | struct ath9k_channel *chan) | ||
1136 | { | ||
1137 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | ||
1138 | struct modal_eep_ar9287_header *pModal = &eep->modalHeader; | ||
1139 | |||
1140 | return pModal->antCtrlCommon; | ||
1141 | } | ||
1142 | |||
1143 | static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, | 973 | static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, |
1144 | u16 i, bool is2GHz) | 974 | u16 i, bool is2GHz) |
1145 | { | 975 | { |
@@ -1149,17 +979,17 @@ static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah, | |||
1149 | struct ath_common *common = ath9k_hw_common(ah); | 979 | struct ath_common *common = ath9k_hw_common(ah); |
1150 | u16 spur_val = AR_NO_SPUR; | 980 | u16 spur_val = AR_NO_SPUR; |
1151 | 981 | ||
1152 | ath_print(common, ATH_DBG_ANI, | 982 | ath_dbg(common, ATH_DBG_ANI, |
1153 | "Getting spur idx %d is2Ghz. %d val %x\n", | 983 | "Getting spur idx:%d is2Ghz:%d val:%x\n", |
1154 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | 984 | i, is2GHz, ah->config.spurchans[i][is2GHz]); |
1155 | 985 | ||
1156 | switch (ah->config.spurmode) { | 986 | switch (ah->config.spurmode) { |
1157 | case SPUR_DISABLE: | 987 | case SPUR_DISABLE: |
1158 | break; | 988 | break; |
1159 | case SPUR_ENABLE_IOCTL: | 989 | case SPUR_ENABLE_IOCTL: |
1160 | spur_val = ah->config.spurchans[i][is2GHz]; | 990 | spur_val = ah->config.spurchans[i][is2GHz]; |
1161 | ath_print(common, ATH_DBG_ANI, | 991 | ath_dbg(common, ATH_DBG_ANI, |
1162 | "Getting spur val from new loc. %d\n", spur_val); | 992 | "Getting spur val from new loc. %d\n", spur_val); |
1163 | break; | 993 | break; |
1164 | case SPUR_ENABLE_EEPROM: | 994 | case SPUR_ENABLE_EEPROM: |
1165 | spur_val = EEP_MAP9287_SPURCHAN; | 995 | spur_val = EEP_MAP9287_SPURCHAN; |
@@ -1177,8 +1007,6 @@ const struct eeprom_ops eep_ar9287_ops = { | |||
1177 | .fill_eeprom = ath9k_hw_ar9287_fill_eeprom, | 1007 | .fill_eeprom = ath9k_hw_ar9287_fill_eeprom, |
1178 | .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, | 1008 | .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, |
1179 | .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, | 1009 | .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, |
1180 | .get_num_ant_config = ath9k_hw_ar9287_get_num_ant_config, | ||
1181 | .get_eeprom_antenna_cfg = ath9k_hw_ar9287_get_eeprom_antenna_cfg, | ||
1182 | .set_board_values = ath9k_hw_ar9287_set_board_values, | 1010 | .set_board_values = ath9k_hw_ar9287_set_board_values, |
1183 | .set_addac = ath9k_hw_ar9287_set_addac, | 1011 | .set_addac = ath9k_hw_ar9287_set_addac, |
1184 | .set_txpower = ath9k_hw_ar9287_set_txpower, | 1012 | .set_txpower = ath9k_hw_ar9287_set_txpower, |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index afa2b73ddbdd..17f0a6806207 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -86,9 +86,10 @@ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) | |||
86 | return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); | 86 | return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); |
87 | } | 87 | } |
88 | 88 | ||
89 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | ||
90 | { | ||
91 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) | 89 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) |
90 | |||
91 | static bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | ||
92 | { | ||
92 | struct ath_common *common = ath9k_hw_common(ah); | 93 | struct ath_common *common = ath9k_hw_common(ah); |
93 | u16 *eep_data = (u16 *)&ah->eeprom.def; | 94 | u16 *eep_data = (u16 *)&ah->eeprom.def; |
94 | int addr, ar5416_eep_start_loc = 0x100; | 95 | int addr, ar5416_eep_start_loc = 0x100; |
@@ -96,16 +97,41 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | |||
96 | for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { | 97 | for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { |
97 | if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc, | 98 | if (!ath9k_hw_nvram_read(common, addr + ar5416_eep_start_loc, |
98 | eep_data)) { | 99 | eep_data)) { |
99 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 100 | ath_err(ath9k_hw_common(ah), |
100 | "Unable to read eeprom region\n"); | 101 | "Unable to read eeprom region\n"); |
101 | return false; | 102 | return false; |
102 | } | 103 | } |
103 | eep_data++; | 104 | eep_data++; |
104 | } | 105 | } |
105 | return true; | 106 | return true; |
106 | #undef SIZE_EEPROM_DEF | ||
107 | } | 107 | } |
108 | 108 | ||
109 | static bool __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah) | ||
110 | { | ||
111 | u16 *eep_data = (u16 *)&ah->eeprom.def; | ||
112 | |||
113 | ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, | ||
114 | 0x100, SIZE_EEPROM_DEF); | ||
115 | return true; | ||
116 | } | ||
117 | |||
118 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | ||
119 | { | ||
120 | struct ath_common *common = ath9k_hw_common(ah); | ||
121 | |||
122 | if (!ath9k_hw_use_flash(ah)) { | ||
123 | ath_dbg(common, ATH_DBG_EEPROM, | ||
124 | "Reading from EEPROM, not flash\n"); | ||
125 | } | ||
126 | |||
127 | if (common->bus_ops->ath_bus_type == ATH_USB) | ||
128 | return __ath9k_hw_usb_def_fill_eeprom(ah); | ||
129 | else | ||
130 | return __ath9k_hw_def_fill_eeprom(ah); | ||
131 | } | ||
132 | |||
133 | #undef SIZE_EEPROM_DEF | ||
134 | |||
109 | static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | 135 | static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) |
110 | { | 136 | { |
111 | struct ar5416_eeprom_def *eep = | 137 | struct ar5416_eeprom_def *eep = |
@@ -117,13 +143,13 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
117 | int i, addr, size; | 143 | int i, addr, size; |
118 | 144 | ||
119 | if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | 145 | if (!ath9k_hw_nvram_read(common, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { |
120 | ath_print(common, ATH_DBG_FATAL, "Reading Magic # failed\n"); | 146 | ath_err(common, "Reading Magic # failed\n"); |
121 | return false; | 147 | return false; |
122 | } | 148 | } |
123 | 149 | ||
124 | if (!ath9k_hw_use_flash(ah)) { | 150 | if (!ath9k_hw_use_flash(ah)) { |
125 | ath_print(common, ATH_DBG_EEPROM, | 151 | ath_dbg(common, ATH_DBG_EEPROM, |
126 | "Read Magic = 0x%04X\n", magic); | 152 | "Read Magic = 0x%04X\n", magic); |
127 | 153 | ||
128 | if (magic != AR5416_EEPROM_MAGIC) { | 154 | if (magic != AR5416_EEPROM_MAGIC) { |
129 | magic2 = swab16(magic); | 155 | magic2 = swab16(magic); |
@@ -139,16 +165,15 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
139 | eepdata++; | 165 | eepdata++; |
140 | } | 166 | } |
141 | } else { | 167 | } else { |
142 | ath_print(common, ATH_DBG_FATAL, | 168 | ath_err(common, |
143 | "Invalid EEPROM Magic. " | 169 | "Invalid EEPROM Magic. Endianness mismatch.\n"); |
144 | "Endianness mismatch.\n"); | ||
145 | return -EINVAL; | 170 | return -EINVAL; |
146 | } | 171 | } |
147 | } | 172 | } |
148 | } | 173 | } |
149 | 174 | ||
150 | ath_print(common, ATH_DBG_EEPROM, "need_swap = %s.\n", | 175 | ath_dbg(common, ATH_DBG_EEPROM, "need_swap = %s.\n", |
151 | need_swap ? "True" : "False"); | 176 | need_swap ? "True" : "False"); |
152 | 177 | ||
153 | if (need_swap) | 178 | if (need_swap) |
154 | el = swab16(ah->eeprom.def.baseEepHeader.length); | 179 | el = swab16(ah->eeprom.def.baseEepHeader.length); |
@@ -169,8 +194,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
169 | u32 integer, j; | 194 | u32 integer, j; |
170 | u16 word; | 195 | u16 word; |
171 | 196 | ||
172 | ath_print(common, ATH_DBG_EEPROM, | 197 | ath_dbg(common, ATH_DBG_EEPROM, |
173 | "EEPROM Endianness is not native.. Changing.\n"); | 198 | "EEPROM Endianness is not native.. Changing.\n"); |
174 | 199 | ||
175 | word = swab16(eep->baseEepHeader.length); | 200 | word = swab16(eep->baseEepHeader.length); |
176 | eep->baseEepHeader.length = word; | 201 | eep->baseEepHeader.length = word; |
@@ -206,8 +231,12 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
206 | integer = swab32(pModal->antCtrlChain[i]); | 231 | integer = swab32(pModal->antCtrlChain[i]); |
207 | pModal->antCtrlChain[i] = integer; | 232 | pModal->antCtrlChain[i] = integer; |
208 | } | 233 | } |
234 | for (i = 0; i < 3; i++) { | ||
235 | word = swab16(pModal->xpaBiasLvlFreq[i]); | ||
236 | pModal->xpaBiasLvlFreq[i] = word; | ||
237 | } | ||
209 | 238 | ||
210 | for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { | 239 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
211 | word = swab16(pModal->spurChans[i].spurChan); | 240 | word = swab16(pModal->spurChans[i].spurChan); |
212 | pModal->spurChans[i].spurChan = word; | 241 | pModal->spurChans[i].spurChan = word; |
213 | } | 242 | } |
@@ -216,18 +245,21 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
216 | 245 | ||
217 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | 246 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || |
218 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 247 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { |
219 | ath_print(common, ATH_DBG_FATAL, | 248 | ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", |
220 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
221 | sum, ah->eep_ops->get_eeprom_ver(ah)); | 249 | sum, ah->eep_ops->get_eeprom_ver(ah)); |
222 | return -EINVAL; | 250 | return -EINVAL; |
223 | } | 251 | } |
224 | 252 | ||
225 | /* Enable fixup for AR_AN_TOP2 if necessary */ | 253 | /* Enable fixup for AR_AN_TOP2 if necessary */ |
226 | if (AR_SREV_9280_10_OR_LATER(ah) && | 254 | if ((ah->hw_version.devid == AR9280_DEVID_PCI) && |
227 | (eep->baseEepHeader.version & 0xff) > 0x0a && | 255 | ((eep->baseEepHeader.version & 0xff) > 0x0a) && |
228 | eep->baseEepHeader.pwdclkind == 0) | 256 | (eep->baseEepHeader.pwdclkind == 0)) |
229 | ah->need_an_top2_fixup = 1; | 257 | ah->need_an_top2_fixup = 1; |
230 | 258 | ||
259 | if ((common->bus_ops->ath_bus_type == ATH_USB) && | ||
260 | (AR_SREV_9280(ah))) | ||
261 | eep->modalHeader[0].xpaBiasLvl = 0; | ||
262 | |||
231 | return 0; | 263 | return 0; |
232 | } | 264 | } |
233 | 265 | ||
@@ -317,7 +349,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah, | |||
317 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { | 349 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { |
318 | txRxAttenLocal = pModal->txRxAttenCh[i]; | 350 | txRxAttenLocal = pModal->txRxAttenCh[i]; |
319 | 351 | ||
320 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 352 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
321 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | 353 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, |
322 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | 354 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, |
323 | pModal->bswMargin[i]); | 355 | pModal->bswMargin[i]); |
@@ -344,7 +376,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah, | |||
344 | } | 376 | } |
345 | } | 377 | } |
346 | 378 | ||
347 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 379 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
348 | REG_RMW_FIELD(ah, | 380 | REG_RMW_FIELD(ah, |
349 | AR_PHY_RXGAIN + regChainOffset, | 381 | AR_PHY_RXGAIN + regChainOffset, |
350 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | 382 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); |
@@ -376,8 +408,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
376 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | 408 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); |
377 | txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; | 409 | txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; |
378 | 410 | ||
379 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | 411 | REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon & 0xffff); |
380 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
381 | 412 | ||
382 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { | 413 | for (i = 0; i < AR5416_MAX_CHAINS; i++) { |
383 | if (AR_SREV_9280(ah)) { | 414 | if (AR_SREV_9280(ah)) { |
@@ -408,7 +439,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
408 | regChainOffset, i); | 439 | regChainOffset, i); |
409 | } | 440 | } |
410 | 441 | ||
411 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 442 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
412 | if (IS_CHAN_2GHZ(chan)) { | 443 | if (IS_CHAN_2GHZ(chan)) { |
413 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, | 444 | ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, |
414 | AR_AN_RF2G1_CH0_OB, | 445 | AR_AN_RF2G1_CH0_OB, |
@@ -451,9 +482,10 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
451 | ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, | 482 | ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, |
452 | AR_AN_TOP2_LOCALBIAS, | 483 | AR_AN_TOP2_LOCALBIAS, |
453 | AR_AN_TOP2_LOCALBIAS_S, | 484 | AR_AN_TOP2_LOCALBIAS_S, |
454 | pModal->local_bias); | 485 | !!(pModal->lna_ctl & |
486 | LNA_CTL_LOCAL_BIAS)); | ||
455 | REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, | 487 | REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, |
456 | pModal->force_xpaon); | 488 | !!(pModal->lna_ctl & LNA_CTL_FORCE_XPA)); |
457 | } | 489 | } |
458 | 490 | ||
459 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, | 491 | REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, |
@@ -461,7 +493,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
461 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, | 493 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, |
462 | pModal->adcDesiredSize); | 494 | pModal->adcDesiredSize); |
463 | 495 | ||
464 | if (!AR_SREV_9280_10_OR_LATER(ah)) | 496 | if (!AR_SREV_9280_20_OR_LATER(ah)) |
465 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | 497 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, |
466 | AR_PHY_DESIRED_SZ_PGA, | 498 | AR_PHY_DESIRED_SZ_PGA, |
467 | pModal->pgaDesiredSize); | 499 | pModal->pgaDesiredSize); |
@@ -478,7 +510,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
478 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, | 510 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, |
479 | pModal->txEndToRxOn); | 511 | pModal->txEndToRxOn); |
480 | 512 | ||
481 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 513 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
482 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, | 514 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, |
483 | pModal->thresh62); | 515 | pModal->thresh62); |
484 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, | 516 | REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, |
@@ -589,168 +621,6 @@ static void ath9k_hw_def_set_addac(struct ath_hw *ah, | |||
589 | #undef XPA_LVL_FREQ | 621 | #undef XPA_LVL_FREQ |
590 | } | 622 | } |
591 | 623 | ||
592 | static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, | ||
593 | struct ath9k_channel *chan, | ||
594 | struct cal_data_per_freq *pRawDataSet, | ||
595 | u8 *bChans, u16 availPiers, | ||
596 | u16 tPdGainOverlap, | ||
597 | u16 *pPdGainBoundaries, u8 *pPDADCValues, | ||
598 | u16 numXpdGains) | ||
599 | { | ||
600 | int i, j, k; | ||
601 | int16_t ss; | ||
602 | u16 idxL = 0, idxR = 0, numPiers; | ||
603 | static u8 vpdTableL[AR5416_NUM_PD_GAINS] | ||
604 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
605 | static u8 vpdTableR[AR5416_NUM_PD_GAINS] | ||
606 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
607 | static u8 vpdTableI[AR5416_NUM_PD_GAINS] | ||
608 | [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; | ||
609 | |||
610 | u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; | ||
611 | u8 minPwrT4[AR5416_NUM_PD_GAINS]; | ||
612 | u8 maxPwrT4[AR5416_NUM_PD_GAINS]; | ||
613 | int16_t vpdStep; | ||
614 | int16_t tmpVal; | ||
615 | u16 sizeCurrVpdTable, maxIndex, tgtIndex; | ||
616 | bool match; | ||
617 | int16_t minDelta = 0; | ||
618 | struct chan_centers centers; | ||
619 | |||
620 | memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS); | ||
621 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
622 | |||
623 | for (numPiers = 0; numPiers < availPiers; numPiers++) { | ||
624 | if (bChans[numPiers] == AR5416_BCHAN_UNUSED) | ||
625 | break; | ||
626 | } | ||
627 | |||
628 | match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center, | ||
629 | IS_CHAN_2GHZ(chan)), | ||
630 | bChans, numPiers, &idxL, &idxR); | ||
631 | |||
632 | if (match) { | ||
633 | for (i = 0; i < numXpdGains; i++) { | ||
634 | minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; | ||
635 | maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; | ||
636 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
637 | pRawDataSet[idxL].pwrPdg[i], | ||
638 | pRawDataSet[idxL].vpdPdg[i], | ||
639 | AR5416_PD_GAIN_ICEPTS, | ||
640 | vpdTableI[i]); | ||
641 | } | ||
642 | } else { | ||
643 | for (i = 0; i < numXpdGains; i++) { | ||
644 | pVpdL = pRawDataSet[idxL].vpdPdg[i]; | ||
645 | pPwrL = pRawDataSet[idxL].pwrPdg[i]; | ||
646 | pVpdR = pRawDataSet[idxR].vpdPdg[i]; | ||
647 | pPwrR = pRawDataSet[idxR].pwrPdg[i]; | ||
648 | |||
649 | minPwrT4[i] = max(pPwrL[0], pPwrR[0]); | ||
650 | |||
651 | maxPwrT4[i] = | ||
652 | min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], | ||
653 | pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); | ||
654 | |||
655 | |||
656 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
657 | pPwrL, pVpdL, | ||
658 | AR5416_PD_GAIN_ICEPTS, | ||
659 | vpdTableL[i]); | ||
660 | ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], | ||
661 | pPwrR, pVpdR, | ||
662 | AR5416_PD_GAIN_ICEPTS, | ||
663 | vpdTableR[i]); | ||
664 | |||
665 | for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { | ||
666 | vpdTableI[i][j] = | ||
667 | (u8)(ath9k_hw_interpolate((u16) | ||
668 | FREQ2FBIN(centers. | ||
669 | synth_center, | ||
670 | IS_CHAN_2GHZ | ||
671 | (chan)), | ||
672 | bChans[idxL], bChans[idxR], | ||
673 | vpdTableL[i][j], vpdTableR[i][j])); | ||
674 | } | ||
675 | } | ||
676 | } | ||
677 | |||
678 | k = 0; | ||
679 | |||
680 | for (i = 0; i < numXpdGains; i++) { | ||
681 | if (i == (numXpdGains - 1)) | ||
682 | pPdGainBoundaries[i] = | ||
683 | (u16)(maxPwrT4[i] / 2); | ||
684 | else | ||
685 | pPdGainBoundaries[i] = | ||
686 | (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); | ||
687 | |||
688 | pPdGainBoundaries[i] = | ||
689 | min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); | ||
690 | |||
691 | if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { | ||
692 | minDelta = pPdGainBoundaries[0] - 23; | ||
693 | pPdGainBoundaries[0] = 23; | ||
694 | } else { | ||
695 | minDelta = 0; | ||
696 | } | ||
697 | |||
698 | if (i == 0) { | ||
699 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
700 | ss = (int16_t)(0 - (minPwrT4[i] / 2)); | ||
701 | else | ||
702 | ss = 0; | ||
703 | } else { | ||
704 | ss = (int16_t)((pPdGainBoundaries[i - 1] - | ||
705 | (minPwrT4[i] / 2)) - | ||
706 | tPdGainOverlap + 1 + minDelta); | ||
707 | } | ||
708 | vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); | ||
709 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
710 | |||
711 | while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
712 | tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); | ||
713 | pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); | ||
714 | ss++; | ||
715 | } | ||
716 | |||
717 | sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); | ||
718 | tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - | ||
719 | (minPwrT4[i] / 2)); | ||
720 | maxIndex = (tgtIndex < sizeCurrVpdTable) ? | ||
721 | tgtIndex : sizeCurrVpdTable; | ||
722 | |||
723 | while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
724 | pPDADCValues[k++] = vpdTableI[i][ss++]; | ||
725 | } | ||
726 | |||
727 | vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - | ||
728 | vpdTableI[i][sizeCurrVpdTable - 2]); | ||
729 | vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); | ||
730 | |||
731 | if (tgtIndex >= maxIndex) { | ||
732 | while ((ss <= tgtIndex) && | ||
733 | (k < (AR5416_NUM_PDADC_VALUES - 1))) { | ||
734 | tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + | ||
735 | (ss - maxIndex + 1) * vpdStep)); | ||
736 | pPDADCValues[k++] = (u8)((tmpVal > 255) ? | ||
737 | 255 : tmpVal); | ||
738 | ss++; | ||
739 | } | ||
740 | } | ||
741 | } | ||
742 | |||
743 | while (i < AR5416_PD_GAINS_IN_MASK) { | ||
744 | pPdGainBoundaries[i] = pPdGainBoundaries[i - 1]; | ||
745 | i++; | ||
746 | } | ||
747 | |||
748 | while (k < AR5416_NUM_PDADC_VALUES) { | ||
749 | pPDADCValues[k] = pPDADCValues[k - 1]; | ||
750 | k++; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah, | 624 | static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah, |
755 | u16 *gb, | 625 | u16 *gb, |
756 | u16 numXpdGain, | 626 | u16 numXpdGain, |
@@ -783,7 +653,7 @@ static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah, | |||
783 | /* Because of a hardware limitation, ensure the gain boundary | 653 | /* Because of a hardware limitation, ensure the gain boundary |
784 | * is not larger than (63 - overlap) | 654 | * is not larger than (63 - overlap) |
785 | */ | 655 | */ |
786 | gb_limit = (u16)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2); | 656 | gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2); |
787 | 657 | ||
788 | for (k = 0; k < numXpdGain; k++) | 658 | for (k = 0; k < numXpdGain; k++) |
789 | gb[k] = (u16)min(gb_limit, gb[k]); | 659 | gb[k] = (u16)min(gb_limit, gb[k]); |
@@ -917,7 +787,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
917 | ath9k_olc_get_pdadcs(ah, pcdacIdx, | 787 | ath9k_olc_get_pdadcs(ah, pcdacIdx, |
918 | txPower/2, pdadcValues); | 788 | txPower/2, pdadcValues); |
919 | } else { | 789 | } else { |
920 | ath9k_hw_get_def_gain_boundaries_pdadcs(ah, | 790 | ath9k_hw_get_gain_boundaries_pdadcs(ah, |
921 | chan, pRawDataset, | 791 | chan, pRawDataset, |
922 | pCalBChans, numPiers, | 792 | pCalBChans, numPiers, |
923 | pdGainOverlap_t2, | 793 | pdGainOverlap_t2, |
@@ -933,6 +803,8 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
933 | pwr_table_offset, | 803 | pwr_table_offset, |
934 | &diff); | 804 | &diff); |
935 | 805 | ||
806 | ENABLE_REGWRITE_BUFFER(ah); | ||
807 | |||
936 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | 808 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { |
937 | if (OLC_FOR_AR9280_20_LATER) { | 809 | if (OLC_FOR_AR9280_20_LATER) { |
938 | REG_WRITE(ah, | 810 | REG_WRITE(ah, |
@@ -965,23 +837,23 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, | |||
965 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); | 837 | ((pdadcValues[4 * j + 3] & 0xFF) << 24); |
966 | REG_WRITE(ah, regOffset, reg32); | 838 | REG_WRITE(ah, regOffset, reg32); |
967 | 839 | ||
968 | ath_print(common, ATH_DBG_EEPROM, | 840 | ath_dbg(common, ATH_DBG_EEPROM, |
969 | "PDADC (%d,%4x): %4.4x %8.8x\n", | 841 | "PDADC (%d,%4x): %4.4x %8.8x\n", |
970 | i, regChainOffset, regOffset, | 842 | i, regChainOffset, regOffset, |
971 | reg32); | 843 | reg32); |
972 | ath_print(common, ATH_DBG_EEPROM, | 844 | ath_dbg(common, ATH_DBG_EEPROM, |
973 | "PDADC: Chain %d | PDADC %3d " | 845 | "PDADC: Chain %d | PDADC %3d " |
974 | "Value %3d | PDADC %3d Value %3d | " | 846 | "Value %3d | PDADC %3d Value %3d | " |
975 | "PDADC %3d Value %3d | PDADC %3d " | 847 | "PDADC %3d Value %3d | PDADC %3d " |
976 | "Value %3d |\n", | 848 | "Value %3d |\n", |
977 | i, 4 * j, pdadcValues[4 * j], | 849 | i, 4 * j, pdadcValues[4 * j], |
978 | 4 * j + 1, pdadcValues[4 * j + 1], | 850 | 4 * j + 1, pdadcValues[4 * j + 1], |
979 | 4 * j + 2, pdadcValues[4 * j + 2], | 851 | 4 * j + 2, pdadcValues[4 * j + 2], |
980 | 4 * j + 3, | 852 | 4 * j + 3, pdadcValues[4 * j + 3]); |
981 | pdadcValues[4 * j + 3]); | ||
982 | 853 | ||
983 | regOffset += 4; | 854 | regOffset += 4; |
984 | } | 855 | } |
856 | REGWRITE_BUFFER_FLUSH(ah); | ||
985 | } | 857 | } |
986 | } | 858 | } |
987 | 859 | ||
@@ -1003,9 +875,9 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
1003 | 875 | ||
1004 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 876 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
1005 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 877 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
1006 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 878 | u16 twiceMaxEdgePower = MAX_RATE_POWER; |
1007 | static const u16 tpScaleReductionTable[5] = | 879 | static const u16 tpScaleReductionTable[5] = |
1008 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | 880 | { 0, 3, 6, 9, MAX_RATE_POWER }; |
1009 | 881 | ||
1010 | int i; | 882 | int i; |
1011 | int16_t twiceLargestAntenna; | 883 | int16_t twiceLargestAntenna; |
@@ -1021,13 +893,16 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
1021 | 0, {0, 0, 0, 0} | 893 | 0, {0, 0, 0, 0} |
1022 | }; | 894 | }; |
1023 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; | 895 | u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; |
1024 | u16 ctlModesFor11a[] = | 896 | static const u16 ctlModesFor11a[] = { |
1025 | { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; | 897 | CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 |
1026 | u16 ctlModesFor11g[] = | 898 | }; |
1027 | { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, | 899 | static const u16 ctlModesFor11g[] = { |
1028 | CTL_2GHT40 | 900 | CTL_11B, CTL_11G, CTL_2GHT20, |
1029 | }; | 901 | CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40 |
1030 | u16 numCtlModes, *pCtlMode, ctlMode, freq; | 902 | }; |
903 | u16 numCtlModes; | ||
904 | const u16 *pCtlMode; | ||
905 | u16 ctlMode, freq; | ||
1031 | struct chan_centers centers; | 906 | struct chan_centers centers; |
1032 | int tx_chainmask; | 907 | int tx_chainmask; |
1033 | u16 twiceMinEdgePower; | 908 | u16 twiceMinEdgePower; |
@@ -1062,15 +937,19 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
1062 | case 1: | 937 | case 1: |
1063 | break; | 938 | break; |
1064 | case 2: | 939 | case 2: |
1065 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | 940 | if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN) |
941 | scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; | ||
942 | else | ||
943 | scaledPower = 0; | ||
1066 | break; | 944 | break; |
1067 | case 3: | 945 | case 3: |
1068 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | 946 | if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN) |
947 | scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; | ||
948 | else | ||
949 | scaledPower = 0; | ||
1069 | break; | 950 | break; |
1070 | } | 951 | } |
1071 | 952 | ||
1072 | scaledPower = max((u16)0, scaledPower); | ||
1073 | |||
1074 | if (IS_CHAN_2GHZ(chan)) { | 953 | if (IS_CHAN_2GHZ(chan)) { |
1075 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - | 954 | numCtlModes = ARRAY_SIZE(ctlModesFor11g) - |
1076 | SUB_NUM_CTL_MODES_AT_2G_40; | 955 | SUB_NUM_CTL_MODES_AT_2G_40; |
@@ -1143,7 +1022,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
1143 | 1022 | ||
1144 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && | 1023 | if (ah->eep_ops->get_eeprom_ver(ah) == 14 && |
1145 | ah->eep_ops->get_eeprom_rev(ah) <= 2) | 1024 | ah->eep_ops->get_eeprom_rev(ah) <= 2) |
1146 | twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 1025 | twiceMaxEdgePower = MAX_RATE_POWER; |
1147 | 1026 | ||
1148 | for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { | 1027 | for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { |
1149 | if ((((cfgCtl & ~CTL_MODE_M) | | 1028 | if ((((cfgCtl & ~CTL_MODE_M) | |
@@ -1258,7 +1137,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1258 | u16 cfgCtl, | 1137 | u16 cfgCtl, |
1259 | u8 twiceAntennaReduction, | 1138 | u8 twiceAntennaReduction, |
1260 | u8 twiceMaxRegulatoryPower, | 1139 | u8 twiceMaxRegulatoryPower, |
1261 | u8 powerLimit) | 1140 | u8 powerLimit, bool test) |
1262 | { | 1141 | { |
1263 | #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) | 1142 | #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) |
1264 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 1143 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
@@ -1285,13 +1164,45 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1285 | 1164 | ||
1286 | ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); | 1165 | ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); |
1287 | 1166 | ||
1167 | regulatory->max_power_level = 0; | ||
1288 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { | 1168 | for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { |
1289 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); | 1169 | ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); |
1290 | if (ratesArray[i] > AR5416_MAX_RATE_POWER) | 1170 | if (ratesArray[i] > MAX_RATE_POWER) |
1291 | ratesArray[i] = AR5416_MAX_RATE_POWER; | 1171 | ratesArray[i] = MAX_RATE_POWER; |
1172 | if (ratesArray[i] > regulatory->max_power_level) | ||
1173 | regulatory->max_power_level = ratesArray[i]; | ||
1174 | } | ||
1175 | |||
1176 | if (!test) { | ||
1177 | i = rate6mb; | ||
1178 | |||
1179 | if (IS_CHAN_HT40(chan)) | ||
1180 | i = rateHt40_0; | ||
1181 | else if (IS_CHAN_HT20(chan)) | ||
1182 | i = rateHt20_0; | ||
1183 | |||
1184 | regulatory->max_power_level = ratesArray[i]; | ||
1292 | } | 1185 | } |
1293 | 1186 | ||
1294 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 1187 | switch(ar5416_get_ntxchains(ah->txchainmask)) { |
1188 | case 1: | ||
1189 | break; | ||
1190 | case 2: | ||
1191 | regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
1192 | break; | ||
1193 | case 3: | ||
1194 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
1195 | break; | ||
1196 | default: | ||
1197 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_EEPROM, | ||
1198 | "Invalid chainmask configuration\n"); | ||
1199 | break; | ||
1200 | } | ||
1201 | |||
1202 | if (test) | ||
1203 | return; | ||
1204 | |||
1205 | if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
1295 | for (i = 0; i < Ar5416RateSize; i++) { | 1206 | for (i = 0; i < Ar5416RateSize; i++) { |
1296 | int8_t pwr_table_offset; | 1207 | int8_t pwr_table_offset; |
1297 | 1208 | ||
@@ -1301,6 +1212,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1301 | } | 1212 | } |
1302 | } | 1213 | } |
1303 | 1214 | ||
1215 | ENABLE_REGWRITE_BUFFER(ah); | ||
1216 | |||
1304 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, | 1217 | REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, |
1305 | ATH9K_POW_SM(ratesArray[rate18mb], 24) | 1218 | ATH9K_POW_SM(ratesArray[rate18mb], 24) |
1306 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) | 1219 | | ATH9K_POW_SM(ratesArray[rate12mb], 16) |
@@ -1388,61 +1301,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1388 | ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) | 1301 | ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) |
1389 | | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); | 1302 | | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); |
1390 | 1303 | ||
1391 | i = rate6mb; | 1304 | REGWRITE_BUFFER_FLUSH(ah); |
1392 | |||
1393 | if (IS_CHAN_HT40(chan)) | ||
1394 | i = rateHt40_0; | ||
1395 | else if (IS_CHAN_HT20(chan)) | ||
1396 | i = rateHt20_0; | ||
1397 | |||
1398 | if (AR_SREV_9280_10_OR_LATER(ah)) | ||
1399 | regulatory->max_power_level = | ||
1400 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; | ||
1401 | else | ||
1402 | regulatory->max_power_level = ratesArray[i]; | ||
1403 | |||
1404 | switch(ar5416_get_ntxchains(ah->txchainmask)) { | ||
1405 | case 1: | ||
1406 | break; | ||
1407 | case 2: | ||
1408 | regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | ||
1409 | break; | ||
1410 | case 3: | ||
1411 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | ||
1412 | break; | ||
1413 | default: | ||
1414 | ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM, | ||
1415 | "Invalid chainmask configuration\n"); | ||
1416 | break; | ||
1417 | } | ||
1418 | } | ||
1419 | |||
1420 | static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, | ||
1421 | enum ieee80211_band freq_band) | ||
1422 | { | ||
1423 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
1424 | struct modal_eep_header *pModal = | ||
1425 | &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]); | ||
1426 | struct base_eep_header *pBase = &eep->baseEepHeader; | ||
1427 | u8 num_ant_config; | ||
1428 | |||
1429 | num_ant_config = 1; | ||
1430 | |||
1431 | if (pBase->version >= 0x0E0D) | ||
1432 | if (pModal->useAnt1) | ||
1433 | num_ant_config += 1; | ||
1434 | |||
1435 | return num_ant_config; | ||
1436 | } | ||
1437 | |||
1438 | static u32 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah, | ||
1439 | struct ath9k_channel *chan) | ||
1440 | { | ||
1441 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | ||
1442 | struct modal_eep_header *pModal = | ||
1443 | &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | ||
1444 | |||
1445 | return pModal->antCtrlCommon; | ||
1446 | } | 1305 | } |
1447 | 1306 | ||
1448 | static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | 1307 | static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) |
@@ -1453,17 +1312,17 @@ static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) | |||
1453 | 1312 | ||
1454 | u16 spur_val = AR_NO_SPUR; | 1313 | u16 spur_val = AR_NO_SPUR; |
1455 | 1314 | ||
1456 | ath_print(common, ATH_DBG_ANI, | 1315 | ath_dbg(common, ATH_DBG_ANI, |
1457 | "Getting spur idx %d is2Ghz. %d val %x\n", | 1316 | "Getting spur idx:%d is2Ghz:%d val:%x\n", |
1458 | i, is2GHz, ah->config.spurchans[i][is2GHz]); | 1317 | i, is2GHz, ah->config.spurchans[i][is2GHz]); |
1459 | 1318 | ||
1460 | switch (ah->config.spurmode) { | 1319 | switch (ah->config.spurmode) { |
1461 | case SPUR_DISABLE: | 1320 | case SPUR_DISABLE: |
1462 | break; | 1321 | break; |
1463 | case SPUR_ENABLE_IOCTL: | 1322 | case SPUR_ENABLE_IOCTL: |
1464 | spur_val = ah->config.spurchans[i][is2GHz]; | 1323 | spur_val = ah->config.spurchans[i][is2GHz]; |
1465 | ath_print(common, ATH_DBG_ANI, | 1324 | ath_dbg(common, ATH_DBG_ANI, |
1466 | "Getting spur val from new loc. %d\n", spur_val); | 1325 | "Getting spur val from new loc. %d\n", spur_val); |
1467 | break; | 1326 | break; |
1468 | case SPUR_ENABLE_EEPROM: | 1327 | case SPUR_ENABLE_EEPROM: |
1469 | spur_val = EEP_DEF_SPURCHAN; | 1328 | spur_val = EEP_DEF_SPURCHAN; |
@@ -1481,8 +1340,6 @@ const struct eeprom_ops eep_def_ops = { | |||
1481 | .fill_eeprom = ath9k_hw_def_fill_eeprom, | 1340 | .fill_eeprom = ath9k_hw_def_fill_eeprom, |
1482 | .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, | 1341 | .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, |
1483 | .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, | 1342 | .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, |
1484 | .get_num_ant_config = ath9k_hw_def_get_num_ant_config, | ||
1485 | .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg, | ||
1486 | .set_board_values = ath9k_hw_def_set_board_values, | 1343 | .set_board_values = ath9k_hw_def_set_board_values, |
1487 | .set_addac = ath9k_hw_def_set_addac, | 1344 | .set_addac = ath9k_hw_def_set_addac, |
1488 | .set_txpower = ath9k_hw_def_set_txpower, | 1345 | .set_txpower = ath9k_hw_def_set_txpower, |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 3a8ee999da5d..bc713fc28191 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -20,123 +20,37 @@ | |||
20 | /* LED functions */ | 20 | /* LED functions */ |
21 | /********************************/ | 21 | /********************************/ |
22 | 22 | ||
23 | static void ath_led_blink_work(struct work_struct *work) | 23 | #ifdef CONFIG_MAC80211_LEDS |
24 | { | ||
25 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
26 | ath_led_blink_work.work); | ||
27 | |||
28 | if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) | ||
29 | return; | ||
30 | |||
31 | if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || | ||
32 | (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | ||
33 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
34 | else | ||
35 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
36 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); | ||
37 | |||
38 | ieee80211_queue_delayed_work(sc->hw, | ||
39 | &sc->ath_led_blink_work, | ||
40 | (sc->sc_flags & SC_OP_LED_ON) ? | ||
41 | msecs_to_jiffies(sc->led_off_duration) : | ||
42 | msecs_to_jiffies(sc->led_on_duration)); | ||
43 | |||
44 | sc->led_on_duration = sc->led_on_cnt ? | ||
45 | max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : | ||
46 | ATH_LED_ON_DURATION_IDLE; | ||
47 | sc->led_off_duration = sc->led_off_cnt ? | ||
48 | max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : | ||
49 | ATH_LED_OFF_DURATION_IDLE; | ||
50 | sc->led_on_cnt = sc->led_off_cnt = 0; | ||
51 | if (sc->sc_flags & SC_OP_LED_ON) | ||
52 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
53 | else | ||
54 | sc->sc_flags |= SC_OP_LED_ON; | ||
55 | } | ||
56 | |||
57 | static void ath_led_brightness(struct led_classdev *led_cdev, | 24 | static void ath_led_brightness(struct led_classdev *led_cdev, |
58 | enum led_brightness brightness) | 25 | enum led_brightness brightness) |
59 | { | 26 | { |
60 | struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); | 27 | struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); |
61 | struct ath_softc *sc = led->sc; | 28 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF)); |
62 | |||
63 | switch (brightness) { | ||
64 | case LED_OFF: | ||
65 | if (led->led_type == ATH_LED_ASSOC || | ||
66 | led->led_type == ATH_LED_RADIO) { | ||
67 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
68 | (led->led_type == ATH_LED_RADIO)); | ||
69 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | ||
70 | if (led->led_type == ATH_LED_RADIO) | ||
71 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
72 | } else { | ||
73 | sc->led_off_cnt++; | ||
74 | } | ||
75 | break; | ||
76 | case LED_FULL: | ||
77 | if (led->led_type == ATH_LED_ASSOC) { | ||
78 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; | ||
79 | if (led_blink) | ||
80 | ieee80211_queue_delayed_work(sc->hw, | ||
81 | &sc->ath_led_blink_work, 0); | ||
82 | } else if (led->led_type == ATH_LED_RADIO) { | ||
83 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
84 | sc->sc_flags |= SC_OP_LED_ON; | ||
85 | } else { | ||
86 | sc->led_on_cnt++; | ||
87 | } | ||
88 | break; | ||
89 | default: | ||
90 | break; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static int ath_register_led(struct ath_softc *sc, struct ath_led *led, | ||
95 | char *trigger) | ||
96 | { | ||
97 | int ret; | ||
98 | |||
99 | led->sc = sc; | ||
100 | led->led_cdev.name = led->name; | ||
101 | led->led_cdev.default_trigger = trigger; | ||
102 | led->led_cdev.brightness_set = ath_led_brightness; | ||
103 | |||
104 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); | ||
105 | if (ret) | ||
106 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | ||
107 | "Failed to register led:%s", led->name); | ||
108 | else | ||
109 | led->registered = 1; | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static void ath_unregister_led(struct ath_led *led) | ||
114 | { | ||
115 | if (led->registered) { | ||
116 | led_classdev_unregister(&led->led_cdev); | ||
117 | led->registered = 0; | ||
118 | } | ||
119 | } | 29 | } |
120 | 30 | ||
121 | void ath_deinit_leds(struct ath_softc *sc) | 31 | void ath_deinit_leds(struct ath_softc *sc) |
122 | { | 32 | { |
123 | ath_unregister_led(&sc->assoc_led); | 33 | if (!sc->led_registered) |
124 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | 34 | return; |
125 | ath_unregister_led(&sc->tx_led); | 35 | |
126 | ath_unregister_led(&sc->rx_led); | 36 | ath_led_brightness(&sc->led_cdev, LED_OFF); |
127 | ath_unregister_led(&sc->radio_led); | 37 | led_classdev_unregister(&sc->led_cdev); |
128 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | ||
129 | } | 38 | } |
130 | 39 | ||
131 | void ath_init_leds(struct ath_softc *sc) | 40 | void ath_init_leds(struct ath_softc *sc) |
132 | { | 41 | { |
133 | char *trigger; | ||
134 | int ret; | 42 | int ret; |
135 | 43 | ||
136 | if (AR_SREV_9287(sc->sc_ah)) | 44 | if (sc->sc_ah->led_pin < 0) { |
137 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; | 45 | if (AR_SREV_9287(sc->sc_ah)) |
138 | else | 46 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; |
139 | sc->sc_ah->led_pin = ATH_LED_PIN_DEF; | 47 | else if (AR_SREV_9485(sc->sc_ah)) |
48 | sc->sc_ah->led_pin = ATH_LED_PIN_9485; | ||
49 | else if (AR_SREV_9300(sc->sc_ah)) | ||
50 | sc->sc_ah->led_pin = ATH_LED_PIN_9300; | ||
51 | else | ||
52 | sc->sc_ah->led_pin = ATH_LED_PIN_DEF; | ||
53 | } | ||
140 | 54 | ||
141 | /* Configure gpio 1 for output */ | 55 | /* Configure gpio 1 for output */ |
142 | ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, | 56 | ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, |
@@ -144,48 +58,22 @@ void ath_init_leds(struct ath_softc *sc) | |||
144 | /* LED off, active low */ | 58 | /* LED off, active low */ |
145 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | 59 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
146 | 60 | ||
147 | if (led_blink) | 61 | if (!led_blink) |
148 | INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); | 62 | sc->led_cdev.default_trigger = |
149 | 63 | ieee80211_get_radio_led_name(sc->hw); | |
150 | trigger = ieee80211_get_radio_led_name(sc->hw); | 64 | |
151 | snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), | 65 | snprintf(sc->led_name, sizeof(sc->led_name), |
152 | "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); | 66 | "ath9k-%s", wiphy_name(sc->hw->wiphy)); |
153 | ret = ath_register_led(sc, &sc->radio_led, trigger); | 67 | sc->led_cdev.name = sc->led_name; |
154 | sc->radio_led.led_type = ATH_LED_RADIO; | 68 | sc->led_cdev.brightness_set = ath_led_brightness; |
155 | if (ret) | 69 | |
156 | goto fail; | 70 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); |
157 | 71 | if (ret < 0) | |
158 | trigger = ieee80211_get_assoc_led_name(sc->hw); | 72 | return; |
159 | snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), | 73 | |
160 | "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); | 74 | sc->led_registered = true; |
161 | ret = ath_register_led(sc, &sc->assoc_led, trigger); | ||
162 | sc->assoc_led.led_type = ATH_LED_ASSOC; | ||
163 | if (ret) | ||
164 | goto fail; | ||
165 | |||
166 | trigger = ieee80211_get_tx_led_name(sc->hw); | ||
167 | snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), | ||
168 | "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); | ||
169 | ret = ath_register_led(sc, &sc->tx_led, trigger); | ||
170 | sc->tx_led.led_type = ATH_LED_TX; | ||
171 | if (ret) | ||
172 | goto fail; | ||
173 | |||
174 | trigger = ieee80211_get_rx_led_name(sc->hw); | ||
175 | snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), | ||
176 | "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); | ||
177 | ret = ath_register_led(sc, &sc->rx_led, trigger); | ||
178 | sc->rx_led.led_type = ATH_LED_RX; | ||
179 | if (ret) | ||
180 | goto fail; | ||
181 | |||
182 | return; | ||
183 | |||
184 | fail: | ||
185 | if (led_blink) | ||
186 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
187 | ath_deinit_leds(sc); | ||
188 | } | 75 | } |
76 | #endif | ||
189 | 77 | ||
190 | /*******************/ | 78 | /*******************/ |
191 | /* Rfkill */ | 79 | /* Rfkill */ |
@@ -201,8 +89,7 @@ static bool ath_is_rfkill_set(struct ath_softc *sc) | |||
201 | 89 | ||
202 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) | 90 | void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) |
203 | { | 91 | { |
204 | struct ath_wiphy *aphy = hw->priv; | 92 | struct ath_softc *sc = hw->priv; |
205 | struct ath_softc *sc = aphy->sc; | ||
206 | bool blocked = !!ath_is_rfkill_set(sc); | 93 | bool blocked = !!ath_is_rfkill_set(sc); |
207 | 94 | ||
208 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | 95 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); |
@@ -236,13 +123,13 @@ static void ath_detect_bt_priority(struct ath_softc *sc) | |||
236 | sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); | 123 | sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN); |
237 | /* Detect if colocated bt started scanning */ | 124 | /* Detect if colocated bt started scanning */ |
238 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { | 125 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { |
239 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, | 126 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, |
240 | "BT scan detected"); | 127 | "BT scan detected\n"); |
241 | sc->sc_flags |= (SC_OP_BT_SCAN | | 128 | sc->sc_flags |= (SC_OP_BT_SCAN | |
242 | SC_OP_BT_PRIORITY_DETECTED); | 129 | SC_OP_BT_PRIORITY_DETECTED); |
243 | } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | 130 | } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { |
244 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, | 131 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, |
245 | "BT priority traffic detected"); | 132 | "BT priority traffic detected\n"); |
246 | sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; | 133 | sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; |
247 | } | 134 | } |
248 | 135 | ||
@@ -251,45 +138,15 @@ static void ath_detect_bt_priority(struct ath_softc *sc) | |||
251 | } | 138 | } |
252 | } | 139 | } |
253 | 140 | ||
254 | /* | ||
255 | * Configures appropriate weight based on stomp type. | ||
256 | */ | ||
257 | static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, | ||
258 | enum ath_stomp_type stomp_type) | ||
259 | { | ||
260 | struct ath_hw *ah = sc->sc_ah; | ||
261 | |||
262 | switch (stomp_type) { | ||
263 | case ATH_BTCOEX_STOMP_ALL: | ||
264 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
265 | AR_STOMP_ALL_WLAN_WGHT); | ||
266 | break; | ||
267 | case ATH_BTCOEX_STOMP_LOW: | ||
268 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
269 | AR_STOMP_LOW_WLAN_WGHT); | ||
270 | break; | ||
271 | case ATH_BTCOEX_STOMP_NONE: | ||
272 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
273 | AR_STOMP_NONE_WLAN_WGHT); | ||
274 | break; | ||
275 | default: | ||
276 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
277 | "Invalid Stomptype\n"); | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | ath9k_hw_btcoex_enable(ah); | ||
282 | } | ||
283 | |||
284 | static void ath9k_gen_timer_start(struct ath_hw *ah, | 141 | static void ath9k_gen_timer_start(struct ath_hw *ah, |
285 | struct ath_gen_timer *timer, | 142 | struct ath_gen_timer *timer, |
286 | u32 timer_next, | 143 | u32 trig_timeout, |
287 | u32 timer_period) | 144 | u32 timer_period) |
288 | { | 145 | { |
289 | ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period); | 146 | ath9k_hw_gen_timer_start(ah, timer, trig_timeout, timer_period); |
290 | 147 | ||
291 | if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { | 148 | if ((ah->imask & ATH9K_INT_GENTIMER) == 0) { |
292 | ath9k_hw_set_interrupts(ah, 0); | 149 | ath9k_hw_disable_interrupts(ah); |
293 | ah->imask |= ATH9K_INT_GENTIMER; | 150 | ah->imask |= ATH9K_INT_GENTIMER; |
294 | ath9k_hw_set_interrupts(ah, ah->imask); | 151 | ath9k_hw_set_interrupts(ah, ah->imask); |
295 | } | 152 | } |
@@ -303,7 +160,7 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | |||
303 | 160 | ||
304 | /* if no timer is enabled, turn off interrupt mask */ | 161 | /* if no timer is enabled, turn off interrupt mask */ |
305 | if (timer_table->timer_mask.val == 0) { | 162 | if (timer_table->timer_mask.val == 0) { |
306 | ath9k_hw_set_interrupts(ah, 0); | 163 | ath9k_hw_disable_interrupts(ah); |
307 | ah->imask &= ~ATH9K_INT_GENTIMER; | 164 | ah->imask &= ~ATH9K_INT_GENTIMER; |
308 | ath9k_hw_set_interrupts(ah, ah->imask); | 165 | ath9k_hw_set_interrupts(ah, ah->imask); |
309 | } | 166 | } |
@@ -322,13 +179,14 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
322 | u32 timer_period; | 179 | u32 timer_period; |
323 | bool is_btscan; | 180 | bool is_btscan; |
324 | 181 | ||
182 | ath9k_ps_wakeup(sc); | ||
325 | ath_detect_bt_priority(sc); | 183 | ath_detect_bt_priority(sc); |
326 | 184 | ||
327 | is_btscan = sc->sc_flags & SC_OP_BT_SCAN; | 185 | is_btscan = sc->sc_flags & SC_OP_BT_SCAN; |
328 | 186 | ||
329 | spin_lock_bh(&btcoex->btcoex_lock); | 187 | spin_lock_bh(&btcoex->btcoex_lock); |
330 | 188 | ||
331 | ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL : | 189 | ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : |
332 | btcoex->bt_stomp_type); | 190 | btcoex->bt_stomp_type); |
333 | 191 | ||
334 | spin_unlock_bh(&btcoex->btcoex_lock); | 192 | spin_unlock_bh(&btcoex->btcoex_lock); |
@@ -339,13 +197,12 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
339 | 197 | ||
340 | timer_period = is_btscan ? btcoex->btscan_no_stomp : | 198 | timer_period = is_btscan ? btcoex->btscan_no_stomp : |
341 | btcoex->btcoex_no_stomp; | 199 | btcoex->btcoex_no_stomp; |
342 | ath9k_gen_timer_start(ah, | 200 | ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period, |
343 | btcoex->no_stomp_timer, | 201 | timer_period * 10); |
344 | (ath9k_hw_gettsf32(ah) + | ||
345 | timer_period), timer_period * 10); | ||
346 | btcoex->hw_timer_enabled = true; | 202 | btcoex->hw_timer_enabled = true; |
347 | } | 203 | } |
348 | 204 | ||
205 | ath9k_ps_restore(sc); | ||
349 | mod_timer(&btcoex->period_timer, jiffies + | 206 | mod_timer(&btcoex->period_timer, jiffies + |
350 | msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); | 207 | msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); |
351 | } | 208 | } |
@@ -359,19 +216,22 @@ static void ath_btcoex_no_stomp_timer(void *arg) | |||
359 | struct ath_softc *sc = (struct ath_softc *)arg; | 216 | struct ath_softc *sc = (struct ath_softc *)arg; |
360 | struct ath_hw *ah = sc->sc_ah; | 217 | struct ath_hw *ah = sc->sc_ah; |
361 | struct ath_btcoex *btcoex = &sc->btcoex; | 218 | struct ath_btcoex *btcoex = &sc->btcoex; |
219 | struct ath_common *common = ath9k_hw_common(ah); | ||
362 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; | 220 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; |
363 | 221 | ||
364 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | 222 | ath_dbg(common, ATH_DBG_BTCOEX, |
365 | "no stomp timer running\n"); | 223 | "no stomp timer running\n"); |
366 | 224 | ||
225 | ath9k_ps_wakeup(sc); | ||
367 | spin_lock_bh(&btcoex->btcoex_lock); | 226 | spin_lock_bh(&btcoex->btcoex_lock); |
368 | 227 | ||
369 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) | 228 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) |
370 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); | 229 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); |
371 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | 230 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) |
372 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); | 231 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); |
373 | 232 | ||
374 | spin_unlock_bh(&btcoex->btcoex_lock); | 233 | spin_unlock_bh(&btcoex->btcoex_lock); |
234 | ath9k_ps_restore(sc); | ||
375 | } | 235 | } |
376 | 236 | ||
377 | int ath_init_btcoex_timer(struct ath_softc *sc) | 237 | int ath_init_btcoex_timer(struct ath_softc *sc) |
@@ -408,8 +268,8 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) | |||
408 | struct ath_btcoex *btcoex = &sc->btcoex; | 268 | struct ath_btcoex *btcoex = &sc->btcoex; |
409 | struct ath_hw *ah = sc->sc_ah; | 269 | struct ath_hw *ah = sc->sc_ah; |
410 | 270 | ||
411 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | 271 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, |
412 | "Starting btcoex timers"); | 272 | "Starting btcoex timers\n"); |
413 | 273 | ||
414 | /* make sure duty cycle timer is also stopped when resuming */ | 274 | /* make sure duty cycle timer is also stopped when resuming */ |
415 | if (btcoex->hw_timer_enabled) | 275 | if (btcoex->hw_timer_enabled) |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 17e7a9a367e7..260f1f37a60e 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,26 +17,42 @@ | |||
17 | #include "htc.h" | 17 | #include "htc.h" |
18 | 18 | ||
19 | /* identify firmware images */ | 19 | /* identify firmware images */ |
20 | #define FIRMWARE_AR7010 "ar7010.fw" | 20 | #define FIRMWARE_AR7010_1_1 "htc_7010.fw" |
21 | #define FIRMWARE_AR7010_1_1 "ar7010_1_1.fw" | 21 | #define FIRMWARE_AR9271 "htc_9271.fw" |
22 | #define FIRMWARE_AR9271 "ar9271.fw" | ||
23 | 22 | ||
24 | MODULE_FIRMWARE(FIRMWARE_AR7010); | ||
25 | MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); | 23 | MODULE_FIRMWARE(FIRMWARE_AR7010_1_1); |
26 | MODULE_FIRMWARE(FIRMWARE_AR9271); | 24 | MODULE_FIRMWARE(FIRMWARE_AR9271); |
27 | 25 | ||
28 | static struct usb_device_id ath9k_hif_usb_ids[] = { | 26 | static struct usb_device_id ath9k_hif_usb_ids[] = { |
29 | { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ | 27 | { USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */ |
30 | { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */ | 28 | { USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */ |
31 | { USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */ | ||
32 | { USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */ | ||
33 | { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */ | 29 | { USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */ |
34 | { USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */ | ||
35 | { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */ | 30 | { USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */ |
36 | { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */ | 31 | { USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */ |
37 | { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */ | 32 | { USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */ |
33 | { USB_DEVICE(0x13D3, 0x3346) }, /* IMC Networks */ | ||
34 | { USB_DEVICE(0x13D3, 0x3348) }, /* Azurewave */ | ||
35 | { USB_DEVICE(0x13D3, 0x3349) }, /* Azurewave */ | ||
36 | { USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */ | ||
38 | { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ | 37 | { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ |
39 | { USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */ | 38 | { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ |
39 | { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ | ||
40 | |||
41 | { USB_DEVICE(0x0cf3, 0x7015), | ||
42 | .driver_info = AR9287_USB }, /* Atheros */ | ||
43 | { USB_DEVICE(0x1668, 0x1200), | ||
44 | .driver_info = AR9287_USB }, /* Verizon */ | ||
45 | |||
46 | { USB_DEVICE(0x0cf3, 0x7010), | ||
47 | .driver_info = AR9280_USB }, /* Atheros */ | ||
48 | { USB_DEVICE(0x0846, 0x9018), | ||
49 | .driver_info = AR9280_USB }, /* Netgear WNDA3200 */ | ||
50 | { USB_DEVICE(0x083A, 0xA704), | ||
51 | .driver_info = AR9280_USB }, /* SMC Networks */ | ||
52 | |||
53 | { USB_DEVICE(0x0cf3, 0x20ff), | ||
54 | .driver_info = STORAGE_DEVICE }, | ||
55 | |||
40 | { }, | 56 | { }, |
41 | }; | 57 | }; |
42 | 58 | ||
@@ -62,7 +78,7 @@ static void hif_usb_regout_cb(struct urb *urb) | |||
62 | 78 | ||
63 | if (cmd) { | 79 | if (cmd) { |
64 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, | 80 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, |
65 | cmd->skb, 1); | 81 | cmd->skb, true); |
66 | kfree(cmd); | 82 | kfree(cmd); |
67 | } | 83 | } |
68 | 84 | ||
@@ -92,10 +108,10 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | |||
92 | cmd->skb = skb; | 108 | cmd->skb = skb; |
93 | cmd->hif_dev = hif_dev; | 109 | cmd->hif_dev = hif_dev; |
94 | 110 | ||
95 | usb_fill_int_urb(urb, hif_dev->udev, | 111 | usb_fill_bulk_urb(urb, hif_dev->udev, |
96 | usb_sndintpipe(hif_dev->udev, USB_REG_OUT_PIPE), | 112 | usb_sndbulkpipe(hif_dev->udev, USB_REG_OUT_PIPE), |
97 | skb->data, skb->len, | 113 | skb->data, skb->len, |
98 | hif_usb_regout_cb, cmd, 1); | 114 | hif_usb_regout_cb, cmd); |
99 | 115 | ||
100 | usb_anchor_urb(urb, &hif_dev->regout_submitted); | 116 | usb_anchor_urb(urb, &hif_dev->regout_submitted); |
101 | ret = usb_submit_urb(urb, GFP_KERNEL); | 117 | ret = usb_submit_urb(urb, GFP_KERNEL); |
@@ -108,6 +124,90 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev, | |||
108 | return ret; | 124 | return ret; |
109 | } | 125 | } |
110 | 126 | ||
127 | static void hif_usb_mgmt_cb(struct urb *urb) | ||
128 | { | ||
129 | struct cmd_buf *cmd = (struct cmd_buf *)urb->context; | ||
130 | struct hif_device_usb *hif_dev = cmd->hif_dev; | ||
131 | bool txok = true; | ||
132 | |||
133 | if (!cmd || !cmd->skb || !cmd->hif_dev) | ||
134 | return; | ||
135 | |||
136 | switch (urb->status) { | ||
137 | case 0: | ||
138 | break; | ||
139 | case -ENOENT: | ||
140 | case -ECONNRESET: | ||
141 | case -ENODEV: | ||
142 | case -ESHUTDOWN: | ||
143 | txok = false; | ||
144 | |||
145 | /* | ||
146 | * If the URBs are being flushed, no need to complete | ||
147 | * this packet. | ||
148 | */ | ||
149 | spin_lock(&hif_dev->tx.tx_lock); | ||
150 | if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { | ||
151 | spin_unlock(&hif_dev->tx.tx_lock); | ||
152 | dev_kfree_skb_any(cmd->skb); | ||
153 | kfree(cmd); | ||
154 | return; | ||
155 | } | ||
156 | spin_unlock(&hif_dev->tx.tx_lock); | ||
157 | |||
158 | break; | ||
159 | default: | ||
160 | txok = false; | ||
161 | break; | ||
162 | } | ||
163 | |||
164 | skb_pull(cmd->skb, 4); | ||
165 | ath9k_htc_txcompletion_cb(cmd->hif_dev->htc_handle, | ||
166 | cmd->skb, txok); | ||
167 | kfree(cmd); | ||
168 | } | ||
169 | |||
170 | static int hif_usb_send_mgmt(struct hif_device_usb *hif_dev, | ||
171 | struct sk_buff *skb) | ||
172 | { | ||
173 | struct urb *urb; | ||
174 | struct cmd_buf *cmd; | ||
175 | int ret = 0; | ||
176 | __le16 *hdr; | ||
177 | |||
178 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
179 | if (urb == NULL) | ||
180 | return -ENOMEM; | ||
181 | |||
182 | cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); | ||
183 | if (cmd == NULL) { | ||
184 | usb_free_urb(urb); | ||
185 | return -ENOMEM; | ||
186 | } | ||
187 | |||
188 | cmd->skb = skb; | ||
189 | cmd->hif_dev = hif_dev; | ||
190 | |||
191 | hdr = (__le16 *) skb_push(skb, 4); | ||
192 | *hdr++ = cpu_to_le16(skb->len - 4); | ||
193 | *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); | ||
194 | |||
195 | usb_fill_bulk_urb(urb, hif_dev->udev, | ||
196 | usb_sndbulkpipe(hif_dev->udev, USB_WLAN_TX_PIPE), | ||
197 | skb->data, skb->len, | ||
198 | hif_usb_mgmt_cb, cmd); | ||
199 | |||
200 | usb_anchor_urb(urb, &hif_dev->mgmt_submitted); | ||
201 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
202 | if (ret) { | ||
203 | usb_unanchor_urb(urb); | ||
204 | kfree(cmd); | ||
205 | } | ||
206 | usb_free_urb(urb); | ||
207 | |||
208 | return ret; | ||
209 | } | ||
210 | |||
111 | static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, | 211 | static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, |
112 | struct sk_buff_head *list) | 212 | struct sk_buff_head *list) |
113 | { | 213 | { |
@@ -115,7 +215,22 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, | |||
115 | 215 | ||
116 | while ((skb = __skb_dequeue(list)) != NULL) { | 216 | while ((skb = __skb_dequeue(list)) != NULL) { |
117 | dev_kfree_skb_any(skb); | 217 | dev_kfree_skb_any(skb); |
118 | TX_STAT_INC(skb_dropped); | 218 | } |
219 | } | ||
220 | |||
221 | static inline void ath9k_skb_queue_complete(struct hif_device_usb *hif_dev, | ||
222 | struct sk_buff_head *queue, | ||
223 | bool txok) | ||
224 | { | ||
225 | struct sk_buff *skb; | ||
226 | |||
227 | while ((skb = __skb_dequeue(queue)) != NULL) { | ||
228 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, | ||
229 | skb, txok); | ||
230 | if (txok) | ||
231 | TX_STAT_INC(skb_success); | ||
232 | else | ||
233 | TX_STAT_INC(skb_failed); | ||
119 | } | 234 | } |
120 | } | 235 | } |
121 | 236 | ||
@@ -123,7 +238,7 @@ static void hif_usb_tx_cb(struct urb *urb) | |||
123 | { | 238 | { |
124 | struct tx_buf *tx_buf = (struct tx_buf *) urb->context; | 239 | struct tx_buf *tx_buf = (struct tx_buf *) urb->context; |
125 | struct hif_device_usb *hif_dev; | 240 | struct hif_device_usb *hif_dev; |
126 | struct sk_buff *skb; | 241 | bool txok = true; |
127 | 242 | ||
128 | if (!tx_buf || !tx_buf->hif_dev) | 243 | if (!tx_buf || !tx_buf->hif_dev) |
129 | return; | 244 | return; |
@@ -137,33 +252,28 @@ static void hif_usb_tx_cb(struct urb *urb) | |||
137 | case -ECONNRESET: | 252 | case -ECONNRESET: |
138 | case -ENODEV: | 253 | case -ENODEV: |
139 | case -ESHUTDOWN: | 254 | case -ESHUTDOWN: |
255 | txok = false; | ||
256 | |||
140 | /* | 257 | /* |
141 | * The URB has been killed, free the SKBs | 258 | * If the URBs are being flushed, no need to add this |
142 | * and return. | 259 | * URB to the free list. |
143 | */ | 260 | */ |
144 | ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); | 261 | spin_lock(&hif_dev->tx.tx_lock); |
145 | return; | 262 | if (hif_dev->tx.flags & HIF_USB_TX_FLUSH) { |
263 | spin_unlock(&hif_dev->tx.tx_lock); | ||
264 | ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); | ||
265 | return; | ||
266 | } | ||
267 | spin_unlock(&hif_dev->tx.tx_lock); | ||
268 | |||
269 | break; | ||
146 | default: | 270 | default: |
271 | txok = false; | ||
147 | break; | 272 | break; |
148 | } | 273 | } |
149 | 274 | ||
150 | /* Check if TX has been stopped */ | 275 | ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, txok); |
151 | spin_lock(&hif_dev->tx.tx_lock); | ||
152 | if (hif_dev->tx.flags & HIF_USB_TX_STOP) { | ||
153 | spin_unlock(&hif_dev->tx.tx_lock); | ||
154 | ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); | ||
155 | goto add_free; | ||
156 | } | ||
157 | spin_unlock(&hif_dev->tx.tx_lock); | ||
158 | |||
159 | /* Complete the queued SKBs. */ | ||
160 | while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) { | ||
161 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, | ||
162 | skb, 1); | ||
163 | TX_STAT_INC(skb_completed); | ||
164 | } | ||
165 | 276 | ||
166 | add_free: | ||
167 | /* Re-initialize the SKB queue */ | 277 | /* Re-initialize the SKB queue */ |
168 | tx_buf->len = tx_buf->offset = 0; | 278 | tx_buf->len = tx_buf->offset = 0; |
169 | __skb_queue_head_init(&tx_buf->skb_queue); | 279 | __skb_queue_head_init(&tx_buf->skb_queue); |
@@ -184,8 +294,9 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) | |||
184 | struct tx_buf *tx_buf = NULL; | 294 | struct tx_buf *tx_buf = NULL; |
185 | struct sk_buff *nskb = NULL; | 295 | struct sk_buff *nskb = NULL; |
186 | int ret = 0, i; | 296 | int ret = 0, i; |
187 | u16 *hdr, tx_skb_cnt = 0; | 297 | u16 tx_skb_cnt = 0; |
188 | u8 *buf; | 298 | u8 *buf; |
299 | __le16 *hdr; | ||
189 | 300 | ||
190 | if (hif_dev->tx.tx_skb_cnt == 0) | 301 | if (hif_dev->tx.tx_skb_cnt == 0) |
191 | return 0; | 302 | return 0; |
@@ -210,9 +321,9 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) | |||
210 | 321 | ||
211 | buf = tx_buf->buf; | 322 | buf = tx_buf->buf; |
212 | buf += tx_buf->offset; | 323 | buf += tx_buf->offset; |
213 | hdr = (u16 *)buf; | 324 | hdr = (__le16 *)buf; |
214 | *hdr++ = nskb->len; | 325 | *hdr++ = cpu_to_le16(nskb->len); |
215 | *hdr++ = ATH_USB_TX_STREAM_MODE_TAG; | 326 | *hdr++ = cpu_to_le16(ATH_USB_TX_STREAM_MODE_TAG); |
216 | buf += 4; | 327 | buf += 4; |
217 | memcpy(buf, nskb->data, nskb->len); | 328 | memcpy(buf, nskb->data, nskb->len); |
218 | tx_buf->len = nskb->len + 4; | 329 | tx_buf->len = nskb->len + 4; |
@@ -235,7 +346,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) | |||
235 | ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); | 346 | ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC); |
236 | if (ret) { | 347 | if (ret) { |
237 | tx_buf->len = tx_buf->offset = 0; | 348 | tx_buf->len = tx_buf->offset = 0; |
238 | ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue); | 349 | ath9k_skb_queue_complete(hif_dev, &tx_buf->skb_queue, false); |
239 | __skb_queue_head_init(&tx_buf->skb_queue); | 350 | __skb_queue_head_init(&tx_buf->skb_queue); |
240 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); | 351 | list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf); |
241 | hif_dev->tx.tx_buf_cnt++; | 352 | hif_dev->tx.tx_buf_cnt++; |
@@ -247,10 +358,11 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) | |||
247 | return ret; | 358 | return ret; |
248 | } | 359 | } |
249 | 360 | ||
250 | static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, | 361 | static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb) |
251 | struct ath9k_htc_tx_ctl *tx_ctl) | ||
252 | { | 362 | { |
363 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
253 | unsigned long flags; | 364 | unsigned long flags; |
365 | int ret = 0; | ||
254 | 366 | ||
255 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | 367 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); |
256 | 368 | ||
@@ -265,26 +377,36 @@ static int hif_usb_send_tx(struct hif_device_usb *hif_dev, struct sk_buff *skb, | |||
265 | return -ENOMEM; | 377 | return -ENOMEM; |
266 | } | 378 | } |
267 | 379 | ||
268 | __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); | 380 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
269 | hif_dev->tx.tx_skb_cnt++; | 381 | |
382 | tx_ctl = HTC_SKB_CB(skb); | ||
270 | 383 | ||
271 | /* Send normal frames immediately */ | 384 | /* Mgmt/Beacon frames don't use the TX buffer pool */ |
272 | if (!tx_ctl || (tx_ctl && (tx_ctl->type == ATH9K_HTC_NORMAL))) | 385 | if ((tx_ctl->type == ATH9K_HTC_MGMT) || |
273 | __hif_usb_tx(hif_dev); | 386 | (tx_ctl->type == ATH9K_HTC_BEACON)) { |
387 | ret = hif_usb_send_mgmt(hif_dev, skb); | ||
388 | } | ||
389 | |||
390 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
391 | |||
392 | if ((tx_ctl->type == ATH9K_HTC_NORMAL) || | ||
393 | (tx_ctl->type == ATH9K_HTC_AMPDU)) { | ||
394 | __skb_queue_tail(&hif_dev->tx.tx_skb_queue, skb); | ||
395 | hif_dev->tx.tx_skb_cnt++; | ||
396 | } | ||
274 | 397 | ||
275 | /* Check if AMPDUs have to be sent immediately */ | 398 | /* Check if AMPDUs have to be sent immediately */ |
276 | if (tx_ctl && (tx_ctl->type == ATH9K_HTC_AMPDU) && | 399 | if ((hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && |
277 | (hif_dev->tx.tx_buf_cnt == MAX_TX_URB_NUM) && | ||
278 | (hif_dev->tx.tx_skb_cnt < 2)) { | 400 | (hif_dev->tx.tx_skb_cnt < 2)) { |
279 | __hif_usb_tx(hif_dev); | 401 | __hif_usb_tx(hif_dev); |
280 | } | 402 | } |
281 | 403 | ||
282 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | 404 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
283 | 405 | ||
284 | return 0; | 406 | return ret; |
285 | } | 407 | } |
286 | 408 | ||
287 | static void hif_usb_start(void *hif_handle, u8 pipe_id) | 409 | static void hif_usb_start(void *hif_handle) |
288 | { | 410 | { |
289 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | 411 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; |
290 | unsigned long flags; | 412 | unsigned long flags; |
@@ -296,27 +418,35 @@ static void hif_usb_start(void *hif_handle, u8 pipe_id) | |||
296 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | 418 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
297 | } | 419 | } |
298 | 420 | ||
299 | static void hif_usb_stop(void *hif_handle, u8 pipe_id) | 421 | static void hif_usb_stop(void *hif_handle) |
300 | { | 422 | { |
301 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | 423 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; |
424 | struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; | ||
302 | unsigned long flags; | 425 | unsigned long flags; |
303 | 426 | ||
304 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | 427 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); |
305 | ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue); | 428 | ath9k_skb_queue_complete(hif_dev, &hif_dev->tx.tx_skb_queue, false); |
306 | hif_dev->tx.tx_skb_cnt = 0; | 429 | hif_dev->tx.tx_skb_cnt = 0; |
307 | hif_dev->tx.flags |= HIF_USB_TX_STOP; | 430 | hif_dev->tx.flags |= HIF_USB_TX_STOP; |
308 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | 431 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); |
432 | |||
433 | /* The pending URBs have to be canceled. */ | ||
434 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, | ||
435 | &hif_dev->tx.tx_pending, list) { | ||
436 | usb_kill_urb(tx_buf->urb); | ||
437 | } | ||
438 | |||
439 | usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); | ||
309 | } | 440 | } |
310 | 441 | ||
311 | static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, | 442 | static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb) |
312 | struct ath9k_htc_tx_ctl *tx_ctl) | ||
313 | { | 443 | { |
314 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | 444 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; |
315 | int ret = 0; | 445 | int ret = 0; |
316 | 446 | ||
317 | switch (pipe_id) { | 447 | switch (pipe_id) { |
318 | case USB_WLAN_TX_PIPE: | 448 | case USB_WLAN_TX_PIPE: |
319 | ret = hif_usb_send_tx(hif_dev, skb, tx_ctl); | 449 | ret = hif_usb_send_tx(hif_dev, skb); |
320 | break; | 450 | break; |
321 | case USB_REG_OUT_PIPE: | 451 | case USB_REG_OUT_PIPE: |
322 | ret = hif_usb_send_regout(hif_dev, skb); | 452 | ret = hif_usb_send_regout(hif_dev, skb); |
@@ -331,6 +461,40 @@ static int hif_usb_send(void *hif_handle, u8 pipe_id, struct sk_buff *skb, | |||
331 | return ret; | 461 | return ret; |
332 | } | 462 | } |
333 | 463 | ||
464 | static inline bool check_index(struct sk_buff *skb, u8 idx) | ||
465 | { | ||
466 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
467 | |||
468 | tx_ctl = HTC_SKB_CB(skb); | ||
469 | |||
470 | if ((tx_ctl->type == ATH9K_HTC_AMPDU) && | ||
471 | (tx_ctl->sta_idx == idx)) | ||
472 | return true; | ||
473 | |||
474 | return false; | ||
475 | } | ||
476 | |||
477 | static void hif_usb_sta_drain(void *hif_handle, u8 idx) | ||
478 | { | ||
479 | struct hif_device_usb *hif_dev = (struct hif_device_usb *)hif_handle; | ||
480 | struct sk_buff *skb, *tmp; | ||
481 | unsigned long flags; | ||
482 | |||
483 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
484 | |||
485 | skb_queue_walk_safe(&hif_dev->tx.tx_skb_queue, skb, tmp) { | ||
486 | if (check_index(skb, idx)) { | ||
487 | __skb_unlink(skb, &hif_dev->tx.tx_skb_queue); | ||
488 | ath9k_htc_txcompletion_cb(hif_dev->htc_handle, | ||
489 | skb, false); | ||
490 | hif_dev->tx.tx_skb_cnt--; | ||
491 | TX_STAT_INC(skb_failed); | ||
492 | } | ||
493 | } | ||
494 | |||
495 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
496 | } | ||
497 | |||
334 | static struct ath9k_htc_hif hif_usb = { | 498 | static struct ath9k_htc_hif hif_usb = { |
335 | .transport = ATH9K_HIF_USB, | 499 | .transport = ATH9K_HIF_USB, |
336 | .name = "ath9k_hif_usb", | 500 | .name = "ath9k_hif_usb", |
@@ -340,6 +504,7 @@ static struct ath9k_htc_hif hif_usb = { | |||
340 | 504 | ||
341 | .start = hif_usb_start, | 505 | .start = hif_usb_start, |
342 | .stop = hif_usb_stop, | 506 | .stop = hif_usb_stop, |
507 | .sta_drain = hif_usb_sta_drain, | ||
343 | .send = hif_usb_send, | 508 | .send = hif_usb_send, |
344 | }; | 509 | }; |
345 | 510 | ||
@@ -347,9 +512,9 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |||
347 | struct sk_buff *skb) | 512 | struct sk_buff *skb) |
348 | { | 513 | { |
349 | struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; | 514 | struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; |
350 | int index = 0, i = 0, chk_idx, len = skb->len; | 515 | int index = 0, i = 0, len = skb->len; |
351 | int rx_remain_len = 0, rx_pkt_len = 0; | 516 | int rx_remain_len, rx_pkt_len; |
352 | u16 pkt_len, pkt_tag, pool_index = 0; | 517 | u16 pool_index = 0; |
353 | u8 *ptr; | 518 | u8 *ptr; |
354 | 519 | ||
355 | spin_lock(&hif_dev->rx_lock); | 520 | spin_lock(&hif_dev->rx_lock); |
@@ -383,64 +548,64 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, | |||
383 | spin_unlock(&hif_dev->rx_lock); | 548 | spin_unlock(&hif_dev->rx_lock); |
384 | 549 | ||
385 | while (index < len) { | 550 | while (index < len) { |
551 | u16 pkt_len; | ||
552 | u16 pkt_tag; | ||
553 | u16 pad_len; | ||
554 | int chk_idx; | ||
555 | |||
386 | ptr = (u8 *) skb->data; | 556 | ptr = (u8 *) skb->data; |
387 | 557 | ||
388 | pkt_len = ptr[index] + (ptr[index+1] << 8); | 558 | pkt_len = ptr[index] + (ptr[index+1] << 8); |
389 | pkt_tag = ptr[index+2] + (ptr[index+3] << 8); | 559 | pkt_tag = ptr[index+2] + (ptr[index+3] << 8); |
390 | 560 | ||
391 | if (pkt_tag == ATH_USB_RX_STREAM_MODE_TAG) { | 561 | if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) { |
392 | u16 pad_len; | 562 | RX_STAT_INC(skb_dropped); |
393 | 563 | return; | |
394 | pad_len = 4 - (pkt_len & 0x3); | 564 | } |
395 | if (pad_len == 4) | 565 | |
396 | pad_len = 0; | 566 | pad_len = 4 - (pkt_len & 0x3); |
397 | 567 | if (pad_len == 4) | |
398 | chk_idx = index; | 568 | pad_len = 0; |
399 | index = index + 4 + pkt_len + pad_len; | 569 | |
400 | 570 | chk_idx = index; | |
401 | if (index > MAX_RX_BUF_SIZE) { | 571 | index = index + 4 + pkt_len + pad_len; |
402 | spin_lock(&hif_dev->rx_lock); | 572 | |
403 | hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; | 573 | if (index > MAX_RX_BUF_SIZE) { |
404 | hif_dev->rx_transfer_len = | 574 | spin_lock(&hif_dev->rx_lock); |
405 | MAX_RX_BUF_SIZE - chk_idx - 4; | 575 | hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE; |
406 | hif_dev->rx_pad_len = pad_len; | 576 | hif_dev->rx_transfer_len = |
407 | 577 | MAX_RX_BUF_SIZE - chk_idx - 4; | |
408 | nskb = __dev_alloc_skb(pkt_len + 32, | 578 | hif_dev->rx_pad_len = pad_len; |
409 | GFP_ATOMIC); | 579 | |
410 | if (!nskb) { | 580 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); |
411 | dev_err(&hif_dev->udev->dev, | 581 | if (!nskb) { |
412 | "ath9k_htc: RX memory allocation" | 582 | dev_err(&hif_dev->udev->dev, |
413 | " error\n"); | 583 | "ath9k_htc: RX memory allocation error\n"); |
414 | spin_unlock(&hif_dev->rx_lock); | ||
415 | goto err; | ||
416 | } | ||
417 | skb_reserve(nskb, 32); | ||
418 | RX_STAT_INC(skb_allocated); | ||
419 | |||
420 | memcpy(nskb->data, &(skb->data[chk_idx+4]), | ||
421 | hif_dev->rx_transfer_len); | ||
422 | |||
423 | /* Record the buffer pointer */ | ||
424 | hif_dev->remain_skb = nskb; | ||
425 | spin_unlock(&hif_dev->rx_lock); | 584 | spin_unlock(&hif_dev->rx_lock); |
426 | } else { | 585 | goto err; |
427 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); | ||
428 | if (!nskb) { | ||
429 | dev_err(&hif_dev->udev->dev, | ||
430 | "ath9k_htc: RX memory allocation" | ||
431 | " error\n"); | ||
432 | goto err; | ||
433 | } | ||
434 | skb_reserve(nskb, 32); | ||
435 | RX_STAT_INC(skb_allocated); | ||
436 | |||
437 | memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); | ||
438 | skb_put(nskb, pkt_len); | ||
439 | skb_pool[pool_index++] = nskb; | ||
440 | } | 586 | } |
587 | skb_reserve(nskb, 32); | ||
588 | RX_STAT_INC(skb_allocated); | ||
589 | |||
590 | memcpy(nskb->data, &(skb->data[chk_idx+4]), | ||
591 | hif_dev->rx_transfer_len); | ||
592 | |||
593 | /* Record the buffer pointer */ | ||
594 | hif_dev->remain_skb = nskb; | ||
595 | spin_unlock(&hif_dev->rx_lock); | ||
441 | } else { | 596 | } else { |
442 | RX_STAT_INC(skb_dropped); | 597 | nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC); |
443 | return; | 598 | if (!nskb) { |
599 | dev_err(&hif_dev->udev->dev, | ||
600 | "ath9k_htc: RX memory allocation error\n"); | ||
601 | goto err; | ||
602 | } | ||
603 | skb_reserve(nskb, 32); | ||
604 | RX_STAT_INC(skb_allocated); | ||
605 | |||
606 | memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len); | ||
607 | skb_put(nskb, pkt_len); | ||
608 | skb_pool[pool_index++] = nskb; | ||
444 | } | 609 | } |
445 | } | 610 | } |
446 | 611 | ||
@@ -455,7 +620,7 @@ err: | |||
455 | static void ath9k_hif_usb_rx_cb(struct urb *urb) | 620 | static void ath9k_hif_usb_rx_cb(struct urb *urb) |
456 | { | 621 | { |
457 | struct sk_buff *skb = (struct sk_buff *) urb->context; | 622 | struct sk_buff *skb = (struct sk_buff *) urb->context; |
458 | struct hif_device_usb *hif_dev = (struct hif_device_usb *) | 623 | struct hif_device_usb *hif_dev = |
459 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | 624 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); |
460 | int ret; | 625 | int ret; |
461 | 626 | ||
@@ -502,7 +667,7 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
502 | { | 667 | { |
503 | struct sk_buff *skb = (struct sk_buff *) urb->context; | 668 | struct sk_buff *skb = (struct sk_buff *) urb->context; |
504 | struct sk_buff *nskb; | 669 | struct sk_buff *nskb; |
505 | struct hif_device_usb *hif_dev = (struct hif_device_usb *) | 670 | struct hif_device_usb *hif_dev = |
506 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | 671 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); |
507 | int ret; | 672 | int ret; |
508 | 673 | ||
@@ -521,6 +686,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
521 | case -ESHUTDOWN: | 686 | case -ESHUTDOWN: |
522 | goto free; | 687 | goto free; |
523 | default: | 688 | default: |
689 | skb_reset_tail_pointer(skb); | ||
690 | skb_trim(skb, 0); | ||
691 | |||
524 | goto resubmit; | 692 | goto resubmit; |
525 | } | 693 | } |
526 | 694 | ||
@@ -540,27 +708,20 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) | |||
540 | return; | 708 | return; |
541 | } | 709 | } |
542 | 710 | ||
543 | usb_fill_int_urb(urb, hif_dev->udev, | 711 | usb_fill_bulk_urb(urb, hif_dev->udev, |
544 | usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), | 712 | usb_rcvbulkpipe(hif_dev->udev, |
713 | USB_REG_IN_PIPE), | ||
545 | nskb->data, MAX_REG_IN_BUF_SIZE, | 714 | nskb->data, MAX_REG_IN_BUF_SIZE, |
546 | ath9k_hif_usb_reg_in_cb, nskb, 1); | 715 | ath9k_hif_usb_reg_in_cb, nskb); |
547 | |||
548 | ret = usb_submit_urb(urb, GFP_ATOMIC); | ||
549 | if (ret) { | ||
550 | kfree_skb(nskb); | ||
551 | urb->context = NULL; | ||
552 | } | ||
553 | |||
554 | return; | ||
555 | } | 716 | } |
556 | 717 | ||
557 | resubmit: | 718 | resubmit: |
558 | skb_reset_tail_pointer(skb); | 719 | usb_anchor_urb(urb, &hif_dev->reg_in_submitted); |
559 | skb_trim(skb, 0); | ||
560 | |||
561 | ret = usb_submit_urb(urb, GFP_ATOMIC); | 720 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
562 | if (ret) | 721 | if (ret) { |
722 | usb_unanchor_urb(urb); | ||
563 | goto free; | 723 | goto free; |
724 | } | ||
564 | 725 | ||
565 | return; | 726 | return; |
566 | free: | 727 | free: |
@@ -571,6 +732,7 @@ free: | |||
571 | static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) | 732 | static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) |
572 | { | 733 | { |
573 | struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; | 734 | struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL; |
735 | unsigned long flags; | ||
574 | 736 | ||
575 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, | 737 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, |
576 | &hif_dev->tx.tx_buf, list) { | 738 | &hif_dev->tx.tx_buf, list) { |
@@ -581,6 +743,10 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) | |||
581 | kfree(tx_buf); | 743 | kfree(tx_buf); |
582 | } | 744 | } |
583 | 745 | ||
746 | spin_lock_irqsave(&hif_dev->tx.tx_lock, flags); | ||
747 | hif_dev->tx.flags |= HIF_USB_TX_FLUSH; | ||
748 | spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags); | ||
749 | |||
584 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, | 750 | list_for_each_entry_safe(tx_buf, tx_buf_tmp, |
585 | &hif_dev->tx.tx_pending, list) { | 751 | &hif_dev->tx.tx_pending, list) { |
586 | usb_kill_urb(tx_buf->urb); | 752 | usb_kill_urb(tx_buf->urb); |
@@ -589,6 +755,8 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev) | |||
589 | kfree(tx_buf->buf); | 755 | kfree(tx_buf->buf); |
590 | kfree(tx_buf); | 756 | kfree(tx_buf); |
591 | } | 757 | } |
758 | |||
759 | usb_kill_anchored_urbs(&hif_dev->mgmt_submitted); | ||
592 | } | 760 | } |
593 | 761 | ||
594 | static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) | 762 | static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) |
@@ -600,6 +768,7 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) | |||
600 | INIT_LIST_HEAD(&hif_dev->tx.tx_pending); | 768 | INIT_LIST_HEAD(&hif_dev->tx.tx_pending); |
601 | spin_lock_init(&hif_dev->tx.tx_lock); | 769 | spin_lock_init(&hif_dev->tx.tx_lock); |
602 | __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); | 770 | __skb_queue_head_init(&hif_dev->tx.tx_skb_queue); |
771 | init_usb_anchor(&hif_dev->mgmt_submitted); | ||
603 | 772 | ||
604 | for (i = 0; i < MAX_TX_URB_NUM; i++) { | 773 | for (i = 0; i < MAX_TX_URB_NUM; i++) { |
605 | tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); | 774 | tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL); |
@@ -696,42 +865,67 @@ err_urb: | |||
696 | return ret; | 865 | return ret; |
697 | } | 866 | } |
698 | 867 | ||
699 | static void ath9k_hif_usb_dealloc_reg_in_urb(struct hif_device_usb *hif_dev) | 868 | static void ath9k_hif_usb_dealloc_reg_in_urbs(struct hif_device_usb *hif_dev) |
700 | { | 869 | { |
701 | if (hif_dev->reg_in_urb) { | 870 | usb_kill_anchored_urbs(&hif_dev->reg_in_submitted); |
702 | usb_kill_urb(hif_dev->reg_in_urb); | ||
703 | if (hif_dev->reg_in_urb->context) | ||
704 | kfree_skb((void *)hif_dev->reg_in_urb->context); | ||
705 | usb_free_urb(hif_dev->reg_in_urb); | ||
706 | hif_dev->reg_in_urb = NULL; | ||
707 | } | ||
708 | } | 871 | } |
709 | 872 | ||
710 | static int ath9k_hif_usb_alloc_reg_in_urb(struct hif_device_usb *hif_dev) | 873 | static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev) |
711 | { | 874 | { |
712 | struct sk_buff *skb; | 875 | struct urb *urb = NULL; |
876 | struct sk_buff *skb = NULL; | ||
877 | int i, ret; | ||
713 | 878 | ||
714 | hif_dev->reg_in_urb = usb_alloc_urb(0, GFP_KERNEL); | 879 | init_usb_anchor(&hif_dev->reg_in_submitted); |
715 | if (hif_dev->reg_in_urb == NULL) | ||
716 | return -ENOMEM; | ||
717 | 880 | ||
718 | skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); | 881 | for (i = 0; i < MAX_REG_IN_URB_NUM; i++) { |
719 | if (!skb) | 882 | |
720 | goto err; | 883 | /* Allocate URB */ |
884 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
885 | if (urb == NULL) { | ||
886 | ret = -ENOMEM; | ||
887 | goto err_urb; | ||
888 | } | ||
721 | 889 | ||
722 | usb_fill_int_urb(hif_dev->reg_in_urb, hif_dev->udev, | 890 | /* Allocate buffer */ |
723 | usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), | 891 | skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_KERNEL); |
724 | skb->data, MAX_REG_IN_BUF_SIZE, | 892 | if (!skb) { |
725 | ath9k_hif_usb_reg_in_cb, skb, 1); | 893 | ret = -ENOMEM; |
894 | goto err_skb; | ||
895 | } | ||
726 | 896 | ||
727 | if (usb_submit_urb(hif_dev->reg_in_urb, GFP_KERNEL) != 0) | 897 | usb_fill_bulk_urb(urb, hif_dev->udev, |
728 | goto err; | 898 | usb_rcvbulkpipe(hif_dev->udev, |
899 | USB_REG_IN_PIPE), | ||
900 | skb->data, MAX_REG_IN_BUF_SIZE, | ||
901 | ath9k_hif_usb_reg_in_cb, skb); | ||
902 | |||
903 | /* Anchor URB */ | ||
904 | usb_anchor_urb(urb, &hif_dev->reg_in_submitted); | ||
905 | |||
906 | /* Submit URB */ | ||
907 | ret = usb_submit_urb(urb, GFP_KERNEL); | ||
908 | if (ret) { | ||
909 | usb_unanchor_urb(urb); | ||
910 | goto err_submit; | ||
911 | } | ||
912 | |||
913 | /* | ||
914 | * Drop reference count. | ||
915 | * This ensures that the URB is freed when killing them. | ||
916 | */ | ||
917 | usb_free_urb(urb); | ||
918 | } | ||
729 | 919 | ||
730 | return 0; | 920 | return 0; |
731 | 921 | ||
732 | err: | 922 | err_submit: |
733 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); | 923 | kfree_skb(skb); |
734 | return -ENOMEM; | 924 | err_skb: |
925 | usb_free_urb(urb); | ||
926 | err_urb: | ||
927 | ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); | ||
928 | return ret; | ||
735 | } | 929 | } |
736 | 930 | ||
737 | static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) | 931 | static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) |
@@ -748,7 +942,7 @@ static int ath9k_hif_usb_alloc_urbs(struct hif_device_usb *hif_dev) | |||
748 | goto err_rx; | 942 | goto err_rx; |
749 | 943 | ||
750 | /* Register Read */ | 944 | /* Register Read */ |
751 | if (ath9k_hif_usb_alloc_reg_in_urb(hif_dev) < 0) | 945 | if (ath9k_hif_usb_alloc_reg_in_urbs(hif_dev) < 0) |
752 | goto err_reg; | 946 | goto err_reg; |
753 | 947 | ||
754 | return 0; | 948 | return 0; |
@@ -763,12 +957,13 @@ err: | |||
763 | static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) | 957 | static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev) |
764 | { | 958 | { |
765 | usb_kill_anchored_urbs(&hif_dev->regout_submitted); | 959 | usb_kill_anchored_urbs(&hif_dev->regout_submitted); |
766 | ath9k_hif_usb_dealloc_reg_in_urb(hif_dev); | 960 | ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev); |
767 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); | 961 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); |
768 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); | 962 | ath9k_hif_usb_dealloc_rx_urbs(hif_dev); |
769 | } | 963 | } |
770 | 964 | ||
771 | static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | 965 | static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev, |
966 | u32 drv_info) | ||
772 | { | 967 | { |
773 | int transfer, err; | 968 | int transfer, err; |
774 | const void *data = hif_dev->firmware->data; | 969 | const void *data = hif_dev->firmware->data; |
@@ -799,7 +994,7 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
799 | } | 994 | } |
800 | kfree(buf); | 995 | kfree(buf); |
801 | 996 | ||
802 | if ((hif_dev->device_id == 0x7010) || (hif_dev->device_id == 0x7015)) | 997 | if (IS_AR7010_DEVICE(drv_info)) |
803 | firm_offset = AR7010_FIRMWARE_TEXT; | 998 | firm_offset = AR7010_FIRMWARE_TEXT; |
804 | else | 999 | else |
805 | firm_offset = AR9271_FIRMWARE_TEXT; | 1000 | firm_offset = AR9271_FIRMWARE_TEXT; |
@@ -820,9 +1015,11 @@ static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev) | |||
820 | return 0; | 1015 | return 0; |
821 | } | 1016 | } |
822 | 1017 | ||
823 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) | 1018 | static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info) |
824 | { | 1019 | { |
825 | int ret; | 1020 | int ret, idx; |
1021 | struct usb_host_interface *alt = &hif_dev->interface->altsetting[0]; | ||
1022 | struct usb_endpoint_descriptor *endp; | ||
826 | 1023 | ||
827 | /* Request firmware */ | 1024 | /* Request firmware */ |
828 | ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name, | 1025 | ret = request_firmware(&hif_dev->firmware, hif_dev->fw_name, |
@@ -833,28 +1030,40 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev) | |||
833 | goto err_fw_req; | 1030 | goto err_fw_req; |
834 | } | 1031 | } |
835 | 1032 | ||
836 | /* Alloc URBs */ | 1033 | /* Download firmware */ |
837 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); | 1034 | ret = ath9k_hif_usb_download_fw(hif_dev, drv_info); |
838 | if (ret) { | 1035 | if (ret) { |
839 | dev_err(&hif_dev->udev->dev, | 1036 | dev_err(&hif_dev->udev->dev, |
840 | "ath9k_htc: Unable to allocate URBs\n"); | 1037 | "ath9k_htc: Firmware - %s download failed\n", |
841 | goto err_urb; | 1038 | hif_dev->fw_name); |
1039 | goto err_fw_download; | ||
842 | } | 1040 | } |
843 | 1041 | ||
844 | /* Download firmware */ | 1042 | /* On downloading the firmware to the target, the USB descriptor of EP4 |
845 | ret = ath9k_hif_usb_download_fw(hif_dev); | 1043 | * is 'patched' to change the type of the endpoint to Bulk. This will |
1044 | * bring down CPU usage during the scan period. | ||
1045 | */ | ||
1046 | for (idx = 0; idx < alt->desc.bNumEndpoints; idx++) { | ||
1047 | endp = &alt->endpoint[idx].desc; | ||
1048 | if ((endp->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
1049 | == USB_ENDPOINT_XFER_INT) { | ||
1050 | endp->bmAttributes &= ~USB_ENDPOINT_XFERTYPE_MASK; | ||
1051 | endp->bmAttributes |= USB_ENDPOINT_XFER_BULK; | ||
1052 | endp->bInterval = 0; | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | /* Alloc URBs */ | ||
1057 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); | ||
846 | if (ret) { | 1058 | if (ret) { |
847 | dev_err(&hif_dev->udev->dev, | 1059 | dev_err(&hif_dev->udev->dev, |
848 | "ath9k_htc: Firmware - %s download failed\n", | 1060 | "ath9k_htc: Unable to allocate URBs\n"); |
849 | hif_dev->fw_name); | ||
850 | goto err_fw_download; | 1061 | goto err_fw_download; |
851 | } | 1062 | } |
852 | 1063 | ||
853 | return 0; | 1064 | return 0; |
854 | 1065 | ||
855 | err_fw_download: | 1066 | err_fw_download: |
856 | ath9k_hif_usb_dealloc_urbs(hif_dev); | ||
857 | err_urb: | ||
858 | release_firmware(hif_dev->firmware); | 1067 | release_firmware(hif_dev->firmware); |
859 | err_fw_req: | 1068 | err_fw_req: |
860 | hif_dev->firmware = NULL; | 1069 | hif_dev->firmware = NULL; |
@@ -868,6 +1077,61 @@ static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) | |||
868 | release_firmware(hif_dev->firmware); | 1077 | release_firmware(hif_dev->firmware); |
869 | } | 1078 | } |
870 | 1079 | ||
1080 | /* | ||
1081 | * An exact copy of the function from zd1211rw. | ||
1082 | */ | ||
1083 | static int send_eject_command(struct usb_interface *interface) | ||
1084 | { | ||
1085 | struct usb_device *udev = interface_to_usbdev(interface); | ||
1086 | struct usb_host_interface *iface_desc = &interface->altsetting[0]; | ||
1087 | struct usb_endpoint_descriptor *endpoint; | ||
1088 | unsigned char *cmd; | ||
1089 | u8 bulk_out_ep; | ||
1090 | int r; | ||
1091 | |||
1092 | /* Find bulk out endpoint */ | ||
1093 | for (r = 1; r >= 0; r--) { | ||
1094 | endpoint = &iface_desc->endpoint[r].desc; | ||
1095 | if (usb_endpoint_dir_out(endpoint) && | ||
1096 | usb_endpoint_xfer_bulk(endpoint)) { | ||
1097 | bulk_out_ep = endpoint->bEndpointAddress; | ||
1098 | break; | ||
1099 | } | ||
1100 | } | ||
1101 | if (r == -1) { | ||
1102 | dev_err(&udev->dev, | ||
1103 | "ath9k_htc: Could not find bulk out endpoint\n"); | ||
1104 | return -ENODEV; | ||
1105 | } | ||
1106 | |||
1107 | cmd = kzalloc(31, GFP_KERNEL); | ||
1108 | if (cmd == NULL) | ||
1109 | return -ENODEV; | ||
1110 | |||
1111 | /* USB bulk command block */ | ||
1112 | cmd[0] = 0x55; /* bulk command signature */ | ||
1113 | cmd[1] = 0x53; /* bulk command signature */ | ||
1114 | cmd[2] = 0x42; /* bulk command signature */ | ||
1115 | cmd[3] = 0x43; /* bulk command signature */ | ||
1116 | cmd[14] = 6; /* command length */ | ||
1117 | |||
1118 | cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */ | ||
1119 | cmd[19] = 0x2; /* eject disc */ | ||
1120 | |||
1121 | dev_info(&udev->dev, "Ejecting storage device...\n"); | ||
1122 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep), | ||
1123 | cmd, 31, NULL, 2000); | ||
1124 | kfree(cmd); | ||
1125 | if (r) | ||
1126 | return r; | ||
1127 | |||
1128 | /* At this point, the device disconnects and reconnects with the real | ||
1129 | * ID numbers. */ | ||
1130 | |||
1131 | usb_set_intfdata(interface, NULL); | ||
1132 | return 0; | ||
1133 | } | ||
1134 | |||
871 | static int ath9k_hif_usb_probe(struct usb_interface *interface, | 1135 | static int ath9k_hif_usb_probe(struct usb_interface *interface, |
872 | const struct usb_device_id *id) | 1136 | const struct usb_device_id *id) |
873 | { | 1137 | { |
@@ -875,6 +1139,9 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, | |||
875 | struct hif_device_usb *hif_dev; | 1139 | struct hif_device_usb *hif_dev; |
876 | int ret = 0; | 1140 | int ret = 0; |
877 | 1141 | ||
1142 | if (id->driver_info == STORAGE_DEVICE) | ||
1143 | return send_eject_command(interface); | ||
1144 | |||
878 | hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); | 1145 | hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); |
879 | if (!hif_dev) { | 1146 | if (!hif_dev) { |
880 | ret = -ENOMEM; | 1147 | ret = -ENOMEM; |
@@ -899,28 +1166,20 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, | |||
899 | 1166 | ||
900 | /* Find out which firmware to load */ | 1167 | /* Find out which firmware to load */ |
901 | 1168 | ||
902 | switch(hif_dev->device_id) { | 1169 | if (IS_AR7010_DEVICE(id->driver_info)) |
903 | case 0x7010: | 1170 | hif_dev->fw_name = FIRMWARE_AR7010_1_1; |
904 | case 0x7015: | 1171 | else |
905 | case 0x9018: | ||
906 | if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202) | ||
907 | hif_dev->fw_name = FIRMWARE_AR7010_1_1; | ||
908 | else | ||
909 | hif_dev->fw_name = FIRMWARE_AR7010; | ||
910 | break; | ||
911 | default: | ||
912 | hif_dev->fw_name = FIRMWARE_AR9271; | 1172 | hif_dev->fw_name = FIRMWARE_AR9271; |
913 | break; | ||
914 | } | ||
915 | 1173 | ||
916 | ret = ath9k_hif_usb_dev_init(hif_dev); | 1174 | ret = ath9k_hif_usb_dev_init(hif_dev, id->driver_info); |
917 | if (ret) { | 1175 | if (ret) { |
918 | ret = -EINVAL; | 1176 | ret = -EINVAL; |
919 | goto err_hif_init_usb; | 1177 | goto err_hif_init_usb; |
920 | } | 1178 | } |
921 | 1179 | ||
922 | ret = ath9k_htc_hw_init(hif_dev->htc_handle, | 1180 | ret = ath9k_htc_hw_init(hif_dev->htc_handle, |
923 | &hif_dev->udev->dev, hif_dev->device_id); | 1181 | &interface->dev, hif_dev->device_id, |
1182 | hif_dev->udev->product, id->driver_info); | ||
924 | if (ret) { | 1183 | if (ret) { |
925 | ret = -EINVAL; | 1184 | ret = -EINVAL; |
926 | goto err_htc_hw_init; | 1185 | goto err_htc_hw_init; |
@@ -963,18 +1222,18 @@ static void ath9k_hif_usb_reboot(struct usb_device *udev) | |||
963 | static void ath9k_hif_usb_disconnect(struct usb_interface *interface) | 1222 | static void ath9k_hif_usb_disconnect(struct usb_interface *interface) |
964 | { | 1223 | { |
965 | struct usb_device *udev = interface_to_usbdev(interface); | 1224 | struct usb_device *udev = interface_to_usbdev(interface); |
966 | struct hif_device_usb *hif_dev = | 1225 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
967 | (struct hif_device_usb *) usb_get_intfdata(interface); | 1226 | bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false; |
968 | 1227 | ||
969 | if (hif_dev) { | 1228 | if (!hif_dev) |
970 | ath9k_htc_hw_deinit(hif_dev->htc_handle, | 1229 | return; |
971 | (udev->state == USB_STATE_NOTATTACHED) ? true : false); | 1230 | |
972 | ath9k_htc_hw_free(hif_dev->htc_handle); | 1231 | ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged); |
973 | ath9k_hif_usb_dev_deinit(hif_dev); | 1232 | ath9k_htc_hw_free(hif_dev->htc_handle); |
974 | usb_set_intfdata(interface, NULL); | 1233 | ath9k_hif_usb_dev_deinit(hif_dev); |
975 | } | 1234 | usb_set_intfdata(interface, NULL); |
976 | 1235 | ||
977 | if (hif_dev->flags & HIF_USB_START) | 1236 | if (!unplugged && (hif_dev->flags & HIF_USB_START)) |
978 | ath9k_hif_usb_reboot(udev); | 1237 | ath9k_hif_usb_reboot(udev); |
979 | 1238 | ||
980 | kfree(hif_dev); | 1239 | kfree(hif_dev); |
@@ -986,8 +1245,14 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) | |||
986 | static int ath9k_hif_usb_suspend(struct usb_interface *interface, | 1245 | static int ath9k_hif_usb_suspend(struct usb_interface *interface, |
987 | pm_message_t message) | 1246 | pm_message_t message) |
988 | { | 1247 | { |
989 | struct hif_device_usb *hif_dev = | 1248 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
990 | (struct hif_device_usb *) usb_get_intfdata(interface); | 1249 | |
1250 | /* | ||
1251 | * The device has to be set to FULLSLEEP mode in case no | ||
1252 | * interface is up. | ||
1253 | */ | ||
1254 | if (!(hif_dev->flags & HIF_USB_START)) | ||
1255 | ath9k_htc_suspend(hif_dev->htc_handle); | ||
991 | 1256 | ||
992 | ath9k_hif_usb_dealloc_urbs(hif_dev); | 1257 | ath9k_hif_usb_dealloc_urbs(hif_dev); |
993 | 1258 | ||
@@ -996,8 +1261,8 @@ static int ath9k_hif_usb_suspend(struct usb_interface *interface, | |||
996 | 1261 | ||
997 | static int ath9k_hif_usb_resume(struct usb_interface *interface) | 1262 | static int ath9k_hif_usb_resume(struct usb_interface *interface) |
998 | { | 1263 | { |
999 | struct hif_device_usb *hif_dev = | 1264 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
1000 | (struct hif_device_usb *) usb_get_intfdata(interface); | 1265 | struct htc_target *htc_handle = hif_dev->htc_handle; |
1001 | int ret; | 1266 | int ret; |
1002 | 1267 | ||
1003 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); | 1268 | ret = ath9k_hif_usb_alloc_urbs(hif_dev); |
@@ -1005,7 +1270,8 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface) | |||
1005 | return ret; | 1270 | return ret; |
1006 | 1271 | ||
1007 | if (hif_dev->firmware) { | 1272 | if (hif_dev->firmware) { |
1008 | ret = ath9k_hif_usb_download_fw(hif_dev); | 1273 | ret = ath9k_hif_usb_download_fw(hif_dev, |
1274 | htc_handle->drv_priv->ah->hw_version.usbdev); | ||
1009 | if (ret) | 1275 | if (ret) |
1010 | goto fail_resume; | 1276 | goto fail_resume; |
1011 | } else { | 1277 | } else { |
@@ -1015,7 +1281,7 @@ static int ath9k_hif_usb_resume(struct usb_interface *interface) | |||
1015 | 1281 | ||
1016 | mdelay(100); | 1282 | mdelay(100); |
1017 | 1283 | ||
1018 | ret = ath9k_htc_resume(hif_dev->htc_handle); | 1284 | ret = ath9k_htc_resume(htc_handle); |
1019 | 1285 | ||
1020 | if (ret) | 1286 | if (ret) |
1021 | goto fail_resume; | 1287 | goto fail_resume; |
@@ -1030,7 +1296,7 @@ fail_resume: | |||
1030 | #endif | 1296 | #endif |
1031 | 1297 | ||
1032 | static struct usb_driver ath9k_hif_usb_driver = { | 1298 | static struct usb_driver ath9k_hif_usb_driver = { |
1033 | .name = "ath9k_hif_usb", | 1299 | .name = KBUILD_MODNAME, |
1034 | .probe = ath9k_hif_usb_probe, | 1300 | .probe = ath9k_hif_usb_probe, |
1035 | .disconnect = ath9k_hif_usb_disconnect, | 1301 | .disconnect = ath9k_hif_usb_disconnect, |
1036 | #ifdef CONFIG_PM | 1302 | #ifdef CONFIG_PM |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.h b/drivers/net/wireless/ath/ath9k/hif_usb.h index 2daf97b11c08..794f63094e5d 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.h +++ b/drivers/net/wireless/ath/ath9k/hif_usb.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,6 +17,11 @@ | |||
17 | #ifndef HTC_USB_H | 17 | #ifndef HTC_USB_H |
18 | #define HTC_USB_H | 18 | #define HTC_USB_H |
19 | 19 | ||
20 | #define MAJOR_VERSION_REQ 1 | ||
21 | #define MINOR_VERSION_REQ 3 | ||
22 | |||
23 | #define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || ((_v) == AR9287_USB)) | ||
24 | |||
20 | #define AR9271_FIRMWARE 0x501000 | 25 | #define AR9271_FIRMWARE 0x501000 |
21 | #define AR9271_FIRMWARE_TEXT 0x903000 | 26 | #define AR9271_FIRMWARE_TEXT 0x903000 |
22 | #define AR7010_FIRMWARE_TEXT 0x906000 | 27 | #define AR7010_FIRMWARE_TEXT 0x906000 |
@@ -29,7 +34,7 @@ | |||
29 | 34 | ||
30 | /* FIXME: Verify these numbers (with Windows) */ | 35 | /* FIXME: Verify these numbers (with Windows) */ |
31 | #define MAX_TX_URB_NUM 8 | 36 | #define MAX_TX_URB_NUM 8 |
32 | #define MAX_TX_BUF_NUM 1024 | 37 | #define MAX_TX_BUF_NUM 256 |
33 | #define MAX_TX_BUF_SIZE 32768 | 38 | #define MAX_TX_BUF_SIZE 32768 |
34 | #define MAX_TX_AGGR_NUM 20 | 39 | #define MAX_TX_AGGR_NUM 20 |
35 | 40 | ||
@@ -38,7 +43,7 @@ | |||
38 | #define MAX_PKT_NUM_IN_TRANSFER 10 | 43 | #define MAX_PKT_NUM_IN_TRANSFER 10 |
39 | 44 | ||
40 | #define MAX_REG_OUT_URB_NUM 1 | 45 | #define MAX_REG_OUT_URB_NUM 1 |
41 | #define MAX_REG_OUT_BUF_NUM 8 | 46 | #define MAX_REG_IN_URB_NUM 64 |
42 | 47 | ||
43 | #define MAX_REG_IN_BUF_SIZE 64 | 48 | #define MAX_REG_IN_BUF_SIZE 64 |
44 | 49 | ||
@@ -62,6 +67,7 @@ struct tx_buf { | |||
62 | }; | 67 | }; |
63 | 68 | ||
64 | #define HIF_USB_TX_STOP BIT(0) | 69 | #define HIF_USB_TX_STOP BIT(0) |
70 | #define HIF_USB_TX_FLUSH BIT(1) | ||
65 | 71 | ||
66 | struct hif_usb_tx { | 72 | struct hif_usb_tx { |
67 | u8 flags; | 73 | u8 flags; |
@@ -87,9 +93,10 @@ struct hif_device_usb { | |||
87 | const struct firmware *firmware; | 93 | const struct firmware *firmware; |
88 | struct htc_target *htc_handle; | 94 | struct htc_target *htc_handle; |
89 | struct hif_usb_tx tx; | 95 | struct hif_usb_tx tx; |
90 | struct urb *reg_in_urb; | ||
91 | struct usb_anchor regout_submitted; | 96 | struct usb_anchor regout_submitted; |
92 | struct usb_anchor rx_submitted; | 97 | struct usb_anchor rx_submitted; |
98 | struct usb_anchor reg_in_submitted; | ||
99 | struct usb_anchor mgmt_submitted; | ||
93 | struct sk_buff *remain_skb; | 100 | struct sk_buff *remain_skb; |
94 | const char *fw_name; | 101 | const char *fw_name; |
95 | int rx_remain_len; | 102 | int rx_remain_len; |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 43b9e21bc562..5bc022087e65 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -32,6 +32,7 @@ | |||
32 | #include "wmi.h" | 32 | #include "wmi.h" |
33 | 33 | ||
34 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ | 34 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ |
35 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ | ||
35 | #define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ | 36 | #define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ |
36 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 37 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
37 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 38 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
@@ -45,15 +46,8 @@ extern struct ieee80211_ops ath9k_htc_ops; | |||
45 | extern int htc_modparam_nohwcrypt; | 46 | extern int htc_modparam_nohwcrypt; |
46 | 47 | ||
47 | enum htc_phymode { | 48 | enum htc_phymode { |
48 | HTC_MODE_AUTO = 0, | 49 | HTC_MODE_11NA = 0, |
49 | HTC_MODE_11A = 1, | 50 | HTC_MODE_11NG = 1 |
50 | HTC_MODE_11B = 2, | ||
51 | HTC_MODE_11G = 3, | ||
52 | HTC_MODE_FH = 4, | ||
53 | HTC_MODE_TURBO_A = 5, | ||
54 | HTC_MODE_TURBO_G = 6, | ||
55 | HTC_MODE_11NA = 7, | ||
56 | HTC_MODE_11NG = 8 | ||
57 | }; | 51 | }; |
58 | 52 | ||
59 | enum htc_opmode { | 53 | enum htc_opmode { |
@@ -65,23 +59,24 @@ enum htc_opmode { | |||
65 | HTC_M_WDS = 2 | 59 | HTC_M_WDS = 2 |
66 | }; | 60 | }; |
67 | 61 | ||
68 | #define ATH9K_HTC_HDRSPACE sizeof(struct htc_frame_hdr) | 62 | #define ATH9K_HTC_AMPDU 1 |
69 | #define ATH9K_HTC_AMPDU 1 | ||
70 | #define ATH9K_HTC_NORMAL 2 | 63 | #define ATH9K_HTC_NORMAL 2 |
64 | #define ATH9K_HTC_BEACON 3 | ||
65 | #define ATH9K_HTC_MGMT 4 | ||
71 | 66 | ||
72 | #define ATH9K_HTC_TX_CTSONLY 0x1 | 67 | #define ATH9K_HTC_TX_CTSONLY 0x1 |
73 | #define ATH9K_HTC_TX_RTSCTS 0x2 | 68 | #define ATH9K_HTC_TX_RTSCTS 0x2 |
74 | #define ATH9K_HTC_TX_USE_MIN_RATE 0x100 | ||
75 | 69 | ||
76 | struct tx_frame_hdr { | 70 | struct tx_frame_hdr { |
77 | u8 data_type; | 71 | u8 data_type; |
78 | u8 node_idx; | 72 | u8 node_idx; |
79 | u8 vif_idx; | 73 | u8 vif_idx; |
80 | u8 tidno; | 74 | u8 tidno; |
81 | u32 flags; /* ATH9K_HTC_TX_* */ | 75 | __be32 flags; /* ATH9K_HTC_TX_* */ |
82 | u8 key_type; | 76 | u8 key_type; |
83 | u8 keyix; | 77 | u8 keyix; |
84 | u8 reserved[26]; | 78 | u8 cookie; |
79 | u8 pad; | ||
85 | } __packed; | 80 | } __packed; |
86 | 81 | ||
87 | struct tx_mgmt_hdr { | 82 | struct tx_mgmt_hdr { |
@@ -91,78 +86,46 @@ struct tx_mgmt_hdr { | |||
91 | u8 flags; | 86 | u8 flags; |
92 | u8 key_type; | 87 | u8 key_type; |
93 | u8 keyix; | 88 | u8 keyix; |
94 | u16 reserved; | 89 | u8 cookie; |
90 | u8 pad; | ||
95 | } __packed; | 91 | } __packed; |
96 | 92 | ||
97 | struct tx_beacon_header { | 93 | struct tx_beacon_header { |
98 | u8 len_changed; | ||
99 | u8 vif_index; | 94 | u8 vif_index; |
95 | u8 len_changed; | ||
100 | u16 rev; | 96 | u16 rev; |
101 | } __packed; | 97 | } __packed; |
102 | 98 | ||
103 | struct ath9k_htc_target_hw { | 99 | #define MAX_TX_AMPDU_SUBFRAMES_9271 17 |
104 | u32 flags; | 100 | #define MAX_TX_AMPDU_SUBFRAMES_7010 22 |
105 | u32 flags_ext; | ||
106 | u32 ampdu_limit; | ||
107 | u8 ampdu_subframes; | ||
108 | u8 tx_chainmask; | ||
109 | u8 tx_chainmask_legacy; | ||
110 | u8 rtscts_ratecode; | ||
111 | u8 protmode; | ||
112 | } __packed; | ||
113 | 101 | ||
114 | struct ath9k_htc_cap_target { | 102 | struct ath9k_htc_cap_target { |
115 | u32 flags; | 103 | __be32 ampdu_limit; |
116 | u32 flags_ext; | ||
117 | u32 ampdu_limit; | ||
118 | u8 ampdu_subframes; | 104 | u8 ampdu_subframes; |
105 | u8 enable_coex; | ||
119 | u8 tx_chainmask; | 106 | u8 tx_chainmask; |
120 | u8 tx_chainmask_legacy; | 107 | u8 pad; |
121 | u8 rtscts_ratecode; | ||
122 | u8 protmode; | ||
123 | } __packed; | 108 | } __packed; |
124 | 109 | ||
125 | struct ath9k_htc_target_vif { | 110 | struct ath9k_htc_target_vif { |
126 | u8 index; | 111 | u8 index; |
127 | u8 des_bssid[ETH_ALEN]; | 112 | u8 opmode; |
128 | __be32 opmode; | ||
129 | u8 myaddr[ETH_ALEN]; | 113 | u8 myaddr[ETH_ALEN]; |
130 | u8 bssid[ETH_ALEN]; | ||
131 | u32 flags; | ||
132 | u32 flags_ext; | ||
133 | u16 ps_sta; | ||
134 | __be16 rtsthreshold; | ||
135 | u8 ath_cap; | 114 | u8 ath_cap; |
136 | u8 node; | 115 | __be16 rtsthreshold; |
137 | s8 mcast_rate; | 116 | u8 pad; |
138 | } __packed; | 117 | } __packed; |
139 | 118 | ||
140 | #define ATH_HTC_STA_AUTH 0x0001 | ||
141 | #define ATH_HTC_STA_QOS 0x0002 | ||
142 | #define ATH_HTC_STA_ERP 0x0004 | ||
143 | #define ATH_HTC_STA_HT 0x0008 | ||
144 | |||
145 | /* FIXME: UAPSD variables */ | ||
146 | struct ath9k_htc_target_sta { | 119 | struct ath9k_htc_target_sta { |
147 | u16 associd; | ||
148 | u16 txpower; | ||
149 | u32 ucastkey; | ||
150 | u8 macaddr[ETH_ALEN]; | 120 | u8 macaddr[ETH_ALEN]; |
151 | u8 bssid[ETH_ALEN]; | 121 | u8 bssid[ETH_ALEN]; |
152 | u8 sta_index; | 122 | u8 sta_index; |
153 | u8 vif_index; | 123 | u8 vif_index; |
154 | u8 vif_sta; | ||
155 | __be16 flags; /* ATH_HTC_STA_* */ | ||
156 | u16 htcap; | ||
157 | u8 valid; | ||
158 | u16 capinfo; | ||
159 | struct ath9k_htc_target_hw *hw; | ||
160 | struct ath9k_htc_target_vif *vif; | ||
161 | u16 txseqmgmt; | ||
162 | u8 is_vif_sta; | 124 | u8 is_vif_sta; |
163 | u16 maxampdu; | 125 | __be16 flags; |
164 | u16 iv16; | 126 | __be16 htcap; |
165 | u32 iv32; | 127 | __be16 maxampdu; |
128 | u8 pad; | ||
166 | } __packed; | 129 | } __packed; |
167 | 130 | ||
168 | struct ath9k_htc_target_aggr { | 131 | struct ath9k_htc_target_aggr { |
@@ -196,16 +159,86 @@ struct ath9k_htc_target_rate { | |||
196 | struct ath9k_htc_rate rates; | 159 | struct ath9k_htc_rate rates; |
197 | }; | 160 | }; |
198 | 161 | ||
199 | struct ath9k_htc_target_stats { | 162 | struct ath9k_htc_target_rate_mask { |
200 | __be32 tx_shortretry; | 163 | u8 vif_index; |
201 | __be32 tx_longretry; | 164 | u8 band; |
202 | __be32 tx_xretries; | 165 | __be32 mask; |
203 | __be32 ht_txunaggr_xretry; | 166 | u16 pad; |
204 | __be32 ht_tx_xretries; | ||
205 | } __packed; | 167 | } __packed; |
206 | 168 | ||
169 | struct ath9k_htc_target_int_stats { | ||
170 | __be32 rx; | ||
171 | __be32 rxorn; | ||
172 | __be32 rxeol; | ||
173 | __be32 txurn; | ||
174 | __be32 txto; | ||
175 | __be32 cst; | ||
176 | } __packed; | ||
177 | |||
178 | struct ath9k_htc_target_tx_stats { | ||
179 | __be32 xretries; | ||
180 | __be32 fifoerr; | ||
181 | __be32 filtered; | ||
182 | __be32 timer_exp; | ||
183 | __be32 shortretries; | ||
184 | __be32 longretries; | ||
185 | __be32 qnull; | ||
186 | __be32 encap_fail; | ||
187 | __be32 nobuf; | ||
188 | } __packed; | ||
189 | |||
190 | struct ath9k_htc_target_rx_stats { | ||
191 | __be32 nobuf; | ||
192 | __be32 host_send; | ||
193 | __be32 host_done; | ||
194 | } __packed; | ||
195 | |||
196 | #define ATH9K_HTC_MAX_VIF 2 | ||
197 | #define ATH9K_HTC_MAX_BCN_VIF 2 | ||
198 | |||
199 | #define INC_VIF(_priv, _type) do { \ | ||
200 | switch (_type) { \ | ||
201 | case NL80211_IFTYPE_STATION: \ | ||
202 | _priv->num_sta_vif++; \ | ||
203 | break; \ | ||
204 | case NL80211_IFTYPE_ADHOC: \ | ||
205 | _priv->num_ibss_vif++; \ | ||
206 | break; \ | ||
207 | case NL80211_IFTYPE_AP: \ | ||
208 | _priv->num_ap_vif++; \ | ||
209 | break; \ | ||
210 | default: \ | ||
211 | break; \ | ||
212 | } \ | ||
213 | } while (0) | ||
214 | |||
215 | #define DEC_VIF(_priv, _type) do { \ | ||
216 | switch (_type) { \ | ||
217 | case NL80211_IFTYPE_STATION: \ | ||
218 | _priv->num_sta_vif--; \ | ||
219 | break; \ | ||
220 | case NL80211_IFTYPE_ADHOC: \ | ||
221 | _priv->num_ibss_vif--; \ | ||
222 | break; \ | ||
223 | case NL80211_IFTYPE_AP: \ | ||
224 | _priv->num_ap_vif--; \ | ||
225 | break; \ | ||
226 | default: \ | ||
227 | break; \ | ||
228 | } \ | ||
229 | } while (0) | ||
230 | |||
207 | struct ath9k_htc_vif { | 231 | struct ath9k_htc_vif { |
208 | u8 index; | 232 | u8 index; |
233 | u16 seq_no; | ||
234 | bool beacon_configured; | ||
235 | int bslot; | ||
236 | __le64 tsfadjust; | ||
237 | }; | ||
238 | |||
239 | struct ath9k_vif_iter_data { | ||
240 | const u8 *hw_macaddr; | ||
241 | u8 mask[ETH_ALEN]; | ||
209 | }; | 242 | }; |
210 | 243 | ||
211 | #define ATH9K_HTC_MAX_STA 8 | 244 | #define ATH9K_HTC_MAX_STA 8 |
@@ -239,23 +272,65 @@ struct ath9k_htc_rx { | |||
239 | spinlock_t rxbuflock; | 272 | spinlock_t rxbuflock; |
240 | }; | 273 | }; |
241 | 274 | ||
275 | #define ATH9K_HTC_TX_CLEANUP_INTERVAL 50 /* ms */ | ||
276 | #define ATH9K_HTC_TX_TIMEOUT_INTERVAL 3000 /* ms */ | ||
277 | #define ATH9K_HTC_TX_RESERVE 10 | ||
278 | #define ATH9K_HTC_TX_TIMEOUT_COUNT 40 | ||
279 | #define ATH9K_HTC_TX_THRESHOLD (MAX_TX_BUF_NUM - ATH9K_HTC_TX_RESERVE) | ||
280 | |||
281 | #define ATH9K_HTC_OP_TX_QUEUES_STOP BIT(0) | ||
282 | #define ATH9K_HTC_OP_TX_DRAIN BIT(1) | ||
283 | |||
284 | struct ath9k_htc_tx { | ||
285 | u8 flags; | ||
286 | int queued_cnt; | ||
287 | struct sk_buff_head mgmt_ep_queue; | ||
288 | struct sk_buff_head cab_ep_queue; | ||
289 | struct sk_buff_head data_be_queue; | ||
290 | struct sk_buff_head data_bk_queue; | ||
291 | struct sk_buff_head data_vi_queue; | ||
292 | struct sk_buff_head data_vo_queue; | ||
293 | struct sk_buff_head tx_failed; | ||
294 | DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM); | ||
295 | struct timer_list cleanup_timer; | ||
296 | spinlock_t tx_lock; | ||
297 | }; | ||
298 | |||
242 | struct ath9k_htc_tx_ctl { | 299 | struct ath9k_htc_tx_ctl { |
243 | u8 type; /* ATH9K_HTC_* */ | 300 | u8 type; /* ATH9K_HTC_* */ |
301 | u8 epid; | ||
302 | u8 txok; | ||
303 | u8 sta_idx; | ||
304 | unsigned long timestamp; | ||
244 | }; | 305 | }; |
245 | 306 | ||
307 | static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) | ||
308 | { | ||
309 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
310 | |||
311 | BUILD_BUG_ON(sizeof(struct ath9k_htc_tx_ctl) > | ||
312 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE); | ||
313 | return (struct ath9k_htc_tx_ctl *) &tx_info->driver_data; | ||
314 | } | ||
315 | |||
246 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 316 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
247 | 317 | ||
248 | #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) | 318 | #define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++) |
249 | #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) | 319 | #define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++) |
320 | #define CAB_STAT_INC priv->debug.tx_stats.cab_queued++ | ||
250 | 321 | ||
251 | #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) | 322 | #define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++) |
252 | 323 | ||
324 | void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | ||
325 | struct ath_htc_rx_status *rxs); | ||
326 | |||
253 | struct ath_tx_stats { | 327 | struct ath_tx_stats { |
254 | u32 buf_queued; | 328 | u32 buf_queued; |
255 | u32 buf_completed; | 329 | u32 buf_completed; |
256 | u32 skb_queued; | 330 | u32 skb_queued; |
257 | u32 skb_completed; | 331 | u32 skb_success; |
258 | u32 skb_dropped; | 332 | u32 skb_failed; |
333 | u32 cab_queued; | ||
259 | u32 queue_stats[WME_NUM_AC]; | 334 | u32 queue_stats[WME_NUM_AC]; |
260 | }; | 335 | }; |
261 | 336 | ||
@@ -263,70 +338,79 @@ struct ath_rx_stats { | |||
263 | u32 skb_allocated; | 338 | u32 skb_allocated; |
264 | u32 skb_completed; | 339 | u32 skb_completed; |
265 | u32 skb_dropped; | 340 | u32 skb_dropped; |
341 | u32 err_crc; | ||
342 | u32 err_decrypt_crc; | ||
343 | u32 err_mic; | ||
344 | u32 err_pre_delim; | ||
345 | u32 err_post_delim; | ||
346 | u32 err_decrypt_busy; | ||
347 | u32 err_phy; | ||
348 | u32 err_phy_stats[ATH9K_PHYERR_MAX]; | ||
266 | }; | 349 | }; |
267 | 350 | ||
268 | struct ath9k_debug { | 351 | struct ath9k_debug { |
269 | struct dentry *debugfs_phy; | 352 | struct dentry *debugfs_phy; |
270 | struct dentry *debugfs_tgt_stats; | ||
271 | struct dentry *debugfs_xmit; | ||
272 | struct dentry *debugfs_recv; | ||
273 | struct ath_tx_stats tx_stats; | 353 | struct ath_tx_stats tx_stats; |
274 | struct ath_rx_stats rx_stats; | 354 | struct ath_rx_stats rx_stats; |
275 | u32 txrate; | ||
276 | }; | 355 | }; |
277 | 356 | ||
278 | #else | 357 | #else |
279 | 358 | ||
280 | #define TX_STAT_INC(c) do { } while (0) | 359 | #define TX_STAT_INC(c) do { } while (0) |
281 | #define RX_STAT_INC(c) do { } while (0) | 360 | #define RX_STAT_INC(c) do { } while (0) |
361 | #define CAB_STAT_INC do { } while (0) | ||
282 | 362 | ||
283 | #define TX_QSTAT_INC(c) do { } while (0) | 363 | #define TX_QSTAT_INC(c) do { } while (0) |
284 | 364 | ||
365 | static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | ||
366 | struct ath_htc_rx_status *rxs) | ||
367 | { | ||
368 | } | ||
369 | |||
285 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | 370 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ |
286 | 371 | ||
287 | #define ATH_LED_PIN_DEF 1 | 372 | #define ATH_LED_PIN_DEF 1 |
288 | #define ATH_LED_PIN_9287 8 | 373 | #define ATH_LED_PIN_9287 10 |
289 | #define ATH_LED_PIN_9271 15 | 374 | #define ATH_LED_PIN_9271 15 |
290 | #define ATH_LED_PIN_7010 12 | 375 | #define ATH_LED_PIN_7010 12 |
291 | #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ | ||
292 | #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ | ||
293 | |||
294 | enum ath_led_type { | ||
295 | ATH_LED_RADIO, | ||
296 | ATH_LED_ASSOC, | ||
297 | ATH_LED_TX, | ||
298 | ATH_LED_RX | ||
299 | }; | ||
300 | 376 | ||
301 | struct ath_led { | 377 | #define BSTUCK_THRESHOLD 10 |
302 | struct ath9k_htc_priv *priv; | 378 | |
303 | struct led_classdev led_cdev; | 379 | /* |
304 | enum ath_led_type led_type; | 380 | * Adjust these when the max. no of beaconing interfaces is |
305 | struct delayed_work brightness_work; | 381 | * increased. |
306 | char name[32]; | 382 | */ |
307 | bool registered; | 383 | #define DEFAULT_SWBA_RESPONSE 40 /* in TUs */ |
308 | int brightness; | 384 | #define MIN_SWBA_RESPONSE 10 /* in TUs */ |
309 | }; | ||
310 | 385 | ||
311 | struct htc_beacon_config { | 386 | struct htc_beacon_config { |
387 | struct ieee80211_vif *bslot[ATH9K_HTC_MAX_BCN_VIF]; | ||
312 | u16 beacon_interval; | 388 | u16 beacon_interval; |
313 | u16 listen_interval; | ||
314 | u16 dtim_period; | 389 | u16 dtim_period; |
315 | u16 bmiss_timeout; | 390 | u16 bmiss_timeout; |
316 | u8 dtim_count; | 391 | u32 bmiss_cnt; |
392 | }; | ||
393 | |||
394 | struct ath_btcoex { | ||
395 | u32 bt_priority_cnt; | ||
396 | unsigned long bt_priority_time; | ||
397 | int bt_stomp_type; /* Types of BT stomping */ | ||
398 | u32 btcoex_no_stomp; | ||
399 | u32 btcoex_period; | ||
400 | u32 btscan_no_stomp; | ||
317 | }; | 401 | }; |
318 | 402 | ||
319 | #define OP_INVALID BIT(0) | 403 | void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv); |
320 | #define OP_SCANNING BIT(1) | 404 | void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv); |
321 | #define OP_FULL_RESET BIT(2) | 405 | void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv); |
322 | #define OP_LED_ASSOCIATED BIT(3) | 406 | |
323 | #define OP_LED_ON BIT(4) | 407 | #define OP_INVALID BIT(0) |
324 | #define OP_PREAMBLE_SHORT BIT(5) | 408 | #define OP_SCANNING BIT(1) |
325 | #define OP_PROTECT_ENABLE BIT(6) | 409 | #define OP_ENABLE_BEACON BIT(2) |
326 | #define OP_ASSOCIATED BIT(7) | 410 | #define OP_BT_PRIORITY_DETECTED BIT(3) |
327 | #define OP_ENABLE_BEACON BIT(8) | 411 | #define OP_BT_SCAN BIT(4) |
328 | #define OP_LED_DEINIT BIT(9) | 412 | #define OP_ANI_RUNNING BIT(5) |
329 | #define OP_UNPLUGGED BIT(10) | 413 | #define OP_TSF_RESET BIT(6) |
330 | 414 | ||
331 | struct ath9k_htc_priv { | 415 | struct ath9k_htc_priv { |
332 | struct device *dev; | 416 | struct device *dev; |
@@ -335,6 +419,9 @@ struct ath9k_htc_priv { | |||
335 | struct htc_target *htc; | 419 | struct htc_target *htc; |
336 | struct wmi *wmi; | 420 | struct wmi *wmi; |
337 | 421 | ||
422 | u16 fw_version_major; | ||
423 | u16 fw_version_minor; | ||
424 | |||
338 | enum htc_endpoint_id wmi_cmd_ep; | 425 | enum htc_endpoint_id wmi_cmd_ep; |
339 | enum htc_endpoint_id beacon_ep; | 426 | enum htc_endpoint_id beacon_ep; |
340 | enum htc_endpoint_id cab_ep; | 427 | enum htc_endpoint_id cab_ep; |
@@ -345,52 +432,60 @@ struct ath9k_htc_priv { | |||
345 | enum htc_endpoint_id data_vi_ep; | 432 | enum htc_endpoint_id data_vi_ep; |
346 | enum htc_endpoint_id data_vo_ep; | 433 | enum htc_endpoint_id data_vo_ep; |
347 | 434 | ||
435 | u8 vif_slot; | ||
436 | u8 mon_vif_idx; | ||
437 | u8 sta_slot; | ||
438 | u8 vif_sta_pos[ATH9K_HTC_MAX_VIF]; | ||
439 | u8 num_ibss_vif; | ||
440 | u8 num_sta_vif; | ||
441 | u8 num_sta_assoc_vif; | ||
442 | u8 num_ap_vif; | ||
443 | |||
348 | u16 op_flags; | 444 | u16 op_flags; |
349 | u16 curtxpow; | 445 | u16 curtxpow; |
350 | u16 txpowlimit; | 446 | u16 txpowlimit; |
351 | u16 nvifs; | 447 | u16 nvifs; |
352 | u16 nstations; | 448 | u16 nstations; |
353 | u16 seq_no; | 449 | bool rearm_ani; |
354 | u32 bmiss_cnt; | 450 | bool reconfig_beacon; |
451 | unsigned int rxfilter; | ||
355 | 452 | ||
356 | struct ath9k_hw_cal_data caldata[38]; | 453 | struct ath9k_hw_cal_data caldata; |
454 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | ||
357 | 455 | ||
358 | spinlock_t beacon_lock; | 456 | spinlock_t beacon_lock; |
457 | struct htc_beacon_config cur_beacon_conf; | ||
359 | 458 | ||
360 | bool tx_queues_stop; | 459 | struct ath9k_htc_rx rx; |
361 | spinlock_t tx_lock; | 460 | struct ath9k_htc_tx tx; |
362 | 461 | ||
363 | struct ieee80211_vif *vif; | 462 | struct tasklet_struct swba_tasklet; |
364 | struct htc_beacon_config cur_beacon_conf; | ||
365 | unsigned int rxfilter; | ||
366 | struct tasklet_struct wmi_tasklet; | ||
367 | struct tasklet_struct rx_tasklet; | 463 | struct tasklet_struct rx_tasklet; |
368 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 464 | struct delayed_work ani_work; |
369 | struct ath9k_htc_rx rx; | 465 | struct tasklet_struct tx_failed_tasklet; |
370 | struct tasklet_struct tx_tasklet; | ||
371 | struct sk_buff_head tx_queue; | ||
372 | struct delayed_work ath9k_ani_work; | ||
373 | struct work_struct ps_work; | 466 | struct work_struct ps_work; |
467 | struct work_struct fatal_work; | ||
374 | 468 | ||
375 | struct mutex htc_pm_lock; | 469 | struct mutex htc_pm_lock; |
376 | unsigned long ps_usecount; | 470 | unsigned long ps_usecount; |
377 | bool ps_enabled; | 471 | bool ps_enabled; |
378 | bool ps_idle; | 472 | bool ps_idle; |
379 | 473 | ||
380 | struct ath_led radio_led; | 474 | #ifdef CONFIG_MAC80211_LEDS |
381 | struct ath_led assoc_led; | 475 | enum led_brightness brightness; |
382 | struct ath_led tx_led; | 476 | bool led_registered; |
383 | struct ath_led rx_led; | 477 | char led_name[32]; |
384 | struct delayed_work ath9k_led_blink_work; | 478 | struct led_classdev led_cdev; |
385 | int led_on_duration; | 479 | struct work_struct led_work; |
386 | int led_off_duration; | 480 | #endif |
387 | int led_on_cnt; | ||
388 | int led_off_cnt; | ||
389 | 481 | ||
390 | int beaconq; | 482 | int beaconq; |
391 | int cabq; | 483 | int cabq; |
392 | int hwq_map[WME_NUM_AC]; | 484 | int hwq_map[WME_NUM_AC]; |
393 | 485 | ||
486 | struct ath_btcoex btcoex; | ||
487 | struct delayed_work coex_period_work; | ||
488 | struct delayed_work duty_cycle_work; | ||
394 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 489 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
395 | struct ath9k_debug debug; | 490 | struct ath9k_debug debug; |
396 | #endif | 491 | #endif |
@@ -402,10 +497,20 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz) | |||
402 | common->bus_ops->read_cachesize(common, csz); | 497 | common->bus_ops->read_cachesize(common, csz); |
403 | } | 498 | } |
404 | 499 | ||
500 | void ath9k_htc_reset(struct ath9k_htc_priv *priv); | ||
501 | |||
502 | void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, | ||
503 | struct ieee80211_vif *vif); | ||
504 | void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, | ||
505 | struct ieee80211_vif *vif); | ||
506 | void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, | ||
507 | struct ieee80211_vif *vif); | ||
405 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); | 508 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); |
406 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 509 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
407 | struct ieee80211_vif *vif); | 510 | struct ieee80211_vif *vif); |
408 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); | 511 | void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv); |
512 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, | ||
513 | struct wmi_event_swba *swba); | ||
409 | 514 | ||
410 | void ath9k_htc_rxep(void *priv, struct sk_buff *skb, | 515 | void ath9k_htc_rxep(void *priv, struct sk_buff *skb, |
411 | enum htc_endpoint_id ep_id); | 516 | enum htc_endpoint_id ep_id); |
@@ -414,19 +519,32 @@ void ath9k_htc_txep(void *priv, struct sk_buff *skb, enum htc_endpoint_id ep_id, | |||
414 | void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, | 519 | void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, |
415 | enum htc_endpoint_id ep_id, bool txok); | 520 | enum htc_endpoint_id ep_id, bool txok); |
416 | 521 | ||
522 | int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, | ||
523 | u8 enable_coex); | ||
417 | void ath9k_htc_station_work(struct work_struct *work); | 524 | void ath9k_htc_station_work(struct work_struct *work); |
418 | void ath9k_htc_aggr_work(struct work_struct *work); | 525 | void ath9k_htc_aggr_work(struct work_struct *work); |
419 | void ath9k_ani_work(struct work_struct *work);; | 526 | void ath9k_htc_ani_work(struct work_struct *work); |
527 | void ath9k_htc_start_ani(struct ath9k_htc_priv *priv); | ||
528 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); | ||
420 | 529 | ||
421 | int ath9k_tx_init(struct ath9k_htc_priv *priv); | 530 | int ath9k_tx_init(struct ath9k_htc_priv *priv); |
422 | void ath9k_tx_tasklet(unsigned long data); | 531 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, |
423 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb); | 532 | struct sk_buff *skb, u8 slot, bool is_cab); |
424 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); | 533 | void ath9k_tx_cleanup(struct ath9k_htc_priv *priv); |
425 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); | 534 | bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype); |
426 | int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); | 535 | int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv); |
427 | int get_hw_qnum(u16 queue, int *hwq_map); | 536 | int get_hw_qnum(u16 queue, int *hwq_map); |
428 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | 537 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, |
429 | struct ath9k_tx_queue_info *qinfo); | 538 | struct ath9k_tx_queue_info *qinfo); |
539 | void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv); | ||
540 | void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv); | ||
541 | int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv); | ||
542 | void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); | ||
543 | void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); | ||
544 | void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); | ||
545 | void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv); | ||
546 | void ath9k_tx_failed_tasklet(unsigned long data); | ||
547 | void ath9k_htc_tx_cleanup_timer(unsigned long data); | ||
430 | 548 | ||
431 | int ath9k_rx_init(struct ath9k_htc_priv *priv); | 549 | int ath9k_rx_init(struct ath9k_htc_priv *priv); |
432 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); | 550 | void ath9k_rx_cleanup(struct ath9k_htc_priv *priv); |
@@ -437,27 +555,43 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv); | |||
437 | void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv); | 555 | void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv); |
438 | void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv); | 556 | void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv); |
439 | void ath9k_ps_work(struct work_struct *work); | 557 | void ath9k_ps_work(struct work_struct *work); |
558 | bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, | ||
559 | enum ath9k_power_mode mode); | ||
440 | 560 | ||
441 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); | 561 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); |
562 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); | ||
563 | void ath9k_htc_radio_enable(struct ieee80211_hw *hw); | ||
564 | void ath9k_htc_radio_disable(struct ieee80211_hw *hw); | ||
565 | |||
566 | #ifdef CONFIG_MAC80211_LEDS | ||
442 | void ath9k_init_leds(struct ath9k_htc_priv *priv); | 567 | void ath9k_init_leds(struct ath9k_htc_priv *priv); |
443 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); | 568 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); |
569 | void ath9k_led_work(struct work_struct *work); | ||
570 | #else | ||
571 | static inline void ath9k_init_leds(struct ath9k_htc_priv *priv) | ||
572 | { | ||
573 | } | ||
574 | |||
575 | static inline void ath9k_deinit_leds(struct ath9k_htc_priv *priv) | ||
576 | { | ||
577 | } | ||
578 | |||
579 | static inline void ath9k_led_work(struct work_struct *work) | ||
580 | { | ||
581 | } | ||
582 | #endif | ||
444 | 583 | ||
445 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | 584 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, |
446 | u16 devid); | 585 | u16 devid, char *product, u32 drv_info); |
447 | void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); | 586 | void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); |
448 | #ifdef CONFIG_PM | 587 | #ifdef CONFIG_PM |
588 | void ath9k_htc_suspend(struct htc_target *htc_handle); | ||
449 | int ath9k_htc_resume(struct htc_target *htc_handle); | 589 | int ath9k_htc_resume(struct htc_target *htc_handle); |
450 | #endif | 590 | #endif |
451 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 591 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
452 | int ath9k_htc_debug_create_root(void); | ||
453 | void ath9k_htc_debug_remove_root(void); | ||
454 | int ath9k_htc_init_debug(struct ath_hw *ah); | 592 | int ath9k_htc_init_debug(struct ath_hw *ah); |
455 | void ath9k_htc_exit_debug(struct ath_hw *ah); | ||
456 | #else | 593 | #else |
457 | static inline int ath9k_htc_debug_create_root(void) { return 0; }; | ||
458 | static inline void ath9k_htc_debug_remove_root(void) {}; | ||
459 | static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; | 594 | static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; |
460 | static inline void ath9k_htc_exit_debug(struct ath_hw *ah) {}; | ||
461 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | 595 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ |
462 | 596 | ||
463 | #endif /* HTC_H */ | 597 | #endif /* HTC_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index bd1506e69105..aa6a73118706 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -18,6 +18,50 @@ | |||
18 | 18 | ||
19 | #define FUDGE 2 | 19 | #define FUDGE 2 |
20 | 20 | ||
21 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | ||
22 | { | ||
23 | struct ath_hw *ah = priv->ah; | ||
24 | struct ath9k_tx_queue_info qi, qi_be; | ||
25 | |||
26 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | ||
27 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); | ||
28 | |||
29 | ath9k_hw_get_txq_props(ah, priv->beaconq, &qi); | ||
30 | |||
31 | if (priv->ah->opmode == NL80211_IFTYPE_AP) { | ||
32 | qi.tqi_aifs = 1; | ||
33 | qi.tqi_cwmin = 0; | ||
34 | qi.tqi_cwmax = 0; | ||
35 | } else if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { | ||
36 | int qnum = priv->hwq_map[WME_AC_BE]; | ||
37 | |||
38 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); | ||
39 | |||
40 | qi.tqi_aifs = qi_be.tqi_aifs; | ||
41 | |||
42 | /* | ||
43 | * For WIFI Beacon Distribution | ||
44 | * Long slot time : 2x cwmin | ||
45 | * Short slot time : 4x cwmin | ||
46 | */ | ||
47 | if (ah->slottime == ATH9K_SLOT_TIME_20) | ||
48 | qi.tqi_cwmin = 2*qi_be.tqi_cwmin; | ||
49 | else | ||
50 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | ||
51 | |||
52 | qi.tqi_cwmax = qi_be.tqi_cwmax; | ||
53 | |||
54 | } | ||
55 | |||
56 | if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { | ||
57 | ath_err(ath9k_hw_common(ah), | ||
58 | "Unable to update beacon queue %u!\n", priv->beaconq); | ||
59 | } else { | ||
60 | ath9k_hw_resettxqueue(ah, priv->beaconq); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | |||
21 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | 65 | static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, |
22 | struct htc_beacon_config *bss_conf) | 66 | struct htc_beacon_config *bss_conf) |
23 | { | 67 | { |
@@ -30,7 +74,7 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
30 | __be32 htc_imask = 0; | 74 | __be32 htc_imask = 0; |
31 | u64 tsf; | 75 | u64 tsf; |
32 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; | 76 | int num_beacons, offset, dtim_dec_count, cfp_dec_count; |
33 | int ret; | 77 | int ret __attribute__ ((unused)); |
34 | u8 cmd_rsp; | 78 | u8 cmd_rsp; |
35 | 79 | ||
36 | memset(&bs, 0, sizeof(bs)); | 80 | memset(&bs, 0, sizeof(bs)); |
@@ -123,11 +167,12 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
123 | /* TSF out of range threshold fixed at 1 second */ | 167 | /* TSF out of range threshold fixed at 1 second */ |
124 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | 168 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; |
125 | 169 | ||
126 | ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); | 170 | ath_dbg(common, ATH_DBG_CONFIG, "intval: %u tsf: %llu tsftu: %u\n", |
127 | ath_print(common, ATH_DBG_BEACON, | 171 | intval, tsf, tsftu); |
128 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", | 172 | ath_dbg(common, ATH_DBG_CONFIG, |
129 | bs.bs_bmissthreshold, bs.bs_sleepduration, | 173 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", |
130 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | 174 | bs.bs_bmissthreshold, bs.bs_sleepduration, |
175 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | ||
131 | 176 | ||
132 | /* Set the computed STA beacon timers */ | 177 | /* Set the computed STA beacon timers */ |
133 | 178 | ||
@@ -138,29 +183,105 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
138 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | 183 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
139 | } | 184 | } |
140 | 185 | ||
186 | static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, | ||
187 | struct htc_beacon_config *bss_conf) | ||
188 | { | ||
189 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
190 | enum ath9k_int imask = 0; | ||
191 | u32 nexttbtt, intval, tsftu; | ||
192 | __be32 htc_imask = 0; | ||
193 | int ret __attribute__ ((unused)); | ||
194 | u8 cmd_rsp; | ||
195 | u64 tsf; | ||
196 | |||
197 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; | ||
198 | intval /= ATH9K_HTC_MAX_BCN_VIF; | ||
199 | nexttbtt = intval; | ||
200 | |||
201 | /* | ||
202 | * To reduce beacon misses under heavy TX load, | ||
203 | * set the beacon response time to a larger value. | ||
204 | */ | ||
205 | if (intval > DEFAULT_SWBA_RESPONSE) | ||
206 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; | ||
207 | else | ||
208 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | ||
209 | |||
210 | if (priv->op_flags & OP_TSF_RESET) { | ||
211 | ath9k_hw_reset_tsf(priv->ah); | ||
212 | priv->op_flags &= ~OP_TSF_RESET; | ||
213 | } else { | ||
214 | /* | ||
215 | * Pull nexttbtt forward to reflect the current TSF. | ||
216 | */ | ||
217 | tsf = ath9k_hw_gettsf64(priv->ah); | ||
218 | tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; | ||
219 | do { | ||
220 | nexttbtt += intval; | ||
221 | } while (nexttbtt < tsftu); | ||
222 | } | ||
223 | |||
224 | if (priv->op_flags & OP_ENABLE_BEACON) | ||
225 | imask |= ATH9K_INT_SWBA; | ||
226 | |||
227 | ath_dbg(common, ATH_DBG_CONFIG, | ||
228 | "AP Beacon config, intval: %d, nexttbtt: %u, resp_time: %d " | ||
229 | "imask: 0x%x\n", | ||
230 | bss_conf->beacon_interval, nexttbtt, | ||
231 | priv->ah->config.sw_beacon_response_time, imask); | ||
232 | |||
233 | ath9k_htc_beaconq_config(priv); | ||
234 | |||
235 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
236 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); | ||
237 | priv->cur_beacon_conf.bmiss_cnt = 0; | ||
238 | htc_imask = cpu_to_be32(imask); | ||
239 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | ||
240 | } | ||
241 | |||
141 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | 242 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, |
142 | struct htc_beacon_config *bss_conf) | 243 | struct htc_beacon_config *bss_conf) |
143 | { | 244 | { |
144 | struct ath_common *common = ath9k_hw_common(priv->ah); | 245 | struct ath_common *common = ath9k_hw_common(priv->ah); |
145 | enum ath9k_int imask = 0; | 246 | enum ath9k_int imask = 0; |
146 | u32 nexttbtt, intval; | 247 | u32 nexttbtt, intval, tsftu; |
147 | __be32 htc_imask = 0; | 248 | __be32 htc_imask = 0; |
148 | int ret; | 249 | int ret __attribute__ ((unused)); |
149 | u8 cmd_rsp; | 250 | u8 cmd_rsp; |
251 | u64 tsf; | ||
150 | 252 | ||
151 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; | 253 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; |
152 | nexttbtt = intval; | 254 | nexttbtt = intval; |
153 | intval |= ATH9K_BEACON_ENA; | 255 | |
256 | /* | ||
257 | * Pull nexttbtt forward to reflect the current TSF. | ||
258 | */ | ||
259 | tsf = ath9k_hw_gettsf64(priv->ah); | ||
260 | tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; | ||
261 | do { | ||
262 | nexttbtt += intval; | ||
263 | } while (nexttbtt < tsftu); | ||
264 | |||
265 | /* | ||
266 | * Only one IBSS interfce is allowed. | ||
267 | */ | ||
268 | if (intval > DEFAULT_SWBA_RESPONSE) | ||
269 | priv->ah->config.sw_beacon_response_time = DEFAULT_SWBA_RESPONSE; | ||
270 | else | ||
271 | priv->ah->config.sw_beacon_response_time = MIN_SWBA_RESPONSE; | ||
272 | |||
154 | if (priv->op_flags & OP_ENABLE_BEACON) | 273 | if (priv->op_flags & OP_ENABLE_BEACON) |
155 | imask |= ATH9K_INT_SWBA; | 274 | imask |= ATH9K_INT_SWBA; |
156 | 275 | ||
157 | ath_print(common, ATH_DBG_BEACON, | 276 | ath_dbg(common, ATH_DBG_CONFIG, |
158 | "IBSS Beacon config, intval: %d, imask: 0x%x\n", | 277 | "IBSS Beacon config, intval: %d, nexttbtt: %u, " |
159 | bss_conf->beacon_interval, imask); | 278 | "resp_time: %d, imask: 0x%x\n", |
279 | bss_conf->beacon_interval, nexttbtt, | ||
280 | priv->ah->config.sw_beacon_response_time, imask); | ||
160 | 281 | ||
161 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 282 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
162 | ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); | 283 | ath9k_hw_beaconinit(priv->ah, TU_TO_USEC(nexttbtt), TU_TO_USEC(intval)); |
163 | priv->bmiss_cnt = 0; | 284 | priv->cur_beacon_conf.bmiss_cnt = 0; |
164 | htc_imask = cpu_to_be32(imask); | 285 | htc_imask = cpu_to_be32(imask); |
165 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | 286 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
166 | } | 287 | } |
@@ -171,79 +292,318 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, | |||
171 | dev_kfree_skb_any(skb); | 292 | dev_kfree_skb_any(skb); |
172 | } | 293 | } |
173 | 294 | ||
174 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) | 295 | static void ath9k_htc_send_buffered(struct ath9k_htc_priv *priv, |
296 | int slot) | ||
175 | { | 297 | { |
176 | struct ath9k_htc_vif *avp = (void *)priv->vif->drv_priv; | 298 | struct ath_common *common = ath9k_hw_common(priv->ah); |
299 | struct ieee80211_vif *vif; | ||
300 | struct sk_buff *skb; | ||
301 | struct ieee80211_hdr *hdr; | ||
302 | int padpos, padsize, ret, tx_slot; | ||
303 | |||
304 | spin_lock_bh(&priv->beacon_lock); | ||
305 | |||
306 | vif = priv->cur_beacon_conf.bslot[slot]; | ||
307 | |||
308 | skb = ieee80211_get_buffered_bc(priv->hw, vif); | ||
309 | |||
310 | while(skb) { | ||
311 | hdr = (struct ieee80211_hdr *) skb->data; | ||
312 | |||
313 | padpos = ath9k_cmn_padpos(hdr->frame_control); | ||
314 | padsize = padpos & 3; | ||
315 | if (padsize && skb->len > padpos) { | ||
316 | if (skb_headroom(skb) < padsize) { | ||
317 | dev_kfree_skb_any(skb); | ||
318 | goto next; | ||
319 | } | ||
320 | skb_push(skb, padsize); | ||
321 | memmove(skb->data, skb->data + padsize, padpos); | ||
322 | } | ||
323 | |||
324 | tx_slot = ath9k_htc_tx_get_slot(priv); | ||
325 | if (tx_slot < 0) { | ||
326 | ath_dbg(common, ATH_DBG_XMIT, "No free CAB slot\n"); | ||
327 | dev_kfree_skb_any(skb); | ||
328 | goto next; | ||
329 | } | ||
330 | |||
331 | ret = ath9k_htc_tx_start(priv, skb, tx_slot, true); | ||
332 | if (ret != 0) { | ||
333 | ath9k_htc_tx_clear_slot(priv, tx_slot); | ||
334 | dev_kfree_skb_any(skb); | ||
335 | |||
336 | ath_dbg(common, ATH_DBG_XMIT, | ||
337 | "Failed to send CAB frame\n"); | ||
338 | } else { | ||
339 | spin_lock_bh(&priv->tx.tx_lock); | ||
340 | priv->tx.queued_cnt++; | ||
341 | spin_unlock_bh(&priv->tx.tx_lock); | ||
342 | } | ||
343 | next: | ||
344 | skb = ieee80211_get_buffered_bc(priv->hw, vif); | ||
345 | } | ||
346 | |||
347 | spin_unlock_bh(&priv->beacon_lock); | ||
348 | } | ||
349 | |||
350 | static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv, | ||
351 | int slot) | ||
352 | { | ||
353 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
354 | struct ieee80211_vif *vif; | ||
355 | struct ath9k_htc_vif *avp; | ||
177 | struct tx_beacon_header beacon_hdr; | 356 | struct tx_beacon_header beacon_hdr; |
178 | struct ath9k_htc_tx_ctl tx_ctl; | 357 | struct ath9k_htc_tx_ctl *tx_ctl; |
179 | struct ieee80211_tx_info *info; | 358 | struct ieee80211_tx_info *info; |
359 | struct ieee80211_mgmt *mgmt; | ||
180 | struct sk_buff *beacon; | 360 | struct sk_buff *beacon; |
181 | u8 *tx_fhdr; | 361 | u8 *tx_fhdr; |
362 | int ret; | ||
182 | 363 | ||
183 | memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); | 364 | memset(&beacon_hdr, 0, sizeof(struct tx_beacon_header)); |
184 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); | ||
185 | |||
186 | /* FIXME: Handle BMISS */ | ||
187 | if (beacon_pending != 0) { | ||
188 | priv->bmiss_cnt++; | ||
189 | return; | ||
190 | } | ||
191 | 365 | ||
192 | spin_lock_bh(&priv->beacon_lock); | 366 | spin_lock_bh(&priv->beacon_lock); |
193 | 367 | ||
368 | vif = priv->cur_beacon_conf.bslot[slot]; | ||
369 | avp = (struct ath9k_htc_vif *)vif->drv_priv; | ||
370 | |||
194 | if (unlikely(priv->op_flags & OP_SCANNING)) { | 371 | if (unlikely(priv->op_flags & OP_SCANNING)) { |
195 | spin_unlock_bh(&priv->beacon_lock); | 372 | spin_unlock_bh(&priv->beacon_lock); |
196 | return; | 373 | return; |
197 | } | 374 | } |
198 | 375 | ||
199 | /* Get a new beacon */ | 376 | /* Get a new beacon */ |
200 | beacon = ieee80211_beacon_get(priv->hw, priv->vif); | 377 | beacon = ieee80211_beacon_get(priv->hw, vif); |
201 | if (!beacon) { | 378 | if (!beacon) { |
202 | spin_unlock_bh(&priv->beacon_lock); | 379 | spin_unlock_bh(&priv->beacon_lock); |
203 | return; | 380 | return; |
204 | } | 381 | } |
205 | 382 | ||
383 | /* | ||
384 | * Update the TSF adjust value here, the HW will | ||
385 | * add this value for every beacon. | ||
386 | */ | ||
387 | mgmt = (struct ieee80211_mgmt *)beacon->data; | ||
388 | mgmt->u.beacon.timestamp = avp->tsfadjust; | ||
389 | |||
206 | info = IEEE80211_SKB_CB(beacon); | 390 | info = IEEE80211_SKB_CB(beacon); |
207 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 391 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
208 | struct ieee80211_hdr *hdr = | 392 | struct ieee80211_hdr *hdr = |
209 | (struct ieee80211_hdr *) beacon->data; | 393 | (struct ieee80211_hdr *) beacon->data; |
210 | priv->seq_no += 0x10; | 394 | avp->seq_no += 0x10; |
211 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | 395 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); |
212 | hdr->seq_ctrl |= cpu_to_le16(priv->seq_no); | 396 | hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); |
213 | } | 397 | } |
214 | 398 | ||
215 | tx_ctl.type = ATH9K_HTC_NORMAL; | 399 | tx_ctl = HTC_SKB_CB(beacon); |
400 | memset(tx_ctl, 0, sizeof(*tx_ctl)); | ||
401 | |||
402 | tx_ctl->type = ATH9K_HTC_BEACON; | ||
403 | tx_ctl->epid = priv->beacon_ep; | ||
404 | |||
216 | beacon_hdr.vif_index = avp->index; | 405 | beacon_hdr.vif_index = avp->index; |
217 | tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); | 406 | tx_fhdr = skb_push(beacon, sizeof(beacon_hdr)); |
218 | memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); | 407 | memcpy(tx_fhdr, (u8 *) &beacon_hdr, sizeof(beacon_hdr)); |
219 | 408 | ||
220 | htc_send(priv->htc, beacon, priv->beacon_ep, &tx_ctl); | 409 | ret = htc_send(priv->htc, beacon); |
410 | if (ret != 0) { | ||
411 | if (ret == -ENOMEM) { | ||
412 | ath_dbg(common, ATH_DBG_BSTUCK, | ||
413 | "Failed to send beacon, no free TX buffer\n"); | ||
414 | } | ||
415 | dev_kfree_skb_any(beacon); | ||
416 | } | ||
221 | 417 | ||
222 | spin_unlock_bh(&priv->beacon_lock); | 418 | spin_unlock_bh(&priv->beacon_lock); |
223 | } | 419 | } |
224 | 420 | ||
225 | /* Currently, only for IBSS */ | 421 | static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv, |
226 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | 422 | struct wmi_event_swba *swba) |
227 | { | 423 | { |
228 | struct ath_hw *ah = priv->ah; | 424 | struct ath_common *common = ath9k_hw_common(priv->ah); |
229 | struct ath9k_tx_queue_info qi, qi_be; | 425 | u64 tsf; |
230 | int qnum = priv->hwq_map[WME_AC_BE]; | 426 | u32 tsftu; |
427 | u16 intval; | ||
428 | int slot; | ||
231 | 429 | ||
232 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | 430 | intval = priv->cur_beacon_conf.beacon_interval & ATH9K_BEACON_PERIOD; |
233 | memset(&qi_be, 0, sizeof(struct ath9k_tx_queue_info)); | ||
234 | 431 | ||
235 | ath9k_hw_get_txq_props(ah, qnum, &qi_be); | 432 | tsf = be64_to_cpu(swba->tsf); |
433 | tsftu = TSF_TO_TU(tsf >> 32, tsf); | ||
434 | slot = ((tsftu % intval) * ATH9K_HTC_MAX_BCN_VIF) / intval; | ||
435 | slot = ATH9K_HTC_MAX_BCN_VIF - slot - 1; | ||
236 | 436 | ||
237 | qi.tqi_aifs = qi_be.tqi_aifs; | 437 | ath_dbg(common, ATH_DBG_BEACON, |
238 | qi.tqi_cwmin = 4*qi_be.tqi_cwmin; | 438 | "Choose slot: %d, tsf: %llu, tsftu: %u, intval: %u\n", |
239 | qi.tqi_cwmax = qi_be.tqi_cwmax; | 439 | slot, tsf, tsftu, intval); |
240 | 440 | ||
241 | if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { | 441 | return slot; |
242 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 442 | } |
243 | "Unable to update beacon queue %u!\n", qnum); | 443 | |
244 | } else { | 444 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, |
245 | ath9k_hw_resettxqueue(ah, priv->beaconq); | 445 | struct wmi_event_swba *swba) |
446 | { | ||
447 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
448 | int slot; | ||
449 | |||
450 | if (swba->beacon_pending != 0) { | ||
451 | priv->cur_beacon_conf.bmiss_cnt++; | ||
452 | if (priv->cur_beacon_conf.bmiss_cnt > BSTUCK_THRESHOLD) { | ||
453 | ath_dbg(common, ATH_DBG_BSTUCK, | ||
454 | "Beacon stuck, HW reset\n"); | ||
455 | ieee80211_queue_work(priv->hw, | ||
456 | &priv->fatal_work); | ||
457 | } | ||
458 | return; | ||
459 | } | ||
460 | |||
461 | if (priv->cur_beacon_conf.bmiss_cnt) { | ||
462 | ath_dbg(common, ATH_DBG_BSTUCK, | ||
463 | "Resuming beacon xmit after %u misses\n", | ||
464 | priv->cur_beacon_conf.bmiss_cnt); | ||
465 | priv->cur_beacon_conf.bmiss_cnt = 0; | ||
466 | } | ||
467 | |||
468 | slot = ath9k_htc_choose_bslot(priv, swba); | ||
469 | spin_lock_bh(&priv->beacon_lock); | ||
470 | if (priv->cur_beacon_conf.bslot[slot] == NULL) { | ||
471 | spin_unlock_bh(&priv->beacon_lock); | ||
472 | return; | ||
473 | } | ||
474 | spin_unlock_bh(&priv->beacon_lock); | ||
475 | |||
476 | ath9k_htc_send_buffered(priv, slot); | ||
477 | ath9k_htc_send_beacon(priv, slot); | ||
478 | } | ||
479 | |||
480 | void ath9k_htc_assign_bslot(struct ath9k_htc_priv *priv, | ||
481 | struct ieee80211_vif *vif) | ||
482 | { | ||
483 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
484 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; | ||
485 | int i = 0; | ||
486 | |||
487 | spin_lock_bh(&priv->beacon_lock); | ||
488 | for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) { | ||
489 | if (priv->cur_beacon_conf.bslot[i] == NULL) { | ||
490 | avp->bslot = i; | ||
491 | break; | ||
492 | } | ||
493 | } | ||
494 | |||
495 | priv->cur_beacon_conf.bslot[avp->bslot] = vif; | ||
496 | spin_unlock_bh(&priv->beacon_lock); | ||
497 | |||
498 | ath_dbg(common, ATH_DBG_CONFIG, | ||
499 | "Added interface at beacon slot: %d\n", avp->bslot); | ||
500 | } | ||
501 | |||
502 | void ath9k_htc_remove_bslot(struct ath9k_htc_priv *priv, | ||
503 | struct ieee80211_vif *vif) | ||
504 | { | ||
505 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
506 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; | ||
507 | |||
508 | spin_lock_bh(&priv->beacon_lock); | ||
509 | priv->cur_beacon_conf.bslot[avp->bslot] = NULL; | ||
510 | spin_unlock_bh(&priv->beacon_lock); | ||
511 | |||
512 | ath_dbg(common, ATH_DBG_CONFIG, | ||
513 | "Removed interface at beacon slot: %d\n", avp->bslot); | ||
514 | } | ||
515 | |||
516 | /* | ||
517 | * Calculate the TSF adjustment value for all slots | ||
518 | * other than zero. | ||
519 | */ | ||
520 | void ath9k_htc_set_tsfadjust(struct ath9k_htc_priv *priv, | ||
521 | struct ieee80211_vif *vif) | ||
522 | { | ||
523 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
524 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *)vif->drv_priv; | ||
525 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | ||
526 | u64 tsfadjust; | ||
527 | |||
528 | if (avp->bslot == 0) | ||
529 | return; | ||
530 | |||
531 | /* | ||
532 | * The beacon interval cannot be different for multi-AP mode, | ||
533 | * and we reach here only for VIF slots greater than zero, | ||
534 | * so beacon_interval is guaranteed to be set in cur_conf. | ||
535 | */ | ||
536 | tsfadjust = cur_conf->beacon_interval * avp->bslot / ATH9K_HTC_MAX_BCN_VIF; | ||
537 | avp->tsfadjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); | ||
538 | |||
539 | ath_dbg(common, ATH_DBG_CONFIG, | ||
540 | "tsfadjust is: %llu for bslot: %d\n", | ||
541 | (unsigned long long)tsfadjust, avp->bslot); | ||
542 | } | ||
543 | |||
544 | static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
545 | { | ||
546 | bool *beacon_configured = (bool *)data; | ||
547 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | ||
548 | |||
549 | if (vif->type == NL80211_IFTYPE_STATION && | ||
550 | avp->beacon_configured) | ||
551 | *beacon_configured = true; | ||
552 | } | ||
553 | |||
554 | static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv, | ||
555 | struct ieee80211_vif *vif) | ||
556 | { | ||
557 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
558 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | ||
559 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
560 | bool beacon_configured; | ||
561 | |||
562 | /* | ||
563 | * Changing the beacon interval when multiple AP interfaces | ||
564 | * are configured will affect beacon transmission of all | ||
565 | * of them. | ||
566 | */ | ||
567 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && | ||
568 | (priv->num_ap_vif > 1) && | ||
569 | (vif->type == NL80211_IFTYPE_AP) && | ||
570 | (cur_conf->beacon_interval != bss_conf->beacon_int)) { | ||
571 | ath_dbg(common, ATH_DBG_CONFIG, | ||
572 | "Changing beacon interval of multiple AP interfaces !\n"); | ||
573 | return false; | ||
246 | } | 574 | } |
575 | |||
576 | /* | ||
577 | * If the HW is operating in AP mode, any new station interfaces that | ||
578 | * are added cannot change the beacon parameters. | ||
579 | */ | ||
580 | if (priv->num_ap_vif && | ||
581 | (vif->type != NL80211_IFTYPE_AP)) { | ||
582 | ath_dbg(common, ATH_DBG_CONFIG, | ||
583 | "HW in AP mode, cannot set STA beacon parameters\n"); | ||
584 | return false; | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * The beacon parameters are configured only for the first | ||
589 | * station interface. | ||
590 | */ | ||
591 | if ((priv->ah->opmode == NL80211_IFTYPE_STATION) && | ||
592 | (priv->num_sta_vif > 1) && | ||
593 | (vif->type == NL80211_IFTYPE_STATION)) { | ||
594 | beacon_configured = false; | ||
595 | ieee80211_iterate_active_interfaces_atomic(priv->hw, | ||
596 | ath9k_htc_beacon_iter, | ||
597 | &beacon_configured); | ||
598 | |||
599 | if (beacon_configured) { | ||
600 | ath_dbg(common, ATH_DBG_CONFIG, | ||
601 | "Beacon already configured for a station interface\n"); | ||
602 | return false; | ||
603 | } | ||
604 | } | ||
605 | |||
606 | return true; | ||
247 | } | 607 | } |
248 | 608 | ||
249 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 609 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
@@ -252,27 +612,55 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | |||
252 | struct ath_common *common = ath9k_hw_common(priv->ah); | 612 | struct ath_common *common = ath9k_hw_common(priv->ah); |
253 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | 613 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; |
254 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 614 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
615 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | ||
616 | |||
617 | if (!ath9k_htc_check_beacon_config(priv, vif)) | ||
618 | return; | ||
255 | 619 | ||
256 | cur_conf->beacon_interval = bss_conf->beacon_int; | 620 | cur_conf->beacon_interval = bss_conf->beacon_int; |
257 | if (cur_conf->beacon_interval == 0) | 621 | if (cur_conf->beacon_interval == 0) |
258 | cur_conf->beacon_interval = 100; | 622 | cur_conf->beacon_interval = 100; |
259 | 623 | ||
260 | cur_conf->dtim_period = bss_conf->dtim_period; | 624 | cur_conf->dtim_period = bss_conf->dtim_period; |
261 | cur_conf->listen_interval = 1; | ||
262 | cur_conf->dtim_count = 1; | ||
263 | cur_conf->bmiss_timeout = | 625 | cur_conf->bmiss_timeout = |
264 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; | 626 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; |
265 | 627 | ||
266 | switch (vif->type) { | 628 | switch (vif->type) { |
267 | case NL80211_IFTYPE_STATION: | 629 | case NL80211_IFTYPE_STATION: |
268 | ath9k_htc_beacon_config_sta(priv, cur_conf); | 630 | ath9k_htc_beacon_config_sta(priv, cur_conf); |
631 | avp->beacon_configured = true; | ||
632 | break; | ||
633 | case NL80211_IFTYPE_ADHOC: | ||
634 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); | ||
635 | break; | ||
636 | case NL80211_IFTYPE_AP: | ||
637 | ath9k_htc_beacon_config_ap(priv, cur_conf); | ||
638 | break; | ||
639 | default: | ||
640 | ath_dbg(common, ATH_DBG_CONFIG, | ||
641 | "Unsupported beaconing mode\n"); | ||
642 | return; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv) | ||
647 | { | ||
648 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
649 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | ||
650 | |||
651 | switch (priv->ah->opmode) { | ||
652 | case NL80211_IFTYPE_STATION: | ||
653 | ath9k_htc_beacon_config_sta(priv, cur_conf); | ||
269 | break; | 654 | break; |
270 | case NL80211_IFTYPE_ADHOC: | 655 | case NL80211_IFTYPE_ADHOC: |
271 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); | 656 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); |
272 | break; | 657 | break; |
658 | case NL80211_IFTYPE_AP: | ||
659 | ath9k_htc_beacon_config_ap(priv, cur_conf); | ||
660 | break; | ||
273 | default: | 661 | default: |
274 | ath_print(common, ATH_DBG_CONFIG, | 662 | ath_dbg(common, ATH_DBG_CONFIG, |
275 | "Unsupported beaconing mode\n"); | 663 | "Unsupported beaconing mode\n"); |
276 | return; | 664 | return; |
277 | } | 665 | } |
278 | } | 666 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c new file mode 100644 index 000000000000..aa48b3abbc48 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c | |||
@@ -0,0 +1,960 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 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 "htc.h" | ||
18 | |||
19 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | ||
20 | { | ||
21 | file->private_data = inode->i_private; | ||
22 | return 0; | ||
23 | } | ||
24 | |||
25 | static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf, | ||
26 | size_t count, loff_t *ppos) | ||
27 | { | ||
28 | struct ath9k_htc_priv *priv = file->private_data; | ||
29 | struct ath9k_htc_target_int_stats cmd_rsp; | ||
30 | char buf[512]; | ||
31 | unsigned int len = 0; | ||
32 | int ret = 0; | ||
33 | |||
34 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
35 | |||
36 | ath9k_htc_ps_wakeup(priv); | ||
37 | |||
38 | WMI_CMD(WMI_INT_STATS_CMDID); | ||
39 | if (ret) { | ||
40 | ath9k_htc_ps_restore(priv); | ||
41 | return -EINVAL; | ||
42 | } | ||
43 | |||
44 | ath9k_htc_ps_restore(priv); | ||
45 | |||
46 | len += snprintf(buf + len, sizeof(buf) - len, | ||
47 | "%20s : %10u\n", "RX", | ||
48 | be32_to_cpu(cmd_rsp.rx)); | ||
49 | |||
50 | len += snprintf(buf + len, sizeof(buf) - len, | ||
51 | "%20s : %10u\n", "RXORN", | ||
52 | be32_to_cpu(cmd_rsp.rxorn)); | ||
53 | |||
54 | len += snprintf(buf + len, sizeof(buf) - len, | ||
55 | "%20s : %10u\n", "RXEOL", | ||
56 | be32_to_cpu(cmd_rsp.rxeol)); | ||
57 | |||
58 | len += snprintf(buf + len, sizeof(buf) - len, | ||
59 | "%20s : %10u\n", "TXURN", | ||
60 | be32_to_cpu(cmd_rsp.txurn)); | ||
61 | |||
62 | len += snprintf(buf + len, sizeof(buf) - len, | ||
63 | "%20s : %10u\n", "TXTO", | ||
64 | be32_to_cpu(cmd_rsp.txto)); | ||
65 | |||
66 | len += snprintf(buf + len, sizeof(buf) - len, | ||
67 | "%20s : %10u\n", "CST", | ||
68 | be32_to_cpu(cmd_rsp.cst)); | ||
69 | |||
70 | if (len > sizeof(buf)) | ||
71 | len = sizeof(buf); | ||
72 | |||
73 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
74 | } | ||
75 | |||
76 | static const struct file_operations fops_tgt_int_stats = { | ||
77 | .read = read_file_tgt_int_stats, | ||
78 | .open = ath9k_debugfs_open, | ||
79 | .owner = THIS_MODULE, | ||
80 | .llseek = default_llseek, | ||
81 | }; | ||
82 | |||
83 | static ssize_t read_file_tgt_tx_stats(struct file *file, char __user *user_buf, | ||
84 | size_t count, loff_t *ppos) | ||
85 | { | ||
86 | struct ath9k_htc_priv *priv = file->private_data; | ||
87 | struct ath9k_htc_target_tx_stats cmd_rsp; | ||
88 | char buf[512]; | ||
89 | unsigned int len = 0; | ||
90 | int ret = 0; | ||
91 | |||
92 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
93 | |||
94 | ath9k_htc_ps_wakeup(priv); | ||
95 | |||
96 | WMI_CMD(WMI_TX_STATS_CMDID); | ||
97 | if (ret) { | ||
98 | ath9k_htc_ps_restore(priv); | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | |||
102 | ath9k_htc_ps_restore(priv); | ||
103 | |||
104 | len += snprintf(buf + len, sizeof(buf) - len, | ||
105 | "%20s : %10u\n", "Xretries", | ||
106 | be32_to_cpu(cmd_rsp.xretries)); | ||
107 | |||
108 | len += snprintf(buf + len, sizeof(buf) - len, | ||
109 | "%20s : %10u\n", "FifoErr", | ||
110 | be32_to_cpu(cmd_rsp.fifoerr)); | ||
111 | |||
112 | len += snprintf(buf + len, sizeof(buf) - len, | ||
113 | "%20s : %10u\n", "Filtered", | ||
114 | be32_to_cpu(cmd_rsp.filtered)); | ||
115 | |||
116 | len += snprintf(buf + len, sizeof(buf) - len, | ||
117 | "%20s : %10u\n", "TimerExp", | ||
118 | be32_to_cpu(cmd_rsp.timer_exp)); | ||
119 | |||
120 | len += snprintf(buf + len, sizeof(buf) - len, | ||
121 | "%20s : %10u\n", "ShortRetries", | ||
122 | be32_to_cpu(cmd_rsp.shortretries)); | ||
123 | |||
124 | len += snprintf(buf + len, sizeof(buf) - len, | ||
125 | "%20s : %10u\n", "LongRetries", | ||
126 | be32_to_cpu(cmd_rsp.longretries)); | ||
127 | |||
128 | len += snprintf(buf + len, sizeof(buf) - len, | ||
129 | "%20s : %10u\n", "QueueNull", | ||
130 | be32_to_cpu(cmd_rsp.qnull)); | ||
131 | |||
132 | len += snprintf(buf + len, sizeof(buf) - len, | ||
133 | "%20s : %10u\n", "EncapFail", | ||
134 | be32_to_cpu(cmd_rsp.encap_fail)); | ||
135 | |||
136 | len += snprintf(buf + len, sizeof(buf) - len, | ||
137 | "%20s : %10u\n", "NoBuf", | ||
138 | be32_to_cpu(cmd_rsp.nobuf)); | ||
139 | |||
140 | if (len > sizeof(buf)) | ||
141 | len = sizeof(buf); | ||
142 | |||
143 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
144 | } | ||
145 | |||
146 | static const struct file_operations fops_tgt_tx_stats = { | ||
147 | .read = read_file_tgt_tx_stats, | ||
148 | .open = ath9k_debugfs_open, | ||
149 | .owner = THIS_MODULE, | ||
150 | .llseek = default_llseek, | ||
151 | }; | ||
152 | |||
153 | static ssize_t read_file_tgt_rx_stats(struct file *file, char __user *user_buf, | ||
154 | size_t count, loff_t *ppos) | ||
155 | { | ||
156 | struct ath9k_htc_priv *priv = file->private_data; | ||
157 | struct ath9k_htc_target_rx_stats cmd_rsp; | ||
158 | char buf[512]; | ||
159 | unsigned int len = 0; | ||
160 | int ret = 0; | ||
161 | |||
162 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
163 | |||
164 | ath9k_htc_ps_wakeup(priv); | ||
165 | |||
166 | WMI_CMD(WMI_RX_STATS_CMDID); | ||
167 | if (ret) { | ||
168 | ath9k_htc_ps_restore(priv); | ||
169 | return -EINVAL; | ||
170 | } | ||
171 | |||
172 | ath9k_htc_ps_restore(priv); | ||
173 | |||
174 | len += snprintf(buf + len, sizeof(buf) - len, | ||
175 | "%20s : %10u\n", "NoBuf", | ||
176 | be32_to_cpu(cmd_rsp.nobuf)); | ||
177 | |||
178 | len += snprintf(buf + len, sizeof(buf) - len, | ||
179 | "%20s : %10u\n", "HostSend", | ||
180 | be32_to_cpu(cmd_rsp.host_send)); | ||
181 | |||
182 | len += snprintf(buf + len, sizeof(buf) - len, | ||
183 | "%20s : %10u\n", "HostDone", | ||
184 | be32_to_cpu(cmd_rsp.host_done)); | ||
185 | |||
186 | if (len > sizeof(buf)) | ||
187 | len = sizeof(buf); | ||
188 | |||
189 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
190 | } | ||
191 | |||
192 | static const struct file_operations fops_tgt_rx_stats = { | ||
193 | .read = read_file_tgt_rx_stats, | ||
194 | .open = ath9k_debugfs_open, | ||
195 | .owner = THIS_MODULE, | ||
196 | .llseek = default_llseek, | ||
197 | }; | ||
198 | |||
199 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | ||
200 | size_t count, loff_t *ppos) | ||
201 | { | ||
202 | struct ath9k_htc_priv *priv = file->private_data; | ||
203 | char buf[512]; | ||
204 | unsigned int len = 0; | ||
205 | |||
206 | len += snprintf(buf + len, sizeof(buf) - len, | ||
207 | "%20s : %10u\n", "Buffers queued", | ||
208 | priv->debug.tx_stats.buf_queued); | ||
209 | len += snprintf(buf + len, sizeof(buf) - len, | ||
210 | "%20s : %10u\n", "Buffers completed", | ||
211 | priv->debug.tx_stats.buf_completed); | ||
212 | len += snprintf(buf + len, sizeof(buf) - len, | ||
213 | "%20s : %10u\n", "SKBs queued", | ||
214 | priv->debug.tx_stats.skb_queued); | ||
215 | len += snprintf(buf + len, sizeof(buf) - len, | ||
216 | "%20s : %10u\n", "SKBs success", | ||
217 | priv->debug.tx_stats.skb_success); | ||
218 | len += snprintf(buf + len, sizeof(buf) - len, | ||
219 | "%20s : %10u\n", "SKBs failed", | ||
220 | priv->debug.tx_stats.skb_failed); | ||
221 | len += snprintf(buf + len, sizeof(buf) - len, | ||
222 | "%20s : %10u\n", "CAB queued", | ||
223 | priv->debug.tx_stats.cab_queued); | ||
224 | |||
225 | len += snprintf(buf + len, sizeof(buf) - len, | ||
226 | "%20s : %10u\n", "BE queued", | ||
227 | priv->debug.tx_stats.queue_stats[WME_AC_BE]); | ||
228 | len += snprintf(buf + len, sizeof(buf) - len, | ||
229 | "%20s : %10u\n", "BK queued", | ||
230 | priv->debug.tx_stats.queue_stats[WME_AC_BK]); | ||
231 | len += snprintf(buf + len, sizeof(buf) - len, | ||
232 | "%20s : %10u\n", "VI queued", | ||
233 | priv->debug.tx_stats.queue_stats[WME_AC_VI]); | ||
234 | len += snprintf(buf + len, sizeof(buf) - len, | ||
235 | "%20s : %10u\n", "VO queued", | ||
236 | priv->debug.tx_stats.queue_stats[WME_AC_VO]); | ||
237 | |||
238 | if (len > sizeof(buf)) | ||
239 | len = sizeof(buf); | ||
240 | |||
241 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
242 | } | ||
243 | |||
244 | static const struct file_operations fops_xmit = { | ||
245 | .read = read_file_xmit, | ||
246 | .open = ath9k_debugfs_open, | ||
247 | .owner = THIS_MODULE, | ||
248 | .llseek = default_llseek, | ||
249 | }; | ||
250 | |||
251 | void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | ||
252 | struct ath_htc_rx_status *rxs) | ||
253 | { | ||
254 | #define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++ | ||
255 | |||
256 | if (rxs->rs_status & ATH9K_RXERR_CRC) | ||
257 | priv->debug.rx_stats.err_crc++; | ||
258 | if (rxs->rs_status & ATH9K_RXERR_DECRYPT) | ||
259 | priv->debug.rx_stats.err_decrypt_crc++; | ||
260 | if (rxs->rs_status & ATH9K_RXERR_MIC) | ||
261 | priv->debug.rx_stats.err_mic++; | ||
262 | if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE) | ||
263 | priv->debug.rx_stats.err_pre_delim++; | ||
264 | if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST) | ||
265 | priv->debug.rx_stats.err_post_delim++; | ||
266 | if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY) | ||
267 | priv->debug.rx_stats.err_decrypt_busy++; | ||
268 | |||
269 | if (rxs->rs_status & ATH9K_RXERR_PHY) { | ||
270 | priv->debug.rx_stats.err_phy++; | ||
271 | if (rxs->rs_phyerr < ATH9K_PHYERR_MAX) | ||
272 | RX_PHY_ERR_INC(rxs->rs_phyerr); | ||
273 | } | ||
274 | |||
275 | #undef RX_PHY_ERR_INC | ||
276 | } | ||
277 | |||
278 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
279 | size_t count, loff_t *ppos) | ||
280 | { | ||
281 | #define PHY_ERR(s, p) \ | ||
282 | len += snprintf(buf + len, size - len, "%20s : %10u\n", s, \ | ||
283 | priv->debug.rx_stats.err_phy_stats[p]); | ||
284 | |||
285 | struct ath9k_htc_priv *priv = file->private_data; | ||
286 | char *buf; | ||
287 | unsigned int len = 0, size = 1500; | ||
288 | ssize_t retval = 0; | ||
289 | |||
290 | buf = kzalloc(size, GFP_KERNEL); | ||
291 | if (buf == NULL) | ||
292 | return -ENOMEM; | ||
293 | |||
294 | len += snprintf(buf + len, size - len, | ||
295 | "%20s : %10u\n", "SKBs allocated", | ||
296 | priv->debug.rx_stats.skb_allocated); | ||
297 | len += snprintf(buf + len, size - len, | ||
298 | "%20s : %10u\n", "SKBs completed", | ||
299 | priv->debug.rx_stats.skb_completed); | ||
300 | len += snprintf(buf + len, size - len, | ||
301 | "%20s : %10u\n", "SKBs Dropped", | ||
302 | priv->debug.rx_stats.skb_dropped); | ||
303 | |||
304 | len += snprintf(buf + len, size - len, | ||
305 | "%20s : %10u\n", "CRC ERR", | ||
306 | priv->debug.rx_stats.err_crc); | ||
307 | len += snprintf(buf + len, size - len, | ||
308 | "%20s : %10u\n", "DECRYPT CRC ERR", | ||
309 | priv->debug.rx_stats.err_decrypt_crc); | ||
310 | len += snprintf(buf + len, size - len, | ||
311 | "%20s : %10u\n", "MIC ERR", | ||
312 | priv->debug.rx_stats.err_mic); | ||
313 | len += snprintf(buf + len, size - len, | ||
314 | "%20s : %10u\n", "PRE-DELIM CRC ERR", | ||
315 | priv->debug.rx_stats.err_pre_delim); | ||
316 | len += snprintf(buf + len, size - len, | ||
317 | "%20s : %10u\n", "POST-DELIM CRC ERR", | ||
318 | priv->debug.rx_stats.err_post_delim); | ||
319 | len += snprintf(buf + len, size - len, | ||
320 | "%20s : %10u\n", "DECRYPT BUSY ERR", | ||
321 | priv->debug.rx_stats.err_decrypt_busy); | ||
322 | len += snprintf(buf + len, size - len, | ||
323 | "%20s : %10u\n", "TOTAL PHY ERR", | ||
324 | priv->debug.rx_stats.err_phy); | ||
325 | |||
326 | |||
327 | PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN); | ||
328 | PHY_ERR("TIMING", ATH9K_PHYERR_TIMING); | ||
329 | PHY_ERR("PARITY", ATH9K_PHYERR_PARITY); | ||
330 | PHY_ERR("RATE", ATH9K_PHYERR_RATE); | ||
331 | PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH); | ||
332 | PHY_ERR("RADAR", ATH9K_PHYERR_RADAR); | ||
333 | PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE); | ||
334 | PHY_ERR("TOR", ATH9K_PHYERR_TOR); | ||
335 | PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING); | ||
336 | PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY); | ||
337 | PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL); | ||
338 | PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL); | ||
339 | PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP); | ||
340 | PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE); | ||
341 | PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART); | ||
342 | PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT); | ||
343 | PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING); | ||
344 | PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC); | ||
345 | PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL); | ||
346 | PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE); | ||
347 | PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART); | ||
348 | PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL); | ||
349 | PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP); | ||
350 | PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR); | ||
351 | PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL); | ||
352 | PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL); | ||
353 | |||
354 | if (len > size) | ||
355 | len = size; | ||
356 | |||
357 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
358 | kfree(buf); | ||
359 | |||
360 | return retval; | ||
361 | |||
362 | #undef PHY_ERR | ||
363 | } | ||
364 | |||
365 | static const struct file_operations fops_recv = { | ||
366 | .read = read_file_recv, | ||
367 | .open = ath9k_debugfs_open, | ||
368 | .owner = THIS_MODULE, | ||
369 | .llseek = default_llseek, | ||
370 | }; | ||
371 | |||
372 | static ssize_t read_file_slot(struct file *file, char __user *user_buf, | ||
373 | size_t count, loff_t *ppos) | ||
374 | { | ||
375 | struct ath9k_htc_priv *priv = file->private_data; | ||
376 | char buf[512]; | ||
377 | unsigned int len = 0; | ||
378 | |||
379 | spin_lock_bh(&priv->tx.tx_lock); | ||
380 | |||
381 | len += snprintf(buf + len, sizeof(buf) - len, "TX slot bitmap : "); | ||
382 | |||
383 | len += bitmap_scnprintf(buf + len, sizeof(buf) - len, | ||
384 | priv->tx.tx_slot, MAX_TX_BUF_NUM); | ||
385 | |||
386 | len += snprintf(buf + len, sizeof(buf) - len, "\n"); | ||
387 | |||
388 | len += snprintf(buf + len, sizeof(buf) - len, | ||
389 | "Used slots : %d\n", | ||
390 | bitmap_weight(priv->tx.tx_slot, MAX_TX_BUF_NUM)); | ||
391 | |||
392 | spin_unlock_bh(&priv->tx.tx_lock); | ||
393 | |||
394 | if (len > sizeof(buf)) | ||
395 | len = sizeof(buf); | ||
396 | |||
397 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
398 | } | ||
399 | |||
400 | static const struct file_operations fops_slot = { | ||
401 | .read = read_file_slot, | ||
402 | .open = ath9k_debugfs_open, | ||
403 | .owner = THIS_MODULE, | ||
404 | .llseek = default_llseek, | ||
405 | }; | ||
406 | |||
407 | static ssize_t read_file_queue(struct file *file, char __user *user_buf, | ||
408 | size_t count, loff_t *ppos) | ||
409 | { | ||
410 | struct ath9k_htc_priv *priv = file->private_data; | ||
411 | char buf[512]; | ||
412 | unsigned int len = 0; | ||
413 | |||
414 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
415 | "Mgmt endpoint", skb_queue_len(&priv->tx.mgmt_ep_queue)); | ||
416 | |||
417 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
418 | "Cab endpoint", skb_queue_len(&priv->tx.cab_ep_queue)); | ||
419 | |||
420 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
421 | "Data BE endpoint", skb_queue_len(&priv->tx.data_be_queue)); | ||
422 | |||
423 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
424 | "Data BK endpoint", skb_queue_len(&priv->tx.data_bk_queue)); | ||
425 | |||
426 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
427 | "Data VI endpoint", skb_queue_len(&priv->tx.data_vi_queue)); | ||
428 | |||
429 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
430 | "Data VO endpoint", skb_queue_len(&priv->tx.data_vo_queue)); | ||
431 | |||
432 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
433 | "Failed queue", skb_queue_len(&priv->tx.tx_failed)); | ||
434 | |||
435 | spin_lock_bh(&priv->tx.tx_lock); | ||
436 | len += snprintf(buf + len, sizeof(buf) - len, "%20s : %10u\n", | ||
437 | "Queued count", priv->tx.queued_cnt); | ||
438 | spin_unlock_bh(&priv->tx.tx_lock); | ||
439 | |||
440 | if (len > sizeof(buf)) | ||
441 | len = sizeof(buf); | ||
442 | |||
443 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
444 | |||
445 | } | ||
446 | |||
447 | static const struct file_operations fops_queue = { | ||
448 | .read = read_file_queue, | ||
449 | .open = ath9k_debugfs_open, | ||
450 | .owner = THIS_MODULE, | ||
451 | .llseek = default_llseek, | ||
452 | }; | ||
453 | |||
454 | static ssize_t read_file_debug(struct file *file, char __user *user_buf, | ||
455 | size_t count, loff_t *ppos) | ||
456 | { | ||
457 | struct ath9k_htc_priv *priv = file->private_data; | ||
458 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
459 | char buf[32]; | ||
460 | unsigned int len; | ||
461 | |||
462 | len = sprintf(buf, "0x%08x\n", common->debug_mask); | ||
463 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
464 | } | ||
465 | |||
466 | static ssize_t write_file_debug(struct file *file, const char __user *user_buf, | ||
467 | size_t count, loff_t *ppos) | ||
468 | { | ||
469 | struct ath9k_htc_priv *priv = file->private_data; | ||
470 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
471 | unsigned long mask; | ||
472 | char buf[32]; | ||
473 | ssize_t len; | ||
474 | |||
475 | len = min(count, sizeof(buf) - 1); | ||
476 | if (copy_from_user(buf, user_buf, len)) | ||
477 | return -EFAULT; | ||
478 | |||
479 | buf[len] = '\0'; | ||
480 | if (strict_strtoul(buf, 0, &mask)) | ||
481 | return -EINVAL; | ||
482 | |||
483 | common->debug_mask = mask; | ||
484 | return count; | ||
485 | } | ||
486 | |||
487 | static const struct file_operations fops_debug = { | ||
488 | .read = read_file_debug, | ||
489 | .write = write_file_debug, | ||
490 | .open = ath9k_debugfs_open, | ||
491 | .owner = THIS_MODULE, | ||
492 | .llseek = default_llseek, | ||
493 | }; | ||
494 | |||
495 | static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf, | ||
496 | size_t count, loff_t *ppos) | ||
497 | { | ||
498 | struct ath9k_htc_priv *priv = file->private_data; | ||
499 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
500 | struct base_eep_header *pBase = NULL; | ||
501 | unsigned int len = 0, size = 1500; | ||
502 | ssize_t retval = 0; | ||
503 | char *buf; | ||
504 | |||
505 | /* | ||
506 | * This can be done since all the 3 EEPROM families have the | ||
507 | * same base header upto a certain point, and we are interested in | ||
508 | * the data only upto that point. | ||
509 | */ | ||
510 | |||
511 | if (AR_SREV_9271(priv->ah)) | ||
512 | pBase = (struct base_eep_header *) | ||
513 | &priv->ah->eeprom.map4k.baseEepHeader; | ||
514 | else if (priv->ah->hw_version.usbdev == AR9280_USB) | ||
515 | pBase = (struct base_eep_header *) | ||
516 | &priv->ah->eeprom.def.baseEepHeader; | ||
517 | else if (priv->ah->hw_version.usbdev == AR9287_USB) | ||
518 | pBase = (struct base_eep_header *) | ||
519 | &priv->ah->eeprom.map9287.baseEepHeader; | ||
520 | |||
521 | if (pBase == NULL) { | ||
522 | ath_err(common, "Unknown EEPROM type\n"); | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | buf = kzalloc(size, GFP_KERNEL); | ||
527 | if (buf == NULL) | ||
528 | return -ENOMEM; | ||
529 | |||
530 | len += snprintf(buf + len, size - len, | ||
531 | "%20s : %10d\n", "Major Version", | ||
532 | pBase->version >> 12); | ||
533 | len += snprintf(buf + len, size - len, | ||
534 | "%20s : %10d\n", "Minor Version", | ||
535 | pBase->version & 0xFFF); | ||
536 | len += snprintf(buf + len, size - len, | ||
537 | "%20s : %10d\n", "Checksum", | ||
538 | pBase->checksum); | ||
539 | len += snprintf(buf + len, size - len, | ||
540 | "%20s : %10d\n", "Length", | ||
541 | pBase->length); | ||
542 | len += snprintf(buf + len, size - len, | ||
543 | "%20s : %10d\n", "RegDomain1", | ||
544 | pBase->regDmn[0]); | ||
545 | len += snprintf(buf + len, size - len, | ||
546 | "%20s : %10d\n", "RegDomain2", | ||
547 | pBase->regDmn[1]); | ||
548 | len += snprintf(buf + len, size - len, | ||
549 | "%20s : %10d\n", | ||
550 | "TX Mask", pBase->txMask); | ||
551 | len += snprintf(buf + len, size - len, | ||
552 | "%20s : %10d\n", | ||
553 | "RX Mask", pBase->rxMask); | ||
554 | len += snprintf(buf + len, size - len, | ||
555 | "%20s : %10d\n", | ||
556 | "Allow 5GHz", | ||
557 | !!(pBase->opCapFlags & AR5416_OPFLAGS_11A)); | ||
558 | len += snprintf(buf + len, size - len, | ||
559 | "%20s : %10d\n", | ||
560 | "Allow 2GHz", | ||
561 | !!(pBase->opCapFlags & AR5416_OPFLAGS_11G)); | ||
562 | len += snprintf(buf + len, size - len, | ||
563 | "%20s : %10d\n", | ||
564 | "Disable 2GHz HT20", | ||
565 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20)); | ||
566 | len += snprintf(buf + len, size - len, | ||
567 | "%20s : %10d\n", | ||
568 | "Disable 2GHz HT40", | ||
569 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40)); | ||
570 | len += snprintf(buf + len, size - len, | ||
571 | "%20s : %10d\n", | ||
572 | "Disable 5Ghz HT20", | ||
573 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20)); | ||
574 | len += snprintf(buf + len, size - len, | ||
575 | "%20s : %10d\n", | ||
576 | "Disable 5Ghz HT40", | ||
577 | !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40)); | ||
578 | len += snprintf(buf + len, size - len, | ||
579 | "%20s : %10d\n", | ||
580 | "Big Endian", | ||
581 | !!(pBase->eepMisc & 0x01)); | ||
582 | len += snprintf(buf + len, size - len, | ||
583 | "%20s : %10d\n", | ||
584 | "Cal Bin Major Ver", | ||
585 | (pBase->binBuildNumber >> 24) & 0xFF); | ||
586 | len += snprintf(buf + len, size - len, | ||
587 | "%20s : %10d\n", | ||
588 | "Cal Bin Minor Ver", | ||
589 | (pBase->binBuildNumber >> 16) & 0xFF); | ||
590 | len += snprintf(buf + len, size - len, | ||
591 | "%20s : %10d\n", | ||
592 | "Cal Bin Build", | ||
593 | (pBase->binBuildNumber >> 8) & 0xFF); | ||
594 | |||
595 | /* | ||
596 | * UB91 specific data. | ||
597 | */ | ||
598 | if (AR_SREV_9271(priv->ah)) { | ||
599 | struct base_eep_header_4k *pBase4k = | ||
600 | &priv->ah->eeprom.map4k.baseEepHeader; | ||
601 | |||
602 | len += snprintf(buf + len, size - len, | ||
603 | "%20s : %10d\n", | ||
604 | "TX Gain type", | ||
605 | pBase4k->txGainType); | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * UB95 specific data. | ||
610 | */ | ||
611 | if (priv->ah->hw_version.usbdev == AR9287_USB) { | ||
612 | struct base_eep_ar9287_header *pBase9287 = | ||
613 | &priv->ah->eeprom.map9287.baseEepHeader; | ||
614 | |||
615 | len += snprintf(buf + len, size - len, | ||
616 | "%20s : %10ddB\n", | ||
617 | "Power Table Offset", | ||
618 | pBase9287->pwrTableOffset); | ||
619 | |||
620 | len += snprintf(buf + len, size - len, | ||
621 | "%20s : %10d\n", | ||
622 | "OpenLoop Power Ctrl", | ||
623 | pBase9287->openLoopPwrCntl); | ||
624 | } | ||
625 | |||
626 | len += snprintf(buf + len, size - len, | ||
627 | "%20s : %02X:%02X:%02X:%02X:%02X:%02X\n", | ||
628 | "MacAddress", | ||
629 | pBase->macAddr[0], pBase->macAddr[1], pBase->macAddr[2], | ||
630 | pBase->macAddr[3], pBase->macAddr[4], pBase->macAddr[5]); | ||
631 | if (len > size) | ||
632 | len = size; | ||
633 | |||
634 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
635 | kfree(buf); | ||
636 | |||
637 | return retval; | ||
638 | } | ||
639 | |||
640 | static const struct file_operations fops_base_eeprom = { | ||
641 | .read = read_file_base_eeprom, | ||
642 | .open = ath9k_debugfs_open, | ||
643 | .owner = THIS_MODULE, | ||
644 | .llseek = default_llseek, | ||
645 | }; | ||
646 | |||
647 | static ssize_t read_4k_modal_eeprom(struct file *file, | ||
648 | char __user *user_buf, | ||
649 | size_t count, loff_t *ppos) | ||
650 | { | ||
651 | #define PR_EEP(_s, _val) \ | ||
652 | do { \ | ||
653 | len += snprintf(buf + len, size - len, "%20s : %10d\n", \ | ||
654 | _s, (_val)); \ | ||
655 | } while (0) | ||
656 | |||
657 | struct ath9k_htc_priv *priv = file->private_data; | ||
658 | struct modal_eep_4k_header *pModal = &priv->ah->eeprom.map4k.modalHeader; | ||
659 | unsigned int len = 0, size = 2048; | ||
660 | ssize_t retval = 0; | ||
661 | char *buf; | ||
662 | |||
663 | buf = kzalloc(size, GFP_KERNEL); | ||
664 | if (buf == NULL) | ||
665 | return -ENOMEM; | ||
666 | |||
667 | PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); | ||
668 | PR_EEP("Ant. Common Control", pModal->antCtrlCommon); | ||
669 | PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); | ||
670 | PR_EEP("Switch Settle", pModal->switchSettling); | ||
671 | PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); | ||
672 | PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); | ||
673 | PR_EEP("ADC Desired size", pModal->adcDesiredSize); | ||
674 | PR_EEP("PGA Desired size", pModal->pgaDesiredSize); | ||
675 | PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]); | ||
676 | PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); | ||
677 | PR_EEP("txEndToRxOn", pModal->txEndToRxOn); | ||
678 | PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); | ||
679 | PR_EEP("CCA Threshold)", pModal->thresh62); | ||
680 | PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); | ||
681 | PR_EEP("xpdGain", pModal->xpdGain); | ||
682 | PR_EEP("External PD", pModal->xpd); | ||
683 | PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); | ||
684 | PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); | ||
685 | PR_EEP("pdGainOverlap", pModal->pdGainOverlap); | ||
686 | PR_EEP("O/D Bias Version", pModal->version); | ||
687 | PR_EEP("CCK OutputBias", pModal->ob_0); | ||
688 | PR_EEP("BPSK OutputBias", pModal->ob_1); | ||
689 | PR_EEP("QPSK OutputBias", pModal->ob_2); | ||
690 | PR_EEP("16QAM OutputBias", pModal->ob_3); | ||
691 | PR_EEP("64QAM OutputBias", pModal->ob_4); | ||
692 | PR_EEP("CCK Driver1_Bias", pModal->db1_0); | ||
693 | PR_EEP("BPSK Driver1_Bias", pModal->db1_1); | ||
694 | PR_EEP("QPSK Driver1_Bias", pModal->db1_2); | ||
695 | PR_EEP("16QAM Driver1_Bias", pModal->db1_3); | ||
696 | PR_EEP("64QAM Driver1_Bias", pModal->db1_4); | ||
697 | PR_EEP("CCK Driver2_Bias", pModal->db2_0); | ||
698 | PR_EEP("BPSK Driver2_Bias", pModal->db2_1); | ||
699 | PR_EEP("QPSK Driver2_Bias", pModal->db2_2); | ||
700 | PR_EEP("16QAM Driver2_Bias", pModal->db2_3); | ||
701 | PR_EEP("64QAM Driver2_Bias", pModal->db2_4); | ||
702 | PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); | ||
703 | PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); | ||
704 | PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); | ||
705 | PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); | ||
706 | PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); | ||
707 | PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); | ||
708 | PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); | ||
709 | PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]); | ||
710 | PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]); | ||
711 | PR_EEP("Ant. Diversity ctl1", pModal->antdiv_ctl1); | ||
712 | PR_EEP("Ant. Diversity ctl2", pModal->antdiv_ctl2); | ||
713 | PR_EEP("TX Diversity", pModal->tx_diversity); | ||
714 | |||
715 | if (len > size) | ||
716 | len = size; | ||
717 | |||
718 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
719 | kfree(buf); | ||
720 | |||
721 | return retval; | ||
722 | |||
723 | #undef PR_EEP | ||
724 | } | ||
725 | |||
726 | static ssize_t read_def_modal_eeprom(struct file *file, | ||
727 | char __user *user_buf, | ||
728 | size_t count, loff_t *ppos) | ||
729 | { | ||
730 | #define PR_EEP(_s, _val) \ | ||
731 | do { \ | ||
732 | if (pBase->opCapFlags & AR5416_OPFLAGS_11G) { \ | ||
733 | pModal = &priv->ah->eeprom.def.modalHeader[1]; \ | ||
734 | len += snprintf(buf + len, size - len, "%20s : %8d%7s", \ | ||
735 | _s, (_val), "|"); \ | ||
736 | } \ | ||
737 | if (pBase->opCapFlags & AR5416_OPFLAGS_11A) { \ | ||
738 | pModal = &priv->ah->eeprom.def.modalHeader[0]; \ | ||
739 | len += snprintf(buf + len, size - len, "%9d\n", \ | ||
740 | (_val)); \ | ||
741 | } \ | ||
742 | } while (0) | ||
743 | |||
744 | struct ath9k_htc_priv *priv = file->private_data; | ||
745 | struct base_eep_header *pBase = &priv->ah->eeprom.def.baseEepHeader; | ||
746 | struct modal_eep_header *pModal = NULL; | ||
747 | unsigned int len = 0, size = 3500; | ||
748 | ssize_t retval = 0; | ||
749 | char *buf; | ||
750 | |||
751 | buf = kzalloc(size, GFP_KERNEL); | ||
752 | if (buf == NULL) | ||
753 | return -ENOMEM; | ||
754 | |||
755 | len += snprintf(buf + len, size - len, | ||
756 | "%31s %15s\n", "2G", "5G"); | ||
757 | len += snprintf(buf + len, size - len, | ||
758 | "%32s %16s\n", "====", "====\n"); | ||
759 | |||
760 | PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); | ||
761 | PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); | ||
762 | PR_EEP("Chain2 Ant. Control", pModal->antCtrlChain[2]); | ||
763 | PR_EEP("Ant. Common Control", pModal->antCtrlCommon); | ||
764 | PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); | ||
765 | PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]); | ||
766 | PR_EEP("Chain2 Ant. Gain", pModal->antennaGainCh[2]); | ||
767 | PR_EEP("Switch Settle", pModal->switchSettling); | ||
768 | PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); | ||
769 | PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]); | ||
770 | PR_EEP("Chain2 TxRxAtten", pModal->txRxAttenCh[2]); | ||
771 | PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); | ||
772 | PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]); | ||
773 | PR_EEP("Chain2 RxTxMargin", pModal->rxTxMarginCh[2]); | ||
774 | PR_EEP("ADC Desired size", pModal->adcDesiredSize); | ||
775 | PR_EEP("PGA Desired size", pModal->pgaDesiredSize); | ||
776 | PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]); | ||
777 | PR_EEP("Chain1 xlna Gain", pModal->xlnaGainCh[1]); | ||
778 | PR_EEP("Chain2 xlna Gain", pModal->xlnaGainCh[2]); | ||
779 | PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); | ||
780 | PR_EEP("txEndToRxOn", pModal->txEndToRxOn); | ||
781 | PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); | ||
782 | PR_EEP("CCA Threshold)", pModal->thresh62); | ||
783 | PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); | ||
784 | PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]); | ||
785 | PR_EEP("Chain2 NF Threshold", pModal->noiseFloorThreshCh[2]); | ||
786 | PR_EEP("xpdGain", pModal->xpdGain); | ||
787 | PR_EEP("External PD", pModal->xpd); | ||
788 | PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); | ||
789 | PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]); | ||
790 | PR_EEP("Chain2 I Coefficient", pModal->iqCalICh[2]); | ||
791 | PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); | ||
792 | PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]); | ||
793 | PR_EEP("Chain2 Q Coefficient", pModal->iqCalQCh[2]); | ||
794 | PR_EEP("pdGainOverlap", pModal->pdGainOverlap); | ||
795 | PR_EEP("Chain0 OutputBias", pModal->ob); | ||
796 | PR_EEP("Chain0 DriverBias", pModal->db); | ||
797 | PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); | ||
798 | PR_EEP("2chain pwr decrease", pModal->pwrDecreaseFor2Chain); | ||
799 | PR_EEP("3chain pwr decrease", pModal->pwrDecreaseFor3Chain); | ||
800 | PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); | ||
801 | PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); | ||
802 | PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); | ||
803 | PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); | ||
804 | PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]); | ||
805 | PR_EEP("Chain2 bswAtten", pModal->bswAtten[2]); | ||
806 | PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); | ||
807 | PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]); | ||
808 | PR_EEP("Chain2 bswMargin", pModal->bswMargin[2]); | ||
809 | PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); | ||
810 | PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]); | ||
811 | PR_EEP("Chain1 xatten2Db", pModal->xatten2Db[1]); | ||
812 | PR_EEP("Chain2 xatten2Db", pModal->xatten2Db[2]); | ||
813 | PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]); | ||
814 | PR_EEP("Chain1 xatten2Margin", pModal->xatten2Margin[1]); | ||
815 | PR_EEP("Chain2 xatten2Margin", pModal->xatten2Margin[2]); | ||
816 | PR_EEP("Chain1 OutputBias", pModal->ob_ch1); | ||
817 | PR_EEP("Chain1 DriverBias", pModal->db_ch1); | ||
818 | PR_EEP("LNA Control", pModal->lna_ctl); | ||
819 | PR_EEP("XPA Bias Freq0", pModal->xpaBiasLvlFreq[0]); | ||
820 | PR_EEP("XPA Bias Freq1", pModal->xpaBiasLvlFreq[1]); | ||
821 | PR_EEP("XPA Bias Freq2", pModal->xpaBiasLvlFreq[2]); | ||
822 | |||
823 | if (len > size) | ||
824 | len = size; | ||
825 | |||
826 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
827 | kfree(buf); | ||
828 | |||
829 | return retval; | ||
830 | |||
831 | #undef PR_EEP | ||
832 | } | ||
833 | |||
834 | static ssize_t read_9287_modal_eeprom(struct file *file, | ||
835 | char __user *user_buf, | ||
836 | size_t count, loff_t *ppos) | ||
837 | { | ||
838 | #define PR_EEP(_s, _val) \ | ||
839 | do { \ | ||
840 | len += snprintf(buf + len, size - len, "%20s : %10d\n", \ | ||
841 | _s, (_val)); \ | ||
842 | } while (0) | ||
843 | |||
844 | struct ath9k_htc_priv *priv = file->private_data; | ||
845 | struct modal_eep_ar9287_header *pModal = &priv->ah->eeprom.map9287.modalHeader; | ||
846 | unsigned int len = 0, size = 3000; | ||
847 | ssize_t retval = 0; | ||
848 | char *buf; | ||
849 | |||
850 | buf = kzalloc(size, GFP_KERNEL); | ||
851 | if (buf == NULL) | ||
852 | return -ENOMEM; | ||
853 | |||
854 | PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]); | ||
855 | PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]); | ||
856 | PR_EEP("Ant. Common Control", pModal->antCtrlCommon); | ||
857 | PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]); | ||
858 | PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]); | ||
859 | PR_EEP("Switch Settle", pModal->switchSettling); | ||
860 | PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]); | ||
861 | PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]); | ||
862 | PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]); | ||
863 | PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]); | ||
864 | PR_EEP("ADC Desired size", pModal->adcDesiredSize); | ||
865 | PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff); | ||
866 | PR_EEP("txEndToRxOn", pModal->txEndToRxOn); | ||
867 | PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn); | ||
868 | PR_EEP("CCA Threshold)", pModal->thresh62); | ||
869 | PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]); | ||
870 | PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]); | ||
871 | PR_EEP("xpdGain", pModal->xpdGain); | ||
872 | PR_EEP("External PD", pModal->xpd); | ||
873 | PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]); | ||
874 | PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]); | ||
875 | PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]); | ||
876 | PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]); | ||
877 | PR_EEP("pdGainOverlap", pModal->pdGainOverlap); | ||
878 | PR_EEP("xPA Bias Level", pModal->xpaBiasLvl); | ||
879 | PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart); | ||
880 | PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn); | ||
881 | PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc); | ||
882 | PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]); | ||
883 | PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]); | ||
884 | PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]); | ||
885 | PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]); | ||
886 | PR_EEP("HT40 Switch Settle", pModal->swSettleHt40); | ||
887 | PR_EEP("AR92x7 Version", pModal->version); | ||
888 | PR_EEP("DriverBias1", pModal->db1); | ||
889 | PR_EEP("DriverBias2", pModal->db1); | ||
890 | PR_EEP("CCK OutputBias", pModal->ob_cck); | ||
891 | PR_EEP("PSK OutputBias", pModal->ob_psk); | ||
892 | PR_EEP("QAM OutputBias", pModal->ob_qam); | ||
893 | PR_EEP("PAL_OFF OutputBias", pModal->ob_pal_off); | ||
894 | |||
895 | if (len > size) | ||
896 | len = size; | ||
897 | |||
898 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
899 | kfree(buf); | ||
900 | |||
901 | return retval; | ||
902 | |||
903 | #undef PR_EEP | ||
904 | } | ||
905 | |||
906 | static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf, | ||
907 | size_t count, loff_t *ppos) | ||
908 | { | ||
909 | struct ath9k_htc_priv *priv = file->private_data; | ||
910 | |||
911 | if (AR_SREV_9271(priv->ah)) | ||
912 | return read_4k_modal_eeprom(file, user_buf, count, ppos); | ||
913 | else if (priv->ah->hw_version.usbdev == AR9280_USB) | ||
914 | return read_def_modal_eeprom(file, user_buf, count, ppos); | ||
915 | else if (priv->ah->hw_version.usbdev == AR9287_USB) | ||
916 | return read_9287_modal_eeprom(file, user_buf, count, ppos); | ||
917 | |||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | static const struct file_operations fops_modal_eeprom = { | ||
922 | .read = read_file_modal_eeprom, | ||
923 | .open = ath9k_debugfs_open, | ||
924 | .owner = THIS_MODULE, | ||
925 | .llseek = default_llseek, | ||
926 | }; | ||
927 | |||
928 | int ath9k_htc_init_debug(struct ath_hw *ah) | ||
929 | { | ||
930 | struct ath_common *common = ath9k_hw_common(ah); | ||
931 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
932 | |||
933 | priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME, | ||
934 | priv->hw->wiphy->debugfsdir); | ||
935 | if (!priv->debug.debugfs_phy) | ||
936 | return -ENOMEM; | ||
937 | |||
938 | debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, | ||
939 | priv, &fops_tgt_int_stats); | ||
940 | debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, | ||
941 | priv, &fops_tgt_tx_stats); | ||
942 | debugfs_create_file("tgt_rx_stats", S_IRUSR, priv->debug.debugfs_phy, | ||
943 | priv, &fops_tgt_rx_stats); | ||
944 | debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy, | ||
945 | priv, &fops_xmit); | ||
946 | debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy, | ||
947 | priv, &fops_recv); | ||
948 | debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy, | ||
949 | priv, &fops_slot); | ||
950 | debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy, | ||
951 | priv, &fops_queue); | ||
952 | debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy, | ||
953 | priv, &fops_debug); | ||
954 | debugfs_create_file("base_eeprom", S_IRUSR, priv->debug.debugfs_phy, | ||
955 | priv, &fops_base_eeprom); | ||
956 | debugfs_create_file("modal_eeprom", S_IRUSR, priv->debug.debugfs_phy, | ||
957 | priv, &fops_modal_eeprom); | ||
958 | |||
959 | return 0; | ||
960 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c new file mode 100644 index 000000000000..db2352e5cc0d --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -0,0 +1,339 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 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 "htc.h" | ||
18 | |||
19 | /******************/ | ||
20 | /* BTCOEX */ | ||
21 | /******************/ | ||
22 | |||
23 | /* | ||
24 | * Detects if there is any priority bt traffic | ||
25 | */ | ||
26 | static void ath_detect_bt_priority(struct ath9k_htc_priv *priv) | ||
27 | { | ||
28 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
29 | struct ath_hw *ah = priv->ah; | ||
30 | |||
31 | if (ath9k_hw_gpio_get(ah, ah->btcoex_hw.btpriority_gpio)) | ||
32 | btcoex->bt_priority_cnt++; | ||
33 | |||
34 | if (time_after(jiffies, btcoex->bt_priority_time + | ||
35 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { | ||
36 | priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); | ||
37 | /* Detect if colocated bt started scanning */ | ||
38 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { | ||
39 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
40 | "BT scan detected\n"); | ||
41 | priv->op_flags |= (OP_BT_SCAN | | ||
42 | OP_BT_PRIORITY_DETECTED); | ||
43 | } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | ||
44 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
45 | "BT priority traffic detected\n"); | ||
46 | priv->op_flags |= OP_BT_PRIORITY_DETECTED; | ||
47 | } | ||
48 | |||
49 | btcoex->bt_priority_cnt = 0; | ||
50 | btcoex->bt_priority_time = jiffies; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * This is the master bt coex work which runs for every | ||
56 | * 45ms, bt traffic will be given priority during 55% of this | ||
57 | * period while wlan gets remaining 45% | ||
58 | */ | ||
59 | static void ath_btcoex_period_work(struct work_struct *work) | ||
60 | { | ||
61 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | ||
62 | coex_period_work.work); | ||
63 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
64 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
65 | u32 timer_period; | ||
66 | bool is_btscan; | ||
67 | int ret; | ||
68 | |||
69 | ath_detect_bt_priority(priv); | ||
70 | |||
71 | is_btscan = !!(priv->op_flags & OP_BT_SCAN); | ||
72 | |||
73 | ret = ath9k_htc_update_cap_target(priv, | ||
74 | !!(priv->op_flags & OP_BT_PRIORITY_DETECTED)); | ||
75 | if (ret) { | ||
76 | ath_err(common, "Unable to set BTCOEX parameters\n"); | ||
77 | return; | ||
78 | } | ||
79 | |||
80 | ath9k_hw_btcoex_bt_stomp(priv->ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : | ||
81 | btcoex->bt_stomp_type); | ||
82 | |||
83 | timer_period = is_btscan ? btcoex->btscan_no_stomp : | ||
84 | btcoex->btcoex_no_stomp; | ||
85 | ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work, | ||
86 | msecs_to_jiffies(timer_period)); | ||
87 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, | ||
88 | msecs_to_jiffies(btcoex->btcoex_period)); | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * Work to time slice between wlan and bt traffic and | ||
93 | * configure weight registers | ||
94 | */ | ||
95 | static void ath_btcoex_duty_cycle_work(struct work_struct *work) | ||
96 | { | ||
97 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | ||
98 | duty_cycle_work.work); | ||
99 | struct ath_hw *ah = priv->ah; | ||
100 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
101 | struct ath_common *common = ath9k_hw_common(ah); | ||
102 | bool is_btscan = priv->op_flags & OP_BT_SCAN; | ||
103 | |||
104 | ath_dbg(common, ATH_DBG_BTCOEX, | ||
105 | "time slice work for bt and wlan\n"); | ||
106 | |||
107 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) | ||
108 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); | ||
109 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | ||
110 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); | ||
111 | } | ||
112 | |||
113 | void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv) | ||
114 | { | ||
115 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
116 | |||
117 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD; | ||
118 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * | ||
119 | btcoex->btcoex_period / 100; | ||
120 | btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * | ||
121 | btcoex->btcoex_period / 100; | ||
122 | INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work); | ||
123 | INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * (Re)start btcoex work | ||
128 | */ | ||
129 | |||
130 | void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv) | ||
131 | { | ||
132 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
133 | struct ath_hw *ah = priv->ah; | ||
134 | |||
135 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_BTCOEX, "Starting btcoex work\n"); | ||
136 | |||
137 | btcoex->bt_priority_cnt = 0; | ||
138 | btcoex->bt_priority_time = jiffies; | ||
139 | priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); | ||
140 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0); | ||
141 | } | ||
142 | |||
143 | |||
144 | /* | ||
145 | * Cancel btcoex and bt duty cycle work. | ||
146 | */ | ||
147 | void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv) | ||
148 | { | ||
149 | cancel_delayed_work_sync(&priv->coex_period_work); | ||
150 | cancel_delayed_work_sync(&priv->duty_cycle_work); | ||
151 | } | ||
152 | |||
153 | /*******/ | ||
154 | /* LED */ | ||
155 | /*******/ | ||
156 | |||
157 | #ifdef CONFIG_MAC80211_LEDS | ||
158 | void ath9k_led_work(struct work_struct *work) | ||
159 | { | ||
160 | struct ath9k_htc_priv *priv = container_of(work, | ||
161 | struct ath9k_htc_priv, | ||
162 | led_work); | ||
163 | |||
164 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, | ||
165 | (priv->brightness == LED_OFF)); | ||
166 | } | ||
167 | |||
168 | static void ath9k_led_brightness(struct led_classdev *led_cdev, | ||
169 | enum led_brightness brightness) | ||
170 | { | ||
171 | struct ath9k_htc_priv *priv = container_of(led_cdev, | ||
172 | struct ath9k_htc_priv, | ||
173 | led_cdev); | ||
174 | |||
175 | /* Not locked, but it's just a tiny green light..*/ | ||
176 | priv->brightness = brightness; | ||
177 | ieee80211_queue_work(priv->hw, &priv->led_work); | ||
178 | } | ||
179 | |||
180 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv) | ||
181 | { | ||
182 | if (!priv->led_registered) | ||
183 | return; | ||
184 | |||
185 | ath9k_led_brightness(&priv->led_cdev, LED_OFF); | ||
186 | led_classdev_unregister(&priv->led_cdev); | ||
187 | cancel_work_sync(&priv->led_work); | ||
188 | } | ||
189 | |||
190 | void ath9k_init_leds(struct ath9k_htc_priv *priv) | ||
191 | { | ||
192 | int ret; | ||
193 | |||
194 | if (AR_SREV_9287(priv->ah)) | ||
195 | priv->ah->led_pin = ATH_LED_PIN_9287; | ||
196 | else if (AR_SREV_9271(priv->ah)) | ||
197 | priv->ah->led_pin = ATH_LED_PIN_9271; | ||
198 | else if (AR_DEVID_7010(priv->ah)) | ||
199 | priv->ah->led_pin = ATH_LED_PIN_7010; | ||
200 | else | ||
201 | priv->ah->led_pin = ATH_LED_PIN_DEF; | ||
202 | |||
203 | /* Configure gpio 1 for output */ | ||
204 | ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, | ||
205 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
206 | /* LED off, active low */ | ||
207 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); | ||
208 | |||
209 | snprintf(priv->led_name, sizeof(priv->led_name), | ||
210 | "ath9k_htc-%s", wiphy_name(priv->hw->wiphy)); | ||
211 | priv->led_cdev.name = priv->led_name; | ||
212 | priv->led_cdev.brightness_set = ath9k_led_brightness; | ||
213 | |||
214 | ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &priv->led_cdev); | ||
215 | if (ret < 0) | ||
216 | return; | ||
217 | |||
218 | INIT_WORK(&priv->led_work, ath9k_led_work); | ||
219 | priv->led_registered = true; | ||
220 | |||
221 | return; | ||
222 | } | ||
223 | #endif | ||
224 | |||
225 | /*******************/ | ||
226 | /* Rfkill */ | ||
227 | /*******************/ | ||
228 | |||
229 | static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) | ||
230 | { | ||
231 | return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == | ||
232 | priv->ah->rfkill_polarity; | ||
233 | } | ||
234 | |||
235 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) | ||
236 | { | ||
237 | struct ath9k_htc_priv *priv = hw->priv; | ||
238 | bool blocked = !!ath_is_rfkill_set(priv); | ||
239 | |||
240 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | ||
241 | } | ||
242 | |||
243 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) | ||
244 | { | ||
245 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
246 | wiphy_rfkill_start_polling(priv->hw->wiphy); | ||
247 | } | ||
248 | |||
249 | void ath9k_htc_radio_enable(struct ieee80211_hw *hw) | ||
250 | { | ||
251 | struct ath9k_htc_priv *priv = hw->priv; | ||
252 | struct ath_hw *ah = priv->ah; | ||
253 | struct ath_common *common = ath9k_hw_common(ah); | ||
254 | int ret; | ||
255 | u8 cmd_rsp; | ||
256 | |||
257 | if (!ah->curchan) | ||
258 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | ||
259 | |||
260 | /* Reset the HW */ | ||
261 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | ||
262 | if (ret) { | ||
263 | ath_err(common, | ||
264 | "Unable to reset hardware; reset status %d (freq %u MHz)\n", | ||
265 | ret, ah->curchan->channel); | ||
266 | } | ||
267 | |||
268 | ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, | ||
269 | &priv->curtxpow); | ||
270 | |||
271 | /* Start RX */ | ||
272 | WMI_CMD(WMI_START_RECV_CMDID); | ||
273 | ath9k_host_rx_init(priv); | ||
274 | |||
275 | /* Start TX */ | ||
276 | htc_start(priv->htc); | ||
277 | spin_lock_bh(&priv->tx.tx_lock); | ||
278 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; | ||
279 | spin_unlock_bh(&priv->tx.tx_lock); | ||
280 | ieee80211_wake_queues(hw); | ||
281 | |||
282 | WMI_CMD(WMI_ENABLE_INTR_CMDID); | ||
283 | |||
284 | /* Enable LED */ | ||
285 | ath9k_hw_cfg_output(ah, ah->led_pin, | ||
286 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
287 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | ||
288 | } | ||
289 | |||
290 | void ath9k_htc_radio_disable(struct ieee80211_hw *hw) | ||
291 | { | ||
292 | struct ath9k_htc_priv *priv = hw->priv; | ||
293 | struct ath_hw *ah = priv->ah; | ||
294 | struct ath_common *common = ath9k_hw_common(ah); | ||
295 | int ret; | ||
296 | u8 cmd_rsp; | ||
297 | |||
298 | ath9k_htc_ps_wakeup(priv); | ||
299 | |||
300 | /* Disable LED */ | ||
301 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | ||
302 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | ||
303 | |||
304 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
305 | |||
306 | /* Stop TX */ | ||
307 | ieee80211_stop_queues(hw); | ||
308 | ath9k_htc_tx_drain(priv); | ||
309 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | ||
310 | |||
311 | /* Stop RX */ | ||
312 | WMI_CMD(WMI_STOP_RECV_CMDID); | ||
313 | |||
314 | /* Clear the WMI event queue */ | ||
315 | ath9k_wmi_event_drain(priv); | ||
316 | |||
317 | /* | ||
318 | * The MIB counters have to be disabled here, | ||
319 | * since the target doesn't do it. | ||
320 | */ | ||
321 | ath9k_hw_disable_mib_counters(ah); | ||
322 | |||
323 | if (!ah->curchan) | ||
324 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | ||
325 | |||
326 | /* Reset the HW */ | ||
327 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | ||
328 | if (ret) { | ||
329 | ath_err(common, | ||
330 | "Unable to reset hardware; reset status %d (freq %u MHz)\n", | ||
331 | ret, ah->curchan->channel); | ||
332 | } | ||
333 | |||
334 | /* Disable the PHY */ | ||
335 | ath9k_hw_phy_disable(ah); | ||
336 | |||
337 | ath9k_htc_ps_restore(priv); | ||
338 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | ||
339 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 2d4279191d7a..61e6d3950718 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | |||
41 | .max_power = 20, \ | 41 | .max_power = 20, \ |
42 | } | 42 | } |
43 | 43 | ||
44 | #define ATH_HTC_BTCOEX_PRODUCT_ID "wb193" | ||
45 | |||
44 | static struct ieee80211_channel ath9k_2ghz_channels[] = { | 46 | static struct ieee80211_channel ath9k_2ghz_channels[] = { |
45 | CHAN2G(2412, 0), /* Channel 1 */ | 47 | CHAN2G(2412, 0), /* Channel 1 */ |
46 | CHAN2G(2417, 1), /* Channel 2 */ | 48 | CHAN2G(2417, 1), /* Channel 2 */ |
@@ -115,6 +117,21 @@ static struct ieee80211_rate ath9k_legacy_rates[] = { | |||
115 | RATE(540, 0x0c, 0), | 117 | RATE(540, 0x0c, 0), |
116 | }; | 118 | }; |
117 | 119 | ||
120 | #ifdef CONFIG_MAC80211_LEDS | ||
121 | static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { | ||
122 | { .throughput = 0 * 1024, .blink_time = 334 }, | ||
123 | { .throughput = 1 * 1024, .blink_time = 260 }, | ||
124 | { .throughput = 5 * 1024, .blink_time = 220 }, | ||
125 | { .throughput = 10 * 1024, .blink_time = 190 }, | ||
126 | { .throughput = 20 * 1024, .blink_time = 170 }, | ||
127 | { .throughput = 50 * 1024, .blink_time = 150 }, | ||
128 | { .throughput = 70 * 1024, .blink_time = 130 }, | ||
129 | { .throughput = 100 * 1024, .blink_time = 110 }, | ||
130 | { .throughput = 200 * 1024, .blink_time = 80 }, | ||
131 | { .throughput = 300 * 1024, .blink_time = 50 }, | ||
132 | }; | ||
133 | #endif | ||
134 | |||
118 | static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) | 135 | static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) |
119 | { | 136 | { |
120 | int time_left; | 137 | int time_left; |
@@ -138,11 +155,7 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) | |||
138 | 155 | ||
139 | static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) | 156 | static void ath9k_deinit_priv(struct ath9k_htc_priv *priv) |
140 | { | 157 | { |
141 | ath9k_htc_exit_debug(priv->ah); | ||
142 | ath9k_hw_deinit(priv->ah); | 158 | ath9k_hw_deinit(priv->ah); |
143 | tasklet_kill(&priv->wmi_tasklet); | ||
144 | tasklet_kill(&priv->rx_tasklet); | ||
145 | tasklet_kill(&priv->tx_tasklet); | ||
146 | kfree(priv->ah); | 159 | kfree(priv->ah); |
147 | priv->ah = NULL; | 160 | priv->ah = NULL; |
148 | } | 161 | } |
@@ -179,7 +192,8 @@ static inline int ath9k_htc_connect_svc(struct ath9k_htc_priv *priv, | |||
179 | return htc_connect_service(priv->htc, &req, ep_id); | 192 | return htc_connect_service(priv->htc, &req, ep_id); |
180 | } | 193 | } |
181 | 194 | ||
182 | static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) | 195 | static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid, |
196 | u32 drv_info) | ||
183 | { | 197 | { |
184 | int ret; | 198 | int ret; |
185 | 199 | ||
@@ -243,15 +257,10 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid) | |||
243 | * the HIF layer, shouldn't matter much. | 257 | * the HIF layer, shouldn't matter much. |
244 | */ | 258 | */ |
245 | 259 | ||
246 | switch(devid) { | 260 | if (IS_AR7010_DEVICE(drv_info)) |
247 | case 0x7010: | ||
248 | case 0x7015: | ||
249 | case 0x9018: | ||
250 | priv->htc->credits = 45; | 261 | priv->htc->credits = 45; |
251 | break; | 262 | else |
252 | default: | ||
253 | priv->htc->credits = 33; | 263 | priv->htc->credits = 33; |
254 | } | ||
255 | 264 | ||
256 | ret = htc_init(priv->htc); | 265 | ret = htc_init(priv->htc); |
257 | if (ret) | 266 | if (ret) |
@@ -290,21 +299,49 @@ static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset) | |||
290 | (u8 *) &val, sizeof(val), | 299 | (u8 *) &val, sizeof(val), |
291 | 100); | 300 | 100); |
292 | if (unlikely(r)) { | 301 | if (unlikely(r)) { |
293 | ath_print(common, ATH_DBG_WMI, | 302 | ath_dbg(common, ATH_DBG_WMI, |
294 | "REGISTER READ FAILED: (0x%04x, %d)\n", | 303 | "REGISTER READ FAILED: (0x%04x, %d)\n", |
295 | reg_offset, r); | 304 | reg_offset, r); |
296 | return -EIO; | 305 | return -EIO; |
297 | } | 306 | } |
298 | 307 | ||
299 | return be32_to_cpu(val); | 308 | return be32_to_cpu(val); |
300 | } | 309 | } |
301 | 310 | ||
311 | static void ath9k_multi_regread(void *hw_priv, u32 *addr, | ||
312 | u32 *val, u16 count) | ||
313 | { | ||
314 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
315 | struct ath_common *common = ath9k_hw_common(ah); | ||
316 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
317 | __be32 tmpaddr[8]; | ||
318 | __be32 tmpval[8]; | ||
319 | int i, ret; | ||
320 | |||
321 | for (i = 0; i < count; i++) { | ||
322 | tmpaddr[i] = cpu_to_be32(addr[i]); | ||
323 | } | ||
324 | |||
325 | ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, | ||
326 | (u8 *)tmpaddr , sizeof(u32) * count, | ||
327 | (u8 *)tmpval, sizeof(u32) * count, | ||
328 | 100); | ||
329 | if (unlikely(ret)) { | ||
330 | ath_dbg(common, ATH_DBG_WMI, | ||
331 | "Multiple REGISTER READ FAILED (count: %d)\n", count); | ||
332 | } | ||
333 | |||
334 | for (i = 0; i < count; i++) { | ||
335 | val[i] = be32_to_cpu(tmpval[i]); | ||
336 | } | ||
337 | } | ||
338 | |||
302 | static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) | 339 | static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) |
303 | { | 340 | { |
304 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | 341 | struct ath_hw *ah = (struct ath_hw *) hw_priv; |
305 | struct ath_common *common = ath9k_hw_common(ah); | 342 | struct ath_common *common = ath9k_hw_common(ah); |
306 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | 343 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; |
307 | __be32 buf[2] = { | 344 | const __be32 buf[2] = { |
308 | cpu_to_be32(reg_offset), | 345 | cpu_to_be32(reg_offset), |
309 | cpu_to_be32(val), | 346 | cpu_to_be32(val), |
310 | }; | 347 | }; |
@@ -315,9 +352,9 @@ static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset) | |||
315 | (u8 *) &val, sizeof(val), | 352 | (u8 *) &val, sizeof(val), |
316 | 100); | 353 | 100); |
317 | if (unlikely(r)) { | 354 | if (unlikely(r)) { |
318 | ath_print(common, ATH_DBG_WMI, | 355 | ath_dbg(common, ATH_DBG_WMI, |
319 | "REGISTER WRITE FAILED:(0x%04x, %d)\n", | 356 | "REGISTER WRITE FAILED:(0x%04x, %d)\n", |
320 | reg_offset, r); | 357 | reg_offset, r); |
321 | } | 358 | } |
322 | } | 359 | } |
323 | 360 | ||
@@ -347,9 +384,9 @@ static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset) | |||
347 | (u8 *) &rsp_status, sizeof(rsp_status), | 384 | (u8 *) &rsp_status, sizeof(rsp_status), |
348 | 100); | 385 | 100); |
349 | if (unlikely(r)) { | 386 | if (unlikely(r)) { |
350 | ath_print(common, ATH_DBG_WMI, | 387 | ath_dbg(common, ATH_DBG_WMI, |
351 | "REGISTER WRITE FAILED, multi len: %d\n", | 388 | "REGISTER WRITE FAILED, multi len: %d\n", |
352 | priv->wmi->multi_write_idx); | 389 | priv->wmi->multi_write_idx); |
353 | } | 390 | } |
354 | priv->wmi->multi_write_idx = 0; | 391 | priv->wmi->multi_write_idx = 0; |
355 | } | 392 | } |
@@ -378,15 +415,6 @@ static void ath9k_enable_regwrite_buffer(void *hw_priv) | |||
378 | atomic_inc(&priv->wmi->mwrite_cnt); | 415 | atomic_inc(&priv->wmi->mwrite_cnt); |
379 | } | 416 | } |
380 | 417 | ||
381 | static void ath9k_disable_regwrite_buffer(void *hw_priv) | ||
382 | { | ||
383 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | ||
384 | struct ath_common *common = ath9k_hw_common(ah); | ||
385 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
386 | |||
387 | atomic_dec(&priv->wmi->mwrite_cnt); | ||
388 | } | ||
389 | |||
390 | static void ath9k_regwrite_flush(void *hw_priv) | 418 | static void ath9k_regwrite_flush(void *hw_priv) |
391 | { | 419 | { |
392 | struct ath_hw *ah = (struct ath_hw *) hw_priv; | 420 | struct ath_hw *ah = (struct ath_hw *) hw_priv; |
@@ -395,6 +423,8 @@ static void ath9k_regwrite_flush(void *hw_priv) | |||
395 | u32 rsp_status; | 423 | u32 rsp_status; |
396 | int r; | 424 | int r; |
397 | 425 | ||
426 | atomic_dec(&priv->wmi->mwrite_cnt); | ||
427 | |||
398 | mutex_lock(&priv->wmi->multi_write_mutex); | 428 | mutex_lock(&priv->wmi->multi_write_mutex); |
399 | 429 | ||
400 | if (priv->wmi->multi_write_idx) { | 430 | if (priv->wmi->multi_write_idx) { |
@@ -404,9 +434,9 @@ static void ath9k_regwrite_flush(void *hw_priv) | |||
404 | (u8 *) &rsp_status, sizeof(rsp_status), | 434 | (u8 *) &rsp_status, sizeof(rsp_status), |
405 | 100); | 435 | 100); |
406 | if (unlikely(r)) { | 436 | if (unlikely(r)) { |
407 | ath_print(common, ATH_DBG_WMI, | 437 | ath_dbg(common, ATH_DBG_WMI, |
408 | "REGISTER WRITE FAILED, multi len: %d\n", | 438 | "REGISTER WRITE FAILED, multi len: %d\n", |
409 | priv->wmi->multi_write_idx); | 439 | priv->wmi->multi_write_idx); |
410 | } | 440 | } |
411 | priv->wmi->multi_write_idx = 0; | 441 | priv->wmi->multi_write_idx = 0; |
412 | } | 442 | } |
@@ -414,13 +444,16 @@ static void ath9k_regwrite_flush(void *hw_priv) | |||
414 | mutex_unlock(&priv->wmi->multi_write_mutex); | 444 | mutex_unlock(&priv->wmi->multi_write_mutex); |
415 | } | 445 | } |
416 | 446 | ||
417 | static const struct ath_ops ath9k_common_ops = { | 447 | static u32 ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) |
418 | .read = ath9k_regread, | 448 | { |
419 | .write = ath9k_regwrite, | 449 | u32 val; |
420 | .enable_write_buffer = ath9k_enable_regwrite_buffer, | 450 | |
421 | .disable_write_buffer = ath9k_disable_regwrite_buffer, | 451 | val = ath9k_regread(hw_priv, reg_offset); |
422 | .write_flush = ath9k_regwrite_flush, | 452 | val &= ~clr; |
423 | }; | 453 | val |= set; |
454 | ath9k_regwrite(hw_priv, val, reg_offset); | ||
455 | return val; | ||
456 | } | ||
424 | 457 | ||
425 | static void ath_usb_read_cachesize(struct ath_common *common, int *csz) | 458 | static void ath_usb_read_cachesize(struct ath_common *common, int *csz) |
426 | { | 459 | { |
@@ -479,9 +512,9 @@ static void setup_ht_cap(struct ath9k_htc_priv *priv, | |||
479 | tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); | 512 | tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, 2); |
480 | rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); | 513 | rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, 2); |
481 | 514 | ||
482 | ath_print(common, ATH_DBG_CONFIG, | 515 | ath_dbg(common, ATH_DBG_CONFIG, |
483 | "TX streams %d, RX streams: %d\n", | 516 | "TX streams %d, RX streams: %d\n", |
484 | tx_streams, rx_streams); | 517 | tx_streams, rx_streams); |
485 | 518 | ||
486 | if (tx_streams != rx_streams) { | 519 | if (tx_streams != rx_streams) { |
487 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | 520 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; |
@@ -505,37 +538,31 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv) | |||
505 | 538 | ||
506 | priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); | 539 | priv->beaconq = ath9k_hw_beaconq_setup(priv->ah); |
507 | if (priv->beaconq == -1) { | 540 | if (priv->beaconq == -1) { |
508 | ath_print(common, ATH_DBG_FATAL, | 541 | ath_err(common, "Unable to setup BEACON xmit queue\n"); |
509 | "Unable to setup BEACON xmit queue\n"); | ||
510 | goto err; | 542 | goto err; |
511 | } | 543 | } |
512 | 544 | ||
513 | priv->cabq = ath9k_htc_cabq_setup(priv); | 545 | priv->cabq = ath9k_htc_cabq_setup(priv); |
514 | if (priv->cabq == -1) { | 546 | if (priv->cabq == -1) { |
515 | ath_print(common, ATH_DBG_FATAL, | 547 | ath_err(common, "Unable to setup CAB xmit queue\n"); |
516 | "Unable to setup CAB xmit queue\n"); | ||
517 | goto err; | 548 | goto err; |
518 | } | 549 | } |
519 | 550 | ||
520 | if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { | 551 | if (!ath9k_htc_txq_setup(priv, WME_AC_BE)) { |
521 | ath_print(common, ATH_DBG_FATAL, | 552 | ath_err(common, "Unable to setup xmit queue for BE traffic\n"); |
522 | "Unable to setup xmit queue for BE traffic\n"); | ||
523 | goto err; | 553 | goto err; |
524 | } | 554 | } |
525 | 555 | ||
526 | if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { | 556 | if (!ath9k_htc_txq_setup(priv, WME_AC_BK)) { |
527 | ath_print(common, ATH_DBG_FATAL, | 557 | ath_err(common, "Unable to setup xmit queue for BK traffic\n"); |
528 | "Unable to setup xmit queue for BK traffic\n"); | ||
529 | goto err; | 558 | goto err; |
530 | } | 559 | } |
531 | if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { | 560 | if (!ath9k_htc_txq_setup(priv, WME_AC_VI)) { |
532 | ath_print(common, ATH_DBG_FATAL, | 561 | ath_err(common, "Unable to setup xmit queue for VI traffic\n"); |
533 | "Unable to setup xmit queue for VI traffic\n"); | ||
534 | goto err; | 562 | goto err; |
535 | } | 563 | } |
536 | if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { | 564 | if (!ath9k_htc_txq_setup(priv, WME_AC_VO)) { |
537 | ath_print(common, ATH_DBG_FATAL, | 565 | ath_err(common, "Unable to setup xmit queue for VO traffic\n"); |
538 | "Unable to setup xmit queue for VO traffic\n"); | ||
539 | goto err; | 566 | goto err; |
540 | } | 567 | } |
541 | 568 | ||
@@ -551,25 +578,22 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) | |||
551 | int i = 0; | 578 | int i = 0; |
552 | 579 | ||
553 | /* Get the hardware key cache size. */ | 580 | /* Get the hardware key cache size. */ |
554 | common->keymax = priv->ah->caps.keycache_size; | 581 | common->keymax = AR_KEYTABLE_SIZE; |
555 | if (common->keymax > ATH_KEYMAX) { | 582 | |
556 | ath_print(common, ATH_DBG_ANY, | 583 | if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) |
557 | "Warning, using only %u entries in %u key cache\n", | 584 | common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; |
558 | ATH_KEYMAX, common->keymax); | ||
559 | common->keymax = ATH_KEYMAX; | ||
560 | } | ||
561 | 585 | ||
562 | /* | 586 | /* |
563 | * Reset the key cache since some parts do not | 587 | * Reset the key cache since some parts do not |
564 | * reset the contents on initial power up. | 588 | * reset the contents on initial power up. |
565 | */ | 589 | */ |
566 | for (i = 0; i < common->keymax; i++) | 590 | for (i = 0; i < common->keymax; i++) |
567 | ath9k_hw_keyreset(priv->ah, (u16) i); | 591 | ath_hw_keyreset(common, (u16) i); |
568 | } | 592 | } |
569 | 593 | ||
570 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) | 594 | static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) |
571 | { | 595 | { |
572 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) { | 596 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { |
573 | priv->sbands[IEEE80211_BAND_2GHZ].channels = | 597 | priv->sbands[IEEE80211_BAND_2GHZ].channels = |
574 | ath9k_2ghz_channels; | 598 | ath9k_2ghz_channels; |
575 | priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | 599 | priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; |
@@ -580,7 +604,7 @@ static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) | |||
580 | ARRAY_SIZE(ath9k_legacy_rates); | 604 | ARRAY_SIZE(ath9k_legacy_rates); |
581 | } | 605 | } |
582 | 606 | ||
583 | if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) { | 607 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { |
584 | priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels; | 608 | priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels; |
585 | priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | 609 | priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; |
586 | priv->sbands[IEEE80211_BAND_5GHZ].n_channels = | 610 | priv->sbands[IEEE80211_BAND_5GHZ].n_channels = |
@@ -599,17 +623,41 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) | |||
599 | common->tx_chainmask = priv->ah->caps.tx_chainmask; | 623 | common->tx_chainmask = priv->ah->caps.tx_chainmask; |
600 | common->rx_chainmask = priv->ah->caps.rx_chainmask; | 624 | common->rx_chainmask = priv->ah->caps.rx_chainmask; |
601 | 625 | ||
602 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 626 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
603 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
604 | 627 | ||
605 | priv->ah->opmode = NL80211_IFTYPE_STATION; | 628 | priv->ah->opmode = NL80211_IFTYPE_STATION; |
606 | } | 629 | } |
607 | 630 | ||
608 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | 631 | static void ath9k_init_btcoex(struct ath9k_htc_priv *priv) |
632 | { | ||
633 | int qnum; | ||
634 | |||
635 | switch (priv->ah->btcoex_hw.scheme) { | ||
636 | case ATH_BTCOEX_CFG_NONE: | ||
637 | break; | ||
638 | case ATH_BTCOEX_CFG_3WIRE: | ||
639 | priv->ah->btcoex_hw.btactive_gpio = 7; | ||
640 | priv->ah->btcoex_hw.btpriority_gpio = 6; | ||
641 | priv->ah->btcoex_hw.wlanactive_gpio = 8; | ||
642 | priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
643 | ath9k_hw_btcoex_init_3wire(priv->ah); | ||
644 | ath_htc_init_btcoex_work(priv); | ||
645 | qnum = priv->hwq_map[WME_AC_BE]; | ||
646 | ath9k_hw_init_btcoex_hw(priv->ah, qnum); | ||
647 | break; | ||
648 | default: | ||
649 | WARN_ON(1); | ||
650 | break; | ||
651 | } | ||
652 | } | ||
653 | |||
654 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, | ||
655 | u16 devid, char *product, | ||
656 | u32 drv_info) | ||
609 | { | 657 | { |
610 | struct ath_hw *ah = NULL; | 658 | struct ath_hw *ah = NULL; |
611 | struct ath_common *common; | 659 | struct ath_common *common; |
612 | int ret = 0, csz = 0; | 660 | int i, ret = 0, csz = 0; |
613 | 661 | ||
614 | priv->op_flags |= OP_INVALID; | 662 | priv->op_flags |= OP_INVALID; |
615 | 663 | ||
@@ -619,28 +667,37 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | |||
619 | 667 | ||
620 | ah->hw_version.devid = devid; | 668 | ah->hw_version.devid = devid; |
621 | ah->hw_version.subsysid = 0; /* FIXME */ | 669 | ah->hw_version.subsysid = 0; /* FIXME */ |
670 | ah->hw_version.usbdev = drv_info; | ||
671 | ah->ah_flags |= AH_USE_EEPROM; | ||
672 | ah->reg_ops.read = ath9k_regread; | ||
673 | ah->reg_ops.multi_read = ath9k_multi_regread; | ||
674 | ah->reg_ops.write = ath9k_regwrite; | ||
675 | ah->reg_ops.enable_write_buffer = ath9k_enable_regwrite_buffer; | ||
676 | ah->reg_ops.write_flush = ath9k_regwrite_flush; | ||
677 | ah->reg_ops.rmw = ath9k_reg_rmw; | ||
622 | priv->ah = ah; | 678 | priv->ah = ah; |
623 | 679 | ||
624 | common = ath9k_hw_common(ah); | 680 | common = ath9k_hw_common(ah); |
625 | common->ops = &ath9k_common_ops; | 681 | common->ops = &ah->reg_ops; |
626 | common->bus_ops = &ath9k_usb_bus_ops; | 682 | common->bus_ops = &ath9k_usb_bus_ops; |
627 | common->ah = ah; | 683 | common->ah = ah; |
628 | common->hw = priv->hw; | 684 | common->hw = priv->hw; |
629 | common->priv = priv; | 685 | common->priv = priv; |
630 | common->debug_mask = ath9k_debug; | 686 | common->debug_mask = ath9k_debug; |
631 | 687 | ||
632 | spin_lock_init(&priv->wmi->wmi_lock); | ||
633 | spin_lock_init(&priv->beacon_lock); | 688 | spin_lock_init(&priv->beacon_lock); |
634 | spin_lock_init(&priv->tx_lock); | 689 | spin_lock_init(&priv->tx.tx_lock); |
635 | mutex_init(&priv->mutex); | 690 | mutex_init(&priv->mutex); |
636 | mutex_init(&priv->htc_pm_lock); | 691 | mutex_init(&priv->htc_pm_lock); |
637 | tasklet_init(&priv->wmi_tasklet, ath9k_wmi_tasklet, | ||
638 | (unsigned long)priv); | ||
639 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, | 692 | tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet, |
640 | (unsigned long)priv); | 693 | (unsigned long)priv); |
641 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, (unsigned long)priv); | 694 | tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet, |
642 | INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); | 695 | (unsigned long)priv); |
696 | INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); | ||
643 | INIT_WORK(&priv->ps_work, ath9k_ps_work); | 697 | INIT_WORK(&priv->ps_work, ath9k_ps_work); |
698 | INIT_WORK(&priv->fatal_work, ath9k_fatal_work); | ||
699 | setup_timer(&priv->tx.cleanup_timer, ath9k_htc_tx_cleanup_timer, | ||
700 | (unsigned long)priv); | ||
644 | 701 | ||
645 | /* | 702 | /* |
646 | * Cache line size is used to size and align various | 703 | * Cache line size is used to size and align various |
@@ -651,32 +708,31 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | |||
651 | 708 | ||
652 | ret = ath9k_hw_init(ah); | 709 | ret = ath9k_hw_init(ah); |
653 | if (ret) { | 710 | if (ret) { |
654 | ath_print(common, ATH_DBG_FATAL, | 711 | ath_err(common, |
655 | "Unable to initialize hardware; " | 712 | "Unable to initialize hardware; initialization status: %d\n", |
656 | "initialization status: %d\n", ret); | 713 | ret); |
657 | goto err_hw; | 714 | goto err_hw; |
658 | } | 715 | } |
659 | 716 | ||
660 | ret = ath9k_htc_init_debug(ah); | ||
661 | if (ret) { | ||
662 | ath_print(common, ATH_DBG_FATAL, | ||
663 | "Unable to create debugfs files\n"); | ||
664 | goto err_debug; | ||
665 | } | ||
666 | |||
667 | ret = ath9k_init_queues(priv); | 717 | ret = ath9k_init_queues(priv); |
668 | if (ret) | 718 | if (ret) |
669 | goto err_queues; | 719 | goto err_queues; |
670 | 720 | ||
721 | for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++) | ||
722 | priv->cur_beacon_conf.bslot[i] = NULL; | ||
723 | |||
671 | ath9k_init_crypto(priv); | 724 | ath9k_init_crypto(priv); |
672 | ath9k_init_channels_rates(priv); | 725 | ath9k_init_channels_rates(priv); |
673 | ath9k_init_misc(priv); | 726 | ath9k_init_misc(priv); |
674 | 727 | ||
728 | if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) { | ||
729 | ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE; | ||
730 | ath9k_init_btcoex(priv); | ||
731 | } | ||
732 | |||
675 | return 0; | 733 | return 0; |
676 | 734 | ||
677 | err_queues: | 735 | err_queues: |
678 | ath9k_htc_exit_debug(ah); | ||
679 | err_debug: | ||
680 | ath9k_hw_deinit(ah); | 736 | ath9k_hw_deinit(ah); |
681 | err_hw: | 737 | err_hw: |
682 | 738 | ||
@@ -697,17 +753,22 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
697 | IEEE80211_HW_HAS_RATE_CONTROL | | 753 | IEEE80211_HW_HAS_RATE_CONTROL | |
698 | IEEE80211_HW_RX_INCLUDES_FCS | | 754 | IEEE80211_HW_RX_INCLUDES_FCS | |
699 | IEEE80211_HW_SUPPORTS_PS | | 755 | IEEE80211_HW_SUPPORTS_PS | |
700 | IEEE80211_HW_PS_NULLFUNC_STACK; | 756 | IEEE80211_HW_PS_NULLFUNC_STACK | |
757 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; | ||
701 | 758 | ||
702 | hw->wiphy->interface_modes = | 759 | hw->wiphy->interface_modes = |
703 | BIT(NL80211_IFTYPE_STATION) | | 760 | BIT(NL80211_IFTYPE_STATION) | |
704 | BIT(NL80211_IFTYPE_ADHOC); | 761 | BIT(NL80211_IFTYPE_ADHOC) | |
762 | BIT(NL80211_IFTYPE_AP) | | ||
763 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
764 | BIT(NL80211_IFTYPE_P2P_CLIENT); | ||
705 | 765 | ||
706 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 766 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
707 | 767 | ||
708 | hw->queues = 4; | 768 | hw->queues = 4; |
709 | hw->channel_change_time = 5000; | 769 | hw->channel_change_time = 5000; |
710 | hw->max_listen_interval = 10; | 770 | hw->max_listen_interval = 10; |
771 | |||
711 | hw->vif_data_size = sizeof(struct ath9k_htc_vif); | 772 | hw->vif_data_size = sizeof(struct ath9k_htc_vif); |
712 | hw->sta_data_size = sizeof(struct ath9k_htc_sta); | 773 | hw->sta_data_size = sizeof(struct ath9k_htc_sta); |
713 | 774 | ||
@@ -715,18 +776,18 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
715 | hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) + | 776 | hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) + |
716 | sizeof(struct htc_frame_hdr) + 4; | 777 | sizeof(struct htc_frame_hdr) + 4; |
717 | 778 | ||
718 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) | 779 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) |
719 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 780 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
720 | &priv->sbands[IEEE80211_BAND_2GHZ]; | 781 | &priv->sbands[IEEE80211_BAND_2GHZ]; |
721 | if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) | 782 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) |
722 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 783 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
723 | &priv->sbands[IEEE80211_BAND_5GHZ]; | 784 | &priv->sbands[IEEE80211_BAND_5GHZ]; |
724 | 785 | ||
725 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | 786 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { |
726 | if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) | 787 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) |
727 | setup_ht_cap(priv, | 788 | setup_ht_cap(priv, |
728 | &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); | 789 | &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); |
729 | if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) | 790 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) |
730 | setup_ht_cap(priv, | 791 | setup_ht_cap(priv, |
731 | &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); | 792 | &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); |
732 | } | 793 | } |
@@ -734,16 +795,55 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
734 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | 795 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); |
735 | } | 796 | } |
736 | 797 | ||
737 | static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) | 798 | static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) |
799 | { | ||
800 | struct ieee80211_hw *hw = priv->hw; | ||
801 | struct wmi_fw_version cmd_rsp; | ||
802 | int ret; | ||
803 | |||
804 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
805 | |||
806 | WMI_CMD(WMI_GET_FW_VERSION); | ||
807 | if (ret) | ||
808 | return -EINVAL; | ||
809 | |||
810 | priv->fw_version_major = be16_to_cpu(cmd_rsp.major); | ||
811 | priv->fw_version_minor = be16_to_cpu(cmd_rsp.minor); | ||
812 | |||
813 | snprintf(hw->wiphy->fw_version, ETHTOOL_BUSINFO_LEN, "%d.%d", | ||
814 | priv->fw_version_major, | ||
815 | priv->fw_version_minor); | ||
816 | |||
817 | dev_info(priv->dev, "ath9k_htc: FW Version: %d.%d\n", | ||
818 | priv->fw_version_major, | ||
819 | priv->fw_version_minor); | ||
820 | |||
821 | /* | ||
822 | * Check if the available FW matches the driver's | ||
823 | * required version. | ||
824 | */ | ||
825 | if (priv->fw_version_major != MAJOR_VERSION_REQ || | ||
826 | priv->fw_version_minor != MINOR_VERSION_REQ) { | ||
827 | dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n", | ||
828 | MAJOR_VERSION_REQ, MINOR_VERSION_REQ); | ||
829 | return -EINVAL; | ||
830 | } | ||
831 | |||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | static int ath9k_init_device(struct ath9k_htc_priv *priv, | ||
836 | u16 devid, char *product, u32 drv_info) | ||
738 | { | 837 | { |
739 | struct ieee80211_hw *hw = priv->hw; | 838 | struct ieee80211_hw *hw = priv->hw; |
740 | struct ath_common *common; | 839 | struct ath_common *common; |
741 | struct ath_hw *ah; | 840 | struct ath_hw *ah; |
742 | int error = 0; | 841 | int error = 0; |
743 | struct ath_regulatory *reg; | 842 | struct ath_regulatory *reg; |
843 | char hw_name[64]; | ||
744 | 844 | ||
745 | /* Bring up device */ | 845 | /* Bring up device */ |
746 | error = ath9k_init_priv(priv, devid); | 846 | error = ath9k_init_priv(priv, devid, product, drv_info); |
747 | if (error != 0) | 847 | if (error != 0) |
748 | goto err_init; | 848 | goto err_init; |
749 | 849 | ||
@@ -751,6 +851,10 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) | |||
751 | common = ath9k_hw_common(ah); | 851 | common = ath9k_hw_common(ah); |
752 | ath9k_set_hw_capab(priv, hw); | 852 | ath9k_set_hw_capab(priv, hw); |
753 | 853 | ||
854 | error = ath9k_init_firmware_version(priv); | ||
855 | if (error != 0) | ||
856 | goto err_fw; | ||
857 | |||
754 | /* Initialize regulatory */ | 858 | /* Initialize regulatory */ |
755 | error = ath_regd_init(&common->regulatory, priv->hw->wiphy, | 859 | error = ath_regd_init(&common->regulatory, priv->hw->wiphy, |
756 | ath9k_reg_notifier); | 860 | ath9k_reg_notifier); |
@@ -769,6 +873,13 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) | |||
769 | if (error != 0) | 873 | if (error != 0) |
770 | goto err_rx; | 874 | goto err_rx; |
771 | 875 | ||
876 | #ifdef CONFIG_MAC80211_LEDS | ||
877 | /* must be initialized before ieee80211_register_hw */ | ||
878 | priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw, | ||
879 | IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_htc_tpt_blink, | ||
880 | ARRAY_SIZE(ath9k_htc_tpt_blink)); | ||
881 | #endif | ||
882 | |||
772 | /* Register with mac80211 */ | 883 | /* Register with mac80211 */ |
773 | error = ieee80211_register_hw(hw); | 884 | error = ieee80211_register_hw(hw); |
774 | if (error) | 885 | if (error) |
@@ -781,6 +892,28 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) | |||
781 | goto err_world; | 892 | goto err_world; |
782 | } | 893 | } |
783 | 894 | ||
895 | error = ath9k_htc_init_debug(priv->ah); | ||
896 | if (error) { | ||
897 | ath_err(common, "Unable to create debugfs files\n"); | ||
898 | goto err_world; | ||
899 | } | ||
900 | |||
901 | ath_dbg(common, ATH_DBG_CONFIG, | ||
902 | "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, " | ||
903 | "BE:%d, BK:%d, VI:%d, VO:%d\n", | ||
904 | priv->wmi_cmd_ep, | ||
905 | priv->beacon_ep, | ||
906 | priv->cab_ep, | ||
907 | priv->uapsd_ep, | ||
908 | priv->mgmt_ep, | ||
909 | priv->data_be_ep, | ||
910 | priv->data_bk_ep, | ||
911 | priv->data_vi_ep, | ||
912 | priv->data_vo_ep); | ||
913 | |||
914 | ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name)); | ||
915 | wiphy_info(hw->wiphy, "%s\n", hw_name); | ||
916 | |||
784 | ath9k_init_leds(priv); | 917 | ath9k_init_leds(priv); |
785 | ath9k_start_rfkill_poll(priv); | 918 | ath9k_start_rfkill_poll(priv); |
786 | 919 | ||
@@ -795,13 +928,15 @@ err_rx: | |||
795 | err_tx: | 928 | err_tx: |
796 | /* Nothing */ | 929 | /* Nothing */ |
797 | err_regd: | 930 | err_regd: |
931 | /* Nothing */ | ||
932 | err_fw: | ||
798 | ath9k_deinit_priv(priv); | 933 | ath9k_deinit_priv(priv); |
799 | err_init: | 934 | err_init: |
800 | return error; | 935 | return error; |
801 | } | 936 | } |
802 | 937 | ||
803 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | 938 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, |
804 | u16 devid) | 939 | u16 devid, char *product, u32 drv_info) |
805 | { | 940 | { |
806 | struct ieee80211_hw *hw; | 941 | struct ieee80211_hw *hw; |
807 | struct ath9k_htc_priv *priv; | 942 | struct ath9k_htc_priv *priv; |
@@ -828,14 +963,11 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | |||
828 | goto err_free; | 963 | goto err_free; |
829 | } | 964 | } |
830 | 965 | ||
831 | ret = ath9k_init_htc_services(priv, devid); | 966 | ret = ath9k_init_htc_services(priv, devid, drv_info); |
832 | if (ret) | 967 | if (ret) |
833 | goto err_init; | 968 | goto err_init; |
834 | 969 | ||
835 | /* The device may have been unplugged earlier. */ | 970 | ret = ath9k_init_device(priv, devid, product, drv_info); |
836 | priv->op_flags &= ~OP_UNPLUGGED; | ||
837 | |||
838 | ret = ath9k_init_device(priv, devid); | ||
839 | if (ret) | 971 | if (ret) |
840 | goto err_init; | 972 | goto err_init; |
841 | 973 | ||
@@ -854,7 +986,7 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) | |||
854 | 986 | ||
855 | /* Check if the device has been yanked out. */ | 987 | /* Check if the device has been yanked out. */ |
856 | if (hotunplug) | 988 | if (hotunplug) |
857 | htc_handle->drv_priv->op_flags |= OP_UNPLUGGED; | 989 | htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED; |
858 | 990 | ||
859 | ath9k_deinit_device(htc_handle->drv_priv); | 991 | ath9k_deinit_device(htc_handle->drv_priv); |
860 | ath9k_deinit_wmi(htc_handle->drv_priv); | 992 | ath9k_deinit_wmi(htc_handle->drv_priv); |
@@ -863,54 +995,43 @@ void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug) | |||
863 | } | 995 | } |
864 | 996 | ||
865 | #ifdef CONFIG_PM | 997 | #ifdef CONFIG_PM |
998 | |||
999 | void ath9k_htc_suspend(struct htc_target *htc_handle) | ||
1000 | { | ||
1001 | ath9k_htc_setpower(htc_handle->drv_priv, ATH9K_PM_FULL_SLEEP); | ||
1002 | } | ||
1003 | |||
866 | int ath9k_htc_resume(struct htc_target *htc_handle) | 1004 | int ath9k_htc_resume(struct htc_target *htc_handle) |
867 | { | 1005 | { |
1006 | struct ath9k_htc_priv *priv = htc_handle->drv_priv; | ||
868 | int ret; | 1007 | int ret; |
869 | 1008 | ||
870 | ret = ath9k_htc_wait_for_target(htc_handle->drv_priv); | 1009 | ret = ath9k_htc_wait_for_target(priv); |
871 | if (ret) | 1010 | if (ret) |
872 | return ret; | 1011 | return ret; |
873 | 1012 | ||
874 | ret = ath9k_init_htc_services(htc_handle->drv_priv, | 1013 | ret = ath9k_init_htc_services(priv, priv->ah->hw_version.devid, |
875 | htc_handle->drv_priv->ah->hw_version.devid); | 1014 | priv->ah->hw_version.usbdev); |
876 | return ret; | 1015 | return ret; |
877 | } | 1016 | } |
878 | #endif | 1017 | #endif |
879 | 1018 | ||
880 | static int __init ath9k_htc_init(void) | 1019 | static int __init ath9k_htc_init(void) |
881 | { | 1020 | { |
882 | int error; | 1021 | if (ath9k_hif_usb_init() < 0) { |
883 | |||
884 | error = ath9k_htc_debug_create_root(); | ||
885 | if (error < 0) { | ||
886 | printk(KERN_ERR | ||
887 | "ath9k_htc: Unable to create debugfs root: %d\n", | ||
888 | error); | ||
889 | goto err_dbg; | ||
890 | } | ||
891 | |||
892 | error = ath9k_hif_usb_init(); | ||
893 | if (error < 0) { | ||
894 | printk(KERN_ERR | 1022 | printk(KERN_ERR |
895 | "ath9k_htc: No USB devices found," | 1023 | "ath9k_htc: No USB devices found," |
896 | " driver not installed.\n"); | 1024 | " driver not installed.\n"); |
897 | error = -ENODEV; | 1025 | return -ENODEV; |
898 | goto err_usb; | ||
899 | } | 1026 | } |
900 | 1027 | ||
901 | return 0; | 1028 | return 0; |
902 | |||
903 | err_usb: | ||
904 | ath9k_htc_debug_remove_root(); | ||
905 | err_dbg: | ||
906 | return error; | ||
907 | } | 1029 | } |
908 | module_init(ath9k_htc_init); | 1030 | module_init(ath9k_htc_init); |
909 | 1031 | ||
910 | static void __exit ath9k_htc_exit(void) | 1032 | static void __exit ath9k_htc_exit(void) |
911 | { | 1033 | { |
912 | ath9k_hif_usb_exit(); | 1034 | ath9k_hif_usb_exit(); |
913 | ath9k_htc_debug_remove_root(); | ||
914 | printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); | 1035 | printk(KERN_INFO "ath9k_htc: Driver unloaded\n"); |
915 | } | 1036 | } |
916 | module_exit(ath9k_htc_exit); | 1037 | module_exit(ath9k_htc_exit); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7d09b4b17bbd..7b7796895432 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -16,32 +16,17 @@ | |||
16 | 16 | ||
17 | #include "htc.h" | 17 | #include "htc.h" |
18 | 18 | ||
19 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
20 | static struct dentry *ath9k_debugfs_root; | ||
21 | #endif | ||
22 | |||
23 | /*************/ | 19 | /*************/ |
24 | /* Utilities */ | 20 | /* Utilities */ |
25 | /*************/ | 21 | /*************/ |
26 | 22 | ||
27 | static void ath_update_txpow(struct ath9k_htc_priv *priv) | ||
28 | { | ||
29 | struct ath_hw *ah = priv->ah; | ||
30 | |||
31 | if (priv->curtxpow != priv->txpowlimit) { | ||
32 | ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit); | ||
33 | /* read back in case value is clamped */ | ||
34 | priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | ||
35 | } | ||
36 | } | ||
37 | |||
38 | /* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */ | 23 | /* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */ |
39 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, | 24 | static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, |
40 | struct ath9k_channel *ichan) | 25 | struct ath9k_channel *ichan) |
41 | { | 26 | { |
42 | enum htc_phymode mode; | 27 | enum htc_phymode mode; |
43 | 28 | ||
44 | mode = HTC_MODE_AUTO; | 29 | mode = -EINVAL; |
45 | 30 | ||
46 | switch (ichan->chanmode) { | 31 | switch (ichan->chanmode) { |
47 | case CHANNEL_G: | 32 | case CHANNEL_G: |
@@ -60,11 +45,13 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv, | |||
60 | break; | 45 | break; |
61 | } | 46 | } |
62 | 47 | ||
48 | WARN_ON(mode < 0); | ||
49 | |||
63 | return mode; | 50 | return mode; |
64 | } | 51 | } |
65 | 52 | ||
66 | static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, | 53 | bool ath9k_htc_setpower(struct ath9k_htc_priv *priv, |
67 | enum ath9k_power_mode mode) | 54 | enum ath9k_power_mode mode) |
68 | { | 55 | { |
69 | bool ret; | 56 | bool ret; |
70 | 57 | ||
@@ -116,6 +103,138 @@ void ath9k_ps_work(struct work_struct *work) | |||
116 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); | 103 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); |
117 | } | 104 | } |
118 | 105 | ||
106 | static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
107 | { | ||
108 | struct ath9k_htc_priv *priv = data; | ||
109 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
110 | |||
111 | if ((vif->type == NL80211_IFTYPE_AP) && bss_conf->enable_beacon) | ||
112 | priv->reconfig_beacon = true; | ||
113 | |||
114 | if (bss_conf->assoc) { | ||
115 | priv->rearm_ani = true; | ||
116 | priv->reconfig_beacon = true; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv) | ||
121 | { | ||
122 | priv->rearm_ani = false; | ||
123 | priv->reconfig_beacon = false; | ||
124 | |||
125 | ieee80211_iterate_active_interfaces_atomic(priv->hw, | ||
126 | ath9k_htc_vif_iter, priv); | ||
127 | if (priv->rearm_ani) | ||
128 | ath9k_htc_start_ani(priv); | ||
129 | |||
130 | if (priv->reconfig_beacon) { | ||
131 | ath9k_htc_ps_wakeup(priv); | ||
132 | ath9k_htc_beacon_reconfig(priv); | ||
133 | ath9k_htc_ps_restore(priv); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
138 | { | ||
139 | struct ath9k_vif_iter_data *iter_data = data; | ||
140 | int i; | ||
141 | |||
142 | for (i = 0; i < ETH_ALEN; i++) | ||
143 | iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); | ||
144 | } | ||
145 | |||
146 | static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, | ||
147 | struct ieee80211_vif *vif) | ||
148 | { | ||
149 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
150 | struct ath9k_vif_iter_data iter_data; | ||
151 | |||
152 | /* | ||
153 | * Use the hardware MAC address as reference, the hardware uses it | ||
154 | * together with the BSSID mask when matching addresses. | ||
155 | */ | ||
156 | iter_data.hw_macaddr = common->macaddr; | ||
157 | memset(&iter_data.mask, 0xff, ETH_ALEN); | ||
158 | |||
159 | if (vif) | ||
160 | ath9k_htc_bssid_iter(&iter_data, vif->addr, vif); | ||
161 | |||
162 | /* Get list of all active MAC addresses */ | ||
163 | ieee80211_iterate_active_interfaces_atomic(priv->hw, ath9k_htc_bssid_iter, | ||
164 | &iter_data); | ||
165 | |||
166 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); | ||
167 | ath_hw_setbssidmask(common); | ||
168 | } | ||
169 | |||
170 | static void ath9k_htc_set_opmode(struct ath9k_htc_priv *priv) | ||
171 | { | ||
172 | if (priv->num_ibss_vif) | ||
173 | priv->ah->opmode = NL80211_IFTYPE_ADHOC; | ||
174 | else if (priv->num_ap_vif) | ||
175 | priv->ah->opmode = NL80211_IFTYPE_AP; | ||
176 | else | ||
177 | priv->ah->opmode = NL80211_IFTYPE_STATION; | ||
178 | |||
179 | ath9k_hw_setopmode(priv->ah); | ||
180 | } | ||
181 | |||
182 | void ath9k_htc_reset(struct ath9k_htc_priv *priv) | ||
183 | { | ||
184 | struct ath_hw *ah = priv->ah; | ||
185 | struct ath_common *common = ath9k_hw_common(ah); | ||
186 | struct ieee80211_channel *channel = priv->hw->conf.channel; | ||
187 | struct ath9k_hw_cal_data *caldata = NULL; | ||
188 | enum htc_phymode mode; | ||
189 | __be16 htc_mode; | ||
190 | u8 cmd_rsp; | ||
191 | int ret; | ||
192 | |||
193 | mutex_lock(&priv->mutex); | ||
194 | ath9k_htc_ps_wakeup(priv); | ||
195 | |||
196 | ath9k_htc_stop_ani(priv); | ||
197 | ieee80211_stop_queues(priv->hw); | ||
198 | |||
199 | del_timer_sync(&priv->tx.cleanup_timer); | ||
200 | ath9k_htc_tx_drain(priv); | ||
201 | |||
202 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
203 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | ||
204 | WMI_CMD(WMI_STOP_RECV_CMDID); | ||
205 | |||
206 | ath9k_wmi_event_drain(priv); | ||
207 | |||
208 | caldata = &priv->caldata; | ||
209 | ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); | ||
210 | if (ret) { | ||
211 | ath_err(common, | ||
212 | "Unable to reset device (%u Mhz) reset status %d\n", | ||
213 | channel->center_freq, ret); | ||
214 | } | ||
215 | |||
216 | ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, | ||
217 | &priv->curtxpow); | ||
218 | |||
219 | WMI_CMD(WMI_START_RECV_CMDID); | ||
220 | ath9k_host_rx_init(priv); | ||
221 | |||
222 | mode = ath9k_htc_get_curmode(priv, ah->curchan); | ||
223 | htc_mode = cpu_to_be16(mode); | ||
224 | WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); | ||
225 | |||
226 | WMI_CMD(WMI_ENABLE_INTR_CMDID); | ||
227 | htc_start(priv->htc); | ||
228 | ath9k_htc_vif_reconfig(priv); | ||
229 | ieee80211_wake_queues(priv->hw); | ||
230 | |||
231 | mod_timer(&priv->tx.cleanup_timer, | ||
232 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
233 | |||
234 | ath9k_htc_ps_restore(priv); | ||
235 | mutex_unlock(&priv->mutex); | ||
236 | } | ||
237 | |||
119 | static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | 238 | static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, |
120 | struct ieee80211_hw *hw, | 239 | struct ieee80211_hw *hw, |
121 | struct ath9k_channel *hchan) | 240 | struct ath9k_channel *hchan) |
@@ -123,9 +242,9 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
123 | struct ath_hw *ah = priv->ah; | 242 | struct ath_hw *ah = priv->ah; |
124 | struct ath_common *common = ath9k_hw_common(ah); | 243 | struct ath_common *common = ath9k_hw_common(ah); |
125 | struct ieee80211_conf *conf = &common->hw->conf; | 244 | struct ieee80211_conf *conf = &common->hw->conf; |
126 | bool fastcc = true; | 245 | bool fastcc; |
127 | struct ieee80211_channel *channel = hw->conf.channel; | 246 | struct ieee80211_channel *channel = hw->conf.channel; |
128 | struct ath9k_hw_cal_data *caldata; | 247 | struct ath9k_hw_cal_data *caldata = NULL; |
129 | enum htc_phymode mode; | 248 | enum htc_phymode mode; |
130 | __be16 htc_mode; | 249 | __be16 htc_mode; |
131 | u8 cmd_rsp; | 250 | u8 cmd_rsp; |
@@ -134,32 +253,38 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
134 | if (priv->op_flags & OP_INVALID) | 253 | if (priv->op_flags & OP_INVALID) |
135 | return -EIO; | 254 | return -EIO; |
136 | 255 | ||
137 | if (priv->op_flags & OP_FULL_RESET) | 256 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); |
138 | fastcc = false; | ||
139 | 257 | ||
140 | /* Fiddle around with fastcc later on, for now just use full reset */ | ||
141 | fastcc = false; | ||
142 | ath9k_htc_ps_wakeup(priv); | 258 | ath9k_htc_ps_wakeup(priv); |
143 | htc_stop(priv->htc); | 259 | |
260 | del_timer_sync(&priv->tx.cleanup_timer); | ||
261 | ath9k_htc_tx_drain(priv); | ||
262 | |||
144 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 263 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
145 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 264 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
146 | WMI_CMD(WMI_STOP_RECV_CMDID); | 265 | WMI_CMD(WMI_STOP_RECV_CMDID); |
147 | 266 | ||
148 | ath_print(common, ATH_DBG_CONFIG, | 267 | ath9k_wmi_event_drain(priv); |
149 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d\n", | 268 | |
150 | priv->ah->curchan->channel, | 269 | ath_dbg(common, ATH_DBG_CONFIG, |
151 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); | 270 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", |
271 | priv->ah->curchan->channel, | ||
272 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), | ||
273 | fastcc); | ||
274 | |||
275 | if (!fastcc) | ||
276 | caldata = &priv->caldata; | ||
152 | 277 | ||
153 | caldata = &priv->caldata[channel->hw_value]; | ||
154 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); | 278 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
155 | if (ret) { | 279 | if (ret) { |
156 | ath_print(common, ATH_DBG_FATAL, | 280 | ath_err(common, |
157 | "Unable to reset channel (%u Mhz) " | 281 | "Unable to reset channel (%u Mhz) reset status %d\n", |
158 | "reset status %d\n", channel->center_freq, ret); | 282 | channel->center_freq, ret); |
159 | goto err; | 283 | goto err; |
160 | } | 284 | } |
161 | 285 | ||
162 | ath_update_txpow(priv); | 286 | ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, |
287 | &priv->curtxpow); | ||
163 | 288 | ||
164 | WMI_CMD(WMI_START_RECV_CMDID); | 289 | WMI_CMD(WMI_START_RECV_CMDID); |
165 | if (ret) | 290 | if (ret) |
@@ -179,51 +304,159 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
179 | 304 | ||
180 | htc_start(priv->htc); | 305 | htc_start(priv->htc); |
181 | 306 | ||
182 | priv->op_flags &= ~OP_FULL_RESET; | 307 | if (!(priv->op_flags & OP_SCANNING) && |
308 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | ||
309 | ath9k_htc_vif_reconfig(priv); | ||
310 | |||
311 | mod_timer(&priv->tx.cleanup_timer, | ||
312 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
313 | |||
183 | err: | 314 | err: |
184 | ath9k_htc_ps_restore(priv); | 315 | ath9k_htc_ps_restore(priv); |
185 | return ret; | 316 | return ret; |
186 | } | 317 | } |
187 | 318 | ||
188 | static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | 319 | /* |
320 | * Monitor mode handling is a tad complicated because the firmware requires | ||
321 | * an interface to be created exclusively, while mac80211 doesn't associate | ||
322 | * an interface with the mode. | ||
323 | * | ||
324 | * So, for now, only one monitor interface can be configured. | ||
325 | */ | ||
326 | static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | ||
189 | { | 327 | { |
190 | struct ath_common *common = ath9k_hw_common(priv->ah); | 328 | struct ath_common *common = ath9k_hw_common(priv->ah); |
191 | struct ath9k_htc_target_vif hvif; | 329 | struct ath9k_htc_target_vif hvif; |
192 | int ret = 0; | 330 | int ret = 0; |
193 | u8 cmd_rsp; | 331 | u8 cmd_rsp; |
194 | 332 | ||
195 | if (priv->nvifs > 0) | 333 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
196 | return -ENOBUFS; | 334 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
335 | hvif.index = priv->mon_vif_idx; | ||
336 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | ||
337 | if (ret) { | ||
338 | ath_err(common, "Unable to remove monitor interface at idx: %d\n", | ||
339 | priv->mon_vif_idx); | ||
340 | } | ||
197 | 341 | ||
342 | priv->nvifs--; | ||
343 | priv->vif_slot &= ~(1 << priv->mon_vif_idx); | ||
344 | } | ||
345 | |||
346 | static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | ||
347 | { | ||
348 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
349 | struct ath9k_htc_target_vif hvif; | ||
350 | struct ath9k_htc_target_sta tsta; | ||
351 | int ret = 0, sta_idx; | ||
352 | u8 cmd_rsp; | ||
353 | |||
354 | if ((priv->nvifs >= ATH9K_HTC_MAX_VIF) || | ||
355 | (priv->nstations >= ATH9K_HTC_MAX_STA)) { | ||
356 | ret = -ENOBUFS; | ||
357 | goto err_vif; | ||
358 | } | ||
359 | |||
360 | sta_idx = ffz(priv->sta_slot); | ||
361 | if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) { | ||
362 | ret = -ENOBUFS; | ||
363 | goto err_vif; | ||
364 | } | ||
365 | |||
366 | /* | ||
367 | * Add an interface. | ||
368 | */ | ||
198 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | 369 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
199 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | 370 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
200 | 371 | ||
201 | hvif.opmode = cpu_to_be32(HTC_M_MONITOR); | 372 | hvif.opmode = HTC_M_MONITOR; |
202 | priv->ah->opmode = NL80211_IFTYPE_MONITOR; | 373 | hvif.index = ffz(priv->vif_slot); |
203 | hvif.index = priv->nvifs; | ||
204 | 374 | ||
205 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); | 375 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); |
206 | if (ret) | 376 | if (ret) |
207 | return ret; | 377 | goto err_vif; |
378 | |||
379 | /* | ||
380 | * Assign the monitor interface index as a special case here. | ||
381 | * This is needed when the interface is brought down. | ||
382 | */ | ||
383 | priv->mon_vif_idx = hvif.index; | ||
384 | priv->vif_slot |= (1 << hvif.index); | ||
385 | |||
386 | /* | ||
387 | * Set the hardware mode to monitor only if there are no | ||
388 | * other interfaces. | ||
389 | */ | ||
390 | if (!priv->nvifs) | ||
391 | priv->ah->opmode = NL80211_IFTYPE_MONITOR; | ||
208 | 392 | ||
209 | priv->nvifs++; | 393 | priv->nvifs++; |
394 | |||
395 | /* | ||
396 | * Associate a station with the interface for packet injection. | ||
397 | */ | ||
398 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); | ||
399 | |||
400 | memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN); | ||
401 | |||
402 | tsta.is_vif_sta = 1; | ||
403 | tsta.sta_index = sta_idx; | ||
404 | tsta.vif_index = hvif.index; | ||
405 | tsta.maxampdu = cpu_to_be16(0xffff); | ||
406 | |||
407 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); | ||
408 | if (ret) { | ||
409 | ath_err(common, "Unable to add station entry for monitor mode\n"); | ||
410 | goto err_sta; | ||
411 | } | ||
412 | |||
413 | priv->sta_slot |= (1 << sta_idx); | ||
414 | priv->nstations++; | ||
415 | priv->vif_sta_pos[priv->mon_vif_idx] = sta_idx; | ||
416 | priv->ah->is_monitoring = true; | ||
417 | |||
418 | ath_dbg(common, ATH_DBG_CONFIG, | ||
419 | "Attached a monitor interface at idx: %d, sta idx: %d\n", | ||
420 | priv->mon_vif_idx, sta_idx); | ||
421 | |||
210 | return 0; | 422 | return 0; |
423 | |||
424 | err_sta: | ||
425 | /* | ||
426 | * Remove the interface from the target. | ||
427 | */ | ||
428 | __ath9k_htc_remove_monitor_interface(priv); | ||
429 | err_vif: | ||
430 | ath_dbg(common, ATH_DBG_FATAL, "Unable to attach a monitor interface\n"); | ||
431 | |||
432 | return ret; | ||
211 | } | 433 | } |
212 | 434 | ||
213 | static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | 435 | static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) |
214 | { | 436 | { |
215 | struct ath_common *common = ath9k_hw_common(priv->ah); | 437 | struct ath_common *common = ath9k_hw_common(priv->ah); |
216 | struct ath9k_htc_target_vif hvif; | ||
217 | int ret = 0; | 438 | int ret = 0; |
218 | u8 cmd_rsp; | 439 | u8 cmd_rsp, sta_idx; |
219 | 440 | ||
220 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | 441 | __ath9k_htc_remove_monitor_interface(priv); |
221 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | ||
222 | hvif.index = 0; /* Should do for now */ | ||
223 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | ||
224 | priv->nvifs--; | ||
225 | 442 | ||
226 | return ret; | 443 | sta_idx = priv->vif_sta_pos[priv->mon_vif_idx]; |
444 | |||
445 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); | ||
446 | if (ret) { | ||
447 | ath_err(common, "Unable to remove station entry for monitor mode\n"); | ||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | priv->sta_slot &= ~(1 << sta_idx); | ||
452 | priv->nstations--; | ||
453 | priv->ah->is_monitoring = false; | ||
454 | |||
455 | ath_dbg(common, ATH_DBG_CONFIG, | ||
456 | "Removed a monitor interface at idx: %d, sta idx: %d\n", | ||
457 | priv->mon_vif_idx, sta_idx); | ||
458 | |||
459 | return 0; | ||
227 | } | 460 | } |
228 | 461 | ||
229 | static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | 462 | static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, |
@@ -234,47 +467,65 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
234 | struct ath9k_htc_target_sta tsta; | 467 | struct ath9k_htc_target_sta tsta; |
235 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | 468 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; |
236 | struct ath9k_htc_sta *ista; | 469 | struct ath9k_htc_sta *ista; |
237 | int ret; | 470 | int ret, sta_idx; |
238 | u8 cmd_rsp; | 471 | u8 cmd_rsp; |
472 | u16 maxampdu; | ||
239 | 473 | ||
240 | if (priv->nstations >= ATH9K_HTC_MAX_STA) | 474 | if (priv->nstations >= ATH9K_HTC_MAX_STA) |
241 | return -ENOBUFS; | 475 | return -ENOBUFS; |
242 | 476 | ||
477 | sta_idx = ffz(priv->sta_slot); | ||
478 | if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) | ||
479 | return -ENOBUFS; | ||
480 | |||
243 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); | 481 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); |
244 | 482 | ||
245 | if (sta) { | 483 | if (sta) { |
246 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 484 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
247 | memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); | 485 | memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); |
248 | memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); | 486 | memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); |
249 | tsta.associd = common->curaid; | ||
250 | tsta.is_vif_sta = 0; | 487 | tsta.is_vif_sta = 0; |
251 | tsta.valid = true; | 488 | ista->index = sta_idx; |
252 | ista->index = priv->nstations; | ||
253 | } else { | 489 | } else { |
254 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); | 490 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); |
255 | tsta.is_vif_sta = 1; | 491 | tsta.is_vif_sta = 1; |
256 | } | 492 | } |
257 | 493 | ||
258 | tsta.sta_index = priv->nstations; | 494 | tsta.sta_index = sta_idx; |
259 | tsta.vif_index = avp->index; | 495 | tsta.vif_index = avp->index; |
260 | tsta.maxampdu = 0xffff; | 496 | |
261 | if (sta && sta->ht_cap.ht_supported) | 497 | if (!sta) { |
262 | tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); | 498 | tsta.maxampdu = cpu_to_be16(0xffff); |
499 | } else { | ||
500 | maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | ||
501 | sta->ht_cap.ampdu_factor); | ||
502 | tsta.maxampdu = cpu_to_be16(maxampdu); | ||
503 | } | ||
263 | 504 | ||
264 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); | 505 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); |
265 | if (ret) { | 506 | if (ret) { |
266 | if (sta) | 507 | if (sta) |
267 | ath_print(common, ATH_DBG_FATAL, | 508 | ath_err(common, |
268 | "Unable to add station entry for: %pM\n", sta->addr); | 509 | "Unable to add station entry for: %pM\n", |
510 | sta->addr); | ||
269 | return ret; | 511 | return ret; |
270 | } | 512 | } |
271 | 513 | ||
272 | if (sta) | 514 | if (sta) { |
273 | ath_print(common, ATH_DBG_CONFIG, | 515 | ath_dbg(common, ATH_DBG_CONFIG, |
274 | "Added a station entry for: %pM (idx: %d)\n", | 516 | "Added a station entry for: %pM (idx: %d)\n", |
275 | sta->addr, tsta.sta_index); | 517 | sta->addr, tsta.sta_index); |
518 | } else { | ||
519 | ath_dbg(common, ATH_DBG_CONFIG, | ||
520 | "Added a station entry for VIF %d (idx: %d)\n", | ||
521 | avp->index, tsta.sta_index); | ||
522 | } | ||
276 | 523 | ||
524 | priv->sta_slot |= (1 << sta_idx); | ||
277 | priv->nstations++; | 525 | priv->nstations++; |
526 | if (!sta) | ||
527 | priv->vif_sta_pos[avp->index] = sta_idx; | ||
528 | |||
278 | return 0; | 529 | return 0; |
279 | } | 530 | } |
280 | 531 | ||
@@ -283,6 +534,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, | |||
283 | struct ieee80211_sta *sta) | 534 | struct ieee80211_sta *sta) |
284 | { | 535 | { |
285 | struct ath_common *common = ath9k_hw_common(priv->ah); | 536 | struct ath_common *common = ath9k_hw_common(priv->ah); |
537 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | ||
286 | struct ath9k_htc_sta *ista; | 538 | struct ath9k_htc_sta *ista; |
287 | int ret; | 539 | int ret; |
288 | u8 cmd_rsp, sta_idx; | 540 | u8 cmd_rsp, sta_idx; |
@@ -291,28 +543,36 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, | |||
291 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 543 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
292 | sta_idx = ista->index; | 544 | sta_idx = ista->index; |
293 | } else { | 545 | } else { |
294 | sta_idx = 0; | 546 | sta_idx = priv->vif_sta_pos[avp->index]; |
295 | } | 547 | } |
296 | 548 | ||
297 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); | 549 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); |
298 | if (ret) { | 550 | if (ret) { |
299 | if (sta) | 551 | if (sta) |
300 | ath_print(common, ATH_DBG_FATAL, | 552 | ath_err(common, |
301 | "Unable to remove station entry for: %pM\n", | 553 | "Unable to remove station entry for: %pM\n", |
302 | sta->addr); | 554 | sta->addr); |
303 | return ret; | 555 | return ret; |
304 | } | 556 | } |
305 | 557 | ||
306 | if (sta) | 558 | if (sta) { |
307 | ath_print(common, ATH_DBG_CONFIG, | 559 | ath_dbg(common, ATH_DBG_CONFIG, |
308 | "Removed a station entry for: %pM (idx: %d)\n", | 560 | "Removed a station entry for: %pM (idx: %d)\n", |
309 | sta->addr, sta_idx); | 561 | sta->addr, sta_idx); |
562 | } else { | ||
563 | ath_dbg(common, ATH_DBG_CONFIG, | ||
564 | "Removed a station entry for VIF %d (idx: %d)\n", | ||
565 | avp->index, sta_idx); | ||
566 | } | ||
310 | 567 | ||
568 | priv->sta_slot &= ~(1 << sta_idx); | ||
311 | priv->nstations--; | 569 | priv->nstations--; |
570 | |||
312 | return 0; | 571 | return 0; |
313 | } | 572 | } |
314 | 573 | ||
315 | static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) | 574 | int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, |
575 | u8 enable_coex) | ||
316 | { | 576 | { |
317 | struct ath9k_htc_cap_target tcap; | 577 | struct ath9k_htc_cap_target tcap; |
318 | int ret; | 578 | int ret; |
@@ -320,13 +580,9 @@ static int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) | |||
320 | 580 | ||
321 | memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); | 581 | memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); |
322 | 582 | ||
323 | /* FIXME: Values are hardcoded */ | 583 | tcap.ampdu_limit = cpu_to_be32(0xffff); |
324 | tcap.flags = 0x240c40; | 584 | tcap.ampdu_subframes = 0xff; |
325 | tcap.flags_ext = 0x80601000; | 585 | tcap.enable_coex = enable_coex; |
326 | tcap.ampdu_limit = 0xffff0000; | ||
327 | tcap.ampdu_subframes = 20; | ||
328 | tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask; | ||
329 | tcap.protmode = 1; | ||
330 | tcap.tx_chainmask = priv->ah->caps.tx_chainmask; | 586 | tcap.tx_chainmask = priv->ah->caps.tx_chainmask; |
331 | 587 | ||
332 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); | 588 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); |
@@ -391,8 +647,8 @@ static int ath9k_htc_send_rate_cmd(struct ath9k_htc_priv *priv, | |||
391 | 647 | ||
392 | WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate); | 648 | WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, trate); |
393 | if (ret) { | 649 | if (ret) { |
394 | ath_print(common, ATH_DBG_FATAL, | 650 | ath_err(common, |
395 | "Unable to initialize Rate information on target\n"); | 651 | "Unable to initialize Rate information on target\n"); |
396 | } | 652 | } |
397 | 653 | ||
398 | return ret; | 654 | return ret; |
@@ -409,9 +665,9 @@ static void ath9k_htc_init_rate(struct ath9k_htc_priv *priv, | |||
409 | ath9k_htc_setup_rate(priv, sta, &trate); | 665 | ath9k_htc_setup_rate(priv, sta, &trate); |
410 | ret = ath9k_htc_send_rate_cmd(priv, &trate); | 666 | ret = ath9k_htc_send_rate_cmd(priv, &trate); |
411 | if (!ret) | 667 | if (!ret) |
412 | ath_print(common, ATH_DBG_CONFIG, | 668 | ath_dbg(common, ATH_DBG_CONFIG, |
413 | "Updated target sta: %pM, rate caps: 0x%X\n", | 669 | "Updated target sta: %pM, rate caps: 0x%X\n", |
414 | sta->addr, be32_to_cpu(trate.capflags)); | 670 | sta->addr, be32_to_cpu(trate.capflags)); |
415 | } | 671 | } |
416 | 672 | ||
417 | static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, | 673 | static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, |
@@ -436,9 +692,9 @@ static void ath9k_htc_update_rate(struct ath9k_htc_priv *priv, | |||
436 | 692 | ||
437 | ret = ath9k_htc_send_rate_cmd(priv, &trate); | 693 | ret = ath9k_htc_send_rate_cmd(priv, &trate); |
438 | if (!ret) | 694 | if (!ret) |
439 | ath_print(common, ATH_DBG_CONFIG, | 695 | ath_dbg(common, ATH_DBG_CONFIG, |
440 | "Updated target sta: %pM, rate caps: 0x%X\n", | 696 | "Updated target sta: %pM, rate caps: 0x%X\n", |
441 | bss_conf->bssid, be32_to_cpu(trate.capflags)); | 697 | bss_conf->bssid, be32_to_cpu(trate.capflags)); |
442 | } | 698 | } |
443 | 699 | ||
444 | static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, | 700 | static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, |
@@ -465,229 +721,27 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, | |||
465 | 721 | ||
466 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); | 722 | WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); |
467 | if (ret) | 723 | if (ret) |
468 | ath_print(common, ATH_DBG_CONFIG, | 724 | ath_dbg(common, ATH_DBG_CONFIG, |
469 | "Unable to %s TX aggregation for (%pM, %d)\n", | 725 | "Unable to %s TX aggregation for (%pM, %d)\n", |
470 | (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid); | 726 | (aggr.aggr_enable) ? "start" : "stop", sta->addr, tid); |
471 | else | 727 | else |
472 | ath_print(common, ATH_DBG_CONFIG, | 728 | ath_dbg(common, ATH_DBG_CONFIG, |
473 | "%s TX aggregation for (%pM, %d)\n", | 729 | "%s TX aggregation for (%pM, %d)\n", |
474 | (aggr.aggr_enable) ? "Starting" : "Stopping", | 730 | (aggr.aggr_enable) ? "Starting" : "Stopping", |
475 | sta->addr, tid); | 731 | sta->addr, tid); |
476 | 732 | ||
477 | spin_lock_bh(&priv->tx_lock); | 733 | spin_lock_bh(&priv->tx.tx_lock); |
478 | ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; | 734 | ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; |
479 | spin_unlock_bh(&priv->tx_lock); | 735 | spin_unlock_bh(&priv->tx.tx_lock); |
480 | 736 | ||
481 | return ret; | 737 | return ret; |
482 | } | 738 | } |
483 | 739 | ||
484 | /*********/ | ||
485 | /* DEBUG */ | ||
486 | /*********/ | ||
487 | |||
488 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
489 | |||
490 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | ||
491 | { | ||
492 | file->private_data = inode->i_private; | ||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, | ||
497 | size_t count, loff_t *ppos) | ||
498 | { | ||
499 | struct ath9k_htc_priv *priv = file->private_data; | ||
500 | struct ath9k_htc_target_stats cmd_rsp; | ||
501 | char buf[512]; | ||
502 | unsigned int len = 0; | ||
503 | int ret = 0; | ||
504 | |||
505 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
506 | |||
507 | WMI_CMD(WMI_TGT_STATS_CMDID); | ||
508 | if (ret) | ||
509 | return -EINVAL; | ||
510 | |||
511 | |||
512 | len += snprintf(buf + len, sizeof(buf) - len, | ||
513 | "%19s : %10u\n", "TX Short Retries", | ||
514 | be32_to_cpu(cmd_rsp.tx_shortretry)); | ||
515 | len += snprintf(buf + len, sizeof(buf) - len, | ||
516 | "%19s : %10u\n", "TX Long Retries", | ||
517 | be32_to_cpu(cmd_rsp.tx_longretry)); | ||
518 | len += snprintf(buf + len, sizeof(buf) - len, | ||
519 | "%19s : %10u\n", "TX Xretries", | ||
520 | be32_to_cpu(cmd_rsp.tx_xretries)); | ||
521 | len += snprintf(buf + len, sizeof(buf) - len, | ||
522 | "%19s : %10u\n", "TX Unaggr. Xretries", | ||
523 | be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); | ||
524 | len += snprintf(buf + len, sizeof(buf) - len, | ||
525 | "%19s : %10u\n", "TX Xretries (HT)", | ||
526 | be32_to_cpu(cmd_rsp.ht_tx_xretries)); | ||
527 | len += snprintf(buf + len, sizeof(buf) - len, | ||
528 | "%19s : %10u\n", "TX Rate", priv->debug.txrate); | ||
529 | |||
530 | if (len > sizeof(buf)) | ||
531 | len = sizeof(buf); | ||
532 | |||
533 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
534 | } | ||
535 | |||
536 | static const struct file_operations fops_tgt_stats = { | ||
537 | .read = read_file_tgt_stats, | ||
538 | .open = ath9k_debugfs_open, | ||
539 | .owner = THIS_MODULE | ||
540 | }; | ||
541 | |||
542 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | ||
543 | size_t count, loff_t *ppos) | ||
544 | { | ||
545 | struct ath9k_htc_priv *priv = file->private_data; | ||
546 | char buf[512]; | ||
547 | unsigned int len = 0; | ||
548 | |||
549 | len += snprintf(buf + len, sizeof(buf) - len, | ||
550 | "%20s : %10u\n", "Buffers queued", | ||
551 | priv->debug.tx_stats.buf_queued); | ||
552 | len += snprintf(buf + len, sizeof(buf) - len, | ||
553 | "%20s : %10u\n", "Buffers completed", | ||
554 | priv->debug.tx_stats.buf_completed); | ||
555 | len += snprintf(buf + len, sizeof(buf) - len, | ||
556 | "%20s : %10u\n", "SKBs queued", | ||
557 | priv->debug.tx_stats.skb_queued); | ||
558 | len += snprintf(buf + len, sizeof(buf) - len, | ||
559 | "%20s : %10u\n", "SKBs completed", | ||
560 | priv->debug.tx_stats.skb_completed); | ||
561 | len += snprintf(buf + len, sizeof(buf) - len, | ||
562 | "%20s : %10u\n", "SKBs dropped", | ||
563 | priv->debug.tx_stats.skb_dropped); | ||
564 | |||
565 | len += snprintf(buf + len, sizeof(buf) - len, | ||
566 | "%20s : %10u\n", "BE queued", | ||
567 | priv->debug.tx_stats.queue_stats[WME_AC_BE]); | ||
568 | len += snprintf(buf + len, sizeof(buf) - len, | ||
569 | "%20s : %10u\n", "BK queued", | ||
570 | priv->debug.tx_stats.queue_stats[WME_AC_BK]); | ||
571 | len += snprintf(buf + len, sizeof(buf) - len, | ||
572 | "%20s : %10u\n", "VI queued", | ||
573 | priv->debug.tx_stats.queue_stats[WME_AC_VI]); | ||
574 | len += snprintf(buf + len, sizeof(buf) - len, | ||
575 | "%20s : %10u\n", "VO queued", | ||
576 | priv->debug.tx_stats.queue_stats[WME_AC_VO]); | ||
577 | |||
578 | if (len > sizeof(buf)) | ||
579 | len = sizeof(buf); | ||
580 | |||
581 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
582 | } | ||
583 | |||
584 | static const struct file_operations fops_xmit = { | ||
585 | .read = read_file_xmit, | ||
586 | .open = ath9k_debugfs_open, | ||
587 | .owner = THIS_MODULE | ||
588 | }; | ||
589 | |||
590 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
591 | size_t count, loff_t *ppos) | ||
592 | { | ||
593 | struct ath9k_htc_priv *priv = file->private_data; | ||
594 | char buf[512]; | ||
595 | unsigned int len = 0; | ||
596 | |||
597 | len += snprintf(buf + len, sizeof(buf) - len, | ||
598 | "%20s : %10u\n", "SKBs allocated", | ||
599 | priv->debug.rx_stats.skb_allocated); | ||
600 | len += snprintf(buf + len, sizeof(buf) - len, | ||
601 | "%20s : %10u\n", "SKBs completed", | ||
602 | priv->debug.rx_stats.skb_completed); | ||
603 | len += snprintf(buf + len, sizeof(buf) - len, | ||
604 | "%20s : %10u\n", "SKBs Dropped", | ||
605 | priv->debug.rx_stats.skb_dropped); | ||
606 | |||
607 | if (len > sizeof(buf)) | ||
608 | len = sizeof(buf); | ||
609 | |||
610 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
611 | } | ||
612 | |||
613 | static const struct file_operations fops_recv = { | ||
614 | .read = read_file_recv, | ||
615 | .open = ath9k_debugfs_open, | ||
616 | .owner = THIS_MODULE | ||
617 | }; | ||
618 | |||
619 | int ath9k_htc_init_debug(struct ath_hw *ah) | ||
620 | { | ||
621 | struct ath_common *common = ath9k_hw_common(ah); | ||
622 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
623 | |||
624 | if (!ath9k_debugfs_root) | ||
625 | return -ENOENT; | ||
626 | |||
627 | priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), | ||
628 | ath9k_debugfs_root); | ||
629 | if (!priv->debug.debugfs_phy) | ||
630 | goto err; | ||
631 | |||
632 | priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, | ||
633 | priv->debug.debugfs_phy, | ||
634 | priv, &fops_tgt_stats); | ||
635 | if (!priv->debug.debugfs_tgt_stats) | ||
636 | goto err; | ||
637 | |||
638 | |||
639 | priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, | ||
640 | priv->debug.debugfs_phy, | ||
641 | priv, &fops_xmit); | ||
642 | if (!priv->debug.debugfs_xmit) | ||
643 | goto err; | ||
644 | |||
645 | priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, | ||
646 | priv->debug.debugfs_phy, | ||
647 | priv, &fops_recv); | ||
648 | if (!priv->debug.debugfs_recv) | ||
649 | goto err; | ||
650 | |||
651 | return 0; | ||
652 | |||
653 | err: | ||
654 | ath9k_htc_exit_debug(ah); | ||
655 | return -ENOMEM; | ||
656 | } | ||
657 | |||
658 | void ath9k_htc_exit_debug(struct ath_hw *ah) | ||
659 | { | ||
660 | struct ath_common *common = ath9k_hw_common(ah); | ||
661 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
662 | |||
663 | debugfs_remove(priv->debug.debugfs_recv); | ||
664 | debugfs_remove(priv->debug.debugfs_xmit); | ||
665 | debugfs_remove(priv->debug.debugfs_tgt_stats); | ||
666 | debugfs_remove(priv->debug.debugfs_phy); | ||
667 | } | ||
668 | |||
669 | int ath9k_htc_debug_create_root(void) | ||
670 | { | ||
671 | ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
672 | if (!ath9k_debugfs_root) | ||
673 | return -ENOENT; | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | void ath9k_htc_debug_remove_root(void) | ||
679 | { | ||
680 | debugfs_remove(ath9k_debugfs_root); | ||
681 | ath9k_debugfs_root = NULL; | ||
682 | } | ||
683 | |||
684 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | ||
685 | |||
686 | /*******/ | 740 | /*******/ |
687 | /* ANI */ | 741 | /* ANI */ |
688 | /*******/ | 742 | /*******/ |
689 | 743 | ||
690 | static void ath_start_ani(struct ath9k_htc_priv *priv) | 744 | void ath9k_htc_start_ani(struct ath9k_htc_priv *priv) |
691 | { | 745 | { |
692 | struct ath_common *common = ath9k_hw_common(priv->ah); | 746 | struct ath_common *common = ath9k_hw_common(priv->ah); |
693 | unsigned long timestamp = jiffies_to_msecs(jiffies); | 747 | unsigned long timestamp = jiffies_to_msecs(jiffies); |
@@ -696,15 +750,22 @@ static void ath_start_ani(struct ath9k_htc_priv *priv) | |||
696 | common->ani.shortcal_timer = timestamp; | 750 | common->ani.shortcal_timer = timestamp; |
697 | common->ani.checkani_timer = timestamp; | 751 | common->ani.checkani_timer = timestamp; |
698 | 752 | ||
699 | ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, | 753 | priv->op_flags |= OP_ANI_RUNNING; |
754 | |||
755 | ieee80211_queue_delayed_work(common->hw, &priv->ani_work, | ||
700 | msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 756 | msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); |
701 | } | 757 | } |
702 | 758 | ||
703 | void ath9k_ani_work(struct work_struct *work) | 759 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv) |
760 | { | ||
761 | cancel_delayed_work_sync(&priv->ani_work); | ||
762 | priv->op_flags &= ~OP_ANI_RUNNING; | ||
763 | } | ||
764 | |||
765 | void ath9k_htc_ani_work(struct work_struct *work) | ||
704 | { | 766 | { |
705 | struct ath9k_htc_priv *priv = | 767 | struct ath9k_htc_priv *priv = |
706 | container_of(work, struct ath9k_htc_priv, | 768 | container_of(work, struct ath9k_htc_priv, ani_work.work); |
707 | ath9k_ani_work.work); | ||
708 | struct ath_hw *ah = priv->ah; | 769 | struct ath_hw *ah = priv->ah; |
709 | struct ath_common *common = ath9k_hw_common(ah); | 770 | struct ath_common *common = ath9k_hw_common(ah); |
710 | bool longcal = false; | 771 | bool longcal = false; |
@@ -713,7 +774,8 @@ void ath9k_ani_work(struct work_struct *work) | |||
713 | unsigned int timestamp = jiffies_to_msecs(jiffies); | 774 | unsigned int timestamp = jiffies_to_msecs(jiffies); |
714 | u32 cal_interval, short_cal_interval; | 775 | u32 cal_interval, short_cal_interval; |
715 | 776 | ||
716 | short_cal_interval = ATH_STA_SHORT_CALINTERVAL; | 777 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? |
778 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | ||
717 | 779 | ||
718 | /* Only calibrate if awake */ | 780 | /* Only calibrate if awake */ |
719 | if (ah->power_mode != ATH9K_PM_AWAKE) | 781 | if (ah->power_mode != ATH9K_PM_AWAKE) |
@@ -722,7 +784,7 @@ void ath9k_ani_work(struct work_struct *work) | |||
722 | /* Long calibration runs independently of short calibration. */ | 784 | /* Long calibration runs independently of short calibration. */ |
723 | if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { | 785 | if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { |
724 | longcal = true; | 786 | longcal = true; |
725 | ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); | 787 | ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); |
726 | common->ani.longcal_timer = timestamp; | 788 | common->ani.longcal_timer = timestamp; |
727 | } | 789 | } |
728 | 790 | ||
@@ -731,8 +793,8 @@ void ath9k_ani_work(struct work_struct *work) | |||
731 | if ((timestamp - common->ani.shortcal_timer) >= | 793 | if ((timestamp - common->ani.shortcal_timer) >= |
732 | short_cal_interval) { | 794 | short_cal_interval) { |
733 | shortcal = true; | 795 | shortcal = true; |
734 | ath_print(common, ATH_DBG_ANI, | 796 | ath_dbg(common, ATH_DBG_ANI, |
735 | "shortcal @%lu\n", jiffies); | 797 | "shortcal @%lu\n", jiffies); |
736 | common->ani.shortcal_timer = timestamp; | 798 | common->ani.shortcal_timer = timestamp; |
737 | common->ani.resetcal_timer = timestamp; | 799 | common->ani.resetcal_timer = timestamp; |
738 | } | 800 | } |
@@ -761,23 +823,12 @@ void ath9k_ani_work(struct work_struct *work) | |||
761 | ath9k_hw_ani_monitor(ah, ah->curchan); | 823 | ath9k_hw_ani_monitor(ah, ah->curchan); |
762 | 824 | ||
763 | /* Perform calibration if necessary */ | 825 | /* Perform calibration if necessary */ |
764 | if (longcal || shortcal) { | 826 | if (longcal || shortcal) |
765 | common->ani.caldone = | 827 | common->ani.caldone = |
766 | ath9k_hw_calibrate(ah, ah->curchan, | 828 | ath9k_hw_calibrate(ah, ah->curchan, |
767 | common->rx_chainmask, | 829 | common->rx_chainmask, |
768 | longcal); | 830 | longcal); |
769 | 831 | ||
770 | if (longcal) | ||
771 | common->ani.noise_floor = | ||
772 | ath9k_hw_getchan_noise(ah, ah->curchan); | ||
773 | |||
774 | ath_print(common, ATH_DBG_ANI, | ||
775 | " calibrate chan %u/%x nf: %d\n", | ||
776 | ah->curchan->channel, | ||
777 | ah->curchan->channelFlags, | ||
778 | common->ani.noise_floor); | ||
779 | } | ||
780 | |||
781 | ath9k_htc_ps_restore(priv); | 832 | ath9k_htc_ps_restore(priv); |
782 | } | 833 | } |
783 | 834 | ||
@@ -793,330 +844,20 @@ set_timer: | |||
793 | if (!common->ani.caldone) | 844 | if (!common->ani.caldone) |
794 | cal_interval = min(cal_interval, (u32)short_cal_interval); | 845 | cal_interval = min(cal_interval, (u32)short_cal_interval); |
795 | 846 | ||
796 | ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, | 847 | ieee80211_queue_delayed_work(common->hw, &priv->ani_work, |
797 | msecs_to_jiffies(cal_interval)); | 848 | msecs_to_jiffies(cal_interval)); |
798 | } | 849 | } |
799 | 850 | ||
800 | /*******/ | ||
801 | /* LED */ | ||
802 | /*******/ | ||
803 | |||
804 | static void ath9k_led_blink_work(struct work_struct *work) | ||
805 | { | ||
806 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | ||
807 | ath9k_led_blink_work.work); | ||
808 | |||
809 | if (!(priv->op_flags & OP_LED_ASSOCIATED)) | ||
810 | return; | ||
811 | |||
812 | if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) || | ||
813 | (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | ||
814 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); | ||
815 | else | ||
816 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, | ||
817 | (priv->op_flags & OP_LED_ON) ? 1 : 0); | ||
818 | |||
819 | ieee80211_queue_delayed_work(priv->hw, | ||
820 | &priv->ath9k_led_blink_work, | ||
821 | (priv->op_flags & OP_LED_ON) ? | ||
822 | msecs_to_jiffies(priv->led_off_duration) : | ||
823 | msecs_to_jiffies(priv->led_on_duration)); | ||
824 | |||
825 | priv->led_on_duration = priv->led_on_cnt ? | ||
826 | max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) : | ||
827 | ATH_LED_ON_DURATION_IDLE; | ||
828 | priv->led_off_duration = priv->led_off_cnt ? | ||
829 | max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) : | ||
830 | ATH_LED_OFF_DURATION_IDLE; | ||
831 | priv->led_on_cnt = priv->led_off_cnt = 0; | ||
832 | |||
833 | if (priv->op_flags & OP_LED_ON) | ||
834 | priv->op_flags &= ~OP_LED_ON; | ||
835 | else | ||
836 | priv->op_flags |= OP_LED_ON; | ||
837 | } | ||
838 | |||
839 | static void ath9k_led_brightness_work(struct work_struct *work) | ||
840 | { | ||
841 | struct ath_led *led = container_of(work, struct ath_led, | ||
842 | brightness_work.work); | ||
843 | struct ath9k_htc_priv *priv = led->priv; | ||
844 | |||
845 | switch (led->brightness) { | ||
846 | case LED_OFF: | ||
847 | if (led->led_type == ATH_LED_ASSOC || | ||
848 | led->led_type == ATH_LED_RADIO) { | ||
849 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, | ||
850 | (led->led_type == ATH_LED_RADIO)); | ||
851 | priv->op_flags &= ~OP_LED_ASSOCIATED; | ||
852 | if (led->led_type == ATH_LED_RADIO) | ||
853 | priv->op_flags &= ~OP_LED_ON; | ||
854 | } else { | ||
855 | priv->led_off_cnt++; | ||
856 | } | ||
857 | break; | ||
858 | case LED_FULL: | ||
859 | if (led->led_type == ATH_LED_ASSOC) { | ||
860 | priv->op_flags |= OP_LED_ASSOCIATED; | ||
861 | ieee80211_queue_delayed_work(priv->hw, | ||
862 | &priv->ath9k_led_blink_work, 0); | ||
863 | } else if (led->led_type == ATH_LED_RADIO) { | ||
864 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); | ||
865 | priv->op_flags |= OP_LED_ON; | ||
866 | } else { | ||
867 | priv->led_on_cnt++; | ||
868 | } | ||
869 | break; | ||
870 | default: | ||
871 | break; | ||
872 | } | ||
873 | } | ||
874 | |||
875 | static void ath9k_led_brightness(struct led_classdev *led_cdev, | ||
876 | enum led_brightness brightness) | ||
877 | { | ||
878 | struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); | ||
879 | struct ath9k_htc_priv *priv = led->priv; | ||
880 | |||
881 | led->brightness = brightness; | ||
882 | if (!(priv->op_flags & OP_LED_DEINIT)) | ||
883 | ieee80211_queue_delayed_work(priv->hw, | ||
884 | &led->brightness_work, 0); | ||
885 | } | ||
886 | |||
887 | static void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv) | ||
888 | { | ||
889 | cancel_delayed_work_sync(&priv->radio_led.brightness_work); | ||
890 | cancel_delayed_work_sync(&priv->assoc_led.brightness_work); | ||
891 | cancel_delayed_work_sync(&priv->tx_led.brightness_work); | ||
892 | cancel_delayed_work_sync(&priv->rx_led.brightness_work); | ||
893 | } | ||
894 | |||
895 | static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led, | ||
896 | char *trigger) | ||
897 | { | ||
898 | int ret; | ||
899 | |||
900 | led->priv = priv; | ||
901 | led->led_cdev.name = led->name; | ||
902 | led->led_cdev.default_trigger = trigger; | ||
903 | led->led_cdev.brightness_set = ath9k_led_brightness; | ||
904 | |||
905 | ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); | ||
906 | if (ret) | ||
907 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, | ||
908 | "Failed to register led:%s", led->name); | ||
909 | else | ||
910 | led->registered = 1; | ||
911 | |||
912 | INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work); | ||
913 | |||
914 | return ret; | ||
915 | } | ||
916 | |||
917 | static void ath9k_unregister_led(struct ath_led *led) | ||
918 | { | ||
919 | if (led->registered) { | ||
920 | led_classdev_unregister(&led->led_cdev); | ||
921 | led->registered = 0; | ||
922 | } | ||
923 | } | ||
924 | |||
925 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv) | ||
926 | { | ||
927 | priv->op_flags |= OP_LED_DEINIT; | ||
928 | ath9k_unregister_led(&priv->assoc_led); | ||
929 | priv->op_flags &= ~OP_LED_ASSOCIATED; | ||
930 | ath9k_unregister_led(&priv->tx_led); | ||
931 | ath9k_unregister_led(&priv->rx_led); | ||
932 | ath9k_unregister_led(&priv->radio_led); | ||
933 | } | ||
934 | |||
935 | void ath9k_init_leds(struct ath9k_htc_priv *priv) | ||
936 | { | ||
937 | char *trigger; | ||
938 | int ret; | ||
939 | |||
940 | if (AR_SREV_9287(priv->ah)) | ||
941 | priv->ah->led_pin = ATH_LED_PIN_9287; | ||
942 | else if (AR_SREV_9271(priv->ah)) | ||
943 | priv->ah->led_pin = ATH_LED_PIN_9271; | ||
944 | else if (AR_DEVID_7010(priv->ah)) | ||
945 | priv->ah->led_pin = ATH_LED_PIN_7010; | ||
946 | else | ||
947 | priv->ah->led_pin = ATH_LED_PIN_DEF; | ||
948 | |||
949 | /* Configure gpio 1 for output */ | ||
950 | ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, | ||
951 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
952 | /* LED off, active low */ | ||
953 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); | ||
954 | |||
955 | INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work); | ||
956 | |||
957 | trigger = ieee80211_get_radio_led_name(priv->hw); | ||
958 | snprintf(priv->radio_led.name, sizeof(priv->radio_led.name), | ||
959 | "ath9k-%s::radio", wiphy_name(priv->hw->wiphy)); | ||
960 | ret = ath9k_register_led(priv, &priv->radio_led, trigger); | ||
961 | priv->radio_led.led_type = ATH_LED_RADIO; | ||
962 | if (ret) | ||
963 | goto fail; | ||
964 | |||
965 | trigger = ieee80211_get_assoc_led_name(priv->hw); | ||
966 | snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name), | ||
967 | "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy)); | ||
968 | ret = ath9k_register_led(priv, &priv->assoc_led, trigger); | ||
969 | priv->assoc_led.led_type = ATH_LED_ASSOC; | ||
970 | if (ret) | ||
971 | goto fail; | ||
972 | |||
973 | trigger = ieee80211_get_tx_led_name(priv->hw); | ||
974 | snprintf(priv->tx_led.name, sizeof(priv->tx_led.name), | ||
975 | "ath9k-%s::tx", wiphy_name(priv->hw->wiphy)); | ||
976 | ret = ath9k_register_led(priv, &priv->tx_led, trigger); | ||
977 | priv->tx_led.led_type = ATH_LED_TX; | ||
978 | if (ret) | ||
979 | goto fail; | ||
980 | |||
981 | trigger = ieee80211_get_rx_led_name(priv->hw); | ||
982 | snprintf(priv->rx_led.name, sizeof(priv->rx_led.name), | ||
983 | "ath9k-%s::rx", wiphy_name(priv->hw->wiphy)); | ||
984 | ret = ath9k_register_led(priv, &priv->rx_led, trigger); | ||
985 | priv->rx_led.led_type = ATH_LED_RX; | ||
986 | if (ret) | ||
987 | goto fail; | ||
988 | |||
989 | priv->op_flags &= ~OP_LED_DEINIT; | ||
990 | |||
991 | return; | ||
992 | |||
993 | fail: | ||
994 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | ||
995 | ath9k_deinit_leds(priv); | ||
996 | } | ||
997 | |||
998 | /*******************/ | ||
999 | /* Rfkill */ | ||
1000 | /*******************/ | ||
1001 | |||
1002 | static bool ath_is_rfkill_set(struct ath9k_htc_priv *priv) | ||
1003 | { | ||
1004 | return ath9k_hw_gpio_get(priv->ah, priv->ah->rfkill_gpio) == | ||
1005 | priv->ah->rfkill_polarity; | ||
1006 | } | ||
1007 | |||
1008 | static void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw) | ||
1009 | { | ||
1010 | struct ath9k_htc_priv *priv = hw->priv; | ||
1011 | bool blocked = !!ath_is_rfkill_set(priv); | ||
1012 | |||
1013 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | ||
1014 | } | ||
1015 | |||
1016 | void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv) | ||
1017 | { | ||
1018 | if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
1019 | wiphy_rfkill_start_polling(priv->hw->wiphy); | ||
1020 | } | ||
1021 | |||
1022 | static void ath9k_htc_radio_enable(struct ieee80211_hw *hw) | ||
1023 | { | ||
1024 | struct ath9k_htc_priv *priv = hw->priv; | ||
1025 | struct ath_hw *ah = priv->ah; | ||
1026 | struct ath_common *common = ath9k_hw_common(ah); | ||
1027 | int ret; | ||
1028 | u8 cmd_rsp; | ||
1029 | |||
1030 | if (!ah->curchan) | ||
1031 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | ||
1032 | |||
1033 | /* Reset the HW */ | ||
1034 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | ||
1035 | if (ret) { | ||
1036 | ath_print(common, ATH_DBG_FATAL, | ||
1037 | "Unable to reset hardware; reset status %d " | ||
1038 | "(freq %u MHz)\n", ret, ah->curchan->channel); | ||
1039 | } | ||
1040 | |||
1041 | ath_update_txpow(priv); | ||
1042 | |||
1043 | /* Start RX */ | ||
1044 | WMI_CMD(WMI_START_RECV_CMDID); | ||
1045 | ath9k_host_rx_init(priv); | ||
1046 | |||
1047 | /* Start TX */ | ||
1048 | htc_start(priv->htc); | ||
1049 | spin_lock_bh(&priv->tx_lock); | ||
1050 | priv->tx_queues_stop = false; | ||
1051 | spin_unlock_bh(&priv->tx_lock); | ||
1052 | ieee80211_wake_queues(hw); | ||
1053 | |||
1054 | WMI_CMD(WMI_ENABLE_INTR_CMDID); | ||
1055 | |||
1056 | /* Enable LED */ | ||
1057 | ath9k_hw_cfg_output(ah, ah->led_pin, | ||
1058 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
1059 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | ||
1060 | } | ||
1061 | |||
1062 | static void ath9k_htc_radio_disable(struct ieee80211_hw *hw) | ||
1063 | { | ||
1064 | struct ath9k_htc_priv *priv = hw->priv; | ||
1065 | struct ath_hw *ah = priv->ah; | ||
1066 | struct ath_common *common = ath9k_hw_common(ah); | ||
1067 | int ret; | ||
1068 | u8 cmd_rsp; | ||
1069 | |||
1070 | ath9k_htc_ps_wakeup(priv); | ||
1071 | |||
1072 | /* Disable LED */ | ||
1073 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | ||
1074 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | ||
1075 | |||
1076 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
1077 | |||
1078 | /* Stop TX */ | ||
1079 | ieee80211_stop_queues(hw); | ||
1080 | htc_stop(priv->htc); | ||
1081 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | ||
1082 | skb_queue_purge(&priv->tx_queue); | ||
1083 | |||
1084 | /* Stop RX */ | ||
1085 | WMI_CMD(WMI_STOP_RECV_CMDID); | ||
1086 | |||
1087 | /* | ||
1088 | * The MIB counters have to be disabled here, | ||
1089 | * since the target doesn't do it. | ||
1090 | */ | ||
1091 | ath9k_hw_disable_mib_counters(ah); | ||
1092 | |||
1093 | if (!ah->curchan) | ||
1094 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | ||
1095 | |||
1096 | /* Reset the HW */ | ||
1097 | ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | ||
1098 | if (ret) { | ||
1099 | ath_print(common, ATH_DBG_FATAL, | ||
1100 | "Unable to reset hardware; reset status %d " | ||
1101 | "(freq %u MHz)\n", ret, ah->curchan->channel); | ||
1102 | } | ||
1103 | |||
1104 | /* Disable the PHY */ | ||
1105 | ath9k_hw_phy_disable(ah); | ||
1106 | |||
1107 | ath9k_htc_ps_restore(priv); | ||
1108 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | ||
1109 | } | ||
1110 | |||
1111 | /**********************/ | 851 | /**********************/ |
1112 | /* mac80211 Callbacks */ | 852 | /* mac80211 Callbacks */ |
1113 | /**********************/ | 853 | /**********************/ |
1114 | 854 | ||
1115 | static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 855 | static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
1116 | { | 856 | { |
1117 | struct ieee80211_hdr *hdr; | 857 | struct ieee80211_hdr *hdr; |
1118 | struct ath9k_htc_priv *priv = hw->priv; | 858 | struct ath9k_htc_priv *priv = hw->priv; |
1119 | int padpos, padsize, ret; | 859 | struct ath_common *common = ath9k_hw_common(priv->ah); |
860 | int padpos, padsize, ret, slot; | ||
1120 | 861 | ||
1121 | hdr = (struct ieee80211_hdr *) skb->data; | 862 | hdr = (struct ieee80211_hdr *) skb->data; |
1122 | 863 | ||
@@ -1124,33 +865,34 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1124 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 865 | padpos = ath9k_cmn_padpos(hdr->frame_control); |
1125 | padsize = padpos & 3; | 866 | padsize = padpos & 3; |
1126 | if (padsize && skb->len > padpos) { | 867 | if (padsize && skb->len > padpos) { |
1127 | if (skb_headroom(skb) < padsize) | 868 | if (skb_headroom(skb) < padsize) { |
1128 | return -1; | 869 | ath_dbg(common, ATH_DBG_XMIT, "No room for padding\n"); |
870 | goto fail_tx; | ||
871 | } | ||
1129 | skb_push(skb, padsize); | 872 | skb_push(skb, padsize); |
1130 | memmove(skb->data, skb->data + padsize, padpos); | 873 | memmove(skb->data, skb->data + padsize, padpos); |
1131 | } | 874 | } |
1132 | 875 | ||
1133 | ret = ath9k_htc_tx_start(priv, skb); | 876 | slot = ath9k_htc_tx_get_slot(priv); |
1134 | if (ret != 0) { | 877 | if (slot < 0) { |
1135 | if (ret == -ENOMEM) { | 878 | ath_dbg(common, ATH_DBG_XMIT, "No free TX slot\n"); |
1136 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1137 | "Stopping TX queues\n"); | ||
1138 | ieee80211_stop_queues(hw); | ||
1139 | spin_lock_bh(&priv->tx_lock); | ||
1140 | priv->tx_queues_stop = true; | ||
1141 | spin_unlock_bh(&priv->tx_lock); | ||
1142 | } else { | ||
1143 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1144 | "Tx failed"); | ||
1145 | } | ||
1146 | goto fail_tx; | 879 | goto fail_tx; |
1147 | } | 880 | } |
1148 | 881 | ||
1149 | return 0; | 882 | ret = ath9k_htc_tx_start(priv, skb, slot, false); |
883 | if (ret != 0) { | ||
884 | ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n"); | ||
885 | goto clear_slot; | ||
886 | } | ||
887 | |||
888 | ath9k_htc_check_stop_queues(priv); | ||
889 | |||
890 | return; | ||
1150 | 891 | ||
892 | clear_slot: | ||
893 | ath9k_htc_tx_clear_slot(priv, slot); | ||
1151 | fail_tx: | 894 | fail_tx: |
1152 | dev_kfree_skb_any(skb); | 895 | dev_kfree_skb_any(skb); |
1153 | return 0; | ||
1154 | } | 896 | } |
1155 | 897 | ||
1156 | static int ath9k_htc_start(struct ieee80211_hw *hw) | 898 | static int ath9k_htc_start(struct ieee80211_hw *hw) |
@@ -1167,9 +909,9 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1167 | 909 | ||
1168 | mutex_lock(&priv->mutex); | 910 | mutex_lock(&priv->mutex); |
1169 | 911 | ||
1170 | ath_print(common, ATH_DBG_CONFIG, | 912 | ath_dbg(common, ATH_DBG_CONFIG, |
1171 | "Starting driver with initial channel: %d MHz\n", | 913 | "Starting driver with initial channel: %d MHz\n", |
1172 | curchan->center_freq); | 914 | curchan->center_freq); |
1173 | 915 | ||
1174 | /* Ensure that HW is awake before flushing RX */ | 916 | /* Ensure that HW is awake before flushing RX */ |
1175 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | 917 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); |
@@ -1178,20 +920,18 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1178 | /* setup initial channel */ | 920 | /* setup initial channel */ |
1179 | init_channel = ath9k_cmn_get_curchannel(hw, ah); | 921 | init_channel = ath9k_cmn_get_curchannel(hw, ah); |
1180 | 922 | ||
1181 | /* Reset SERDES registers */ | ||
1182 | ath9k_hw_configpcipowersave(ah, 0, 0); | ||
1183 | |||
1184 | ath9k_hw_htc_resetinit(ah); | 923 | ath9k_hw_htc_resetinit(ah); |
1185 | ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); | 924 | ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
1186 | if (ret) { | 925 | if (ret) { |
1187 | ath_print(common, ATH_DBG_FATAL, | 926 | ath_err(common, |
1188 | "Unable to reset hardware; reset status %d " | 927 | "Unable to reset hardware; reset status %d (freq %u MHz)\n", |
1189 | "(freq %u MHz)\n", ret, curchan->center_freq); | 928 | ret, curchan->center_freq); |
1190 | mutex_unlock(&priv->mutex); | 929 | mutex_unlock(&priv->mutex); |
1191 | return ret; | 930 | return ret; |
1192 | } | 931 | } |
1193 | 932 | ||
1194 | ath_update_txpow(priv); | 933 | ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, |
934 | &priv->curtxpow); | ||
1195 | 935 | ||
1196 | mode = ath9k_htc_get_curmode(priv, init_channel); | 936 | mode = ath9k_htc_get_curmode(priv, init_channel); |
1197 | htc_mode = cpu_to_be16(mode); | 937 | htc_mode = cpu_to_be16(mode); |
@@ -1201,15 +941,29 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1201 | 941 | ||
1202 | ath9k_host_rx_init(priv); | 942 | ath9k_host_rx_init(priv); |
1203 | 943 | ||
944 | ret = ath9k_htc_update_cap_target(priv, 0); | ||
945 | if (ret) | ||
946 | ath_dbg(common, ATH_DBG_CONFIG, | ||
947 | "Failed to update capability in target\n"); | ||
948 | |||
1204 | priv->op_flags &= ~OP_INVALID; | 949 | priv->op_flags &= ~OP_INVALID; |
1205 | htc_start(priv->htc); | 950 | htc_start(priv->htc); |
1206 | 951 | ||
1207 | spin_lock_bh(&priv->tx_lock); | 952 | spin_lock_bh(&priv->tx.tx_lock); |
1208 | priv->tx_queues_stop = false; | 953 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; |
1209 | spin_unlock_bh(&priv->tx_lock); | 954 | spin_unlock_bh(&priv->tx.tx_lock); |
1210 | 955 | ||
1211 | ieee80211_wake_queues(hw); | 956 | ieee80211_wake_queues(hw); |
1212 | 957 | ||
958 | mod_timer(&priv->tx.cleanup_timer, | ||
959 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
960 | |||
961 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { | ||
962 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
963 | AR_STOMP_LOW_WLAN_WGHT); | ||
964 | ath9k_hw_btcoex_enable(ah); | ||
965 | ath_htc_resume_btcoex_work(priv); | ||
966 | } | ||
1213 | mutex_unlock(&priv->mutex); | 967 | mutex_unlock(&priv->mutex); |
1214 | 968 | ||
1215 | return ret; | 969 | return ret; |
@@ -1220,49 +974,60 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1220 | struct ath9k_htc_priv *priv = hw->priv; | 974 | struct ath9k_htc_priv *priv = hw->priv; |
1221 | struct ath_hw *ah = priv->ah; | 975 | struct ath_hw *ah = priv->ah; |
1222 | struct ath_common *common = ath9k_hw_common(ah); | 976 | struct ath_common *common = ath9k_hw_common(ah); |
1223 | int ret = 0; | 977 | int ret __attribute__ ((unused)); |
1224 | u8 cmd_rsp; | 978 | u8 cmd_rsp; |
1225 | 979 | ||
1226 | mutex_lock(&priv->mutex); | 980 | mutex_lock(&priv->mutex); |
1227 | 981 | ||
1228 | if (priv->op_flags & OP_INVALID) { | 982 | if (priv->op_flags & OP_INVALID) { |
1229 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); | 983 | ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); |
1230 | mutex_unlock(&priv->mutex); | 984 | mutex_unlock(&priv->mutex); |
1231 | return; | 985 | return; |
1232 | } | 986 | } |
1233 | 987 | ||
1234 | /* Cancel all the running timers/work .. */ | ||
1235 | cancel_work_sync(&priv->ps_work); | ||
1236 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | ||
1237 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | ||
1238 | ath9k_led_stop_brightness(priv); | ||
1239 | |||
1240 | ath9k_htc_ps_wakeup(priv); | 988 | ath9k_htc_ps_wakeup(priv); |
1241 | htc_stop(priv->htc); | 989 | |
1242 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 990 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
1243 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 991 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
1244 | WMI_CMD(WMI_STOP_RECV_CMDID); | 992 | WMI_CMD(WMI_STOP_RECV_CMDID); |
1245 | skb_queue_purge(&priv->tx_queue); | ||
1246 | 993 | ||
1247 | /* Remove monitor interface here */ | 994 | tasklet_kill(&priv->rx_tasklet); |
1248 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { | 995 | |
1249 | if (ath9k_htc_remove_monitor_interface(priv)) | 996 | del_timer_sync(&priv->tx.cleanup_timer); |
1250 | ath_print(common, ATH_DBG_FATAL, | 997 | ath9k_htc_tx_drain(priv); |
1251 | "Unable to remove monitor interface\n"); | 998 | ath9k_wmi_event_drain(priv); |
1252 | else | 999 | |
1253 | ath_print(common, ATH_DBG_CONFIG, | 1000 | mutex_unlock(&priv->mutex); |
1254 | "Monitor interface removed\n"); | 1001 | |
1002 | /* Cancel all the running timers/work .. */ | ||
1003 | cancel_work_sync(&priv->fatal_work); | ||
1004 | cancel_work_sync(&priv->ps_work); | ||
1005 | |||
1006 | #ifdef CONFIG_MAC80211_LEDS | ||
1007 | cancel_work_sync(&priv->led_work); | ||
1008 | #endif | ||
1009 | ath9k_htc_stop_ani(priv); | ||
1010 | |||
1011 | mutex_lock(&priv->mutex); | ||
1012 | |||
1013 | if (ah->btcoex_hw.enabled) { | ||
1014 | ath9k_hw_btcoex_disable(ah); | ||
1015 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | ||
1016 | ath_htc_cancel_btcoex_work(priv); | ||
1255 | } | 1017 | } |
1256 | 1018 | ||
1019 | /* Remove a monitor interface if it's present. */ | ||
1020 | if (priv->ah->is_monitoring) | ||
1021 | ath9k_htc_remove_monitor_interface(priv); | ||
1022 | |||
1257 | ath9k_hw_phy_disable(ah); | 1023 | ath9k_hw_phy_disable(ah); |
1258 | ath9k_hw_disable(ah); | 1024 | ath9k_hw_disable(ah); |
1259 | ath9k_hw_configpcipowersave(ah, 1, 1); | ||
1260 | ath9k_htc_ps_restore(priv); | 1025 | ath9k_htc_ps_restore(priv); |
1261 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); | 1026 | ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); |
1262 | 1027 | ||
1263 | priv->op_flags |= OP_INVALID; | 1028 | priv->op_flags |= OP_INVALID; |
1264 | 1029 | ||
1265 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); | 1030 | ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); |
1266 | mutex_unlock(&priv->mutex); | 1031 | mutex_unlock(&priv->mutex); |
1267 | } | 1032 | } |
1268 | 1033 | ||
@@ -1278,10 +1043,24 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1278 | 1043 | ||
1279 | mutex_lock(&priv->mutex); | 1044 | mutex_lock(&priv->mutex); |
1280 | 1045 | ||
1281 | /* Only one interface for now */ | 1046 | if (priv->nvifs >= ATH9K_HTC_MAX_VIF) { |
1282 | if (priv->nvifs > 0) { | 1047 | mutex_unlock(&priv->mutex); |
1283 | ret = -ENOBUFS; | 1048 | return -ENOBUFS; |
1284 | goto out; | 1049 | } |
1050 | |||
1051 | if (priv->num_ibss_vif || | ||
1052 | (priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { | ||
1053 | ath_err(common, "IBSS coexistence with other modes is not allowed\n"); | ||
1054 | mutex_unlock(&priv->mutex); | ||
1055 | return -ENOBUFS; | ||
1056 | } | ||
1057 | |||
1058 | if (((vif->type == NL80211_IFTYPE_AP) || | ||
1059 | (vif->type == NL80211_IFTYPE_ADHOC)) && | ||
1060 | ((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) { | ||
1061 | ath_err(common, "Max. number of beaconing interfaces reached\n"); | ||
1062 | mutex_unlock(&priv->mutex); | ||
1063 | return -ENOBUFS; | ||
1285 | } | 1064 | } |
1286 | 1065 | ||
1287 | ath9k_htc_ps_wakeup(priv); | 1066 | ath9k_htc_ps_wakeup(priv); |
@@ -1290,46 +1069,60 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1290 | 1069 | ||
1291 | switch (vif->type) { | 1070 | switch (vif->type) { |
1292 | case NL80211_IFTYPE_STATION: | 1071 | case NL80211_IFTYPE_STATION: |
1293 | hvif.opmode = cpu_to_be32(HTC_M_STA); | 1072 | hvif.opmode = HTC_M_STA; |
1294 | break; | 1073 | break; |
1295 | case NL80211_IFTYPE_ADHOC: | 1074 | case NL80211_IFTYPE_ADHOC: |
1296 | hvif.opmode = cpu_to_be32(HTC_M_IBSS); | 1075 | hvif.opmode = HTC_M_IBSS; |
1076 | break; | ||
1077 | case NL80211_IFTYPE_AP: | ||
1078 | hvif.opmode = HTC_M_HOSTAP; | ||
1297 | break; | 1079 | break; |
1298 | default: | 1080 | default: |
1299 | ath_print(common, ATH_DBG_FATAL, | 1081 | ath_err(common, |
1300 | "Interface type %d not yet supported\n", vif->type); | 1082 | "Interface type %d not yet supported\n", vif->type); |
1301 | ret = -EOPNOTSUPP; | 1083 | ret = -EOPNOTSUPP; |
1302 | goto out; | 1084 | goto out; |
1303 | } | 1085 | } |
1304 | 1086 | ||
1305 | ath_print(common, ATH_DBG_CONFIG, | ||
1306 | "Attach a VIF of type: %d\n", vif->type); | ||
1307 | |||
1308 | priv->ah->opmode = vif->type; | ||
1309 | |||
1310 | /* Index starts from zero on the target */ | 1087 | /* Index starts from zero on the target */ |
1311 | avp->index = hvif.index = priv->nvifs; | 1088 | avp->index = hvif.index = ffz(priv->vif_slot); |
1312 | hvif.rtsthreshold = cpu_to_be16(2304); | 1089 | hvif.rtsthreshold = cpu_to_be16(2304); |
1313 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); | 1090 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); |
1314 | if (ret) | 1091 | if (ret) |
1315 | goto out; | 1092 | goto out; |
1316 | 1093 | ||
1317 | priv->nvifs++; | ||
1318 | |||
1319 | /* | 1094 | /* |
1320 | * We need a node in target to tx mgmt frames | 1095 | * We need a node in target to tx mgmt frames |
1321 | * before association. | 1096 | * before association. |
1322 | */ | 1097 | */ |
1323 | ret = ath9k_htc_add_station(priv, vif, NULL); | 1098 | ret = ath9k_htc_add_station(priv, vif, NULL); |
1324 | if (ret) | 1099 | if (ret) { |
1100 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | ||
1325 | goto out; | 1101 | goto out; |
1102 | } | ||
1326 | 1103 | ||
1327 | ret = ath9k_htc_update_cap_target(priv); | 1104 | ath9k_htc_set_bssid_mask(priv, vif); |
1328 | if (ret) | 1105 | |
1329 | ath_print(common, ATH_DBG_CONFIG, "Failed to update" | 1106 | priv->vif_slot |= (1 << avp->index); |
1330 | " capability in target \n"); | 1107 | priv->nvifs++; |
1108 | |||
1109 | INC_VIF(priv, vif->type); | ||
1110 | |||
1111 | if ((vif->type == NL80211_IFTYPE_AP) || | ||
1112 | (vif->type == NL80211_IFTYPE_ADHOC)) | ||
1113 | ath9k_htc_assign_bslot(priv, vif); | ||
1114 | |||
1115 | ath9k_htc_set_opmode(priv); | ||
1116 | |||
1117 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && | ||
1118 | !(priv->op_flags & OP_ANI_RUNNING)) { | ||
1119 | ath9k_hw_set_tsfadjust(priv->ah, 1); | ||
1120 | ath9k_htc_start_ani(priv); | ||
1121 | } | ||
1122 | |||
1123 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1124 | "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); | ||
1331 | 1125 | ||
1332 | priv->vif = vif; | ||
1333 | out: | 1126 | out: |
1334 | ath9k_htc_ps_restore(priv); | 1127 | ath9k_htc_ps_restore(priv); |
1335 | mutex_unlock(&priv->mutex); | 1128 | mutex_unlock(&priv->mutex); |
@@ -1347,8 +1140,6 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1347 | int ret = 0; | 1140 | int ret = 0; |
1348 | u8 cmd_rsp; | 1141 | u8 cmd_rsp; |
1349 | 1142 | ||
1350 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); | ||
1351 | |||
1352 | mutex_lock(&priv->mutex); | 1143 | mutex_lock(&priv->mutex); |
1353 | ath9k_htc_ps_wakeup(priv); | 1144 | ath9k_htc_ps_wakeup(priv); |
1354 | 1145 | ||
@@ -1356,10 +1147,37 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1356 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); | 1147 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); |
1357 | hvif.index = avp->index; | 1148 | hvif.index = avp->index; |
1358 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | 1149 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
1150 | if (ret) { | ||
1151 | ath_err(common, "Unable to remove interface at idx: %d\n", | ||
1152 | avp->index); | ||
1153 | } | ||
1359 | priv->nvifs--; | 1154 | priv->nvifs--; |
1155 | priv->vif_slot &= ~(1 << avp->index); | ||
1360 | 1156 | ||
1361 | ath9k_htc_remove_station(priv, vif, NULL); | 1157 | ath9k_htc_remove_station(priv, vif, NULL); |
1362 | priv->vif = NULL; | 1158 | |
1159 | DEC_VIF(priv, vif->type); | ||
1160 | |||
1161 | if ((vif->type == NL80211_IFTYPE_AP) || | ||
1162 | (vif->type == NL80211_IFTYPE_ADHOC)) | ||
1163 | ath9k_htc_remove_bslot(priv, vif); | ||
1164 | |||
1165 | ath9k_htc_set_opmode(priv); | ||
1166 | |||
1167 | ath9k_htc_set_bssid_mask(priv, vif); | ||
1168 | |||
1169 | /* | ||
1170 | * Stop ANI only if there are no associated station interfaces. | ||
1171 | */ | ||
1172 | if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) { | ||
1173 | priv->rearm_ani = false; | ||
1174 | ieee80211_iterate_active_interfaces_atomic(priv->hw, | ||
1175 | ath9k_htc_vif_iter, priv); | ||
1176 | if (!priv->rearm_ani) | ||
1177 | ath9k_htc_stop_ani(priv); | ||
1178 | } | ||
1179 | |||
1180 | ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface at idx: %d\n", avp->index); | ||
1363 | 1181 | ||
1364 | ath9k_htc_ps_restore(priv); | 1182 | ath9k_htc_ps_restore(priv); |
1365 | mutex_unlock(&priv->mutex); | 1183 | mutex_unlock(&priv->mutex); |
@@ -1384,30 +1202,44 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1384 | mutex_unlock(&priv->htc_pm_lock); | 1202 | mutex_unlock(&priv->htc_pm_lock); |
1385 | 1203 | ||
1386 | if (enable_radio) { | 1204 | if (enable_radio) { |
1387 | ath_print(common, ATH_DBG_CONFIG, | 1205 | ath_dbg(common, ATH_DBG_CONFIG, |
1388 | "not-idle: enabling radio\n"); | 1206 | "not-idle: enabling radio\n"); |
1389 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); | 1207 | ath9k_htc_setpower(priv, ATH9K_PM_AWAKE); |
1390 | ath9k_htc_radio_enable(hw); | 1208 | ath9k_htc_radio_enable(hw); |
1391 | } | 1209 | } |
1392 | } | 1210 | } |
1393 | 1211 | ||
1212 | /* | ||
1213 | * Monitor interface should be added before | ||
1214 | * IEEE80211_CONF_CHANGE_CHANNEL is handled. | ||
1215 | */ | ||
1216 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | ||
1217 | if ((conf->flags & IEEE80211_CONF_MONITOR) && | ||
1218 | !priv->ah->is_monitoring) | ||
1219 | ath9k_htc_add_monitor_interface(priv); | ||
1220 | else if (priv->ah->is_monitoring) | ||
1221 | ath9k_htc_remove_monitor_interface(priv); | ||
1222 | } | ||
1223 | |||
1394 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1224 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
1395 | struct ieee80211_channel *curchan = hw->conf.channel; | 1225 | struct ieee80211_channel *curchan = hw->conf.channel; |
1396 | int pos = curchan->hw_value; | 1226 | int pos = curchan->hw_value; |
1397 | 1227 | ||
1398 | ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", | 1228 | ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", |
1399 | curchan->center_freq); | 1229 | curchan->center_freq); |
1400 | 1230 | ||
1401 | ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]); | 1231 | ath9k_cmn_update_ichannel(&priv->ah->channels[pos], |
1232 | hw->conf.channel, | ||
1233 | hw->conf.channel_type); | ||
1402 | 1234 | ||
1403 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { | 1235 | if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) { |
1404 | ath_print(common, ATH_DBG_FATAL, | 1236 | ath_err(common, "Unable to set channel\n"); |
1405 | "Unable to set channel\n"); | ||
1406 | mutex_unlock(&priv->mutex); | 1237 | mutex_unlock(&priv->mutex); |
1407 | return -EINVAL; | 1238 | return -EINVAL; |
1408 | } | 1239 | } |
1409 | 1240 | ||
1410 | } | 1241 | } |
1242 | |||
1411 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 1243 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
1412 | if (conf->flags & IEEE80211_CONF_PS) { | 1244 | if (conf->flags & IEEE80211_CONF_PS) { |
1413 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); | 1245 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); |
@@ -1419,15 +1251,10 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1419 | } | 1251 | } |
1420 | } | 1252 | } |
1421 | 1253 | ||
1422 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | 1254 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
1423 | if (conf->flags & IEEE80211_CONF_MONITOR) { | 1255 | priv->txpowlimit = 2 * conf->power_level; |
1424 | if (ath9k_htc_add_monitor_interface(priv)) | 1256 | ath9k_cmn_update_txpow(priv->ah, priv->curtxpow, |
1425 | ath_print(common, ATH_DBG_FATAL, | 1257 | priv->txpowlimit, &priv->curtxpow); |
1426 | "Failed to set monitor mode\n"); | ||
1427 | else | ||
1428 | ath_print(common, ATH_DBG_CONFIG, | ||
1429 | "HW opmode set to Monitor mode\n"); | ||
1430 | } | ||
1431 | } | 1258 | } |
1432 | 1259 | ||
1433 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1260 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
@@ -1438,8 +1265,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1438 | } | 1265 | } |
1439 | mutex_unlock(&priv->htc_pm_lock); | 1266 | mutex_unlock(&priv->htc_pm_lock); |
1440 | 1267 | ||
1441 | ath_print(common, ATH_DBG_CONFIG, | 1268 | ath_dbg(common, ATH_DBG_CONFIG, |
1442 | "idle: disabling radio\n"); | 1269 | "idle: disabling radio\n"); |
1443 | ath9k_htc_radio_disable(hw); | 1270 | ath9k_htc_radio_disable(hw); |
1444 | } | 1271 | } |
1445 | 1272 | ||
@@ -1455,6 +1282,7 @@ out: | |||
1455 | FIF_PSPOLL | \ | 1282 | FIF_PSPOLL | \ |
1456 | FIF_OTHER_BSS | \ | 1283 | FIF_OTHER_BSS | \ |
1457 | FIF_BCN_PRBRESP_PROMISC | \ | 1284 | FIF_BCN_PRBRESP_PROMISC | \ |
1285 | FIF_PROBE_REQ | \ | ||
1458 | FIF_FCSFAIL) | 1286 | FIF_FCSFAIL) |
1459 | 1287 | ||
1460 | static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, | 1288 | static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, |
@@ -1475,8 +1303,8 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, | |||
1475 | rfilt = ath9k_htc_calcrxfilter(priv); | 1303 | rfilt = ath9k_htc_calcrxfilter(priv); |
1476 | ath9k_hw_setrxfilter(priv->ah, rfilt); | 1304 | ath9k_hw_setrxfilter(priv->ah, rfilt); |
1477 | 1305 | ||
1478 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, | 1306 | ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, |
1479 | "Set HW RX filter: 0x%x\n", rfilt); | 1307 | "Set HW RX filter: 0x%x\n", rfilt); |
1480 | 1308 | ||
1481 | ath9k_htc_ps_restore(priv); | 1309 | ath9k_htc_ps_restore(priv); |
1482 | mutex_unlock(&priv->mutex); | 1310 | mutex_unlock(&priv->mutex); |
@@ -1505,10 +1333,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, | |||
1505 | struct ieee80211_sta *sta) | 1333 | struct ieee80211_sta *sta) |
1506 | { | 1334 | { |
1507 | struct ath9k_htc_priv *priv = hw->priv; | 1335 | struct ath9k_htc_priv *priv = hw->priv; |
1336 | struct ath9k_htc_sta *ista; | ||
1508 | int ret; | 1337 | int ret; |
1509 | 1338 | ||
1510 | mutex_lock(&priv->mutex); | 1339 | mutex_lock(&priv->mutex); |
1511 | ath9k_htc_ps_wakeup(priv); | 1340 | ath9k_htc_ps_wakeup(priv); |
1341 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
1342 | htc_sta_drain(priv->htc, ista->index); | ||
1512 | ret = ath9k_htc_remove_station(priv, vif, sta); | 1343 | ret = ath9k_htc_remove_station(priv, vif, sta); |
1513 | ath9k_htc_ps_restore(priv); | 1344 | ath9k_htc_ps_restore(priv); |
1514 | mutex_unlock(&priv->mutex); | 1345 | mutex_unlock(&priv->mutex); |
@@ -1539,15 +1370,14 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1539 | 1370 | ||
1540 | qnum = get_hw_qnum(queue, priv->hwq_map); | 1371 | qnum = get_hw_qnum(queue, priv->hwq_map); |
1541 | 1372 | ||
1542 | ath_print(common, ATH_DBG_CONFIG, | 1373 | ath_dbg(common, ATH_DBG_CONFIG, |
1543 | "Configure tx [queue/hwq] [%d/%d], " | 1374 | "Configure tx [queue/hwq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", |
1544 | "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", | 1375 | queue, qnum, params->aifs, params->cw_min, |
1545 | queue, qnum, params->aifs, params->cw_min, | 1376 | params->cw_max, params->txop); |
1546 | params->cw_max, params->txop); | ||
1547 | 1377 | ||
1548 | ret = ath_htc_txq_update(priv, qnum, &qi); | 1378 | ret = ath_htc_txq_update(priv, qnum, &qi); |
1549 | if (ret) { | 1379 | if (ret) { |
1550 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); | 1380 | ath_err(common, "TXQ Update failed\n"); |
1551 | goto out; | 1381 | goto out; |
1552 | } | 1382 | } |
1553 | 1383 | ||
@@ -1575,25 +1405,26 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1575 | return -ENOSPC; | 1405 | return -ENOSPC; |
1576 | 1406 | ||
1577 | mutex_lock(&priv->mutex); | 1407 | mutex_lock(&priv->mutex); |
1578 | ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); | 1408 | ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n"); |
1579 | ath9k_htc_ps_wakeup(priv); | 1409 | ath9k_htc_ps_wakeup(priv); |
1580 | 1410 | ||
1581 | switch (cmd) { | 1411 | switch (cmd) { |
1582 | case SET_KEY: | 1412 | case SET_KEY: |
1583 | ret = ath9k_cmn_key_config(common, vif, sta, key); | 1413 | ret = ath_key_config(common, vif, sta, key); |
1584 | if (ret >= 0) { | 1414 | if (ret >= 0) { |
1585 | key->hw_key_idx = ret; | 1415 | key->hw_key_idx = ret; |
1586 | /* push IV and Michael MIC generation to stack */ | 1416 | /* push IV and Michael MIC generation to stack */ |
1587 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1417 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1588 | if (key->alg == ALG_TKIP) | 1418 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
1589 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1419 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1590 | if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP) | 1420 | if (priv->ah->sw_mgmt_crypto && |
1421 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | ||
1591 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | 1422 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; |
1592 | ret = 0; | 1423 | ret = 0; |
1593 | } | 1424 | } |
1594 | break; | 1425 | break; |
1595 | case DISABLE_KEY: | 1426 | case DISABLE_KEY: |
1596 | ath9k_cmn_key_delete(common, key); | 1427 | ath_key_delete(common, key); |
1597 | break; | 1428 | break; |
1598 | default: | 1429 | default: |
1599 | ret = -EINVAL; | 1430 | ret = -EINVAL; |
@@ -1605,6 +1436,37 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1605 | return ret; | 1436 | return ret; |
1606 | } | 1437 | } |
1607 | 1438 | ||
1439 | static void ath9k_htc_set_bssid(struct ath9k_htc_priv *priv) | ||
1440 | { | ||
1441 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1442 | |||
1443 | ath9k_hw_write_associd(priv->ah); | ||
1444 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1445 | "BSSID: %pM aid: 0x%x\n", | ||
1446 | common->curbssid, common->curaid); | ||
1447 | } | ||
1448 | |||
1449 | static void ath9k_htc_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
1450 | { | ||
1451 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | ||
1452 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1453 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
1454 | |||
1455 | if ((vif->type == NL80211_IFTYPE_STATION) && bss_conf->assoc) { | ||
1456 | common->curaid = bss_conf->aid; | ||
1457 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1458 | } | ||
1459 | } | ||
1460 | |||
1461 | static void ath9k_htc_choose_set_bssid(struct ath9k_htc_priv *priv) | ||
1462 | { | ||
1463 | if (priv->num_sta_assoc_vif == 1) { | ||
1464 | ieee80211_iterate_active_interfaces_atomic(priv->hw, | ||
1465 | ath9k_htc_bss_iter, priv); | ||
1466 | ath9k_htc_set_bssid(priv); | ||
1467 | } | ||
1468 | } | ||
1469 | |||
1608 | static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | 1470 | static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, |
1609 | struct ieee80211_vif *vif, | 1471 | struct ieee80211_vif *vif, |
1610 | struct ieee80211_bss_conf *bss_conf, | 1472 | struct ieee80211_bss_conf *bss_conf, |
@@ -1618,61 +1480,66 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1618 | ath9k_htc_ps_wakeup(priv); | 1480 | ath9k_htc_ps_wakeup(priv); |
1619 | 1481 | ||
1620 | if (changed & BSS_CHANGED_ASSOC) { | 1482 | if (changed & BSS_CHANGED_ASSOC) { |
1621 | common->curaid = bss_conf->assoc ? | 1483 | ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", |
1622 | bss_conf->aid : 0; | ||
1623 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", | ||
1624 | bss_conf->assoc); | 1484 | bss_conf->assoc); |
1625 | 1485 | ||
1626 | if (bss_conf->assoc) { | 1486 | bss_conf->assoc ? |
1627 | priv->op_flags |= OP_ASSOCIATED; | 1487 | priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; |
1628 | ath_start_ani(priv); | 1488 | |
1629 | } else { | 1489 | if (priv->ah->opmode == NL80211_IFTYPE_STATION) { |
1630 | priv->op_flags &= ~OP_ASSOCIATED; | 1490 | if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1)) |
1631 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1491 | ath9k_htc_start_ani(priv); |
1492 | else if (priv->num_sta_assoc_vif == 0) | ||
1493 | ath9k_htc_stop_ani(priv); | ||
1632 | } | 1494 | } |
1633 | } | 1495 | } |
1634 | 1496 | ||
1635 | if (changed & BSS_CHANGED_BSSID) { | 1497 | if (changed & BSS_CHANGED_BSSID) { |
1636 | /* Set BSSID */ | 1498 | if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { |
1637 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | 1499 | common->curaid = bss_conf->aid; |
1638 | ath9k_hw_write_associd(ah); | 1500 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
1639 | 1501 | ath9k_htc_set_bssid(priv); | |
1640 | ath_print(common, ATH_DBG_CONFIG, | 1502 | } else if (priv->ah->opmode == NL80211_IFTYPE_STATION) { |
1641 | "BSSID: %pM aid: 0x%x\n", | 1503 | ath9k_htc_choose_set_bssid(priv); |
1642 | common->curbssid, common->curaid); | 1504 | } |
1643 | } | 1505 | } |
1644 | 1506 | ||
1645 | if ((changed & BSS_CHANGED_BEACON_INT) || | 1507 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { |
1646 | (changed & BSS_CHANGED_BEACON) || | 1508 | ath_dbg(common, ATH_DBG_CONFIG, |
1647 | ((changed & BSS_CHANGED_BEACON_ENABLED) && | 1509 | "Beacon enabled for BSS: %pM\n", bss_conf->bssid); |
1648 | bss_conf->enable_beacon)) { | 1510 | ath9k_htc_set_tsfadjust(priv, vif); |
1649 | priv->op_flags |= OP_ENABLE_BEACON; | 1511 | priv->op_flags |= OP_ENABLE_BEACON; |
1650 | ath9k_htc_beacon_config(priv, vif); | 1512 | ath9k_htc_beacon_config(priv, vif); |
1651 | } | 1513 | } |
1652 | 1514 | ||
1653 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | 1515 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) { |
1654 | !bss_conf->enable_beacon) { | 1516 | /* |
1655 | priv->op_flags &= ~OP_ENABLE_BEACON; | 1517 | * Disable SWBA interrupt only if there are no |
1656 | ath9k_htc_beacon_config(priv, vif); | 1518 | * AP/IBSS interfaces. |
1657 | } | 1519 | */ |
1658 | 1520 | if ((priv->num_ap_vif <= 1) || priv->num_ibss_vif) { | |
1659 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 1521 | ath_dbg(common, ATH_DBG_CONFIG, |
1660 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", | 1522 | "Beacon disabled for BSS: %pM\n", |
1661 | bss_conf->use_short_preamble); | 1523 | bss_conf->bssid); |
1662 | if (bss_conf->use_short_preamble) | 1524 | priv->op_flags &= ~OP_ENABLE_BEACON; |
1663 | priv->op_flags |= OP_PREAMBLE_SHORT; | 1525 | ath9k_htc_beacon_config(priv, vif); |
1664 | else | 1526 | } |
1665 | priv->op_flags &= ~OP_PREAMBLE_SHORT; | ||
1666 | } | 1527 | } |
1667 | 1528 | ||
1668 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 1529 | if (changed & BSS_CHANGED_BEACON_INT) { |
1669 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", | 1530 | /* |
1670 | bss_conf->use_cts_prot); | 1531 | * Reset the HW TSF for the first AP interface. |
1671 | if (bss_conf->use_cts_prot && | 1532 | */ |
1672 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) | 1533 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && |
1673 | priv->op_flags |= OP_PROTECT_ENABLE; | 1534 | (priv->nvifs == 1) && |
1674 | else | 1535 | (priv->num_ap_vif == 1) && |
1675 | priv->op_flags &= ~OP_PROTECT_ENABLE; | 1536 | (vif->type == NL80211_IFTYPE_AP)) { |
1537 | priv->op_flags |= OP_TSF_RESET; | ||
1538 | } | ||
1539 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1540 | "Beacon interval changed for BSS: %pM\n", | ||
1541 | bss_conf->bssid); | ||
1542 | ath9k_htc_beacon_config(priv, vif); | ||
1676 | } | 1543 | } |
1677 | 1544 | ||
1678 | if (changed & BSS_CHANGED_ERP_SLOT) { | 1545 | if (changed & BSS_CHANGED_ERP_SLOT) { |
@@ -1731,12 +1598,15 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1731 | struct ieee80211_vif *vif, | 1598 | struct ieee80211_vif *vif, |
1732 | enum ieee80211_ampdu_mlme_action action, | 1599 | enum ieee80211_ampdu_mlme_action action, |
1733 | struct ieee80211_sta *sta, | 1600 | struct ieee80211_sta *sta, |
1734 | u16 tid, u16 *ssn) | 1601 | u16 tid, u16 *ssn, u8 buf_size) |
1735 | { | 1602 | { |
1736 | struct ath9k_htc_priv *priv = hw->priv; | 1603 | struct ath9k_htc_priv *priv = hw->priv; |
1737 | struct ath9k_htc_sta *ista; | 1604 | struct ath9k_htc_sta *ista; |
1738 | int ret = 0; | 1605 | int ret = 0; |
1739 | 1606 | ||
1607 | mutex_lock(&priv->mutex); | ||
1608 | ath9k_htc_ps_wakeup(priv); | ||
1609 | |||
1740 | switch (action) { | 1610 | switch (action) { |
1741 | case IEEE80211_AMPDU_RX_START: | 1611 | case IEEE80211_AMPDU_RX_START: |
1742 | break; | 1612 | break; |
@@ -1753,15 +1623,17 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1753 | break; | 1623 | break; |
1754 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 1624 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
1755 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 1625 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
1756 | spin_lock_bh(&priv->tx_lock); | 1626 | spin_lock_bh(&priv->tx.tx_lock); |
1757 | ista->tid_state[tid] = AGGR_OPERATIONAL; | 1627 | ista->tid_state[tid] = AGGR_OPERATIONAL; |
1758 | spin_unlock_bh(&priv->tx_lock); | 1628 | spin_unlock_bh(&priv->tx.tx_lock); |
1759 | break; | 1629 | break; |
1760 | default: | 1630 | default: |
1761 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_FATAL, | 1631 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); |
1762 | "Unknown AMPDU action\n"); | ||
1763 | } | 1632 | } |
1764 | 1633 | ||
1634 | ath9k_htc_ps_restore(priv); | ||
1635 | mutex_unlock(&priv->mutex); | ||
1636 | |||
1765 | return ret; | 1637 | return ret; |
1766 | } | 1638 | } |
1767 | 1639 | ||
@@ -1774,7 +1646,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | |||
1774 | priv->op_flags |= OP_SCANNING; | 1646 | priv->op_flags |= OP_SCANNING; |
1775 | spin_unlock_bh(&priv->beacon_lock); | 1647 | spin_unlock_bh(&priv->beacon_lock); |
1776 | cancel_work_sync(&priv->ps_work); | 1648 | cancel_work_sync(&priv->ps_work); |
1777 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1649 | ath9k_htc_stop_ani(priv); |
1778 | mutex_unlock(&priv->mutex); | 1650 | mutex_unlock(&priv->mutex); |
1779 | } | 1651 | } |
1780 | 1652 | ||
@@ -1783,14 +1655,11 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) | |||
1783 | struct ath9k_htc_priv *priv = hw->priv; | 1655 | struct ath9k_htc_priv *priv = hw->priv; |
1784 | 1656 | ||
1785 | mutex_lock(&priv->mutex); | 1657 | mutex_lock(&priv->mutex); |
1786 | ath9k_htc_ps_wakeup(priv); | ||
1787 | spin_lock_bh(&priv->beacon_lock); | 1658 | spin_lock_bh(&priv->beacon_lock); |
1788 | priv->op_flags &= ~OP_SCANNING; | 1659 | priv->op_flags &= ~OP_SCANNING; |
1789 | spin_unlock_bh(&priv->beacon_lock); | 1660 | spin_unlock_bh(&priv->beacon_lock); |
1790 | priv->op_flags |= OP_FULL_RESET; | 1661 | ath9k_htc_ps_wakeup(priv); |
1791 | if (priv->op_flags & OP_ASSOCIATED) | 1662 | ath9k_htc_vif_reconfig(priv); |
1792 | ath9k_htc_beacon_config(priv, priv->vif); | ||
1793 | ath_start_ani(priv); | ||
1794 | ath9k_htc_ps_restore(priv); | 1663 | ath9k_htc_ps_restore(priv); |
1795 | mutex_unlock(&priv->mutex); | 1664 | mutex_unlock(&priv->mutex); |
1796 | } | 1665 | } |
@@ -1813,6 +1682,55 @@ static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, | |||
1813 | mutex_unlock(&priv->mutex); | 1682 | mutex_unlock(&priv->mutex); |
1814 | } | 1683 | } |
1815 | 1684 | ||
1685 | /* | ||
1686 | * Currently, this is used only for selecting the minimum rate | ||
1687 | * for management frames, rate selection for data frames remain | ||
1688 | * unaffected. | ||
1689 | */ | ||
1690 | static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, | ||
1691 | struct ieee80211_vif *vif, | ||
1692 | const struct cfg80211_bitrate_mask *mask) | ||
1693 | { | ||
1694 | struct ath9k_htc_priv *priv = hw->priv; | ||
1695 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1696 | struct ath9k_htc_target_rate_mask tmask; | ||
1697 | struct ath9k_htc_vif *avp = (void *)vif->drv_priv; | ||
1698 | int ret = 0; | ||
1699 | u8 cmd_rsp; | ||
1700 | |||
1701 | memset(&tmask, 0, sizeof(struct ath9k_htc_target_rate_mask)); | ||
1702 | |||
1703 | tmask.vif_index = avp->index; | ||
1704 | tmask.band = IEEE80211_BAND_2GHZ; | ||
1705 | tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_2GHZ].legacy); | ||
1706 | |||
1707 | WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); | ||
1708 | if (ret) { | ||
1709 | ath_err(common, | ||
1710 | "Unable to set 2G rate mask for " | ||
1711 | "interface at idx: %d\n", avp->index); | ||
1712 | goto out; | ||
1713 | } | ||
1714 | |||
1715 | tmask.band = IEEE80211_BAND_5GHZ; | ||
1716 | tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_5GHZ].legacy); | ||
1717 | |||
1718 | WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); | ||
1719 | if (ret) { | ||
1720 | ath_err(common, | ||
1721 | "Unable to set 5G rate mask for " | ||
1722 | "interface at idx: %d\n", avp->index); | ||
1723 | goto out; | ||
1724 | } | ||
1725 | |||
1726 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1727 | "Set bitrate masks: 0x%x, 0x%x\n", | ||
1728 | mask->control[IEEE80211_BAND_2GHZ].legacy, | ||
1729 | mask->control[IEEE80211_BAND_5GHZ].legacy); | ||
1730 | out: | ||
1731 | return ret; | ||
1732 | } | ||
1733 | |||
1816 | struct ieee80211_ops ath9k_htc_ops = { | 1734 | struct ieee80211_ops ath9k_htc_ops = { |
1817 | .tx = ath9k_htc_tx, | 1735 | .tx = ath9k_htc_tx, |
1818 | .start = ath9k_htc_start, | 1736 | .start = ath9k_htc_start, |
@@ -1835,4 +1753,5 @@ struct ieee80211_ops ath9k_htc_ops = { | |||
1835 | .set_rts_threshold = ath9k_htc_set_rts_threshold, | 1753 | .set_rts_threshold = ath9k_htc_set_rts_threshold, |
1836 | .rfkill_poll = ath9k_htc_rfkill_poll_state, | 1754 | .rfkill_poll = ath9k_htc_rfkill_poll_state, |
1837 | .set_coverage_class = ath9k_htc_set_coverage_class, | 1755 | .set_coverage_class = ath9k_htc_set_coverage_class, |
1756 | .set_bitrate_mask = ath9k_htc_set_bitrate_mask, | ||
1838 | }; | 1757 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 2a6e45a293a9..2d81c700e201 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -20,8 +20,15 @@ | |||
20 | /* TX */ | 20 | /* TX */ |
21 | /******/ | 21 | /******/ |
22 | 22 | ||
23 | static const int subtype_txq_to_hwq[] = { | ||
24 | [WME_AC_BE] = ATH_TXQ_AC_BE, | ||
25 | [WME_AC_BK] = ATH_TXQ_AC_BK, | ||
26 | [WME_AC_VI] = ATH_TXQ_AC_VI, | ||
27 | [WME_AC_VO] = ATH_TXQ_AC_VO, | ||
28 | }; | ||
29 | |||
23 | #define ATH9K_HTC_INIT_TXQ(subtype) do { \ | 30 | #define ATH9K_HTC_INIT_TXQ(subtype) do { \ |
24 | qi.tqi_subtype = subtype; \ | 31 | qi.tqi_subtype = subtype_txq_to_hwq[subtype]; \ |
25 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \ | 32 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \ |
26 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \ | 33 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \ |
27 | qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \ | 34 | qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \ |
@@ -46,6 +53,138 @@ int get_hw_qnum(u16 queue, int *hwq_map) | |||
46 | } | 53 | } |
47 | } | 54 | } |
48 | 55 | ||
56 | void ath9k_htc_check_stop_queues(struct ath9k_htc_priv *priv) | ||
57 | { | ||
58 | spin_lock_bh(&priv->tx.tx_lock); | ||
59 | priv->tx.queued_cnt++; | ||
60 | if ((priv->tx.queued_cnt >= ATH9K_HTC_TX_THRESHOLD) && | ||
61 | !(priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { | ||
62 | priv->tx.flags |= ATH9K_HTC_OP_TX_QUEUES_STOP; | ||
63 | ieee80211_stop_queues(priv->hw); | ||
64 | } | ||
65 | spin_unlock_bh(&priv->tx.tx_lock); | ||
66 | } | ||
67 | |||
68 | void ath9k_htc_check_wake_queues(struct ath9k_htc_priv *priv) | ||
69 | { | ||
70 | spin_lock_bh(&priv->tx.tx_lock); | ||
71 | if ((priv->tx.queued_cnt < ATH9K_HTC_TX_THRESHOLD) && | ||
72 | (priv->tx.flags & ATH9K_HTC_OP_TX_QUEUES_STOP)) { | ||
73 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; | ||
74 | ieee80211_wake_queues(priv->hw); | ||
75 | } | ||
76 | spin_unlock_bh(&priv->tx.tx_lock); | ||
77 | } | ||
78 | |||
79 | int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv) | ||
80 | { | ||
81 | int slot; | ||
82 | |||
83 | spin_lock_bh(&priv->tx.tx_lock); | ||
84 | slot = find_first_zero_bit(priv->tx.tx_slot, MAX_TX_BUF_NUM); | ||
85 | if (slot >= MAX_TX_BUF_NUM) { | ||
86 | spin_unlock_bh(&priv->tx.tx_lock); | ||
87 | return -ENOBUFS; | ||
88 | } | ||
89 | __set_bit(slot, priv->tx.tx_slot); | ||
90 | spin_unlock_bh(&priv->tx.tx_lock); | ||
91 | |||
92 | return slot; | ||
93 | } | ||
94 | |||
95 | void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot) | ||
96 | { | ||
97 | spin_lock_bh(&priv->tx.tx_lock); | ||
98 | __clear_bit(slot, priv->tx.tx_slot); | ||
99 | spin_unlock_bh(&priv->tx.tx_lock); | ||
100 | } | ||
101 | |||
102 | static inline enum htc_endpoint_id get_htc_epid(struct ath9k_htc_priv *priv, | ||
103 | u16 qnum) | ||
104 | { | ||
105 | enum htc_endpoint_id epid; | ||
106 | |||
107 | switch (qnum) { | ||
108 | case 0: | ||
109 | TX_QSTAT_INC(WME_AC_VO); | ||
110 | epid = priv->data_vo_ep; | ||
111 | break; | ||
112 | case 1: | ||
113 | TX_QSTAT_INC(WME_AC_VI); | ||
114 | epid = priv->data_vi_ep; | ||
115 | break; | ||
116 | case 2: | ||
117 | TX_QSTAT_INC(WME_AC_BE); | ||
118 | epid = priv->data_be_ep; | ||
119 | break; | ||
120 | case 3: | ||
121 | default: | ||
122 | TX_QSTAT_INC(WME_AC_BK); | ||
123 | epid = priv->data_bk_ep; | ||
124 | break; | ||
125 | } | ||
126 | |||
127 | return epid; | ||
128 | } | ||
129 | |||
130 | static inline struct sk_buff_head* | ||
131 | get_htc_epid_queue(struct ath9k_htc_priv *priv, u8 epid) | ||
132 | { | ||
133 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
134 | struct sk_buff_head *epid_queue = NULL; | ||
135 | |||
136 | if (epid == priv->mgmt_ep) | ||
137 | epid_queue = &priv->tx.mgmt_ep_queue; | ||
138 | else if (epid == priv->cab_ep) | ||
139 | epid_queue = &priv->tx.cab_ep_queue; | ||
140 | else if (epid == priv->data_be_ep) | ||
141 | epid_queue = &priv->tx.data_be_queue; | ||
142 | else if (epid == priv->data_bk_ep) | ||
143 | epid_queue = &priv->tx.data_bk_queue; | ||
144 | else if (epid == priv->data_vi_ep) | ||
145 | epid_queue = &priv->tx.data_vi_queue; | ||
146 | else if (epid == priv->data_vo_ep) | ||
147 | epid_queue = &priv->tx.data_vo_queue; | ||
148 | else | ||
149 | ath_err(common, "Invalid EPID: %d\n", epid); | ||
150 | |||
151 | return epid_queue; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Removes the driver header and returns the TX slot number | ||
156 | */ | ||
157 | static inline int strip_drv_header(struct ath9k_htc_priv *priv, | ||
158 | struct sk_buff *skb) | ||
159 | { | ||
160 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
161 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
162 | int slot; | ||
163 | |||
164 | tx_ctl = HTC_SKB_CB(skb); | ||
165 | |||
166 | if (tx_ctl->epid == priv->mgmt_ep) { | ||
167 | struct tx_mgmt_hdr *tx_mhdr = | ||
168 | (struct tx_mgmt_hdr *)skb->data; | ||
169 | slot = tx_mhdr->cookie; | ||
170 | skb_pull(skb, sizeof(struct tx_mgmt_hdr)); | ||
171 | } else if ((tx_ctl->epid == priv->data_bk_ep) || | ||
172 | (tx_ctl->epid == priv->data_be_ep) || | ||
173 | (tx_ctl->epid == priv->data_vi_ep) || | ||
174 | (tx_ctl->epid == priv->data_vo_ep) || | ||
175 | (tx_ctl->epid == priv->cab_ep)) { | ||
176 | struct tx_frame_hdr *tx_fhdr = | ||
177 | (struct tx_frame_hdr *)skb->data; | ||
178 | slot = tx_fhdr->cookie; | ||
179 | skb_pull(skb, sizeof(struct tx_frame_hdr)); | ||
180 | } else { | ||
181 | ath_err(common, "Unsupported EPID: %d\n", tx_ctl->epid); | ||
182 | slot = -EINVAL; | ||
183 | } | ||
184 | |||
185 | return slot; | ||
186 | } | ||
187 | |||
49 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | 188 | int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, |
50 | struct ath9k_tx_queue_info *qinfo) | 189 | struct ath9k_tx_queue_info *qinfo) |
51 | { | 190 | { |
@@ -62,8 +201,8 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | |||
62 | qi.tqi_readyTime = qinfo->tqi_readyTime; | 201 | qi.tqi_readyTime = qinfo->tqi_readyTime; |
63 | 202 | ||
64 | if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { | 203 | if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { |
65 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 204 | ath_err(ath9k_hw_common(ah), |
66 | "Unable to update hardware queue %u!\n", qnum); | 205 | "Unable to update hardware queue %u!\n", qnum); |
67 | error = -EIO; | 206 | error = -EIO; |
68 | } else { | 207 | } else { |
69 | ath9k_hw_resettxqueue(ah, qnum); | 208 | ath9k_hw_resettxqueue(ah, qnum); |
@@ -72,241 +211,592 @@ int ath_htc_txq_update(struct ath9k_htc_priv *priv, int qnum, | |||
72 | return error; | 211 | return error; |
73 | } | 212 | } |
74 | 213 | ||
75 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | 214 | static void ath9k_htc_tx_mgmt(struct ath9k_htc_priv *priv, |
215 | struct ath9k_htc_vif *avp, | ||
216 | struct sk_buff *skb, | ||
217 | u8 sta_idx, u8 vif_idx, u8 slot) | ||
218 | { | ||
219 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
220 | struct ieee80211_mgmt *mgmt; | ||
221 | struct ieee80211_hdr *hdr; | ||
222 | struct tx_mgmt_hdr mgmt_hdr; | ||
223 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
224 | u8 *tx_fhdr; | ||
225 | |||
226 | tx_ctl = HTC_SKB_CB(skb); | ||
227 | hdr = (struct ieee80211_hdr *) skb->data; | ||
228 | |||
229 | memset(tx_ctl, 0, sizeof(*tx_ctl)); | ||
230 | memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); | ||
231 | |||
232 | /* | ||
233 | * Set the TSF adjust value for probe response | ||
234 | * frame also. | ||
235 | */ | ||
236 | if (avp && unlikely(ieee80211_is_probe_resp(hdr->frame_control))) { | ||
237 | mgmt = (struct ieee80211_mgmt *)skb->data; | ||
238 | mgmt->u.probe_resp.timestamp = avp->tsfadjust; | ||
239 | } | ||
240 | |||
241 | tx_ctl->type = ATH9K_HTC_MGMT; | ||
242 | |||
243 | mgmt_hdr.node_idx = sta_idx; | ||
244 | mgmt_hdr.vif_idx = vif_idx; | ||
245 | mgmt_hdr.tidno = 0; | ||
246 | mgmt_hdr.flags = 0; | ||
247 | mgmt_hdr.cookie = slot; | ||
248 | |||
249 | mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
250 | if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
251 | mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
252 | else | ||
253 | mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
254 | |||
255 | tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); | ||
256 | memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); | ||
257 | tx_ctl->epid = priv->mgmt_ep; | ||
258 | } | ||
259 | |||
260 | static void ath9k_htc_tx_data(struct ath9k_htc_priv *priv, | ||
261 | struct ieee80211_vif *vif, | ||
262 | struct sk_buff *skb, | ||
263 | u8 sta_idx, u8 vif_idx, u8 slot, | ||
264 | bool is_cab) | ||
265 | { | ||
266 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
267 | struct ieee80211_hdr *hdr; | ||
268 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
269 | struct tx_frame_hdr tx_hdr; | ||
270 | u32 flags = 0; | ||
271 | u8 *qc, *tx_fhdr; | ||
272 | u16 qnum; | ||
273 | |||
274 | tx_ctl = HTC_SKB_CB(skb); | ||
275 | hdr = (struct ieee80211_hdr *) skb->data; | ||
276 | |||
277 | memset(tx_ctl, 0, sizeof(*tx_ctl)); | ||
278 | memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); | ||
279 | |||
280 | tx_hdr.node_idx = sta_idx; | ||
281 | tx_hdr.vif_idx = vif_idx; | ||
282 | tx_hdr.cookie = slot; | ||
283 | |||
284 | /* | ||
285 | * This is a bit redundant but it helps to get | ||
286 | * the per-packet index quickly when draining the | ||
287 | * TX queue in the HIF layer. Otherwise we would | ||
288 | * have to parse the packet contents ... | ||
289 | */ | ||
290 | tx_ctl->sta_idx = sta_idx; | ||
291 | |||
292 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
293 | tx_ctl->type = ATH9K_HTC_AMPDU; | ||
294 | tx_hdr.data_type = ATH9K_HTC_AMPDU; | ||
295 | } else { | ||
296 | tx_ctl->type = ATH9K_HTC_NORMAL; | ||
297 | tx_hdr.data_type = ATH9K_HTC_NORMAL; | ||
298 | } | ||
299 | |||
300 | if (ieee80211_is_data_qos(hdr->frame_control)) { | ||
301 | qc = ieee80211_get_qos_ctl(hdr); | ||
302 | tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | ||
303 | } | ||
304 | |||
305 | /* Check for RTS protection */ | ||
306 | if (priv->hw->wiphy->rts_threshold != (u32) -1) | ||
307 | if (skb->len > priv->hw->wiphy->rts_threshold) | ||
308 | flags |= ATH9K_HTC_TX_RTSCTS; | ||
309 | |||
310 | /* CTS-to-self */ | ||
311 | if (!(flags & ATH9K_HTC_TX_RTSCTS) && | ||
312 | (vif && vif->bss_conf.use_cts_prot)) | ||
313 | flags |= ATH9K_HTC_TX_CTSONLY; | ||
314 | |||
315 | tx_hdr.flags = cpu_to_be32(flags); | ||
316 | tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | ||
317 | if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | ||
318 | tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
319 | else | ||
320 | tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
321 | |||
322 | tx_fhdr = skb_push(skb, sizeof(tx_hdr)); | ||
323 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); | ||
324 | |||
325 | if (is_cab) { | ||
326 | CAB_STAT_INC; | ||
327 | tx_ctl->epid = priv->cab_ep; | ||
328 | return; | ||
329 | } | ||
330 | |||
331 | qnum = skb_get_queue_mapping(skb); | ||
332 | tx_ctl->epid = get_htc_epid(priv, qnum); | ||
333 | } | ||
334 | |||
335 | int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, | ||
336 | struct sk_buff *skb, | ||
337 | u8 slot, bool is_cab) | ||
76 | { | 338 | { |
77 | struct ieee80211_hdr *hdr; | 339 | struct ieee80211_hdr *hdr; |
78 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 340 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
79 | struct ieee80211_sta *sta = tx_info->control.sta; | 341 | struct ieee80211_sta *sta = tx_info->control.sta; |
342 | struct ieee80211_vif *vif = tx_info->control.vif; | ||
80 | struct ath9k_htc_sta *ista; | 343 | struct ath9k_htc_sta *ista; |
81 | struct ath9k_htc_tx_ctl tx_ctl; | 344 | struct ath9k_htc_vif *avp = NULL; |
82 | enum htc_endpoint_id epid; | ||
83 | u16 qnum; | ||
84 | __le16 fc; | ||
85 | u8 *tx_fhdr; | ||
86 | u8 sta_idx, vif_idx; | 345 | u8 sta_idx, vif_idx; |
87 | 346 | ||
88 | hdr = (struct ieee80211_hdr *) skb->data; | 347 | hdr = (struct ieee80211_hdr *) skb->data; |
89 | fc = hdr->frame_control; | ||
90 | 348 | ||
91 | if (tx_info->control.vif && | 349 | /* |
92 | (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv) | 350 | * Find out on which interface this packet has to be |
93 | vif_idx = ((struct ath9k_htc_vif *) | 351 | * sent out. |
94 | tx_info->control.vif->drv_priv)->index; | 352 | */ |
95 | else | 353 | if (vif) { |
96 | vif_idx = priv->nvifs; | 354 | avp = (struct ath9k_htc_vif *) vif->drv_priv; |
355 | vif_idx = avp->index; | ||
356 | } else { | ||
357 | if (!priv->ah->is_monitoring) { | ||
358 | ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
359 | "VIF is null, but no monitor interface !\n"); | ||
360 | return -EINVAL; | ||
361 | } | ||
362 | |||
363 | vif_idx = priv->mon_vif_idx; | ||
364 | } | ||
97 | 365 | ||
366 | /* | ||
367 | * Find out which station this packet is destined for. | ||
368 | */ | ||
98 | if (sta) { | 369 | if (sta) { |
99 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 370 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
100 | sta_idx = ista->index; | 371 | sta_idx = ista->index; |
101 | } else { | 372 | } else { |
102 | sta_idx = 0; | 373 | sta_idx = priv->vif_sta_pos[vif_idx]; |
103 | } | 374 | } |
104 | 375 | ||
105 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); | 376 | if (ieee80211_is_data(hdr->frame_control)) |
377 | ath9k_htc_tx_data(priv, vif, skb, | ||
378 | sta_idx, vif_idx, slot, is_cab); | ||
379 | else | ||
380 | ath9k_htc_tx_mgmt(priv, avp, skb, | ||
381 | sta_idx, vif_idx, slot); | ||
106 | 382 | ||
107 | if (ieee80211_is_data(fc)) { | ||
108 | struct tx_frame_hdr tx_hdr; | ||
109 | u8 *qc; | ||
110 | 383 | ||
111 | memset(&tx_hdr, 0, sizeof(struct tx_frame_hdr)); | 384 | return htc_send(priv->htc, skb); |
385 | } | ||
112 | 386 | ||
113 | tx_hdr.node_idx = sta_idx; | 387 | static inline bool __ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, |
114 | tx_hdr.vif_idx = vif_idx; | 388 | struct ath9k_htc_sta *ista, u8 tid) |
389 | { | ||
390 | bool ret = false; | ||
115 | 391 | ||
116 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { | 392 | spin_lock_bh(&priv->tx.tx_lock); |
117 | tx_ctl.type = ATH9K_HTC_AMPDU; | 393 | if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) |
118 | tx_hdr.data_type = ATH9K_HTC_AMPDU; | 394 | ret = true; |
119 | } else { | 395 | spin_unlock_bh(&priv->tx.tx_lock); |
120 | tx_ctl.type = ATH9K_HTC_NORMAL; | 396 | |
121 | tx_hdr.data_type = ATH9K_HTC_NORMAL; | 397 | return ret; |
122 | } | 398 | } |
399 | |||
400 | static void ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, | ||
401 | struct ieee80211_vif *vif, | ||
402 | struct sk_buff *skb) | ||
403 | { | ||
404 | struct ieee80211_sta *sta; | ||
405 | struct ieee80211_hdr *hdr; | ||
406 | __le16 fc; | ||
407 | |||
408 | hdr = (struct ieee80211_hdr *) skb->data; | ||
409 | fc = hdr->frame_control; | ||
410 | |||
411 | rcu_read_lock(); | ||
412 | |||
413 | sta = ieee80211_find_sta(vif, hdr->addr1); | ||
414 | if (!sta) { | ||
415 | rcu_read_unlock(); | ||
416 | return; | ||
417 | } | ||
418 | |||
419 | if (sta && conf_is_ht(&priv->hw->conf) && | ||
420 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | ||
421 | if (ieee80211_is_data_qos(fc)) { | ||
422 | u8 *qc, tid; | ||
423 | struct ath9k_htc_sta *ista; | ||
123 | 424 | ||
124 | if (ieee80211_is_data(fc)) { | ||
125 | qc = ieee80211_get_qos_ctl(hdr); | 425 | qc = ieee80211_get_qos_ctl(hdr); |
126 | tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 426 | tid = qc[0] & 0xf; |
427 | ista = (struct ath9k_htc_sta *)sta->drv_priv; | ||
428 | if (__ath9k_htc_check_tx_aggr(priv, ista, tid)) { | ||
429 | ieee80211_start_tx_ba_session(sta, tid, 0); | ||
430 | spin_lock_bh(&priv->tx.tx_lock); | ||
431 | ista->tid_state[tid] = AGGR_PROGRESS; | ||
432 | spin_unlock_bh(&priv->tx.tx_lock); | ||
433 | } | ||
127 | } | 434 | } |
435 | } | ||
128 | 436 | ||
129 | /* Check for RTS protection */ | 437 | rcu_read_unlock(); |
130 | if (priv->hw->wiphy->rts_threshold != (u32) -1) | 438 | } |
131 | if (skb->len > priv->hw->wiphy->rts_threshold) | ||
132 | tx_hdr.flags |= ATH9K_HTC_TX_RTSCTS; | ||
133 | 439 | ||
134 | /* CTS-to-self */ | 440 | static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, |
135 | if (!(tx_hdr.flags & ATH9K_HTC_TX_RTSCTS) && | 441 | struct sk_buff *skb, |
136 | (priv->op_flags & OP_PROTECT_ENABLE)) | 442 | struct __wmi_event_txstatus *txs) |
137 | tx_hdr.flags |= ATH9K_HTC_TX_CTSONLY; | 443 | { |
444 | struct ieee80211_vif *vif; | ||
445 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
446 | struct ieee80211_tx_info *tx_info; | ||
447 | struct ieee80211_tx_rate *rate; | ||
448 | struct ieee80211_conf *cur_conf = &priv->hw->conf; | ||
449 | bool txok; | ||
450 | int slot; | ||
138 | 451 | ||
139 | tx_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | 452 | slot = strip_drv_header(priv, skb); |
140 | if (tx_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | 453 | if (slot < 0) { |
141 | tx_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | 454 | dev_kfree_skb_any(skb); |
142 | else | 455 | return; |
143 | tx_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | 456 | } |
144 | 457 | ||
145 | tx_fhdr = skb_push(skb, sizeof(tx_hdr)); | 458 | tx_ctl = HTC_SKB_CB(skb); |
146 | memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr)); | 459 | txok = tx_ctl->txok; |
460 | tx_info = IEEE80211_SKB_CB(skb); | ||
461 | vif = tx_info->control.vif; | ||
462 | rate = &tx_info->status.rates[0]; | ||
147 | 463 | ||
148 | qnum = skb_get_queue_mapping(skb); | 464 | memset(&tx_info->status, 0, sizeof(tx_info->status)); |
149 | 465 | ||
150 | switch (qnum) { | 466 | /* |
151 | case 0: | 467 | * URB submission failed for this frame, it never reached |
152 | TX_QSTAT_INC(WME_AC_VO); | 468 | * the target. |
153 | epid = priv->data_vo_ep; | 469 | */ |
154 | break; | 470 | if (!txok || !vif || !txs) |
155 | case 1: | 471 | goto send_mac80211; |
156 | TX_QSTAT_INC(WME_AC_VI); | 472 | |
157 | epid = priv->data_vi_ep; | 473 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_ACK) |
158 | break; | 474 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
159 | case 2: | ||
160 | TX_QSTAT_INC(WME_AC_BE); | ||
161 | epid = priv->data_be_ep; | ||
162 | break; | ||
163 | case 3: | ||
164 | default: | ||
165 | TX_QSTAT_INC(WME_AC_BK); | ||
166 | epid = priv->data_bk_ep; | ||
167 | break; | ||
168 | } | ||
169 | } else { | ||
170 | struct tx_mgmt_hdr mgmt_hdr; | ||
171 | 475 | ||
172 | memset(&mgmt_hdr, 0, sizeof(struct tx_mgmt_hdr)); | 476 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_FILT) |
477 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | ||
173 | 478 | ||
174 | tx_ctl.type = ATH9K_HTC_NORMAL; | 479 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_RTC_CTS) |
480 | rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; | ||
175 | 481 | ||
176 | mgmt_hdr.node_idx = sta_idx; | 482 | rate->count = 1; |
177 | mgmt_hdr.vif_idx = vif_idx; | 483 | rate->idx = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_RATE); |
178 | mgmt_hdr.tidno = 0; | ||
179 | mgmt_hdr.flags = 0; | ||
180 | 484 | ||
181 | mgmt_hdr.key_type = ath9k_cmn_get_hw_crypto_keytype(skb); | 485 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_MCS) { |
182 | if (mgmt_hdr.key_type == ATH9K_KEY_TYPE_CLEAR) | 486 | rate->flags |= IEEE80211_TX_RC_MCS; |
183 | mgmt_hdr.keyix = (u8) ATH9K_TXKEYIX_INVALID; | ||
184 | else | ||
185 | mgmt_hdr.keyix = tx_info->control.hw_key->hw_key_idx; | ||
186 | 487 | ||
187 | tx_fhdr = skb_push(skb, sizeof(mgmt_hdr)); | 488 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_CW40) |
188 | memcpy(tx_fhdr, (u8 *) &mgmt_hdr, sizeof(mgmt_hdr)); | 489 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
189 | epid = priv->mgmt_ep; | 490 | if (txs->ts_flags & ATH9K_HTC_TXSTAT_SGI) |
491 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
492 | } else { | ||
493 | if (cur_conf->channel->band == IEEE80211_BAND_5GHZ) | ||
494 | rate->idx += 4; /* No CCK rates */ | ||
190 | } | 495 | } |
191 | 496 | ||
192 | return htc_send(priv->htc, skb, epid, &tx_ctl); | 497 | ath9k_htc_check_tx_aggr(priv, vif, skb); |
498 | |||
499 | send_mac80211: | ||
500 | spin_lock_bh(&priv->tx.tx_lock); | ||
501 | if (WARN_ON(--priv->tx.queued_cnt < 0)) | ||
502 | priv->tx.queued_cnt = 0; | ||
503 | spin_unlock_bh(&priv->tx.tx_lock); | ||
504 | |||
505 | ath9k_htc_tx_clear_slot(priv, slot); | ||
506 | |||
507 | /* Send status to mac80211 */ | ||
508 | ieee80211_tx_status(priv->hw, skb); | ||
193 | } | 509 | } |
194 | 510 | ||
195 | static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, | 511 | static inline void ath9k_htc_tx_drainq(struct ath9k_htc_priv *priv, |
196 | struct ath9k_htc_sta *ista, u8 tid) | 512 | struct sk_buff_head *queue) |
197 | { | 513 | { |
198 | bool ret = false; | 514 | struct sk_buff *skb; |
199 | 515 | ||
200 | spin_lock_bh(&priv->tx_lock); | 516 | while ((skb = skb_dequeue(queue)) != NULL) { |
201 | if ((tid < ATH9K_HTC_MAX_TID) && (ista->tid_state[tid] == AGGR_STOP)) | 517 | ath9k_htc_tx_process(priv, skb, NULL); |
202 | ret = true; | 518 | } |
203 | spin_unlock_bh(&priv->tx_lock); | 519 | } |
204 | 520 | ||
205 | return ret; | 521 | void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv) |
522 | { | ||
523 | struct ath9k_htc_tx_event *event, *tmp; | ||
524 | |||
525 | spin_lock_bh(&priv->tx.tx_lock); | ||
526 | priv->tx.flags |= ATH9K_HTC_OP_TX_DRAIN; | ||
527 | spin_unlock_bh(&priv->tx.tx_lock); | ||
528 | |||
529 | /* | ||
530 | * Ensure that all pending TX frames are flushed, | ||
531 | * and that the TX completion/failed tasklets is killed. | ||
532 | */ | ||
533 | htc_stop(priv->htc); | ||
534 | tasklet_kill(&priv->wmi->wmi_event_tasklet); | ||
535 | tasklet_kill(&priv->tx_failed_tasklet); | ||
536 | |||
537 | ath9k_htc_tx_drainq(priv, &priv->tx.mgmt_ep_queue); | ||
538 | ath9k_htc_tx_drainq(priv, &priv->tx.cab_ep_queue); | ||
539 | ath9k_htc_tx_drainq(priv, &priv->tx.data_be_queue); | ||
540 | ath9k_htc_tx_drainq(priv, &priv->tx.data_bk_queue); | ||
541 | ath9k_htc_tx_drainq(priv, &priv->tx.data_vi_queue); | ||
542 | ath9k_htc_tx_drainq(priv, &priv->tx.data_vo_queue); | ||
543 | ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); | ||
544 | |||
545 | /* | ||
546 | * The TX cleanup timer has already been killed. | ||
547 | */ | ||
548 | spin_lock_bh(&priv->wmi->event_lock); | ||
549 | list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { | ||
550 | list_del(&event->list); | ||
551 | kfree(event); | ||
552 | } | ||
553 | spin_unlock_bh(&priv->wmi->event_lock); | ||
554 | |||
555 | spin_lock_bh(&priv->tx.tx_lock); | ||
556 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_DRAIN; | ||
557 | spin_unlock_bh(&priv->tx.tx_lock); | ||
206 | } | 558 | } |
207 | 559 | ||
208 | void ath9k_tx_tasklet(unsigned long data) | 560 | void ath9k_tx_failed_tasklet(unsigned long data) |
209 | { | 561 | { |
210 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | 562 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
211 | struct ieee80211_sta *sta; | ||
212 | struct ieee80211_hdr *hdr; | ||
213 | struct ieee80211_tx_info *tx_info; | ||
214 | struct sk_buff *skb = NULL; | ||
215 | __le16 fc; | ||
216 | 563 | ||
217 | while ((skb = skb_dequeue(&priv->tx_queue)) != NULL) { | 564 | spin_lock_bh(&priv->tx.tx_lock); |
565 | if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { | ||
566 | spin_unlock_bh(&priv->tx.tx_lock); | ||
567 | return; | ||
568 | } | ||
569 | spin_unlock_bh(&priv->tx.tx_lock); | ||
218 | 570 | ||
219 | hdr = (struct ieee80211_hdr *) skb->data; | 571 | ath9k_htc_tx_drainq(priv, &priv->tx.tx_failed); |
220 | fc = hdr->frame_control; | 572 | } |
221 | tx_info = IEEE80211_SKB_CB(skb); | ||
222 | 573 | ||
223 | memset(&tx_info->status, 0, sizeof(tx_info->status)); | 574 | static inline bool check_cookie(struct ath9k_htc_priv *priv, |
575 | struct sk_buff *skb, | ||
576 | u8 cookie, u8 epid) | ||
577 | { | ||
578 | u8 fcookie = 0; | ||
579 | |||
580 | if (epid == priv->mgmt_ep) { | ||
581 | struct tx_mgmt_hdr *hdr; | ||
582 | hdr = (struct tx_mgmt_hdr *) skb->data; | ||
583 | fcookie = hdr->cookie; | ||
584 | } else if ((epid == priv->data_bk_ep) || | ||
585 | (epid == priv->data_be_ep) || | ||
586 | (epid == priv->data_vi_ep) || | ||
587 | (epid == priv->data_vo_ep) || | ||
588 | (epid == priv->cab_ep)) { | ||
589 | struct tx_frame_hdr *hdr; | ||
590 | hdr = (struct tx_frame_hdr *) skb->data; | ||
591 | fcookie = hdr->cookie; | ||
592 | } | ||
224 | 593 | ||
225 | rcu_read_lock(); | 594 | if (fcookie == cookie) |
595 | return true; | ||
226 | 596 | ||
227 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | 597 | return false; |
228 | if (!sta) { | 598 | } |
229 | rcu_read_unlock(); | 599 | |
230 | ieee80211_tx_status(priv->hw, skb); | 600 | static struct sk_buff* ath9k_htc_tx_get_packet(struct ath9k_htc_priv *priv, |
231 | continue; | 601 | struct __wmi_event_txstatus *txs) |
602 | { | ||
603 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
604 | struct sk_buff_head *epid_queue; | ||
605 | struct sk_buff *skb, *tmp; | ||
606 | unsigned long flags; | ||
607 | u8 epid = MS(txs->ts_rate, ATH9K_HTC_TXSTAT_EPID); | ||
608 | |||
609 | epid_queue = get_htc_epid_queue(priv, epid); | ||
610 | if (!epid_queue) | ||
611 | return NULL; | ||
612 | |||
613 | spin_lock_irqsave(&epid_queue->lock, flags); | ||
614 | skb_queue_walk_safe(epid_queue, skb, tmp) { | ||
615 | if (check_cookie(priv, skb, txs->cookie, epid)) { | ||
616 | __skb_unlink(skb, epid_queue); | ||
617 | spin_unlock_irqrestore(&epid_queue->lock, flags); | ||
618 | return skb; | ||
232 | } | 619 | } |
620 | } | ||
621 | spin_unlock_irqrestore(&epid_queue->lock, flags); | ||
233 | 622 | ||
234 | /* Check if we need to start aggregation */ | 623 | ath_dbg(common, ATH_DBG_XMIT, |
624 | "No matching packet for cookie: %d, epid: %d\n", | ||
625 | txs->cookie, epid); | ||
235 | 626 | ||
236 | if (sta && conf_is_ht(&priv->hw->conf) && | 627 | return NULL; |
237 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | 628 | } |
238 | if (ieee80211_is_data_qos(fc)) { | ||
239 | u8 *qc, tid; | ||
240 | struct ath9k_htc_sta *ista; | ||
241 | 629 | ||
242 | qc = ieee80211_get_qos_ctl(hdr); | 630 | void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event) |
243 | tid = qc[0] & 0xf; | 631 | { |
244 | ista = (struct ath9k_htc_sta *)sta->drv_priv; | 632 | struct wmi_event_txstatus *txs = (struct wmi_event_txstatus *)wmi_event; |
633 | struct __wmi_event_txstatus *__txs; | ||
634 | struct sk_buff *skb; | ||
635 | struct ath9k_htc_tx_event *tx_pend; | ||
636 | int i; | ||
245 | 637 | ||
246 | if (ath9k_htc_check_tx_aggr(priv, ista, tid)) { | 638 | for (i = 0; i < txs->cnt; i++) { |
247 | ieee80211_start_tx_ba_session(sta, tid); | 639 | WARN_ON(txs->cnt > HTC_MAX_TX_STATUS); |
248 | spin_lock_bh(&priv->tx_lock); | ||
249 | ista->tid_state[tid] = AGGR_PROGRESS; | ||
250 | spin_unlock_bh(&priv->tx_lock); | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | 640 | ||
255 | rcu_read_unlock(); | 641 | __txs = &txs->txstatus[i]; |
642 | |||
643 | skb = ath9k_htc_tx_get_packet(priv, __txs); | ||
644 | if (!skb) { | ||
645 | /* | ||
646 | * Store this event, so that the TX cleanup | ||
647 | * routine can check later for the needed packet. | ||
648 | */ | ||
649 | tx_pend = kzalloc(sizeof(struct ath9k_htc_tx_event), | ||
650 | GFP_ATOMIC); | ||
651 | if (!tx_pend) | ||
652 | continue; | ||
653 | |||
654 | memcpy(&tx_pend->txs, __txs, | ||
655 | sizeof(struct __wmi_event_txstatus)); | ||
256 | 656 | ||
257 | /* Send status to mac80211 */ | 657 | spin_lock(&priv->wmi->event_lock); |
258 | ieee80211_tx_status(priv->hw, skb); | 658 | list_add_tail(&tx_pend->list, |
659 | &priv->wmi->pending_tx_events); | ||
660 | spin_unlock(&priv->wmi->event_lock); | ||
661 | |||
662 | continue; | ||
663 | } | ||
664 | |||
665 | ath9k_htc_tx_process(priv, skb, __txs); | ||
259 | } | 666 | } |
260 | 667 | ||
261 | /* Wake TX queues if needed */ | 668 | /* Wake TX queues if needed */ |
262 | spin_lock_bh(&priv->tx_lock); | 669 | ath9k_htc_check_wake_queues(priv); |
263 | if (priv->tx_queues_stop) { | ||
264 | priv->tx_queues_stop = false; | ||
265 | spin_unlock_bh(&priv->tx_lock); | ||
266 | ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
267 | "Waking up TX queues\n"); | ||
268 | ieee80211_wake_queues(priv->hw); | ||
269 | return; | ||
270 | } | ||
271 | spin_unlock_bh(&priv->tx_lock); | ||
272 | } | 670 | } |
273 | 671 | ||
274 | void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, | 672 | void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb, |
275 | enum htc_endpoint_id ep_id, bool txok) | 673 | enum htc_endpoint_id ep_id, bool txok) |
276 | { | 674 | { |
277 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; | 675 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv; |
278 | struct ath_common *common = ath9k_hw_common(priv->ah); | 676 | struct ath9k_htc_tx_ctl *tx_ctl; |
279 | struct ieee80211_tx_info *tx_info; | 677 | struct sk_buff_head *epid_queue; |
678 | |||
679 | tx_ctl = HTC_SKB_CB(skb); | ||
680 | tx_ctl->txok = txok; | ||
681 | tx_ctl->timestamp = jiffies; | ||
280 | 682 | ||
281 | if (!skb) | 683 | if (!txok) { |
684 | skb_queue_tail(&priv->tx.tx_failed, skb); | ||
685 | tasklet_schedule(&priv->tx_failed_tasklet); | ||
282 | return; | 686 | return; |
687 | } | ||
283 | 688 | ||
284 | if (ep_id == priv->mgmt_ep) { | 689 | epid_queue = get_htc_epid_queue(priv, ep_id); |
285 | skb_pull(skb, sizeof(struct tx_mgmt_hdr)); | 690 | if (!epid_queue) { |
286 | } else if ((ep_id == priv->data_bk_ep) || | ||
287 | (ep_id == priv->data_be_ep) || | ||
288 | (ep_id == priv->data_vi_ep) || | ||
289 | (ep_id == priv->data_vo_ep)) { | ||
290 | skb_pull(skb, sizeof(struct tx_frame_hdr)); | ||
291 | } else { | ||
292 | ath_print(common, ATH_DBG_FATAL, | ||
293 | "Unsupported TX EPID: %d\n", ep_id); | ||
294 | dev_kfree_skb_any(skb); | 691 | dev_kfree_skb_any(skb); |
295 | return; | 692 | return; |
296 | } | 693 | } |
297 | 694 | ||
298 | tx_info = IEEE80211_SKB_CB(skb); | 695 | skb_queue_tail(epid_queue, skb); |
696 | } | ||
299 | 697 | ||
300 | if (txok) | 698 | static inline bool check_packet(struct ath9k_htc_priv *priv, struct sk_buff *skb) |
301 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 699 | { |
700 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
701 | struct ath9k_htc_tx_ctl *tx_ctl; | ||
702 | |||
703 | tx_ctl = HTC_SKB_CB(skb); | ||
704 | |||
705 | if (time_after(jiffies, | ||
706 | tx_ctl->timestamp + | ||
707 | msecs_to_jiffies(ATH9K_HTC_TX_TIMEOUT_INTERVAL))) { | ||
708 | ath_dbg(common, ATH_DBG_XMIT, | ||
709 | "Dropping a packet due to TX timeout\n"); | ||
710 | return true; | ||
711 | } | ||
302 | 712 | ||
303 | skb_queue_tail(&priv->tx_queue, skb); | 713 | return false; |
304 | tasklet_schedule(&priv->tx_tasklet); | 714 | } |
715 | |||
716 | static void ath9k_htc_tx_cleanup_queue(struct ath9k_htc_priv *priv, | ||
717 | struct sk_buff_head *epid_queue) | ||
718 | { | ||
719 | bool process = false; | ||
720 | unsigned long flags; | ||
721 | struct sk_buff *skb, *tmp; | ||
722 | struct sk_buff_head queue; | ||
723 | |||
724 | skb_queue_head_init(&queue); | ||
725 | |||
726 | spin_lock_irqsave(&epid_queue->lock, flags); | ||
727 | skb_queue_walk_safe(epid_queue, skb, tmp) { | ||
728 | if (check_packet(priv, skb)) { | ||
729 | __skb_unlink(skb, epid_queue); | ||
730 | __skb_queue_tail(&queue, skb); | ||
731 | process = true; | ||
732 | } | ||
733 | } | ||
734 | spin_unlock_irqrestore(&epid_queue->lock, flags); | ||
735 | |||
736 | if (process) { | ||
737 | skb_queue_walk_safe(&queue, skb, tmp) { | ||
738 | __skb_unlink(skb, &queue); | ||
739 | ath9k_htc_tx_process(priv, skb, NULL); | ||
740 | } | ||
741 | } | ||
742 | } | ||
743 | |||
744 | void ath9k_htc_tx_cleanup_timer(unsigned long data) | ||
745 | { | ||
746 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) data; | ||
747 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
748 | struct ath9k_htc_tx_event *event, *tmp; | ||
749 | struct sk_buff *skb; | ||
750 | |||
751 | spin_lock(&priv->wmi->event_lock); | ||
752 | list_for_each_entry_safe(event, tmp, &priv->wmi->pending_tx_events, list) { | ||
753 | |||
754 | skb = ath9k_htc_tx_get_packet(priv, &event->txs); | ||
755 | if (skb) { | ||
756 | ath_dbg(common, ATH_DBG_XMIT, | ||
757 | "Found packet for cookie: %d, epid: %d\n", | ||
758 | event->txs.cookie, | ||
759 | MS(event->txs.ts_rate, ATH9K_HTC_TXSTAT_EPID)); | ||
760 | |||
761 | ath9k_htc_tx_process(priv, skb, &event->txs); | ||
762 | list_del(&event->list); | ||
763 | kfree(event); | ||
764 | continue; | ||
765 | } | ||
766 | |||
767 | if (++event->count >= ATH9K_HTC_TX_TIMEOUT_COUNT) { | ||
768 | list_del(&event->list); | ||
769 | kfree(event); | ||
770 | } | ||
771 | } | ||
772 | spin_unlock(&priv->wmi->event_lock); | ||
773 | |||
774 | /* | ||
775 | * Check if status-pending packets have to be cleaned up. | ||
776 | */ | ||
777 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.mgmt_ep_queue); | ||
778 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.cab_ep_queue); | ||
779 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_be_queue); | ||
780 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_bk_queue); | ||
781 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vi_queue); | ||
782 | ath9k_htc_tx_cleanup_queue(priv, &priv->tx.data_vo_queue); | ||
783 | |||
784 | /* Wake TX queues if needed */ | ||
785 | ath9k_htc_check_wake_queues(priv); | ||
786 | |||
787 | mod_timer(&priv->tx.cleanup_timer, | ||
788 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
305 | } | 789 | } |
306 | 790 | ||
307 | int ath9k_tx_init(struct ath9k_htc_priv *priv) | 791 | int ath9k_tx_init(struct ath9k_htc_priv *priv) |
308 | { | 792 | { |
309 | skb_queue_head_init(&priv->tx_queue); | 793 | skb_queue_head_init(&priv->tx.mgmt_ep_queue); |
794 | skb_queue_head_init(&priv->tx.cab_ep_queue); | ||
795 | skb_queue_head_init(&priv->tx.data_be_queue); | ||
796 | skb_queue_head_init(&priv->tx.data_bk_queue); | ||
797 | skb_queue_head_init(&priv->tx.data_vi_queue); | ||
798 | skb_queue_head_init(&priv->tx.data_vo_queue); | ||
799 | skb_queue_head_init(&priv->tx.tx_failed); | ||
310 | return 0; | 800 | return 0; |
311 | } | 801 | } |
312 | 802 | ||
@@ -330,9 +820,8 @@ bool ath9k_htc_txq_setup(struct ath9k_htc_priv *priv, int subtype) | |||
330 | return false; | 820 | return false; |
331 | 821 | ||
332 | if (qnum >= ARRAY_SIZE(priv->hwq_map)) { | 822 | if (qnum >= ARRAY_SIZE(priv->hwq_map)) { |
333 | ath_print(common, ATH_DBG_FATAL, | 823 | ath_err(common, "qnum %u out of range, max %zu!\n", |
334 | "qnum %u out of range, max %u!\n", | 824 | qnum, ARRAY_SIZE(priv->hwq_map)); |
335 | qnum, (unsigned int)ARRAY_SIZE(priv->hwq_map)); | ||
336 | ath9k_hw_releasetxqueue(ah, qnum); | 825 | ath9k_hw_releasetxqueue(ah, qnum); |
337 | return false; | 826 | return false; |
338 | } | 827 | } |
@@ -369,8 +858,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) | |||
369 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | 858 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
370 | | ATH9K_RX_FILTER_MCAST; | 859 | | ATH9K_RX_FILTER_MCAST; |
371 | 860 | ||
372 | /* If not a STA, enable processing of Probe Requests */ | 861 | if (priv->rxfilter & FIF_PROBE_REQ) |
373 | if (ah->opmode != NL80211_IFTYPE_STATION) | ||
374 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | 862 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; |
375 | 863 | ||
376 | /* | 864 | /* |
@@ -380,20 +868,29 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) | |||
380 | */ | 868 | */ |
381 | if (((ah->opmode != NL80211_IFTYPE_AP) && | 869 | if (((ah->opmode != NL80211_IFTYPE_AP) && |
382 | (priv->rxfilter & FIF_PROMISC_IN_BSS)) || | 870 | (priv->rxfilter & FIF_PROMISC_IN_BSS)) || |
383 | (ah->opmode == NL80211_IFTYPE_MONITOR)) | 871 | ah->is_monitoring) |
384 | rfilt |= ATH9K_RX_FILTER_PROM; | 872 | rfilt |= ATH9K_RX_FILTER_PROM; |
385 | 873 | ||
386 | if (priv->rxfilter & FIF_CONTROL) | 874 | if (priv->rxfilter & FIF_CONTROL) |
387 | rfilt |= ATH9K_RX_FILTER_CONTROL; | 875 | rfilt |= ATH9K_RX_FILTER_CONTROL; |
388 | 876 | ||
389 | if ((ah->opmode == NL80211_IFTYPE_STATION) && | 877 | if ((ah->opmode == NL80211_IFTYPE_STATION) && |
878 | (priv->nvifs <= 1) && | ||
390 | !(priv->rxfilter & FIF_BCN_PRBRESP_PROMISC)) | 879 | !(priv->rxfilter & FIF_BCN_PRBRESP_PROMISC)) |
391 | rfilt |= ATH9K_RX_FILTER_MYBEACON; | 880 | rfilt |= ATH9K_RX_FILTER_MYBEACON; |
392 | else | 881 | else |
393 | rfilt |= ATH9K_RX_FILTER_BEACON; | 882 | rfilt |= ATH9K_RX_FILTER_BEACON; |
394 | 883 | ||
395 | if (conf_is_ht(&priv->hw->conf)) | 884 | if (conf_is_ht(&priv->hw->conf)) { |
396 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | 885 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; |
886 | rfilt |= ATH9K_RX_FILTER_UNCOMP_BA_BAR; | ||
887 | } | ||
888 | |||
889 | if (priv->rxfilter & FIF_PSPOLL) | ||
890 | rfilt |= ATH9K_RX_FILTER_PSPOLL; | ||
891 | |||
892 | if (priv->nvifs > 1) | ||
893 | rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; | ||
397 | 894 | ||
398 | return rfilt; | 895 | return rfilt; |
399 | 896 | ||
@@ -406,21 +903,12 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) | |||
406 | static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) | 903 | static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) |
407 | { | 904 | { |
408 | struct ath_hw *ah = priv->ah; | 905 | struct ath_hw *ah = priv->ah; |
409 | struct ath_common *common = ath9k_hw_common(ah); | ||
410 | |||
411 | u32 rfilt, mfilt[2]; | 906 | u32 rfilt, mfilt[2]; |
412 | 907 | ||
413 | /* configure rx filter */ | 908 | /* configure rx filter */ |
414 | rfilt = ath9k_htc_calcrxfilter(priv); | 909 | rfilt = ath9k_htc_calcrxfilter(priv); |
415 | ath9k_hw_setrxfilter(ah, rfilt); | 910 | ath9k_hw_setrxfilter(ah, rfilt); |
416 | 911 | ||
417 | /* configure bssid mask */ | ||
418 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | ||
419 | ath_hw_setbssidmask(common); | ||
420 | |||
421 | /* configure operational mode */ | ||
422 | ath9k_hw_setopmode(ah); | ||
423 | |||
424 | /* calculate and install multicast filter */ | 912 | /* calculate and install multicast filter */ |
425 | mfilt[0] = mfilt[1] = ~0; | 913 | mfilt[0] = mfilt[1] = ~0; |
426 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | 914 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); |
@@ -484,9 +972,9 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
484 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | 972 | int last_rssi = ATH_RSSI_DUMMY_MARKER; |
485 | __le16 fc; | 973 | __le16 fc; |
486 | 974 | ||
487 | if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) { | 975 | if (skb->len < HTC_RX_FRAME_HEADER_SIZE) { |
488 | ath_print(common, ATH_DBG_FATAL, | 976 | ath_err(common, "Corrupted RX frame, dropping (len: %d)\n", |
489 | "Corrupted RX frame, dropping\n"); | 977 | skb->len); |
490 | goto rx_next; | 978 | goto rx_next; |
491 | } | 979 | } |
492 | 980 | ||
@@ -494,13 +982,14 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
494 | 982 | ||
495 | if (be16_to_cpu(rxstatus->rs_datalen) - | 983 | if (be16_to_cpu(rxstatus->rs_datalen) - |
496 | (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) { | 984 | (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) { |
497 | ath_print(common, ATH_DBG_FATAL, | 985 | ath_err(common, |
498 | "Corrupted RX data len, dropping " | 986 | "Corrupted RX data len, dropping (dlen: %d, skblen: %d)\n", |
499 | "(dlen: %d, skblen: %d)\n", | 987 | rxstatus->rs_datalen, skb->len); |
500 | rxstatus->rs_datalen, skb->len); | ||
501 | goto rx_next; | 988 | goto rx_next; |
502 | } | 989 | } |
503 | 990 | ||
991 | ath9k_htc_err_stat_rx(priv, rxstatus); | ||
992 | |||
504 | /* Get the RX status information */ | 993 | /* Get the RX status information */ |
505 | memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); | 994 | memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE); |
506 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); | 995 | skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE); |
@@ -573,31 +1062,29 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
573 | ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate, | 1062 | ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate, |
574 | rxbuf->rxstatus.rs_flags); | 1063 | rxbuf->rxstatus.rs_flags); |
575 | 1064 | ||
576 | if (priv->op_flags & OP_ASSOCIATED) { | 1065 | if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD && |
577 | if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD && | 1066 | !rxbuf->rxstatus.rs_moreaggr) |
578 | !rxbuf->rxstatus.rs_moreaggr) | 1067 | ATH_RSSI_LPF(priv->rx.last_rssi, |
579 | ATH_RSSI_LPF(priv->rx.last_rssi, | 1068 | rxbuf->rxstatus.rs_rssi); |
580 | rxbuf->rxstatus.rs_rssi); | ||
581 | 1069 | ||
582 | last_rssi = priv->rx.last_rssi; | 1070 | last_rssi = priv->rx.last_rssi; |
583 | 1071 | ||
584 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 1072 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
585 | rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, | 1073 | rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, |
586 | ATH_RSSI_EP_MULTIPLIER); | 1074 | ATH_RSSI_EP_MULTIPLIER); |
587 | 1075 | ||
588 | if (rxbuf->rxstatus.rs_rssi < 0) | 1076 | if (rxbuf->rxstatus.rs_rssi < 0) |
589 | rxbuf->rxstatus.rs_rssi = 0; | 1077 | rxbuf->rxstatus.rs_rssi = 0; |
590 | 1078 | ||
591 | if (ieee80211_is_beacon(fc)) | 1079 | if (ieee80211_is_beacon(fc)) |
592 | priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; | 1080 | priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; |
593 | } | ||
594 | 1081 | ||
595 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); | 1082 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); |
596 | rx_status->band = hw->conf.channel->band; | 1083 | rx_status->band = hw->conf.channel->band; |
597 | rx_status->freq = hw->conf.channel->center_freq; | 1084 | rx_status->freq = hw->conf.channel->center_freq; |
598 | rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; | 1085 | rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; |
599 | rx_status->antenna = rxbuf->rxstatus.rs_antenna; | 1086 | rx_status->antenna = rxbuf->rxstatus.rs_antenna; |
600 | rx_status->flag |= RX_FLAG_TSFT; | 1087 | rx_status->flag |= RX_FLAG_MACTIME_MPDU; |
601 | 1088 | ||
602 | return true; | 1089 | return true; |
603 | 1090 | ||
@@ -680,8 +1167,8 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb, | |||
680 | spin_unlock(&priv->rx.rxbuflock); | 1167 | spin_unlock(&priv->rx.rxbuflock); |
681 | 1168 | ||
682 | if (rxbuf == NULL) { | 1169 | if (rxbuf == NULL) { |
683 | ath_print(common, ATH_DBG_ANY, | 1170 | ath_dbg(common, ATH_DBG_ANY, |
684 | "No free RX buffer\n"); | 1171 | "No free RX buffer\n"); |
685 | goto err; | 1172 | goto err; |
686 | } | 1173 | } |
687 | 1174 | ||
@@ -723,8 +1210,7 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv) | |||
723 | for (i = 0; i < ATH9K_HTC_RXBUF; i++) { | 1210 | for (i = 0; i < ATH9K_HTC_RXBUF; i++) { |
724 | rxbuf = kzalloc(sizeof(struct ath9k_htc_rxbuf), GFP_KERNEL); | 1211 | rxbuf = kzalloc(sizeof(struct ath9k_htc_rxbuf), GFP_KERNEL); |
725 | if (rxbuf == NULL) { | 1212 | if (rxbuf == NULL) { |
726 | ath_print(common, ATH_DBG_FATAL, | 1213 | ath_err(common, "Unable to allocate RX buffers\n"); |
727 | "Unable to allocate RX buffers\n"); | ||
728 | goto err; | 1214 | goto err; |
729 | } | 1215 | } |
730 | list_add_tail(&rxbuf->list, &priv->rx.rxbuf); | 1216 | list_add_tail(&rxbuf->list, &priv->rx.rxbuf); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 705c0f342e1c..1b90ed8795c3 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,8 +17,8 @@ | |||
17 | #include "htc.h" | 17 | #include "htc.h" |
18 | 18 | ||
19 | static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, | 19 | static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, |
20 | u16 len, u8 flags, u8 epid, | 20 | u16 len, u8 flags, u8 epid) |
21 | struct ath9k_htc_tx_ctl *tx_ctl) | 21 | |
22 | { | 22 | { |
23 | struct htc_frame_hdr *hdr; | 23 | struct htc_frame_hdr *hdr; |
24 | struct htc_endpoint *endpoint = &target->endpoint[epid]; | 24 | struct htc_endpoint *endpoint = &target->endpoint[epid]; |
@@ -30,8 +30,8 @@ static int htc_issue_send(struct htc_target *target, struct sk_buff* skb, | |||
30 | hdr->flags = flags; | 30 | hdr->flags = flags; |
31 | hdr->payload_len = cpu_to_be16(len); | 31 | hdr->payload_len = cpu_to_be16(len); |
32 | 32 | ||
33 | status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb, | 33 | status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb); |
34 | tx_ctl); | 34 | |
35 | return status; | 35 | return status; |
36 | } | 36 | } |
37 | 37 | ||
@@ -162,7 +162,7 @@ static int htc_config_pipe_credits(struct htc_target *target) | |||
162 | 162 | ||
163 | target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; | 163 | target->htc_flags |= HTC_OP_CONFIG_PIPE_CREDITS; |
164 | 164 | ||
165 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); | 165 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); |
166 | if (ret) | 166 | if (ret) |
167 | goto err; | 167 | goto err; |
168 | 168 | ||
@@ -197,7 +197,7 @@ static int htc_setup_complete(struct htc_target *target) | |||
197 | 197 | ||
198 | target->htc_flags |= HTC_OP_START_WAIT; | 198 | target->htc_flags |= HTC_OP_START_WAIT; |
199 | 199 | ||
200 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); | 200 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); |
201 | if (ret) | 201 | if (ret) |
202 | goto err; | 202 | goto err; |
203 | 203 | ||
@@ -268,7 +268,7 @@ int htc_connect_service(struct htc_target *target, | |||
268 | conn_msg->dl_pipeid = endpoint->dl_pipeid; | 268 | conn_msg->dl_pipeid = endpoint->dl_pipeid; |
269 | conn_msg->ul_pipeid = endpoint->ul_pipeid; | 269 | conn_msg->ul_pipeid = endpoint->ul_pipeid; |
270 | 270 | ||
271 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0, NULL); | 271 | ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0); |
272 | if (ret) | 272 | if (ret) |
273 | goto err; | 273 | goto err; |
274 | 274 | ||
@@ -286,35 +286,33 @@ err: | |||
286 | return ret; | 286 | return ret; |
287 | } | 287 | } |
288 | 288 | ||
289 | int htc_send(struct htc_target *target, struct sk_buff *skb, | 289 | int htc_send(struct htc_target *target, struct sk_buff *skb) |
290 | enum htc_endpoint_id epid, struct ath9k_htc_tx_ctl *tx_ctl) | ||
291 | { | 290 | { |
292 | return htc_issue_send(target, skb, skb->len, 0, epid, tx_ctl); | 291 | struct ath9k_htc_tx_ctl *tx_ctl; |
292 | |||
293 | tx_ctl = HTC_SKB_CB(skb); | ||
294 | return htc_issue_send(target, skb, skb->len, 0, tx_ctl->epid); | ||
293 | } | 295 | } |
294 | 296 | ||
295 | void htc_stop(struct htc_target *target) | 297 | int htc_send_epid(struct htc_target *target, struct sk_buff *skb, |
298 | enum htc_endpoint_id epid) | ||
296 | { | 299 | { |
297 | enum htc_endpoint_id epid; | 300 | return htc_issue_send(target, skb, skb->len, 0, epid); |
298 | struct htc_endpoint *endpoint; | 301 | } |
299 | 302 | ||
300 | for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { | 303 | void htc_stop(struct htc_target *target) |
301 | endpoint = &target->endpoint[epid]; | 304 | { |
302 | if (endpoint->service_id != 0) | 305 | target->hif->stop(target->hif_dev); |
303 | target->hif->stop(target->hif_dev, endpoint->ul_pipeid); | ||
304 | } | ||
305 | } | 306 | } |
306 | 307 | ||
307 | void htc_start(struct htc_target *target) | 308 | void htc_start(struct htc_target *target) |
308 | { | 309 | { |
309 | enum htc_endpoint_id epid; | 310 | target->hif->start(target->hif_dev); |
310 | struct htc_endpoint *endpoint; | 311 | } |
311 | 312 | ||
312 | for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) { | 313 | void htc_sta_drain(struct htc_target *target, u8 idx) |
313 | endpoint = &target->endpoint[epid]; | 314 | { |
314 | if (endpoint->service_id != 0) | 315 | target->hif->sta_drain(target->hif_dev, idx); |
315 | target->hif->start(target->hif_dev, | ||
316 | endpoint->ul_pipeid); | ||
317 | } | ||
318 | } | 316 | } |
319 | 317 | ||
320 | void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, | 318 | void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, |
@@ -360,7 +358,7 @@ ret: | |||
360 | * HTC Messages are handled directly here and the obtained SKB | 358 | * HTC Messages are handled directly here and the obtained SKB |
361 | * is freed. | 359 | * is freed. |
362 | * | 360 | * |
363 | * Sevice messages (Data, WMI) passed to the corresponding | 361 | * Service messages (Data, WMI) passed to the corresponding |
364 | * endpoint RX handlers, which have to free the SKB. | 362 | * endpoint RX handlers, which have to free the SKB. |
365 | */ | 363 | */ |
366 | void ath9k_htc_rx_msg(struct htc_target *htc_handle, | 364 | void ath9k_htc_rx_msg(struct htc_target *htc_handle, |
@@ -462,9 +460,10 @@ void ath9k_htc_hw_free(struct htc_target *htc) | |||
462 | } | 460 | } |
463 | 461 | ||
464 | int ath9k_htc_hw_init(struct htc_target *target, | 462 | int ath9k_htc_hw_init(struct htc_target *target, |
465 | struct device *dev, u16 devid) | 463 | struct device *dev, u16 devid, |
464 | char *product, u32 drv_info) | ||
466 | { | 465 | { |
467 | if (ath9k_htc_probe_device(target, dev, devid)) { | 466 | if (ath9k_htc_probe_device(target, dev, devid, product, drv_info)) { |
468 | printk(KERN_ERR "Failed to initialize the device\n"); | 467 | printk(KERN_ERR "Failed to initialize the device\n"); |
469 | return -ENODEV; | 468 | return -ENODEV; |
470 | } | 469 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index faba6790328b..e1ffbb6bd636 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -33,10 +33,10 @@ struct ath9k_htc_hif { | |||
33 | u8 control_dl_pipe; | 33 | u8 control_dl_pipe; |
34 | u8 control_ul_pipe; | 34 | u8 control_ul_pipe; |
35 | 35 | ||
36 | void (*start) (void *hif_handle, u8 pipe); | 36 | void (*start) (void *hif_handle); |
37 | void (*stop) (void *hif_handle, u8 pipe); | 37 | void (*stop) (void *hif_handle); |
38 | int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf, | 38 | void (*sta_drain) (void *hif_handle, u8 idx); |
39 | struct ath9k_htc_tx_ctl *tx_ctl); | 39 | int (*send) (void *hif_handle, u8 pipe, struct sk_buff *buf); |
40 | }; | 40 | }; |
41 | 41 | ||
42 | enum htc_endpoint_id { | 42 | enum htc_endpoint_id { |
@@ -77,41 +77,16 @@ struct htc_config_pipe_msg { | |||
77 | u8 credits; | 77 | u8 credits; |
78 | } __packed; | 78 | } __packed; |
79 | 79 | ||
80 | struct htc_packet { | ||
81 | void *pktcontext; | ||
82 | u8 *buf; | ||
83 | u8 *buf_payload; | ||
84 | u32 buflen; | ||
85 | u32 payload_len; | ||
86 | |||
87 | int endpoint; | ||
88 | int status; | ||
89 | |||
90 | void *context; | ||
91 | u32 reserved; | ||
92 | }; | ||
93 | |||
94 | struct htc_ep_callbacks { | 80 | struct htc_ep_callbacks { |
95 | void *priv; | 81 | void *priv; |
96 | void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok); | 82 | void (*tx) (void *, struct sk_buff *, enum htc_endpoint_id, bool txok); |
97 | void (*rx) (void *, struct sk_buff *, enum htc_endpoint_id); | 83 | void (*rx) (void *, struct sk_buff *, enum htc_endpoint_id); |
98 | }; | 84 | }; |
99 | 85 | ||
100 | #define HTC_TX_QUEUE_SIZE 256 | ||
101 | |||
102 | struct htc_txq { | ||
103 | struct sk_buff *buf[HTC_TX_QUEUE_SIZE]; | ||
104 | u32 txqdepth; | ||
105 | u16 txbuf_cnt; | ||
106 | u16 txq_head; | ||
107 | u16 txq_tail; | ||
108 | }; | ||
109 | |||
110 | struct htc_endpoint { | 86 | struct htc_endpoint { |
111 | u16 service_id; | 87 | u16 service_id; |
112 | 88 | ||
113 | struct htc_ep_callbacks ep_callbacks; | 89 | struct htc_ep_callbacks ep_callbacks; |
114 | struct htc_txq htc_txq; | ||
115 | u32 max_txqdepth; | 90 | u32 max_txqdepth; |
116 | int max_msglen; | 91 | int max_msglen; |
117 | 92 | ||
@@ -123,11 +98,6 @@ struct htc_endpoint { | |||
123 | #define HTC_CONTROL_BUFFER_SIZE \ | 98 | #define HTC_CONTROL_BUFFER_SIZE \ |
124 | (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) | 99 | (HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr)) |
125 | 100 | ||
126 | struct htc_control_buf { | ||
127 | struct htc_packet htc_pkt; | ||
128 | u8 buf[HTC_CONTROL_BUFFER_SIZE]; | ||
129 | }; | ||
130 | |||
131 | #define HTC_OP_START_WAIT BIT(0) | 101 | #define HTC_OP_START_WAIT BIT(0) |
132 | #define HTC_OP_CONFIG_PIPE_CREDITS BIT(1) | 102 | #define HTC_OP_CONFIG_PIPE_CREDITS BIT(1) |
133 | 103 | ||
@@ -224,10 +194,12 @@ int htc_init(struct htc_target *target); | |||
224 | int htc_connect_service(struct htc_target *target, | 194 | int htc_connect_service(struct htc_target *target, |
225 | struct htc_service_connreq *service_connreq, | 195 | struct htc_service_connreq *service_connreq, |
226 | enum htc_endpoint_id *conn_rsp_eid); | 196 | enum htc_endpoint_id *conn_rsp_eid); |
227 | int htc_send(struct htc_target *target, struct sk_buff *skb, | 197 | int htc_send(struct htc_target *target, struct sk_buff *skb); |
228 | enum htc_endpoint_id eid, struct ath9k_htc_tx_ctl *tx_ctl); | 198 | int htc_send_epid(struct htc_target *target, struct sk_buff *skb, |
199 | enum htc_endpoint_id epid); | ||
229 | void htc_stop(struct htc_target *target); | 200 | void htc_stop(struct htc_target *target); |
230 | void htc_start(struct htc_target *target); | 201 | void htc_start(struct htc_target *target); |
202 | void htc_sta_drain(struct htc_target *target, u8 idx); | ||
231 | 203 | ||
232 | void ath9k_htc_rx_msg(struct htc_target *htc_handle, | 204 | void ath9k_htc_rx_msg(struct htc_target *htc_handle, |
233 | struct sk_buff *skb, u32 len, u8 pipe_id); | 205 | struct sk_buff *skb, u32 len, u8 pipe_id); |
@@ -239,7 +211,8 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, | |||
239 | struct device *dev); | 211 | struct device *dev); |
240 | void ath9k_htc_hw_free(struct htc_target *htc); | 212 | void ath9k_htc_hw_free(struct htc_target *htc); |
241 | int ath9k_htc_hw_init(struct htc_target *target, | 213 | int ath9k_htc_hw_init(struct htc_target *target, |
242 | struct device *dev, u16 devid); | 214 | struct device *dev, u16 devid, char *product, |
215 | u32 drv_info); | ||
243 | void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); | 216 | void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); |
244 | 217 | ||
245 | #endif /* HTC_HST_H */ | 218 | #endif /* HTC_HST_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index ffecbadaea4a..2f3e07263fcb 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -116,27 +116,21 @@ static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds) | |||
116 | ath9k_hw_ops(ah)->clr11n_aggr(ah, ds); | 116 | ath9k_hw_ops(ah)->clr11n_aggr(ah, ds); |
117 | } | 117 | } |
118 | 118 | ||
119 | static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, | 119 | static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) |
120 | u32 burstDuration) | ||
121 | { | 120 | { |
122 | ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); | 121 | ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); |
123 | } | 122 | } |
124 | 123 | ||
125 | static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds, | 124 | static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, |
126 | u32 vmf) | 125 | struct ath_hw_antcomb_conf *antconf) |
127 | { | 126 | { |
128 | ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf); | 127 | ath9k_hw_ops(ah)->antdiv_comb_conf_get(ah, antconf); |
129 | } | 128 | } |
130 | 129 | ||
131 | static inline void ath9k_hw_procmibevent(struct ath_hw *ah) | 130 | static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, |
131 | struct ath_hw_antcomb_conf *antconf) | ||
132 | { | 132 | { |
133 | ath9k_hw_ops(ah)->ani_proc_mib_event(ah); | 133 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); |
134 | } | ||
135 | |||
136 | static inline void ath9k_hw_ani_monitor(struct ath_hw *ah, | ||
137 | struct ath9k_channel *chan) | ||
138 | { | ||
139 | ath9k_hw_ops(ah)->ani_monitor(ah, chan); | ||
140 | } | 134 | } |
141 | 135 | ||
142 | /* Private hardware call ops */ | 136 | /* Private hardware call ops */ |
@@ -234,11 +228,6 @@ static inline void ath9k_hw_rfbus_done(struct ath_hw *ah) | |||
234 | return ath9k_hw_private_ops(ah)->rfbus_done(ah); | 228 | return ath9k_hw_private_ops(ah)->rfbus_done(ah); |
235 | } | 229 | } |
236 | 230 | ||
237 | static inline void ath9k_enable_rfkill(struct ath_hw *ah) | ||
238 | { | ||
239 | return ath9k_hw_private_ops(ah)->enable_rfkill(ah); | ||
240 | } | ||
241 | |||
242 | static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah) | 231 | static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah) |
243 | { | 232 | { |
244 | if (!ath9k_hw_private_ops(ah)->restore_chainmask) | 233 | if (!ath9k_hw_private_ops(ah)->restore_chainmask) |
@@ -276,15 +265,4 @@ static inline void ath9k_hw_setup_calibration(struct ath_hw *ah, | |||
276 | ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal); | 265 | ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal); |
277 | } | 266 | } |
278 | 267 | ||
279 | static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah, | ||
280 | enum ath9k_cal_types calType) | ||
281 | { | ||
282 | return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType); | ||
283 | } | ||
284 | |||
285 | static inline void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) | ||
286 | { | ||
287 | ath9k_hw_private_ops(ah)->ani_reset(ah, is_scanning); | ||
288 | } | ||
289 | |||
290 | #endif /* ATH9K_HW_OPS_H */ | 268 | #endif /* ATH9K_HW_OPS_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 3384ca164562..1be7c8bbef84 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -54,13 +54,6 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah) | |||
54 | ath9k_hw_private_ops(ah)->init_mode_regs(ah); | 54 | ath9k_hw_private_ops(ah)->init_mode_regs(ah); |
55 | } | 55 | } |
56 | 56 | ||
57 | static bool ath9k_hw_macversion_supported(struct ath_hw *ah) | ||
58 | { | ||
59 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
60 | |||
61 | return priv_ops->macversion_supported(ah->hw_version.macVersion); | ||
62 | } | ||
63 | |||
64 | static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, | 57 | static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah, |
65 | struct ath9k_channel *chan) | 58 | struct ath9k_channel *chan) |
66 | { | 59 | { |
@@ -88,29 +81,32 @@ static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
88 | /* Helper Functions */ | 81 | /* Helper Functions */ |
89 | /********************/ | 82 | /********************/ |
90 | 83 | ||
91 | static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) | 84 | static void ath9k_hw_set_clockrate(struct ath_hw *ah) |
92 | { | 85 | { |
93 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 86 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; |
87 | struct ath_common *common = ath9k_hw_common(ah); | ||
88 | unsigned int clockrate; | ||
94 | 89 | ||
95 | if (!ah->curchan) /* should really check for CCK instead */ | 90 | if (!ah->curchan) /* should really check for CCK instead */ |
96 | return usecs *ATH9K_CLOCK_RATE_CCK; | 91 | clockrate = ATH9K_CLOCK_RATE_CCK; |
97 | if (conf->channel->band == IEEE80211_BAND_2GHZ) | 92 | else if (conf->channel->band == IEEE80211_BAND_2GHZ) |
98 | return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM; | 93 | clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; |
99 | 94 | else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) | |
100 | if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) | 95 | clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; |
101 | return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; | ||
102 | else | 96 | else |
103 | return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM; | 97 | clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; |
98 | |||
99 | if (conf_is_ht40(conf)) | ||
100 | clockrate *= 2; | ||
101 | |||
102 | common->clockrate = clockrate; | ||
104 | } | 103 | } |
105 | 104 | ||
106 | static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) | 105 | static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) |
107 | { | 106 | { |
108 | struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; | 107 | struct ath_common *common = ath9k_hw_common(ah); |
109 | 108 | ||
110 | if (conf_is_ht40(conf)) | 109 | return usecs * common->clockrate; |
111 | return ath9k_hw_mac_clks(ah, usecs) * 2; | ||
112 | else | ||
113 | return ath9k_hw_mac_clks(ah, usecs); | ||
114 | } | 110 | } |
115 | 111 | ||
116 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) | 112 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) |
@@ -126,14 +122,28 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) | |||
126 | udelay(AH_TIME_QUANTUM); | 122 | udelay(AH_TIME_QUANTUM); |
127 | } | 123 | } |
128 | 124 | ||
129 | ath_print(ath9k_hw_common(ah), ATH_DBG_ANY, | 125 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_ANY, |
130 | "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", | 126 | "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", |
131 | timeout, reg, REG_READ(ah, reg), mask, val); | 127 | timeout, reg, REG_READ(ah, reg), mask, val); |
132 | 128 | ||
133 | return false; | 129 | return false; |
134 | } | 130 | } |
135 | EXPORT_SYMBOL(ath9k_hw_wait); | 131 | EXPORT_SYMBOL(ath9k_hw_wait); |
136 | 132 | ||
133 | void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, | ||
134 | int column, unsigned int *writecnt) | ||
135 | { | ||
136 | int r; | ||
137 | |||
138 | ENABLE_REGWRITE_BUFFER(ah); | ||
139 | for (r = 0; r < array->ia_rows; r++) { | ||
140 | REG_WRITE(ah, INI_RA(array, r, 0), | ||
141 | INI_RA(array, r, column)); | ||
142 | DO_DELAY(*writecnt); | ||
143 | } | ||
144 | REGWRITE_BUFFER_FLUSH(ah); | ||
145 | } | ||
146 | |||
137 | u32 ath9k_hw_reverse_bits(u32 val, u32 n) | 147 | u32 ath9k_hw_reverse_bits(u32 val, u32 n) |
138 | { | 148 | { |
139 | u32 retval; | 149 | u32 retval; |
@@ -146,25 +156,6 @@ u32 ath9k_hw_reverse_bits(u32 val, u32 n) | |||
146 | return retval; | 156 | return retval; |
147 | } | 157 | } |
148 | 158 | ||
149 | bool ath9k_get_channel_edges(struct ath_hw *ah, | ||
150 | u16 flags, u16 *low, | ||
151 | u16 *high) | ||
152 | { | ||
153 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
154 | |||
155 | if (flags & CHANNEL_5GHZ) { | ||
156 | *low = pCap->low_5ghz_chan; | ||
157 | *high = pCap->high_5ghz_chan; | ||
158 | return true; | ||
159 | } | ||
160 | if ((flags & CHANNEL_2GHZ)) { | ||
161 | *low = pCap->low_2ghz_chan; | ||
162 | *high = pCap->high_2ghz_chan; | ||
163 | return true; | ||
164 | } | ||
165 | return false; | ||
166 | } | ||
167 | |||
168 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, | 159 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, |
169 | u8 phy, int kbps, | 160 | u8 phy, int kbps, |
170 | u32 frameLen, u16 rateix, | 161 | u32 frameLen, u16 rateix, |
@@ -208,8 +199,8 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah, | |||
208 | } | 199 | } |
209 | break; | 200 | break; |
210 | default: | 201 | default: |
211 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 202 | ath_err(ath9k_hw_common(ah), |
212 | "Unknown phy %u (rate ix %u)\n", phy, rateix); | 203 | "Unknown phy %u (rate ix %u)\n", phy, rateix); |
213 | txTime = 0; | 204 | txTime = 0; |
214 | break; | 205 | break; |
215 | } | 206 | } |
@@ -256,6 +247,17 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) | |||
256 | { | 247 | { |
257 | u32 val; | 248 | u32 val; |
258 | 249 | ||
250 | switch (ah->hw_version.devid) { | ||
251 | case AR5416_AR9100_DEVID: | ||
252 | ah->hw_version.macVersion = AR_SREV_VERSION_9100; | ||
253 | break; | ||
254 | case AR9300_DEVID_AR9340: | ||
255 | ah->hw_version.macVersion = AR_SREV_VERSION_9340; | ||
256 | val = REG_READ(ah, AR_SREV); | ||
257 | ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); | ||
258 | return; | ||
259 | } | ||
260 | |||
259 | val = REG_READ(ah, AR_SREV) & AR_SREV_ID; | 261 | val = REG_READ(ah, AR_SREV) & AR_SREV_ID; |
260 | 262 | ||
261 | if (val == 0xFF) { | 263 | if (val == 0xFF) { |
@@ -281,11 +283,9 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah) | |||
281 | 283 | ||
282 | static void ath9k_hw_disablepcie(struct ath_hw *ah) | 284 | static void ath9k_hw_disablepcie(struct ath_hw *ah) |
283 | { | 285 | { |
284 | if (AR_SREV_9100(ah)) | 286 | if (!AR_SREV_5416(ah)) |
285 | return; | 287 | return; |
286 | 288 | ||
287 | ENABLE_REGWRITE_BUFFER(ah); | ||
288 | |||
289 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); | 289 | REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); |
290 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); | 290 | REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); |
291 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); | 291 | REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); |
@@ -297,9 +297,6 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah) | |||
297 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); | 297 | REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); |
298 | 298 | ||
299 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); | 299 | REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); |
300 | |||
301 | REGWRITE_BUFFER_FLUSH(ah); | ||
302 | DISABLE_REGWRITE_BUFFER(ah); | ||
303 | } | 300 | } |
304 | 301 | ||
305 | /* This should work for all families including legacy */ | 302 | /* This should work for all families including legacy */ |
@@ -308,10 +305,9 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
308 | struct ath_common *common = ath9k_hw_common(ah); | 305 | struct ath_common *common = ath9k_hw_common(ah); |
309 | u32 regAddr[2] = { AR_STA_ID0 }; | 306 | u32 regAddr[2] = { AR_STA_ID0 }; |
310 | u32 regHold[2]; | 307 | u32 regHold[2]; |
311 | u32 patternData[4] = { 0x55555555, | 308 | static const u32 patternData[4] = { |
312 | 0xaaaaaaaa, | 309 | 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999 |
313 | 0x66666666, | 310 | }; |
314 | 0x99999999 }; | ||
315 | int i, j, loop_max; | 311 | int i, j, loop_max; |
316 | 312 | ||
317 | if (!AR_SREV_9300_20_OR_LATER(ah)) { | 313 | if (!AR_SREV_9300_20_OR_LATER(ah)) { |
@@ -330,11 +326,9 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
330 | REG_WRITE(ah, addr, wrData); | 326 | REG_WRITE(ah, addr, wrData); |
331 | rdData = REG_READ(ah, addr); | 327 | rdData = REG_READ(ah, addr); |
332 | if (rdData != wrData) { | 328 | if (rdData != wrData) { |
333 | ath_print(common, ATH_DBG_FATAL, | 329 | ath_err(common, |
334 | "address test failed " | 330 | "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", |
335 | "addr: 0x%08x - wr:0x%08x != " | 331 | addr, wrData, rdData); |
336 | "rd:0x%08x\n", | ||
337 | addr, wrData, rdData); | ||
338 | return false; | 332 | return false; |
339 | } | 333 | } |
340 | } | 334 | } |
@@ -343,11 +337,9 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah) | |||
343 | REG_WRITE(ah, addr, wrData); | 337 | REG_WRITE(ah, addr, wrData); |
344 | rdData = REG_READ(ah, addr); | 338 | rdData = REG_READ(ah, addr); |
345 | if (wrData != rdData) { | 339 | if (wrData != rdData) { |
346 | ath_print(common, ATH_DBG_FATAL, | 340 | ath_err(common, |
347 | "address test failed " | 341 | "address test failed addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", |
348 | "addr: 0x%08x - wr:0x%08x != " | 342 | addr, wrData, rdData); |
349 | "rd:0x%08x\n", | ||
350 | addr, wrData, rdData); | ||
351 | return false; | 343 | return false; |
352 | } | 344 | } |
353 | } | 345 | } |
@@ -371,10 +363,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
371 | ah->config.pcie_clock_req = 0; | 363 | ah->config.pcie_clock_req = 0; |
372 | ah->config.pcie_waen = 0; | 364 | ah->config.pcie_waen = 0; |
373 | ah->config.analog_shiftreg = 1; | 365 | ah->config.analog_shiftreg = 1; |
374 | ah->config.ofdm_trig_low = 200; | ||
375 | ah->config.ofdm_trig_high = 500; | ||
376 | ah->config.cck_trig_high = 200; | ||
377 | ah->config.cck_trig_low = 100; | ||
378 | ah->config.enable_ani = true; | 366 | ah->config.enable_ani = true; |
379 | 367 | ||
380 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | 368 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
@@ -382,10 +370,8 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
382 | ah->config.spurchans[i][1] = AR_NO_SPUR; | 370 | ah->config.spurchans[i][1] = AR_NO_SPUR; |
383 | } | 371 | } |
384 | 372 | ||
385 | if (ah->hw_version.devid != AR2427_DEVID_PCIE) | 373 | /* PAPRD needs some more work to be enabled */ |
386 | ah->config.ht_enable = 1; | 374 | ah->config.paprd_disable = 1; |
387 | else | ||
388 | ah->config.ht_enable = 0; | ||
389 | 375 | ||
390 | ah->config.rx_intr_mitigation = true; | 376 | ah->config.rx_intr_mitigation = true; |
391 | ah->config.pcieSerDesWrite = true; | 377 | ah->config.pcieSerDesWrite = true; |
@@ -421,17 +407,14 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
421 | ah->hw_version.magic = AR5416_MAGIC; | 407 | ah->hw_version.magic = AR5416_MAGIC; |
422 | ah->hw_version.subvendorid = 0; | 408 | ah->hw_version.subvendorid = 0; |
423 | 409 | ||
424 | ah->ah_flags = 0; | ||
425 | if (!AR_SREV_9100(ah)) | ||
426 | ah->ah_flags = AH_USE_EEPROM; | ||
427 | |||
428 | ah->atim_window = 0; | 410 | ah->atim_window = 0; |
429 | ah->sta_id1_defaults = | 411 | ah->sta_id1_defaults = |
430 | AR_STA_ID1_CRPT_MIC_ENABLE | | 412 | AR_STA_ID1_CRPT_MIC_ENABLE | |
431 | AR_STA_ID1_MCAST_KSRCH; | 413 | AR_STA_ID1_MCAST_KSRCH; |
432 | ah->beacon_interval = 100; | 414 | if (AR_SREV_9100(ah)) |
415 | ah->sta_id1_defaults |= AR_STA_ID1_AR9100_BA_FIX; | ||
433 | ah->enable_32kHz_clock = DONT_USE_32KHZ; | 416 | ah->enable_32kHz_clock = DONT_USE_32KHZ; |
434 | ah->slottime = (u32) -1; | 417 | ah->slottime = 20; |
435 | ah->globaltxtimeout = (u32) -1; | 418 | ah->globaltxtimeout = (u32) -1; |
436 | ah->power_mode = ATH9K_PM_UNDEFINED; | 419 | ah->power_mode = ATH9K_PM_UNDEFINED; |
437 | } | 420 | } |
@@ -442,7 +425,7 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) | |||
442 | u32 sum; | 425 | u32 sum; |
443 | int i; | 426 | int i; |
444 | u16 eeval; | 427 | u16 eeval; |
445 | u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW }; | 428 | static const u32 EEP_MAC[] = { EEP_MAC_LSW, EEP_MAC_MID, EEP_MAC_MSW }; |
446 | 429 | ||
447 | sum = 0; | 430 | sum = 0; |
448 | for (i = 0; i < 3; i++) { | 431 | for (i = 0; i < 3; i++) { |
@@ -459,9 +442,10 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) | |||
459 | 442 | ||
460 | static int ath9k_hw_post_init(struct ath_hw *ah) | 443 | static int ath9k_hw_post_init(struct ath_hw *ah) |
461 | { | 444 | { |
445 | struct ath_common *common = ath9k_hw_common(ah); | ||
462 | int ecode; | 446 | int ecode; |
463 | 447 | ||
464 | if (!AR_SREV_9271(ah)) { | 448 | if (common->bus_ops->ath_bus_type != ATH_USB) { |
465 | if (!ath9k_hw_chip_test(ah)) | 449 | if (!ath9k_hw_chip_test(ah)) |
466 | return -ENODEV; | 450 | return -ENODEV; |
467 | } | 451 | } |
@@ -476,20 +460,20 @@ static int ath9k_hw_post_init(struct ath_hw *ah) | |||
476 | if (ecode != 0) | 460 | if (ecode != 0) |
477 | return ecode; | 461 | return ecode; |
478 | 462 | ||
479 | ath_print(ath9k_hw_common(ah), ATH_DBG_CONFIG, | 463 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_CONFIG, |
480 | "Eeprom VER: %d, REV: %d\n", | 464 | "Eeprom VER: %d, REV: %d\n", |
481 | ah->eep_ops->get_eeprom_ver(ah), | 465 | ah->eep_ops->get_eeprom_ver(ah), |
482 | ah->eep_ops->get_eeprom_rev(ah)); | 466 | ah->eep_ops->get_eeprom_rev(ah)); |
483 | 467 | ||
484 | ecode = ath9k_hw_rf_alloc_ext_banks(ah); | 468 | ecode = ath9k_hw_rf_alloc_ext_banks(ah); |
485 | if (ecode) { | 469 | if (ecode) { |
486 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 470 | ath_err(ath9k_hw_common(ah), |
487 | "Failed allocating banks for " | 471 | "Failed allocating banks for external radio\n"); |
488 | "external radio\n"); | 472 | ath9k_hw_rf_free_ext_banks(ah); |
489 | return ecode; | 473 | return ecode; |
490 | } | 474 | } |
491 | 475 | ||
492 | if (!AR_SREV_9100(ah)) { | 476 | if (!AR_SREV_9100(ah) && !AR_SREV_9340(ah)) { |
493 | ath9k_hw_ani_setup(ah); | 477 | ath9k_hw_ani_setup(ah); |
494 | ath9k_hw_ani_init(ah); | 478 | ath9k_hw_ani_init(ah); |
495 | } | 479 | } |
@@ -511,12 +495,19 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
511 | struct ath_common *common = ath9k_hw_common(ah); | 495 | struct ath_common *common = ath9k_hw_common(ah); |
512 | int r = 0; | 496 | int r = 0; |
513 | 497 | ||
514 | if (ah->hw_version.devid == AR5416_AR9100_DEVID) | 498 | ath9k_hw_read_revisions(ah); |
515 | ah->hw_version.macVersion = AR_SREV_VERSION_9100; | 499 | |
500 | /* | ||
501 | * Read back AR_WA into a permanent copy and set bits 14 and 17. | ||
502 | * We need to do this to avoid RMW of this register. We cannot | ||
503 | * read the reg when chip is asleep. | ||
504 | */ | ||
505 | ah->WARegVal = REG_READ(ah, AR_WA); | ||
506 | ah->WARegVal |= (AR_WA_D3_L1_DISABLE | | ||
507 | AR_WA_ASPM_TIMER_BASED_DISABLE); | ||
516 | 508 | ||
517 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { | 509 | if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { |
518 | ath_print(common, ATH_DBG_FATAL, | 510 | ath_err(common, "Couldn't reset chip\n"); |
519 | "Couldn't reset chip\n"); | ||
520 | return -EIO; | 511 | return -EIO; |
521 | } | 512 | } |
522 | 513 | ||
@@ -526,7 +517,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
526 | ath9k_hw_attach_ops(ah); | 517 | ath9k_hw_attach_ops(ah); |
527 | 518 | ||
528 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { | 519 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { |
529 | ath_print(common, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); | 520 | ath_err(common, "Couldn't wakeup chip\n"); |
530 | return -EIO; | 521 | return -EIO; |
531 | } | 522 | } |
532 | 523 | ||
@@ -542,7 +533,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
542 | } | 533 | } |
543 | } | 534 | } |
544 | 535 | ||
545 | ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n", | 536 | ath_dbg(common, ATH_DBG_RESET, "serialize_regmode is %d\n", |
546 | ah->config.serialize_regmode); | 537 | ah->config.serialize_regmode); |
547 | 538 | ||
548 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | 539 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) |
@@ -550,36 +541,40 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
550 | else | 541 | else |
551 | ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; | 542 | ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; |
552 | 543 | ||
553 | if (!ath9k_hw_macversion_supported(ah)) { | 544 | switch (ah->hw_version.macVersion) { |
554 | ath_print(common, ATH_DBG_FATAL, | 545 | case AR_SREV_VERSION_5416_PCI: |
555 | "Mac Chip Rev 0x%02x.%x is not supported by " | 546 | case AR_SREV_VERSION_5416_PCIE: |
556 | "this driver\n", ah->hw_version.macVersion, | 547 | case AR_SREV_VERSION_9160: |
557 | ah->hw_version.macRev); | 548 | case AR_SREV_VERSION_9100: |
549 | case AR_SREV_VERSION_9280: | ||
550 | case AR_SREV_VERSION_9285: | ||
551 | case AR_SREV_VERSION_9287: | ||
552 | case AR_SREV_VERSION_9271: | ||
553 | case AR_SREV_VERSION_9300: | ||
554 | case AR_SREV_VERSION_9485: | ||
555 | case AR_SREV_VERSION_9340: | ||
556 | break; | ||
557 | default: | ||
558 | ath_err(common, | ||
559 | "Mac Chip Rev 0x%02x.%x is not supported by this driver\n", | ||
560 | ah->hw_version.macVersion, ah->hw_version.macRev); | ||
558 | return -EOPNOTSUPP; | 561 | return -EOPNOTSUPP; |
559 | } | 562 | } |
560 | 563 | ||
561 | if (AR_SREV_9271(ah) || AR_SREV_9100(ah)) | 564 | if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah)) |
562 | ah->is_pciexpress = false; | 565 | ah->is_pciexpress = false; |
563 | 566 | ||
564 | ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); | 567 | ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); |
565 | ath9k_hw_init_cal_settings(ah); | 568 | ath9k_hw_init_cal_settings(ah); |
566 | 569 | ||
567 | ah->ani_function = ATH9K_ANI_ALL; | 570 | ah->ani_function = ATH9K_ANI_ALL; |
568 | if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) | 571 | if (AR_SREV_9280_20_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) |
569 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; | 572 | ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; |
570 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 573 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
571 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; | 574 | ah->ani_function &= ~ATH9K_ANI_MRC_CCK; |
572 | 575 | ||
573 | ath9k_hw_init_mode_regs(ah); | 576 | ath9k_hw_init_mode_regs(ah); |
574 | 577 | ||
575 | /* | ||
576 | * Read back AR_WA into a permanent copy and set bits 14 and 17. | ||
577 | * We need to do this to avoid RMW of this register. We cannot | ||
578 | * read the reg when chip is asleep. | ||
579 | */ | ||
580 | ah->WARegVal = REG_READ(ah, AR_WA); | ||
581 | ah->WARegVal |= (AR_WA_D3_L1_DISABLE | | ||
582 | AR_WA_ASPM_TIMER_BASED_DISABLE); | ||
583 | 578 | ||
584 | if (ah->is_pciexpress) | 579 | if (ah->is_pciexpress) |
585 | ath9k_hw_configpcipowersave(ah, 0, 0); | 580 | ath9k_hw_configpcipowersave(ah, 0, 0); |
@@ -600,8 +595,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) | |||
600 | 595 | ||
601 | r = ath9k_hw_init_macaddr(ah); | 596 | r = ath9k_hw_init_macaddr(ah); |
602 | if (r) { | 597 | if (r) { |
603 | ath_print(common, ATH_DBG_FATAL, | 598 | ath_err(common, "Failed to initialize MAC address\n"); |
604 | "Failed to initialize MAC address\n"); | ||
605 | return r; | 599 | return r; |
606 | } | 600 | } |
607 | 601 | ||
@@ -635,21 +629,22 @@ int ath9k_hw_init(struct ath_hw *ah) | |||
635 | case AR9287_DEVID_PCIE: | 629 | case AR9287_DEVID_PCIE: |
636 | case AR2427_DEVID_PCIE: | 630 | case AR2427_DEVID_PCIE: |
637 | case AR9300_DEVID_PCIE: | 631 | case AR9300_DEVID_PCIE: |
632 | case AR9300_DEVID_AR9485_PCIE: | ||
633 | case AR9300_DEVID_AR9340: | ||
638 | break; | 634 | break; |
639 | default: | 635 | default: |
640 | if (common->bus_ops->ath_bus_type == ATH_USB) | 636 | if (common->bus_ops->ath_bus_type == ATH_USB) |
641 | break; | 637 | break; |
642 | ath_print(common, ATH_DBG_FATAL, | 638 | ath_err(common, "Hardware device ID 0x%04x not supported\n", |
643 | "Hardware device ID 0x%04x not supported\n", | 639 | ah->hw_version.devid); |
644 | ah->hw_version.devid); | ||
645 | return -EOPNOTSUPP; | 640 | return -EOPNOTSUPP; |
646 | } | 641 | } |
647 | 642 | ||
648 | ret = __ath9k_hw_init(ah); | 643 | ret = __ath9k_hw_init(ah); |
649 | if (ret) { | 644 | if (ret) { |
650 | ath_print(common, ATH_DBG_FATAL, | 645 | ath_err(common, |
651 | "Unable to initialize hardware; " | 646 | "Unable to initialize hardware; initialization status: %d\n", |
652 | "initialization status: %d\n", ret); | 647 | ret); |
653 | return ret; | 648 | return ret; |
654 | } | 649 | } |
655 | 650 | ||
@@ -676,16 +671,101 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) | |||
676 | REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); | 671 | REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); |
677 | 672 | ||
678 | REGWRITE_BUFFER_FLUSH(ah); | 673 | REGWRITE_BUFFER_FLUSH(ah); |
679 | DISABLE_REGWRITE_BUFFER(ah); | ||
680 | } | 674 | } |
681 | 675 | ||
676 | u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) | ||
677 | { | ||
678 | REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); | ||
679 | udelay(100); | ||
680 | REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); | ||
681 | |||
682 | while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) | ||
683 | udelay(100); | ||
684 | |||
685 | return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; | ||
686 | } | ||
687 | EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); | ||
688 | |||
682 | static void ath9k_hw_init_pll(struct ath_hw *ah, | 689 | static void ath9k_hw_init_pll(struct ath_hw *ah, |
683 | struct ath9k_channel *chan) | 690 | struct ath9k_channel *chan) |
684 | { | 691 | { |
685 | u32 pll = ath9k_hw_compute_pll_control(ah, chan); | 692 | u32 pll; |
693 | |||
694 | if (AR_SREV_9485(ah)) { | ||
695 | |||
696 | /* program BB PLL ki and kd value, ki=0x4, kd=0x40 */ | ||
697 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
698 | AR_CH0_BB_DPLL2_PLL_PWD, 0x1); | ||
699 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
700 | AR_CH0_DPLL2_KD, 0x40); | ||
701 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
702 | AR_CH0_DPLL2_KI, 0x4); | ||
703 | |||
704 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, | ||
705 | AR_CH0_BB_DPLL1_REFDIV, 0x5); | ||
706 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, | ||
707 | AR_CH0_BB_DPLL1_NINI, 0x58); | ||
708 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL1, | ||
709 | AR_CH0_BB_DPLL1_NFRAC, 0x0); | ||
710 | |||
711 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
712 | AR_CH0_BB_DPLL2_OUTDIV, 0x1); | ||
713 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
714 | AR_CH0_BB_DPLL2_LOCAL_PLL, 0x1); | ||
715 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
716 | AR_CH0_BB_DPLL2_EN_NEGTRIG, 0x1); | ||
717 | |||
718 | /* program BB PLL phase_shift to 0x6 */ | ||
719 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, | ||
720 | AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x6); | ||
721 | |||
722 | REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, | ||
723 | AR_CH0_BB_DPLL2_PLL_PWD, 0x0); | ||
724 | udelay(1000); | ||
725 | } else if (AR_SREV_9340(ah)) { | ||
726 | u32 regval, pll2_divint, pll2_divfrac, refdiv; | ||
727 | |||
728 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); | ||
729 | udelay(1000); | ||
730 | |||
731 | REG_SET_BIT(ah, AR_PHY_PLL_MODE, 0x1 << 16); | ||
732 | udelay(100); | ||
733 | |||
734 | if (ah->is_clk_25mhz) { | ||
735 | pll2_divint = 0x54; | ||
736 | pll2_divfrac = 0x1eb85; | ||
737 | refdiv = 3; | ||
738 | } else { | ||
739 | pll2_divint = 88; | ||
740 | pll2_divfrac = 0; | ||
741 | refdiv = 5; | ||
742 | } | ||
743 | |||
744 | regval = REG_READ(ah, AR_PHY_PLL_MODE); | ||
745 | regval |= (0x1 << 16); | ||
746 | REG_WRITE(ah, AR_PHY_PLL_MODE, regval); | ||
747 | udelay(100); | ||
748 | |||
749 | REG_WRITE(ah, AR_PHY_PLL_CONTROL, (refdiv << 27) | | ||
750 | (pll2_divint << 18) | pll2_divfrac); | ||
751 | udelay(100); | ||
752 | |||
753 | regval = REG_READ(ah, AR_PHY_PLL_MODE); | ||
754 | regval = (regval & 0x80071fff) | (0x1 << 30) | (0x1 << 13) | | ||
755 | (0x4 << 26) | (0x18 << 19); | ||
756 | REG_WRITE(ah, AR_PHY_PLL_MODE, regval); | ||
757 | REG_WRITE(ah, AR_PHY_PLL_MODE, | ||
758 | REG_READ(ah, AR_PHY_PLL_MODE) & 0xfffeffff); | ||
759 | udelay(1000); | ||
760 | } | ||
761 | |||
762 | pll = ath9k_hw_compute_pll_control(ah, chan); | ||
686 | 763 | ||
687 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); | 764 | REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); |
688 | 765 | ||
766 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) | ||
767 | udelay(1000); | ||
768 | |||
689 | /* Switch the core clock for ar9271 to 117Mhz */ | 769 | /* Switch the core clock for ar9271 to 117Mhz */ |
690 | if (AR_SREV_9271(ah)) { | 770 | if (AR_SREV_9271(ah)) { |
691 | udelay(500); | 771 | udelay(500); |
@@ -695,17 +775,34 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
695 | udelay(RTC_PLL_SETTLE_DELAY); | 775 | udelay(RTC_PLL_SETTLE_DELAY); |
696 | 776 | ||
697 | REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); | 777 | REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); |
778 | |||
779 | if (AR_SREV_9340(ah)) { | ||
780 | if (ah->is_clk_25mhz) { | ||
781 | REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); | ||
782 | REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); | ||
783 | REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); | ||
784 | } else { | ||
785 | REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); | ||
786 | REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); | ||
787 | REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); | ||
788 | } | ||
789 | udelay(100); | ||
790 | } | ||
698 | } | 791 | } |
699 | 792 | ||
700 | static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | 793 | static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, |
701 | enum nl80211_iftype opmode) | 794 | enum nl80211_iftype opmode) |
702 | { | 795 | { |
796 | u32 sync_default = AR_INTR_SYNC_DEFAULT; | ||
703 | u32 imr_reg = AR_IMR_TXERR | | 797 | u32 imr_reg = AR_IMR_TXERR | |
704 | AR_IMR_TXURN | | 798 | AR_IMR_TXURN | |
705 | AR_IMR_RXERR | | 799 | AR_IMR_RXERR | |
706 | AR_IMR_RXORN | | 800 | AR_IMR_RXORN | |
707 | AR_IMR_BCNMISC; | 801 | AR_IMR_BCNMISC; |
708 | 802 | ||
803 | if (AR_SREV_9340(ah)) | ||
804 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; | ||
805 | |||
709 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 806 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
710 | imr_reg |= AR_IMR_RXOK_HP; | 807 | imr_reg |= AR_IMR_RXOK_HP; |
711 | if (ah->config.rx_intr_mitigation) | 808 | if (ah->config.rx_intr_mitigation) |
@@ -736,12 +833,11 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | |||
736 | 833 | ||
737 | if (!AR_SREV_9100(ah)) { | 834 | if (!AR_SREV_9100(ah)) { |
738 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); | 835 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); |
739 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); | 836 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); |
740 | REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); | 837 | REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); |
741 | } | 838 | } |
742 | 839 | ||
743 | REGWRITE_BUFFER_FLUSH(ah); | 840 | REGWRITE_BUFFER_FLUSH(ah); |
744 | DISABLE_REGWRITE_BUFFER(ah); | ||
745 | 841 | ||
746 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 842 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
747 | REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0); | 843 | REG_WRITE(ah, AR_INTR_PRIO_ASYNC_ENABLE, 0); |
@@ -775,8 +871,8 @@ static void ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) | |||
775 | static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) | 871 | static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) |
776 | { | 872 | { |
777 | if (tu > 0xFFFF) { | 873 | if (tu > 0xFFFF) { |
778 | ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT, | 874 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_XMIT, |
779 | "bad global tx timeout %u\n", tu); | 875 | "bad global tx timeout %u\n", tu); |
780 | ah->globaltxtimeout = (u32) -1; | 876 | ah->globaltxtimeout = (u32) -1; |
781 | return false; | 877 | return false; |
782 | } else { | 878 | } else { |
@@ -793,12 +889,11 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
793 | int slottime; | 889 | int slottime; |
794 | int sifstime; | 890 | int sifstime; |
795 | 891 | ||
796 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", | 892 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, "ah->misc_mode 0x%x\n", |
797 | ah->misc_mode); | 893 | ah->misc_mode); |
798 | 894 | ||
799 | if (ah->misc_mode != 0) | 895 | if (ah->misc_mode != 0) |
800 | REG_WRITE(ah, AR_PCU_MISC, | 896 | REG_SET_BIT(ah, AR_PCU_MISC, ah->misc_mode); |
801 | REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); | ||
802 | 897 | ||
803 | if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) | 898 | if (conf->channel && conf->channel->band == IEEE80211_BAND_5GHZ) |
804 | sifstime = 16; | 899 | sifstime = 16; |
@@ -819,7 +914,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah) | |||
819 | if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) | 914 | if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ) |
820 | acktimeout += 64 - sifstime - ah->slottime; | 915 | acktimeout += 64 - sifstime - ah->slottime; |
821 | 916 | ||
822 | ath9k_hw_setslottime(ah, slottime); | 917 | ath9k_hw_setslottime(ah, ah->slottime); |
823 | ath9k_hw_set_ack_timeout(ah, acktimeout); | 918 | ath9k_hw_set_ack_timeout(ah, acktimeout); |
824 | ath9k_hw_set_cts_timeout(ah, acktimeout); | 919 | ath9k_hw_set_cts_timeout(ah, acktimeout); |
825 | if (ah->globaltxtimeout != (u32) -1) | 920 | if (ah->globaltxtimeout != (u32) -1) |
@@ -866,26 +961,21 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) | |||
866 | static inline void ath9k_hw_set_dma(struct ath_hw *ah) | 961 | static inline void ath9k_hw_set_dma(struct ath_hw *ah) |
867 | { | 962 | { |
868 | struct ath_common *common = ath9k_hw_common(ah); | 963 | struct ath_common *common = ath9k_hw_common(ah); |
869 | u32 regval; | ||
870 | 964 | ||
871 | ENABLE_REGWRITE_BUFFER(ah); | 965 | ENABLE_REGWRITE_BUFFER(ah); |
872 | 966 | ||
873 | /* | 967 | /* |
874 | * set AHB_MODE not to do cacheline prefetches | 968 | * set AHB_MODE not to do cacheline prefetches |
875 | */ | 969 | */ |
876 | if (!AR_SREV_9300_20_OR_LATER(ah)) { | 970 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
877 | regval = REG_READ(ah, AR_AHB_MODE); | 971 | REG_SET_BIT(ah, AR_AHB_MODE, AR_AHB_PREFETCH_RD_EN); |
878 | REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); | ||
879 | } | ||
880 | 972 | ||
881 | /* | 973 | /* |
882 | * let mac dma reads be in 128 byte chunks | 974 | * let mac dma reads be in 128 byte chunks |
883 | */ | 975 | */ |
884 | regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; | 976 | REG_RMW(ah, AR_TXCFG, AR_TXCFG_DMASZ_128B, AR_TXCFG_DMASZ_MASK); |
885 | REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); | ||
886 | 977 | ||
887 | REGWRITE_BUFFER_FLUSH(ah); | 978 | REGWRITE_BUFFER_FLUSH(ah); |
888 | DISABLE_REGWRITE_BUFFER(ah); | ||
889 | 979 | ||
890 | /* | 980 | /* |
891 | * Restore TX Trigger Level to its pre-reset value. | 981 | * Restore TX Trigger Level to its pre-reset value. |
@@ -900,8 +990,7 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) | |||
900 | /* | 990 | /* |
901 | * let mac dma writes be in 128 byte chunks | 991 | * let mac dma writes be in 128 byte chunks |
902 | */ | 992 | */ |
903 | regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; | 993 | REG_RMW(ah, AR_RXCFG, AR_RXCFG_DMASZ_128B, AR_RXCFG_DMASZ_MASK); |
904 | REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); | ||
905 | 994 | ||
906 | /* | 995 | /* |
907 | * Setup receive FIFO threshold to hold off TX activities | 996 | * Setup receive FIFO threshold to hold off TX activities |
@@ -933,7 +1022,6 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) | |||
933 | } | 1022 | } |
934 | 1023 | ||
935 | REGWRITE_BUFFER_FLUSH(ah); | 1024 | REGWRITE_BUFFER_FLUSH(ah); |
936 | DISABLE_REGWRITE_BUFFER(ah); | ||
937 | 1025 | ||
938 | if (AR_SREV_9300_20_OR_LATER(ah)) | 1026 | if (AR_SREV_9300_20_OR_LATER(ah)) |
939 | ath9k_hw_reset_txstatus_ring(ah); | 1027 | ath9k_hw_reset_txstatus_ring(ah); |
@@ -941,27 +1029,27 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) | |||
941 | 1029 | ||
942 | static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) | 1030 | static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) |
943 | { | 1031 | { |
944 | u32 val; | 1032 | u32 mask = AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC; |
1033 | u32 set = AR_STA_ID1_KSRCH_MODE; | ||
945 | 1034 | ||
946 | val = REG_READ(ah, AR_STA_ID1); | ||
947 | val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); | ||
948 | switch (opmode) { | 1035 | switch (opmode) { |
949 | case NL80211_IFTYPE_AP: | ||
950 | REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP | ||
951 | | AR_STA_ID1_KSRCH_MODE); | ||
952 | REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); | ||
953 | break; | ||
954 | case NL80211_IFTYPE_ADHOC: | 1036 | case NL80211_IFTYPE_ADHOC: |
955 | case NL80211_IFTYPE_MESH_POINT: | 1037 | case NL80211_IFTYPE_MESH_POINT: |
956 | REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC | 1038 | set |= AR_STA_ID1_ADHOC; |
957 | | AR_STA_ID1_KSRCH_MODE); | ||
958 | REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); | 1039 | REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); |
959 | break; | 1040 | break; |
1041 | case NL80211_IFTYPE_AP: | ||
1042 | set |= AR_STA_ID1_STA_AP; | ||
1043 | /* fall through */ | ||
960 | case NL80211_IFTYPE_STATION: | 1044 | case NL80211_IFTYPE_STATION: |
961 | case NL80211_IFTYPE_MONITOR: | 1045 | REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); |
962 | REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); | 1046 | break; |
1047 | default: | ||
1048 | if (!ah->is_monitoring) | ||
1049 | set = 0; | ||
963 | break; | 1050 | break; |
964 | } | 1051 | } |
1052 | REG_RMW(ah, AR_STA_ID1, set, mask); | ||
965 | } | 1053 | } |
966 | 1054 | ||
967 | void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, | 1055 | void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, |
@@ -987,10 +1075,8 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
987 | u32 tmpReg; | 1075 | u32 tmpReg; |
988 | 1076 | ||
989 | if (AR_SREV_9100(ah)) { | 1077 | if (AR_SREV_9100(ah)) { |
990 | u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK); | 1078 | REG_RMW_FIELD(ah, AR_RTC_DERIVED_CLK, |
991 | val &= ~AR_RTC_DERIVED_CLK_PERIOD; | 1079 | AR_RTC_DERIVED_CLK_PERIOD, 1); |
992 | val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); | ||
993 | REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); | ||
994 | (void)REG_READ(ah, AR_RTC_DERIVED_CLK); | 1080 | (void)REG_READ(ah, AR_RTC_DERIVED_CLK); |
995 | } | 1081 | } |
996 | 1082 | ||
@@ -1031,14 +1117,13 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) | |||
1031 | REG_WRITE(ah, AR_RTC_RC, rst_flags); | 1117 | REG_WRITE(ah, AR_RTC_RC, rst_flags); |
1032 | 1118 | ||
1033 | REGWRITE_BUFFER_FLUSH(ah); | 1119 | REGWRITE_BUFFER_FLUSH(ah); |
1034 | DISABLE_REGWRITE_BUFFER(ah); | ||
1035 | 1120 | ||
1036 | udelay(50); | 1121 | udelay(50); |
1037 | 1122 | ||
1038 | REG_WRITE(ah, AR_RTC_RC, 0); | 1123 | REG_WRITE(ah, AR_RTC_RC, 0); |
1039 | if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { | 1124 | if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { |
1040 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, | 1125 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, |
1041 | "RTC stuck in MAC reset\n"); | 1126 | "RTC stuck in MAC reset\n"); |
1042 | return false; | 1127 | return false; |
1043 | } | 1128 | } |
1044 | 1129 | ||
@@ -1067,10 +1152,8 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1067 | REG_WRITE(ah, AR_RC, AR_RC_AHB); | 1152 | REG_WRITE(ah, AR_RC, AR_RC_AHB); |
1068 | 1153 | ||
1069 | REG_WRITE(ah, AR_RTC_RESET, 0); | 1154 | REG_WRITE(ah, AR_RTC_RESET, 0); |
1070 | udelay(2); | ||
1071 | 1155 | ||
1072 | REGWRITE_BUFFER_FLUSH(ah); | 1156 | REGWRITE_BUFFER_FLUSH(ah); |
1073 | DISABLE_REGWRITE_BUFFER(ah); | ||
1074 | 1157 | ||
1075 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 1158 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
1076 | udelay(2); | 1159 | udelay(2); |
@@ -1085,13 +1168,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) | |||
1085 | AR_RTC_STATUS_M, | 1168 | AR_RTC_STATUS_M, |
1086 | AR_RTC_STATUS_ON, | 1169 | AR_RTC_STATUS_ON, |
1087 | AH_WAIT_TIMEOUT)) { | 1170 | AH_WAIT_TIMEOUT)) { |
1088 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, | 1171 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, |
1089 | "RTC not waking up\n"); | 1172 | "RTC not waking up\n"); |
1090 | return false; | 1173 | return false; |
1091 | } | 1174 | } |
1092 | 1175 | ||
1093 | ath9k_hw_read_revisions(ah); | ||
1094 | |||
1095 | return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); | 1176 | return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); |
1096 | } | 1177 | } |
1097 | 1178 | ||
@@ -1146,16 +1227,14 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1146 | 1227 | ||
1147 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { | 1228 | for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { |
1148 | if (ath9k_hw_numtxpending(ah, qnum)) { | 1229 | if (ath9k_hw_numtxpending(ah, qnum)) { |
1149 | ath_print(common, ATH_DBG_QUEUE, | 1230 | ath_dbg(common, ATH_DBG_QUEUE, |
1150 | "Transmit frames pending on " | 1231 | "Transmit frames pending on queue %d\n", qnum); |
1151 | "queue %d\n", qnum); | ||
1152 | return false; | 1232 | return false; |
1153 | } | 1233 | } |
1154 | } | 1234 | } |
1155 | 1235 | ||
1156 | if (!ath9k_hw_rfbus_req(ah)) { | 1236 | if (!ath9k_hw_rfbus_req(ah)) { |
1157 | ath_print(common, ATH_DBG_FATAL, | 1237 | ath_err(common, "Could not kill baseband RX\n"); |
1158 | "Could not kill baseband RX\n"); | ||
1159 | return false; | 1238 | return false; |
1160 | } | 1239 | } |
1161 | 1240 | ||
@@ -1163,17 +1242,17 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1163 | 1242 | ||
1164 | r = ath9k_hw_rf_set_freq(ah, chan); | 1243 | r = ath9k_hw_rf_set_freq(ah, chan); |
1165 | if (r) { | 1244 | if (r) { |
1166 | ath_print(common, ATH_DBG_FATAL, | 1245 | ath_err(common, "Failed to set channel\n"); |
1167 | "Failed to set channel\n"); | ||
1168 | return false; | 1246 | return false; |
1169 | } | 1247 | } |
1248 | ath9k_hw_set_clockrate(ah); | ||
1170 | 1249 | ||
1171 | ah->eep_ops->set_txpower(ah, chan, | 1250 | ah->eep_ops->set_txpower(ah, chan, |
1172 | ath9k_regd_get_ctl(regulatory, chan), | 1251 | ath9k_regd_get_ctl(regulatory, chan), |
1173 | channel->max_antenna_gain * 2, | 1252 | channel->max_antenna_gain * 2, |
1174 | channel->max_power * 2, | 1253 | channel->max_power * 2, |
1175 | min((u32) MAX_RATE_POWER, | 1254 | min((u32) MAX_RATE_POWER, |
1176 | (u32) regulatory->power_limit)); | 1255 | (u32) regulatory->power_limit), false); |
1177 | 1256 | ||
1178 | ath9k_hw_rfbus_done(ah); | 1257 | ath9k_hw_rfbus_done(ah); |
1179 | 1258 | ||
@@ -1185,12 +1264,26 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1185 | return true; | 1264 | return true; |
1186 | } | 1265 | } |
1187 | 1266 | ||
1267 | static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) | ||
1268 | { | ||
1269 | u32 gpio_mask = ah->gpio_mask; | ||
1270 | int i; | ||
1271 | |||
1272 | for (i = 0; gpio_mask; i++, gpio_mask >>= 1) { | ||
1273 | if (!(gpio_mask & 1)) | ||
1274 | continue; | ||
1275 | |||
1276 | ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | ||
1277 | ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i))); | ||
1278 | } | ||
1279 | } | ||
1280 | |||
1188 | bool ath9k_hw_check_alive(struct ath_hw *ah) | 1281 | bool ath9k_hw_check_alive(struct ath_hw *ah) |
1189 | { | 1282 | { |
1190 | int count = 50; | 1283 | int count = 50; |
1191 | u32 reg; | 1284 | u32 reg; |
1192 | 1285 | ||
1193 | if (AR_SREV_9285_10_OR_LATER(ah)) | 1286 | if (AR_SREV_9285_12_OR_LATER(ah)) |
1194 | return true; | 1287 | return true; |
1195 | 1288 | ||
1196 | do { | 1289 | do { |
@@ -1227,19 +1320,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1227 | ah->txchainmask = common->tx_chainmask; | 1320 | ah->txchainmask = common->tx_chainmask; |
1228 | ah->rxchainmask = common->rx_chainmask; | 1321 | ah->rxchainmask = common->rx_chainmask; |
1229 | 1322 | ||
1230 | if (!ah->chip_fullsleep) { | ||
1231 | ath9k_hw_abortpcurecv(ah); | ||
1232 | if (!ath9k_hw_stopdmarecv(ah)) { | ||
1233 | ath_print(common, ATH_DBG_XMIT, | ||
1234 | "Failed to stop receive dma\n"); | ||
1235 | bChannelChange = false; | ||
1236 | } | ||
1237 | } | ||
1238 | |||
1239 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) | 1323 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
1240 | return -EIO; | 1324 | return -EIO; |
1241 | 1325 | ||
1242 | if (curchan && !ah->chip_fullsleep && ah->caldata) | 1326 | if (curchan && !ah->chip_fullsleep) |
1243 | ath9k_hw_getnf(ah, curchan); | 1327 | ath9k_hw_getnf(ah, curchan); |
1244 | 1328 | ||
1245 | ah->caldata = caldata; | 1329 | ah->caldata = caldata; |
@@ -1258,11 +1342,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1258 | (chan->channel != ah->curchan->channel) && | 1342 | (chan->channel != ah->curchan->channel) && |
1259 | ((chan->channelFlags & CHANNEL_ALL) == | 1343 | ((chan->channelFlags & CHANNEL_ALL) == |
1260 | (ah->curchan->channelFlags & CHANNEL_ALL)) && | 1344 | (ah->curchan->channelFlags & CHANNEL_ALL)) && |
1261 | !AR_SREV_9280(ah)) { | 1345 | (!AR_SREV_9280(ah) || AR_DEVID_7010(ah))) { |
1262 | 1346 | ||
1263 | if (ath9k_hw_channel_change(ah, chan)) { | 1347 | if (ath9k_hw_channel_change(ah, chan)) { |
1264 | ath9k_hw_loadnf(ah, ah->curchan); | 1348 | ath9k_hw_loadnf(ah, ah->curchan); |
1265 | ath9k_hw_start_nfcal(ah, true); | 1349 | ath9k_hw_start_nfcal(ah, true); |
1350 | if (AR_SREV_9271(ah)) | ||
1351 | ar9002_hw_load_ani_reg(ah, chan); | ||
1266 | return 0; | 1352 | return 0; |
1267 | } | 1353 | } |
1268 | } | 1354 | } |
@@ -1284,6 +1370,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1284 | 1370 | ||
1285 | ath9k_hw_mark_phy_inactive(ah); | 1371 | ath9k_hw_mark_phy_inactive(ah); |
1286 | 1372 | ||
1373 | ah->paprd_table_write_done = false; | ||
1374 | |||
1287 | /* Only required on the first reset */ | 1375 | /* Only required on the first reset */ |
1288 | if (AR_SREV_9271(ah) && ah->htc_reset_init) { | 1376 | if (AR_SREV_9271(ah) && ah->htc_reset_init) { |
1289 | REG_WRITE(ah, | 1377 | REG_WRITE(ah, |
@@ -1293,7 +1381,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1293 | } | 1381 | } |
1294 | 1382 | ||
1295 | if (!ath9k_hw_chip_reset(ah, chan)) { | 1383 | if (!ath9k_hw_chip_reset(ah, chan)) { |
1296 | ath_print(common, ATH_DBG_FATAL, "Chip reset failed\n"); | 1384 | ath_err(common, "Chip reset failed\n"); |
1297 | return -EINVAL; | 1385 | return -EINVAL; |
1298 | } | 1386 | } |
1299 | 1387 | ||
@@ -1310,7 +1398,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1310 | if (tsf) | 1398 | if (tsf) |
1311 | ath9k_hw_settsf64(ah, tsf); | 1399 | ath9k_hw_settsf64(ah, tsf); |
1312 | 1400 | ||
1313 | if (AR_SREV_9280_10_OR_LATER(ah)) | 1401 | if (AR_SREV_9280_20_OR_LATER(ah)) |
1314 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); | 1402 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); |
1315 | 1403 | ||
1316 | if (!AR_SREV_9300_20_OR_LATER(ah)) | 1404 | if (!AR_SREV_9300_20_OR_LATER(ah)) |
@@ -1354,8 +1442,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1354 | ath9k_hw_spur_mitigate_freq(ah, chan); | 1442 | ath9k_hw_spur_mitigate_freq(ah, chan); |
1355 | ah->eep_ops->set_board_values(ah, chan); | 1443 | ah->eep_ops->set_board_values(ah, chan); |
1356 | 1444 | ||
1357 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1358 | |||
1359 | ENABLE_REGWRITE_BUFFER(ah); | 1445 | ENABLE_REGWRITE_BUFFER(ah); |
1360 | 1446 | ||
1361 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); | 1447 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); |
@@ -1372,22 +1458,24 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1372 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); | 1458 | REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); |
1373 | 1459 | ||
1374 | REGWRITE_BUFFER_FLUSH(ah); | 1460 | REGWRITE_BUFFER_FLUSH(ah); |
1375 | DISABLE_REGWRITE_BUFFER(ah); | 1461 | |
1462 | ath9k_hw_set_operating_mode(ah, ah->opmode); | ||
1376 | 1463 | ||
1377 | r = ath9k_hw_rf_set_freq(ah, chan); | 1464 | r = ath9k_hw_rf_set_freq(ah, chan); |
1378 | if (r) | 1465 | if (r) |
1379 | return r; | 1466 | return r; |
1380 | 1467 | ||
1468 | ath9k_hw_set_clockrate(ah); | ||
1469 | |||
1381 | ENABLE_REGWRITE_BUFFER(ah); | 1470 | ENABLE_REGWRITE_BUFFER(ah); |
1382 | 1471 | ||
1383 | for (i = 0; i < AR_NUM_DCU; i++) | 1472 | for (i = 0; i < AR_NUM_DCU; i++) |
1384 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); | 1473 | REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); |
1385 | 1474 | ||
1386 | REGWRITE_BUFFER_FLUSH(ah); | 1475 | REGWRITE_BUFFER_FLUSH(ah); |
1387 | DISABLE_REGWRITE_BUFFER(ah); | ||
1388 | 1476 | ||
1389 | ah->intr_txqs = 0; | 1477 | ah->intr_txqs = 0; |
1390 | for (i = 0; i < ah->caps.total_queues; i++) | 1478 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
1391 | ath9k_hw_resettxqueue(ah, i); | 1479 | ath9k_hw_resettxqueue(ah, i); |
1392 | 1480 | ||
1393 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); | 1481 | ath9k_hw_init_interrupt_masks(ah, ah->opmode); |
@@ -1395,7 +1483,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1395 | ath9k_hw_init_qos(ah); | 1483 | ath9k_hw_init_qos(ah); |
1396 | 1484 | ||
1397 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | 1485 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
1398 | ath9k_enable_rfkill(ah); | 1486 | ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); |
1399 | 1487 | ||
1400 | ath9k_hw_init_global_settings(ah); | 1488 | ath9k_hw_init_global_settings(ah); |
1401 | 1489 | ||
@@ -1404,8 +1492,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1404 | ar9002_hw_enable_wep_aggregation(ah); | 1492 | ar9002_hw_enable_wep_aggregation(ah); |
1405 | } | 1493 | } |
1406 | 1494 | ||
1407 | REG_WRITE(ah, AR_STA_ID1, | 1495 | REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM); |
1408 | REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); | ||
1409 | 1496 | ||
1410 | ath9k_hw_set_dma(ah); | 1497 | ath9k_hw_set_dma(ah); |
1411 | 1498 | ||
@@ -1432,7 +1519,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1432 | REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); | 1519 | REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); |
1433 | 1520 | ||
1434 | REGWRITE_BUFFER_FLUSH(ah); | 1521 | REGWRITE_BUFFER_FLUSH(ah); |
1435 | DISABLE_REGWRITE_BUFFER(ah); | ||
1436 | 1522 | ||
1437 | /* | 1523 | /* |
1438 | * For big endian systems turn on swapping for descriptors | 1524 | * For big endian systems turn on swapping for descriptors |
@@ -1441,13 +1527,13 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1441 | u32 mask; | 1527 | u32 mask; |
1442 | mask = REG_READ(ah, AR_CFG); | 1528 | mask = REG_READ(ah, AR_CFG); |
1443 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { | 1529 | if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { |
1444 | ath_print(common, ATH_DBG_RESET, | 1530 | ath_dbg(common, ATH_DBG_RESET, |
1445 | "CFG Byte Swap Set 0x%x\n", mask); | 1531 | "CFG Byte Swap Set 0x%x\n", mask); |
1446 | } else { | 1532 | } else { |
1447 | mask = | 1533 | mask = |
1448 | INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; | 1534 | INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; |
1449 | REG_WRITE(ah, AR_CFG, mask); | 1535 | REG_WRITE(ah, AR_CFG, mask); |
1450 | ath_print(common, ATH_DBG_RESET, | 1536 | ath_dbg(common, ATH_DBG_RESET, |
1451 | "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); | 1537 | "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); |
1452 | } | 1538 | } |
1453 | } else { | 1539 | } else { |
@@ -1459,7 +1545,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1459 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | 1545 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); |
1460 | } | 1546 | } |
1461 | #ifdef __BIG_ENDIAN | 1547 | #ifdef __BIG_ENDIAN |
1462 | else | 1548 | else if (AR_SREV_9340(ah)) |
1549 | REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0); | ||
1550 | else | ||
1463 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); | 1551 | REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); |
1464 | #endif | 1552 | #endif |
1465 | } | 1553 | } |
@@ -1467,289 +1555,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1467 | if (ah->btcoex_hw.enabled) | 1555 | if (ah->btcoex_hw.enabled) |
1468 | ath9k_hw_btcoex_enable(ah); | 1556 | ath9k_hw_btcoex_enable(ah); |
1469 | 1557 | ||
1470 | if (AR_SREV_9300_20_OR_LATER(ah)) | 1558 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
1471 | ar9003_hw_bb_watchdog_config(ah); | 1559 | ar9003_hw_bb_watchdog_config(ah); |
1472 | 1560 | ||
1473 | return 0; | 1561 | ar9003_hw_disable_phy_restart(ah); |
1474 | } | ||
1475 | EXPORT_SYMBOL(ath9k_hw_reset); | ||
1476 | |||
1477 | /************************/ | ||
1478 | /* Key Cache Management */ | ||
1479 | /************************/ | ||
1480 | |||
1481 | bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) | ||
1482 | { | ||
1483 | u32 keyType; | ||
1484 | |||
1485 | if (entry >= ah->caps.keycache_size) { | ||
1486 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | ||
1487 | "keychache entry %u out of range\n", entry); | ||
1488 | return false; | ||
1489 | } | 1562 | } |
1490 | 1563 | ||
1491 | keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); | 1564 | ath9k_hw_apply_gpio_override(ah); |
1492 | 1565 | ||
1493 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); | 1566 | return 0; |
1494 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); | ||
1495 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); | ||
1496 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); | ||
1497 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); | ||
1498 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); | ||
1499 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); | ||
1500 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); | ||
1501 | |||
1502 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
1503 | u16 micentry = entry + 64; | ||
1504 | |||
1505 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); | ||
1506 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
1507 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); | ||
1508 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
1509 | |||
1510 | } | ||
1511 | |||
1512 | return true; | ||
1513 | } | ||
1514 | EXPORT_SYMBOL(ath9k_hw_keyreset); | ||
1515 | |||
1516 | static bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) | ||
1517 | { | ||
1518 | u32 macHi, macLo; | ||
1519 | u32 unicast_flag = AR_KEYTABLE_VALID; | ||
1520 | |||
1521 | if (entry >= ah->caps.keycache_size) { | ||
1522 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | ||
1523 | "keychache entry %u out of range\n", entry); | ||
1524 | return false; | ||
1525 | } | ||
1526 | |||
1527 | if (mac != NULL) { | ||
1528 | /* | ||
1529 | * AR_KEYTABLE_VALID indicates that the address is a unicast | ||
1530 | * address, which must match the transmitter address for | ||
1531 | * decrypting frames. | ||
1532 | * Not setting this bit allows the hardware to use the key | ||
1533 | * for multicast frame decryption. | ||
1534 | */ | ||
1535 | if (mac[0] & 0x01) | ||
1536 | unicast_flag = 0; | ||
1537 | |||
1538 | macHi = (mac[5] << 8) | mac[4]; | ||
1539 | macLo = (mac[3] << 24) | | ||
1540 | (mac[2] << 16) | | ||
1541 | (mac[1] << 8) | | ||
1542 | mac[0]; | ||
1543 | macLo >>= 1; | ||
1544 | macLo |= (macHi & 1) << 31; | ||
1545 | macHi >>= 1; | ||
1546 | } else { | ||
1547 | macLo = macHi = 0; | ||
1548 | } | ||
1549 | REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); | ||
1550 | REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag); | ||
1551 | |||
1552 | return true; | ||
1553 | } | ||
1554 | |||
1555 | bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | ||
1556 | const struct ath9k_keyval *k, | ||
1557 | const u8 *mac) | ||
1558 | { | ||
1559 | const struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
1560 | struct ath_common *common = ath9k_hw_common(ah); | ||
1561 | u32 key0, key1, key2, key3, key4; | ||
1562 | u32 keyType; | ||
1563 | |||
1564 | if (entry >= pCap->keycache_size) { | ||
1565 | ath_print(common, ATH_DBG_FATAL, | ||
1566 | "keycache entry %u out of range\n", entry); | ||
1567 | return false; | ||
1568 | } | ||
1569 | |||
1570 | switch (k->kv_type) { | ||
1571 | case ATH9K_CIPHER_AES_OCB: | ||
1572 | keyType = AR_KEYTABLE_TYPE_AES; | ||
1573 | break; | ||
1574 | case ATH9K_CIPHER_AES_CCM: | ||
1575 | if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { | ||
1576 | ath_print(common, ATH_DBG_ANY, | ||
1577 | "AES-CCM not supported by mac rev 0x%x\n", | ||
1578 | ah->hw_version.macRev); | ||
1579 | return false; | ||
1580 | } | ||
1581 | keyType = AR_KEYTABLE_TYPE_CCM; | ||
1582 | break; | ||
1583 | case ATH9K_CIPHER_TKIP: | ||
1584 | keyType = AR_KEYTABLE_TYPE_TKIP; | ||
1585 | if (ATH9K_IS_MIC_ENABLED(ah) | ||
1586 | && entry + 64 >= pCap->keycache_size) { | ||
1587 | ath_print(common, ATH_DBG_ANY, | ||
1588 | "entry %u inappropriate for TKIP\n", entry); | ||
1589 | return false; | ||
1590 | } | ||
1591 | break; | ||
1592 | case ATH9K_CIPHER_WEP: | ||
1593 | if (k->kv_len < WLAN_KEY_LEN_WEP40) { | ||
1594 | ath_print(common, ATH_DBG_ANY, | ||
1595 | "WEP key length %u too small\n", k->kv_len); | ||
1596 | return false; | ||
1597 | } | ||
1598 | if (k->kv_len <= WLAN_KEY_LEN_WEP40) | ||
1599 | keyType = AR_KEYTABLE_TYPE_40; | ||
1600 | else if (k->kv_len <= WLAN_KEY_LEN_WEP104) | ||
1601 | keyType = AR_KEYTABLE_TYPE_104; | ||
1602 | else | ||
1603 | keyType = AR_KEYTABLE_TYPE_128; | ||
1604 | break; | ||
1605 | case ATH9K_CIPHER_CLR: | ||
1606 | keyType = AR_KEYTABLE_TYPE_CLR; | ||
1607 | break; | ||
1608 | default: | ||
1609 | ath_print(common, ATH_DBG_FATAL, | ||
1610 | "cipher %u not supported\n", k->kv_type); | ||
1611 | return false; | ||
1612 | } | ||
1613 | |||
1614 | key0 = get_unaligned_le32(k->kv_val + 0); | ||
1615 | key1 = get_unaligned_le16(k->kv_val + 4); | ||
1616 | key2 = get_unaligned_le32(k->kv_val + 6); | ||
1617 | key3 = get_unaligned_le16(k->kv_val + 10); | ||
1618 | key4 = get_unaligned_le32(k->kv_val + 12); | ||
1619 | if (k->kv_len <= WLAN_KEY_LEN_WEP104) | ||
1620 | key4 &= 0xff; | ||
1621 | |||
1622 | /* | ||
1623 | * Note: Key cache registers access special memory area that requires | ||
1624 | * two 32-bit writes to actually update the values in the internal | ||
1625 | * memory. Consequently, the exact order and pairs used here must be | ||
1626 | * maintained. | ||
1627 | */ | ||
1628 | |||
1629 | if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { | ||
1630 | u16 micentry = entry + 64; | ||
1631 | |||
1632 | /* | ||
1633 | * Write inverted key[47:0] first to avoid Michael MIC errors | ||
1634 | * on frames that could be sent or received at the same time. | ||
1635 | * The correct key will be written in the end once everything | ||
1636 | * else is ready. | ||
1637 | */ | ||
1638 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); | ||
1639 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); | ||
1640 | |||
1641 | /* Write key[95:48] */ | ||
1642 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
1643 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
1644 | |||
1645 | /* Write key[127:96] and key type */ | ||
1646 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
1647 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
1648 | |||
1649 | /* Write MAC address for the entry */ | ||
1650 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
1651 | |||
1652 | if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) { | ||
1653 | /* | ||
1654 | * TKIP uses two key cache entries: | ||
1655 | * Michael MIC TX/RX keys in the same key cache entry | ||
1656 | * (idx = main index + 64): | ||
1657 | * key0 [31:0] = RX key [31:0] | ||
1658 | * key1 [15:0] = TX key [31:16] | ||
1659 | * key1 [31:16] = reserved | ||
1660 | * key2 [31:0] = RX key [63:32] | ||
1661 | * key3 [15:0] = TX key [15:0] | ||
1662 | * key3 [31:16] = reserved | ||
1663 | * key4 [31:0] = TX key [63:32] | ||
1664 | */ | ||
1665 | u32 mic0, mic1, mic2, mic3, mic4; | ||
1666 | |||
1667 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
1668 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
1669 | mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; | ||
1670 | mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; | ||
1671 | mic4 = get_unaligned_le32(k->kv_txmic + 4); | ||
1672 | |||
1673 | /* Write RX[31:0] and TX[31:16] */ | ||
1674 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
1675 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); | ||
1676 | |||
1677 | /* Write RX[63:32] and TX[15:0] */ | ||
1678 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
1679 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); | ||
1680 | |||
1681 | /* Write TX[63:32] and keyType(reserved) */ | ||
1682 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); | ||
1683 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
1684 | AR_KEYTABLE_TYPE_CLR); | ||
1685 | |||
1686 | } else { | ||
1687 | /* | ||
1688 | * TKIP uses four key cache entries (two for group | ||
1689 | * keys): | ||
1690 | * Michael MIC TX/RX keys are in different key cache | ||
1691 | * entries (idx = main index + 64 for TX and | ||
1692 | * main index + 32 + 96 for RX): | ||
1693 | * key0 [31:0] = TX/RX MIC key [31:0] | ||
1694 | * key1 [31:0] = reserved | ||
1695 | * key2 [31:0] = TX/RX MIC key [63:32] | ||
1696 | * key3 [31:0] = reserved | ||
1697 | * key4 [31:0] = reserved | ||
1698 | * | ||
1699 | * Upper layer code will call this function separately | ||
1700 | * for TX and RX keys when these registers offsets are | ||
1701 | * used. | ||
1702 | */ | ||
1703 | u32 mic0, mic2; | ||
1704 | |||
1705 | mic0 = get_unaligned_le32(k->kv_mic + 0); | ||
1706 | mic2 = get_unaligned_le32(k->kv_mic + 4); | ||
1707 | |||
1708 | /* Write MIC key[31:0] */ | ||
1709 | REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); | ||
1710 | REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); | ||
1711 | |||
1712 | /* Write MIC key[63:32] */ | ||
1713 | REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); | ||
1714 | REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); | ||
1715 | |||
1716 | /* Write TX[63:32] and keyType(reserved) */ | ||
1717 | REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); | ||
1718 | REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), | ||
1719 | AR_KEYTABLE_TYPE_CLR); | ||
1720 | } | ||
1721 | |||
1722 | /* MAC address registers are reserved for the MIC entry */ | ||
1723 | REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); | ||
1724 | REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); | ||
1725 | |||
1726 | /* | ||
1727 | * Write the correct (un-inverted) key[47:0] last to enable | ||
1728 | * TKIP now that all other registers are set with correct | ||
1729 | * values. | ||
1730 | */ | ||
1731 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
1732 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
1733 | } else { | ||
1734 | /* Write key[47:0] */ | ||
1735 | REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); | ||
1736 | REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); | ||
1737 | |||
1738 | /* Write key[95:48] */ | ||
1739 | REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); | ||
1740 | REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); | ||
1741 | |||
1742 | /* Write key[127:96] and key type */ | ||
1743 | REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); | ||
1744 | REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); | ||
1745 | |||
1746 | /* Write MAC address for the entry */ | ||
1747 | (void) ath9k_hw_keysetmac(ah, entry, mac); | ||
1748 | } | ||
1749 | |||
1750 | return true; | ||
1751 | } | 1567 | } |
1752 | EXPORT_SYMBOL(ath9k_hw_set_keycache_entry); | 1568 | EXPORT_SYMBOL(ath9k_hw_reset); |
1753 | 1569 | ||
1754 | /******************************/ | 1570 | /******************************/ |
1755 | /* Power Management (Chipset) */ | 1571 | /* Power Management (Chipset) */ |
@@ -1852,9 +1668,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) | |||
1852 | AR_RTC_FORCE_WAKE_EN); | 1668 | AR_RTC_FORCE_WAKE_EN); |
1853 | } | 1669 | } |
1854 | if (i == 0) { | 1670 | if (i == 0) { |
1855 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 1671 | ath_err(ath9k_hw_common(ah), |
1856 | "Failed to wakeup in %uus\n", | 1672 | "Failed to wakeup in %uus\n", |
1857 | POWER_UP_TIME / 20); | 1673 | POWER_UP_TIME / 20); |
1858 | return false; | 1674 | return false; |
1859 | } | 1675 | } |
1860 | } | 1676 | } |
@@ -1878,8 +1694,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | |||
1878 | if (ah->power_mode == mode) | 1694 | if (ah->power_mode == mode) |
1879 | return status; | 1695 | return status; |
1880 | 1696 | ||
1881 | ath_print(common, ATH_DBG_RESET, "%s -> %s\n", | 1697 | ath_dbg(common, ATH_DBG_RESET, "%s -> %s\n", |
1882 | modes[ah->power_mode], modes[mode]); | 1698 | modes[ah->power_mode], modes[mode]); |
1883 | 1699 | ||
1884 | switch (mode) { | 1700 | switch (mode) { |
1885 | case ATH9K_PM_AWAKE: | 1701 | case ATH9K_PM_AWAKE: |
@@ -1893,12 +1709,20 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) | |||
1893 | ath9k_set_power_network_sleep(ah, setChip); | 1709 | ath9k_set_power_network_sleep(ah, setChip); |
1894 | break; | 1710 | break; |
1895 | default: | 1711 | default: |
1896 | ath_print(common, ATH_DBG_FATAL, | 1712 | ath_err(common, "Unknown power mode %u\n", mode); |
1897 | "Unknown power mode %u\n", mode); | ||
1898 | return false; | 1713 | return false; |
1899 | } | 1714 | } |
1900 | ah->power_mode = mode; | 1715 | ah->power_mode = mode; |
1901 | 1716 | ||
1717 | /* | ||
1718 | * XXX: If this warning never comes up after a while then | ||
1719 | * simply keep the ATH_DBG_WARN_ON_ONCE() but make | ||
1720 | * ath9k_hw_setpower() return type void. | ||
1721 | */ | ||
1722 | |||
1723 | if (!(ah->ah_flags & AH_UNPLUGGED)) | ||
1724 | ATH_DBG_WARN_ON_ONCE(!status); | ||
1725 | |||
1902 | return status; | 1726 | return status; |
1903 | } | 1727 | } |
1904 | EXPORT_SYMBOL(ath9k_hw_setpower); | 1728 | EXPORT_SYMBOL(ath9k_hw_setpower); |
@@ -1911,60 +1735,39 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) | |||
1911 | { | 1735 | { |
1912 | int flags = 0; | 1736 | int flags = 0; |
1913 | 1737 | ||
1914 | ah->beacon_interval = beacon_period; | ||
1915 | |||
1916 | ENABLE_REGWRITE_BUFFER(ah); | 1738 | ENABLE_REGWRITE_BUFFER(ah); |
1917 | 1739 | ||
1918 | switch (ah->opmode) { | 1740 | switch (ah->opmode) { |
1919 | case NL80211_IFTYPE_STATION: | ||
1920 | case NL80211_IFTYPE_MONITOR: | ||
1921 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); | ||
1922 | REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff); | ||
1923 | REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff); | ||
1924 | flags |= AR_TBTT_TIMER_EN; | ||
1925 | break; | ||
1926 | case NL80211_IFTYPE_ADHOC: | 1741 | case NL80211_IFTYPE_ADHOC: |
1927 | case NL80211_IFTYPE_MESH_POINT: | 1742 | case NL80211_IFTYPE_MESH_POINT: |
1928 | REG_SET_BIT(ah, AR_TXCFG, | 1743 | REG_SET_BIT(ah, AR_TXCFG, |
1929 | AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); | 1744 | AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); |
1930 | REG_WRITE(ah, AR_NEXT_NDP_TIMER, | 1745 | REG_WRITE(ah, AR_NEXT_NDP_TIMER, next_beacon + |
1931 | TU_TO_USEC(next_beacon + | 1746 | TU_TO_USEC(ah->atim_window ? ah->atim_window : 1)); |
1932 | (ah->atim_window ? ah-> | ||
1933 | atim_window : 1))); | ||
1934 | flags |= AR_NDP_TIMER_EN; | 1747 | flags |= AR_NDP_TIMER_EN; |
1935 | case NL80211_IFTYPE_AP: | 1748 | case NL80211_IFTYPE_AP: |
1936 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); | 1749 | REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon); |
1937 | REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, | 1750 | REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, next_beacon - |
1938 | TU_TO_USEC(next_beacon - | 1751 | TU_TO_USEC(ah->config.dma_beacon_response_time)); |
1939 | ah->config. | 1752 | REG_WRITE(ah, AR_NEXT_SWBA, next_beacon - |
1940 | dma_beacon_response_time)); | 1753 | TU_TO_USEC(ah->config.sw_beacon_response_time)); |
1941 | REG_WRITE(ah, AR_NEXT_SWBA, | ||
1942 | TU_TO_USEC(next_beacon - | ||
1943 | ah->config. | ||
1944 | sw_beacon_response_time)); | ||
1945 | flags |= | 1754 | flags |= |
1946 | AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; | 1755 | AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; |
1947 | break; | 1756 | break; |
1948 | default: | 1757 | default: |
1949 | ath_print(ath9k_hw_common(ah), ATH_DBG_BEACON, | 1758 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_BEACON, |
1950 | "%s: unsupported opmode: %d\n", | 1759 | "%s: unsupported opmode: %d\n", |
1951 | __func__, ah->opmode); | 1760 | __func__, ah->opmode); |
1952 | return; | 1761 | return; |
1953 | break; | 1762 | break; |
1954 | } | 1763 | } |
1955 | 1764 | ||
1956 | REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); | 1765 | REG_WRITE(ah, AR_BEACON_PERIOD, beacon_period); |
1957 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); | 1766 | REG_WRITE(ah, AR_DMA_BEACON_PERIOD, beacon_period); |
1958 | REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); | 1767 | REG_WRITE(ah, AR_SWBA_PERIOD, beacon_period); |
1959 | REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); | 1768 | REG_WRITE(ah, AR_NDP_PERIOD, beacon_period); |
1960 | 1769 | ||
1961 | REGWRITE_BUFFER_FLUSH(ah); | 1770 | REGWRITE_BUFFER_FLUSH(ah); |
1962 | DISABLE_REGWRITE_BUFFER(ah); | ||
1963 | |||
1964 | beacon_period &= ~ATH9K_BEACON_ENA; | ||
1965 | if (beacon_period & ATH9K_BEACON_RESET_TSF) { | ||
1966 | ath9k_hw_reset_tsf(ah); | ||
1967 | } | ||
1968 | 1771 | ||
1969 | REG_SET_BIT(ah, AR_TIMER_MODE, flags); | 1772 | REG_SET_BIT(ah, AR_TIMER_MODE, flags); |
1970 | } | 1773 | } |
@@ -1987,7 +1790,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
1987 | TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); | 1790 | TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); |
1988 | 1791 | ||
1989 | REGWRITE_BUFFER_FLUSH(ah); | 1792 | REGWRITE_BUFFER_FLUSH(ah); |
1990 | DISABLE_REGWRITE_BUFFER(ah); | ||
1991 | 1793 | ||
1992 | REG_RMW_FIELD(ah, AR_RSSI_THR, | 1794 | REG_RMW_FIELD(ah, AR_RSSI_THR, |
1993 | AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); | 1795 | AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); |
@@ -2006,10 +1808,10 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
2006 | else | 1808 | else |
2007 | nextTbtt = bs->bs_nexttbtt; | 1809 | nextTbtt = bs->bs_nexttbtt; |
2008 | 1810 | ||
2009 | ath_print(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); | 1811 | ath_dbg(common, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); |
2010 | ath_print(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); | 1812 | ath_dbg(common, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); |
2011 | ath_print(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); | 1813 | ath_dbg(common, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); |
2012 | ath_print(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); | 1814 | ath_dbg(common, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); |
2013 | 1815 | ||
2014 | ENABLE_REGWRITE_BUFFER(ah); | 1816 | ENABLE_REGWRITE_BUFFER(ah); |
2015 | 1817 | ||
@@ -2033,7 +1835,6 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
2033 | REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); | 1835 | REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); |
2034 | 1836 | ||
2035 | REGWRITE_BUFFER_FLUSH(ah); | 1837 | REGWRITE_BUFFER_FLUSH(ah); |
2036 | DISABLE_REGWRITE_BUFFER(ah); | ||
2037 | 1838 | ||
2038 | REG_SET_BIT(ah, AR_TIMER_MODE, | 1839 | REG_SET_BIT(ah, AR_TIMER_MODE, |
2039 | AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | | 1840 | AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | |
@@ -2055,18 +1856,17 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2055 | struct ath_common *common = ath9k_hw_common(ah); | 1856 | struct ath_common *common = ath9k_hw_common(ah); |
2056 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | 1857 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
2057 | 1858 | ||
2058 | u16 capField = 0, eeval; | 1859 | u16 eeval; |
1860 | u8 ant_div_ctl1, tx_chainmask, rx_chainmask; | ||
2059 | 1861 | ||
2060 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); | 1862 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); |
2061 | regulatory->current_rd = eeval; | 1863 | regulatory->current_rd = eeval; |
2062 | 1864 | ||
2063 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); | 1865 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); |
2064 | if (AR_SREV_9285_10_OR_LATER(ah)) | 1866 | if (AR_SREV_9285_12_OR_LATER(ah)) |
2065 | eeval |= AR9285_RDEXT_DEFAULT; | 1867 | eeval |= AR9285_RDEXT_DEFAULT; |
2066 | regulatory->current_rd_ext = eeval; | 1868 | regulatory->current_rd_ext = eeval; |
2067 | 1869 | ||
2068 | capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); | ||
2069 | |||
2070 | if (ah->opmode != NL80211_IFTYPE_AP && | 1870 | if (ah->opmode != NL80211_IFTYPE_AP && |
2071 | ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { | 1871 | ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { |
2072 | if (regulatory->current_rd == 0x64 || | 1872 | if (regulatory->current_rd == 0x64 || |
@@ -2074,48 +1874,22 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2074 | regulatory->current_rd += 5; | 1874 | regulatory->current_rd += 5; |
2075 | else if (regulatory->current_rd == 0x41) | 1875 | else if (regulatory->current_rd == 0x41) |
2076 | regulatory->current_rd = 0x43; | 1876 | regulatory->current_rd = 0x43; |
2077 | ath_print(common, ATH_DBG_REGULATORY, | 1877 | ath_dbg(common, ATH_DBG_REGULATORY, |
2078 | "regdomain mapped to 0x%x\n", regulatory->current_rd); | 1878 | "regdomain mapped to 0x%x\n", regulatory->current_rd); |
2079 | } | 1879 | } |
2080 | 1880 | ||
2081 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); | 1881 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); |
2082 | if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) { | 1882 | if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) { |
2083 | ath_print(common, ATH_DBG_FATAL, | 1883 | ath_err(common, |
2084 | "no band has been marked as supported in EEPROM.\n"); | 1884 | "no band has been marked as supported in EEPROM\n"); |
2085 | return -EINVAL; | 1885 | return -EINVAL; |
2086 | } | 1886 | } |
2087 | 1887 | ||
2088 | bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX); | 1888 | if (eeval & AR5416_OPFLAGS_11A) |
1889 | pCap->hw_caps |= ATH9K_HW_CAP_5GHZ; | ||
2089 | 1890 | ||
2090 | if (eeval & AR5416_OPFLAGS_11A) { | 1891 | if (eeval & AR5416_OPFLAGS_11G) |
2091 | set_bit(ATH9K_MODE_11A, pCap->wireless_modes); | 1892 | pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; |
2092 | if (ah->config.ht_enable) { | ||
2093 | if (!(eeval & AR5416_OPFLAGS_N_5G_HT20)) | ||
2094 | set_bit(ATH9K_MODE_11NA_HT20, | ||
2095 | pCap->wireless_modes); | ||
2096 | if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) { | ||
2097 | set_bit(ATH9K_MODE_11NA_HT40PLUS, | ||
2098 | pCap->wireless_modes); | ||
2099 | set_bit(ATH9K_MODE_11NA_HT40MINUS, | ||
2100 | pCap->wireless_modes); | ||
2101 | } | ||
2102 | } | ||
2103 | } | ||
2104 | |||
2105 | if (eeval & AR5416_OPFLAGS_11G) { | ||
2106 | set_bit(ATH9K_MODE_11G, pCap->wireless_modes); | ||
2107 | if (ah->config.ht_enable) { | ||
2108 | if (!(eeval & AR5416_OPFLAGS_N_2G_HT20)) | ||
2109 | set_bit(ATH9K_MODE_11NG_HT20, | ||
2110 | pCap->wireless_modes); | ||
2111 | if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) { | ||
2112 | set_bit(ATH9K_MODE_11NG_HT40PLUS, | ||
2113 | pCap->wireless_modes); | ||
2114 | set_bit(ATH9K_MODE_11NG_HT40MINUS, | ||
2115 | pCap->wireless_modes); | ||
2116 | } | ||
2117 | } | ||
2118 | } | ||
2119 | 1893 | ||
2120 | pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); | 1894 | pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); |
2121 | /* | 1895 | /* |
@@ -2127,63 +1901,32 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2127 | !(AR_SREV_9271(ah))) | 1901 | !(AR_SREV_9271(ah))) |
2128 | /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */ | 1902 | /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */ |
2129 | pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; | 1903 | pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; |
1904 | else if (AR_SREV_9100(ah)) | ||
1905 | pCap->rx_chainmask = 0x7; | ||
2130 | else | 1906 | else |
2131 | /* Use rx_chainmask from EEPROM. */ | 1907 | /* Use rx_chainmask from EEPROM. */ |
2132 | pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); | 1908 | pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); |
2133 | 1909 | ||
2134 | if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0))) | 1910 | ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; |
2135 | ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; | ||
2136 | 1911 | ||
2137 | pCap->low_2ghz_chan = 2312; | 1912 | /* enable key search for every frame in an aggregate */ |
2138 | pCap->high_2ghz_chan = 2732; | 1913 | if (AR_SREV_9300_20_OR_LATER(ah)) |
2139 | 1914 | ah->misc_mode |= AR_PCU_ALWAYS_PERFORM_KEYSEARCH; | |
2140 | pCap->low_5ghz_chan = 4920; | ||
2141 | pCap->high_5ghz_chan = 6100; | ||
2142 | |||
2143 | pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP; | ||
2144 | pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP; | ||
2145 | pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM; | ||
2146 | 1915 | ||
2147 | pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP; | 1916 | common->crypt_caps |= ATH_CRYPT_CAP_CIPHER_AESCCM; |
2148 | pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; | ||
2149 | pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; | ||
2150 | 1917 | ||
2151 | if (ah->config.ht_enable) | 1918 | if (ah->hw_version.devid != AR2427_DEVID_PCIE) |
2152 | pCap->hw_caps |= ATH9K_HW_CAP_HT; | 1919 | pCap->hw_caps |= ATH9K_HW_CAP_HT; |
2153 | else | 1920 | else |
2154 | pCap->hw_caps &= ~ATH9K_HW_CAP_HT; | 1921 | pCap->hw_caps &= ~ATH9K_HW_CAP_HT; |
2155 | 1922 | ||
2156 | pCap->hw_caps |= ATH9K_HW_CAP_GTT; | ||
2157 | pCap->hw_caps |= ATH9K_HW_CAP_VEOL; | ||
2158 | pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK; | ||
2159 | pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH; | ||
2160 | |||
2161 | if (capField & AR_EEPROM_EEPCAP_MAXQCU) | ||
2162 | pCap->total_queues = | ||
2163 | MS(capField, AR_EEPROM_EEPCAP_MAXQCU); | ||
2164 | else | ||
2165 | pCap->total_queues = ATH9K_NUM_TX_QUEUES; | ||
2166 | |||
2167 | if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) | ||
2168 | pCap->keycache_size = | ||
2169 | 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); | ||
2170 | else | ||
2171 | pCap->keycache_size = AR_KEYTABLE_SIZE; | ||
2172 | |||
2173 | pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; | ||
2174 | |||
2175 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | ||
2176 | pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; | ||
2177 | else | ||
2178 | pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; | ||
2179 | |||
2180 | if (AR_SREV_9271(ah)) | 1923 | if (AR_SREV_9271(ah)) |
2181 | pCap->num_gpio_pins = AR9271_NUM_GPIO; | 1924 | pCap->num_gpio_pins = AR9271_NUM_GPIO; |
2182 | else if (AR_DEVID_7010(ah)) | 1925 | else if (AR_DEVID_7010(ah)) |
2183 | pCap->num_gpio_pins = AR7010_NUM_GPIO; | 1926 | pCap->num_gpio_pins = AR7010_NUM_GPIO; |
2184 | else if (AR_SREV_9285_10_OR_LATER(ah)) | 1927 | else if (AR_SREV_9285_12_OR_LATER(ah)) |
2185 | pCap->num_gpio_pins = AR9285_NUM_GPIO; | 1928 | pCap->num_gpio_pins = AR9285_NUM_GPIO; |
2186 | else if (AR_SREV_9280_10_OR_LATER(ah)) | 1929 | else if (AR_SREV_9280_20_OR_LATER(ah)) |
2187 | pCap->num_gpio_pins = AR928X_NUM_GPIO; | 1930 | pCap->num_gpio_pins = AR928X_NUM_GPIO; |
2188 | else | 1931 | else |
2189 | pCap->num_gpio_pins = AR_NUM_GPIO; | 1932 | pCap->num_gpio_pins = AR_NUM_GPIO; |
@@ -2195,8 +1938,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2195 | pCap->rts_aggr_limit = (8 * 1024); | 1938 | pCap->rts_aggr_limit = (8 * 1024); |
2196 | } | 1939 | } |
2197 | 1940 | ||
2198 | pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; | ||
2199 | |||
2200 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | 1941 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) |
2201 | ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); | 1942 | ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); |
2202 | if (ah->rfsilent & EEP_RFSILENT_ENABLED) { | 1943 | if (ah->rfsilent & EEP_RFSILENT_ENABLED) { |
@@ -2218,52 +1959,40 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2218 | else | 1959 | else |
2219 | pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; | 1960 | pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; |
2220 | 1961 | ||
2221 | if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { | 1962 | if (common->btcoex_enabled) { |
2222 | pCap->reg_cap = | 1963 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
2223 | AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | | ||
2224 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | | ||
2225 | AR_EEPROM_EEREGCAP_EN_KK_U2 | | ||
2226 | AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; | ||
2227 | } else { | ||
2228 | pCap->reg_cap = | ||
2229 | AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | | ||
2230 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; | ||
2231 | } | ||
2232 | |||
2233 | /* Advertise midband for AR5416 with FCC midband set in eeprom */ | ||
2234 | if (regulatory->current_rd_ext & (1 << REG_EXT_FCC_MIDBAND) && | ||
2235 | AR_SREV_5416(ah)) | ||
2236 | pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; | ||
2237 | |||
2238 | pCap->num_antcfg_5ghz = | ||
2239 | ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ); | ||
2240 | pCap->num_antcfg_2ghz = | ||
2241 | ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); | ||
2242 | |||
2243 | if (AR_SREV_9280_10_OR_LATER(ah) && | ||
2244 | ath9k_hw_btcoex_supported(ah)) { | ||
2245 | btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; | ||
2246 | btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; | ||
2247 | |||
2248 | if (AR_SREV_9285(ah)) { | ||
2249 | btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; | 1964 | btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; |
2250 | btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO; | 1965 | btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300; |
2251 | } else { | 1966 | btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300; |
2252 | btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; | 1967 | btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9300; |
1968 | } else if (AR_SREV_9280_20_OR_LATER(ah)) { | ||
1969 | btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9280; | ||
1970 | btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9280; | ||
1971 | |||
1972 | if (AR_SREV_9285(ah)) { | ||
1973 | btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; | ||
1974 | btcoex_hw->btpriority_gpio = | ||
1975 | ATH_BTPRIORITY_GPIO_9285; | ||
1976 | } else { | ||
1977 | btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; | ||
1978 | } | ||
2253 | } | 1979 | } |
2254 | } else { | 1980 | } else { |
2255 | btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; | 1981 | btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; |
2256 | } | 1982 | } |
2257 | 1983 | ||
2258 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 1984 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
2259 | pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC | | 1985 | pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK; |
2260 | ATH9K_HW_CAP_FASTCLOCK; | 1986 | if (!AR_SREV_9485(ah)) |
1987 | pCap->hw_caps |= ATH9K_HW_CAP_LDPC; | ||
1988 | |||
2261 | pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; | 1989 | pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH; |
2262 | pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; | 1990 | pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH; |
2263 | pCap->rx_status_len = sizeof(struct ar9003_rxs); | 1991 | pCap->rx_status_len = sizeof(struct ar9003_rxs); |
2264 | pCap->tx_desc_len = sizeof(struct ar9003_txc); | 1992 | pCap->tx_desc_len = sizeof(struct ar9003_txc); |
2265 | pCap->txs_len = sizeof(struct ar9003_txs); | 1993 | pCap->txs_len = sizeof(struct ar9003_txs); |
2266 | if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) | 1994 | if (!ah->config.paprd_disable && |
1995 | ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) | ||
2267 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; | 1996 | pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; |
2268 | } else { | 1997 | } else { |
2269 | pCap->tx_desc_len = sizeof(struct ath_desc); | 1998 | pCap->tx_desc_len = sizeof(struct ath_desc); |
@@ -2277,9 +2006,59 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2277 | if (AR_SREV_9300_20_OR_LATER(ah)) | 2006 | if (AR_SREV_9300_20_OR_LATER(ah)) |
2278 | pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; | 2007 | pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; |
2279 | 2008 | ||
2280 | if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah)) | 2009 | if (AR_SREV_9300_20_OR_LATER(ah)) |
2010 | ah->ent_mode = REG_READ(ah, AR_ENT_OTP); | ||
2011 | |||
2012 | if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) | ||
2281 | pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; | 2013 | pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; |
2282 | 2014 | ||
2015 | if (AR_SREV_9285(ah)) | ||
2016 | if (ah->eep_ops->get_eeprom(ah, EEP_MODAL_VER) >= 3) { | ||
2017 | ant_div_ctl1 = | ||
2018 | ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | ||
2019 | if ((ant_div_ctl1 & 0x1) && ((ant_div_ctl1 >> 3) & 0x1)) | ||
2020 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; | ||
2021 | } | ||
2022 | if (AR_SREV_9300_20_OR_LATER(ah)) { | ||
2023 | if (ah->eep_ops->get_eeprom(ah, EEP_CHAIN_MASK_REDUCE)) | ||
2024 | pCap->hw_caps |= ATH9K_HW_CAP_APM; | ||
2025 | } | ||
2026 | |||
2027 | |||
2028 | if (AR_SREV_9485(ah)) { | ||
2029 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | ||
2030 | /* | ||
2031 | * enable the diversity-combining algorithm only when | ||
2032 | * both enable_lna_div and enable_fast_div are set | ||
2033 | * Table for Diversity | ||
2034 | * ant_div_alt_lnaconf bit 0-1 | ||
2035 | * ant_div_main_lnaconf bit 2-3 | ||
2036 | * ant_div_alt_gaintb bit 4 | ||
2037 | * ant_div_main_gaintb bit 5 | ||
2038 | * enable_ant_div_lnadiv bit 6 | ||
2039 | * enable_ant_fast_div bit 7 | ||
2040 | */ | ||
2041 | if ((ant_div_ctl1 >> 0x6) == 0x3) | ||
2042 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; | ||
2043 | } | ||
2044 | |||
2045 | if (AR_SREV_9485_10(ah)) { | ||
2046 | pCap->pcie_lcr_extsync_en = true; | ||
2047 | pCap->pcie_lcr_offset = 0x80; | ||
2048 | } | ||
2049 | |||
2050 | tx_chainmask = pCap->tx_chainmask; | ||
2051 | rx_chainmask = pCap->rx_chainmask; | ||
2052 | while (tx_chainmask || rx_chainmask) { | ||
2053 | if (tx_chainmask & BIT(0)) | ||
2054 | pCap->max_txchains++; | ||
2055 | if (rx_chainmask & BIT(0)) | ||
2056 | pCap->max_rxchains++; | ||
2057 | |||
2058 | tx_chainmask >>= 1; | ||
2059 | rx_chainmask >>= 1; | ||
2060 | } | ||
2061 | |||
2283 | return 0; | 2062 | return 0; |
2284 | } | 2063 | } |
2285 | 2064 | ||
@@ -2350,14 +2129,15 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) | |||
2350 | val = REG_READ(ah, AR7010_GPIO_IN); | 2129 | val = REG_READ(ah, AR7010_GPIO_IN); |
2351 | return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0; | 2130 | return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0; |
2352 | } else if (AR_SREV_9300_20_OR_LATER(ah)) | 2131 | } else if (AR_SREV_9300_20_OR_LATER(ah)) |
2353 | return MS_REG_READ(AR9300, gpio) != 0; | 2132 | return (MS(REG_READ(ah, AR_GPIO_IN), AR9300_GPIO_IN_VAL) & |
2133 | AR_GPIO_BIT(gpio)) != 0; | ||
2354 | else if (AR_SREV_9271(ah)) | 2134 | else if (AR_SREV_9271(ah)) |
2355 | return MS_REG_READ(AR9271, gpio) != 0; | 2135 | return MS_REG_READ(AR9271, gpio) != 0; |
2356 | else if (AR_SREV_9287_10_OR_LATER(ah)) | 2136 | else if (AR_SREV_9287_11_OR_LATER(ah)) |
2357 | return MS_REG_READ(AR9287, gpio) != 0; | 2137 | return MS_REG_READ(AR9287, gpio) != 0; |
2358 | else if (AR_SREV_9285_10_OR_LATER(ah)) | 2138 | else if (AR_SREV_9285_12_OR_LATER(ah)) |
2359 | return MS_REG_READ(AR9285, gpio) != 0; | 2139 | return MS_REG_READ(AR9285, gpio) != 0; |
2360 | else if (AR_SREV_9280_10_OR_LATER(ah)) | 2140 | else if (AR_SREV_9280_20_OR_LATER(ah)) |
2361 | return MS_REG_READ(AR928X, gpio) != 0; | 2141 | return MS_REG_READ(AR928X, gpio) != 0; |
2362 | else | 2142 | else |
2363 | return MS_REG_READ(AR, gpio) != 0; | 2143 | return MS_REG_READ(AR, gpio) != 0; |
@@ -2449,14 +2229,11 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) | |||
2449 | REG_WRITE(ah, AR_PHY_ERR, phybits); | 2229 | REG_WRITE(ah, AR_PHY_ERR, phybits); |
2450 | 2230 | ||
2451 | if (phybits) | 2231 | if (phybits) |
2452 | REG_WRITE(ah, AR_RXCFG, | 2232 | REG_SET_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); |
2453 | REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); | ||
2454 | else | 2233 | else |
2455 | REG_WRITE(ah, AR_RXCFG, | 2234 | REG_CLR_BIT(ah, AR_RXCFG, AR_RXCFG_ZLFDMA); |
2456 | REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); | ||
2457 | 2235 | ||
2458 | REGWRITE_BUFFER_FLUSH(ah); | 2236 | REGWRITE_BUFFER_FLUSH(ah); |
2459 | DISABLE_REGWRITE_BUFFER(ah); | ||
2460 | } | 2237 | } |
2461 | EXPORT_SYMBOL(ath9k_hw_setrxfilter); | 2238 | EXPORT_SYMBOL(ath9k_hw_setrxfilter); |
2462 | 2239 | ||
@@ -2483,7 +2260,7 @@ bool ath9k_hw_disable(struct ath_hw *ah) | |||
2483 | } | 2260 | } |
2484 | EXPORT_SYMBOL(ath9k_hw_disable); | 2261 | EXPORT_SYMBOL(ath9k_hw_disable); |
2485 | 2262 | ||
2486 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) | 2263 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test) |
2487 | { | 2264 | { |
2488 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 2265 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
2489 | struct ath9k_channel *chan = ah->curchan; | 2266 | struct ath9k_channel *chan = ah->curchan; |
@@ -2496,7 +2273,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) | |||
2496 | channel->max_antenna_gain * 2, | 2273 | channel->max_antenna_gain * 2, |
2497 | channel->max_power * 2, | 2274 | channel->max_power * 2, |
2498 | min((u32) MAX_RATE_POWER, | 2275 | min((u32) MAX_RATE_POWER, |
2499 | (u32) regulatory->power_limit)); | 2276 | (u32) regulatory->power_limit), test); |
2500 | } | 2277 | } |
2501 | EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); | 2278 | EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); |
2502 | 2279 | ||
@@ -2556,8 +2333,8 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah) | |||
2556 | { | 2333 | { |
2557 | if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, | 2334 | if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, |
2558 | AH_TSF_WRITE_TIMEOUT)) | 2335 | AH_TSF_WRITE_TIMEOUT)) |
2559 | ath_print(ath9k_hw_common(ah), ATH_DBG_RESET, | 2336 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET, |
2560 | "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); | 2337 | "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); |
2561 | 2338 | ||
2562 | REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); | 2339 | REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); |
2563 | } | 2340 | } |
@@ -2648,9 +2425,9 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | |||
2648 | timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); | 2425 | timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); |
2649 | 2426 | ||
2650 | if (timer == NULL) { | 2427 | if (timer == NULL) { |
2651 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 2428 | ath_err(ath9k_hw_common(ah), |
2652 | "Failed to allocate memory" | 2429 | "Failed to allocate memory for hw timer[%d]\n", |
2653 | "for hw timer[%d]\n", timer_index); | 2430 | timer_index); |
2654 | return NULL; | 2431 | return NULL; |
2655 | } | 2432 | } |
2656 | 2433 | ||
@@ -2667,11 +2444,11 @@ EXPORT_SYMBOL(ath_gen_timer_alloc); | |||
2667 | 2444 | ||
2668 | void ath9k_hw_gen_timer_start(struct ath_hw *ah, | 2445 | void ath9k_hw_gen_timer_start(struct ath_hw *ah, |
2669 | struct ath_gen_timer *timer, | 2446 | struct ath_gen_timer *timer, |
2670 | u32 timer_next, | 2447 | u32 trig_timeout, |
2671 | u32 timer_period) | 2448 | u32 timer_period) |
2672 | { | 2449 | { |
2673 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | 2450 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; |
2674 | u32 tsf; | 2451 | u32 tsf, timer_next; |
2675 | 2452 | ||
2676 | BUG_ON(!timer_period); | 2453 | BUG_ON(!timer_period); |
2677 | 2454 | ||
@@ -2679,16 +2456,11 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, | |||
2679 | 2456 | ||
2680 | tsf = ath9k_hw_gettsf32(ah); | 2457 | tsf = ath9k_hw_gettsf32(ah); |
2681 | 2458 | ||
2682 | ath_print(ath9k_hw_common(ah), ATH_DBG_HWTIMER, | 2459 | timer_next = tsf + trig_timeout; |
2683 | "curent tsf %x period %x" | ||
2684 | "timer_next %x\n", tsf, timer_period, timer_next); | ||
2685 | 2460 | ||
2686 | /* | 2461 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_HWTIMER, |
2687 | * Pull timer_next forward if the current TSF already passed it | 2462 | "current tsf %x period %x timer_next %x\n", |
2688 | * because of software latency | 2463 | tsf, timer_period, timer_next); |
2689 | */ | ||
2690 | if (timer_next < tsf) | ||
2691 | timer_next = tsf + timer_period; | ||
2692 | 2464 | ||
2693 | /* | 2465 | /* |
2694 | * Program generic timer registers | 2466 | * Program generic timer registers |
@@ -2761,8 +2533,8 @@ void ath_gen_timer_isr(struct ath_hw *ah) | |||
2761 | index = rightmost_index(timer_table, &thresh_mask); | 2533 | index = rightmost_index(timer_table, &thresh_mask); |
2762 | timer = timer_table->timers[index]; | 2534 | timer = timer_table->timers[index]; |
2763 | BUG_ON(!timer); | 2535 | BUG_ON(!timer); |
2764 | ath_print(common, ATH_DBG_HWTIMER, | 2536 | ath_dbg(common, ATH_DBG_HWTIMER, |
2765 | "TSF overflow for Gen timer %d\n", index); | 2537 | "TSF overflow for Gen timer %d\n", index); |
2766 | timer->overflow(timer->arg); | 2538 | timer->overflow(timer->arg); |
2767 | } | 2539 | } |
2768 | 2540 | ||
@@ -2770,8 +2542,8 @@ void ath_gen_timer_isr(struct ath_hw *ah) | |||
2770 | index = rightmost_index(timer_table, &trigger_mask); | 2542 | index = rightmost_index(timer_table, &trigger_mask); |
2771 | timer = timer_table->timers[index]; | 2543 | timer = timer_table->timers[index]; |
2772 | BUG_ON(!timer); | 2544 | BUG_ON(!timer); |
2773 | ath_print(common, ATH_DBG_HWTIMER, | 2545 | ath_dbg(common, ATH_DBG_HWTIMER, |
2774 | "Gen timer[%d] trigger\n", index); | 2546 | "Gen timer[%d] trigger\n", index); |
2775 | timer->trigger(timer->arg); | 2547 | timer->trigger(timer->arg); |
2776 | } | 2548 | } |
2777 | } | 2549 | } |
@@ -2802,6 +2574,7 @@ static struct { | |||
2802 | { AR_SREV_VERSION_9287, "9287" }, | 2574 | { AR_SREV_VERSION_9287, "9287" }, |
2803 | { AR_SREV_VERSION_9271, "9271" }, | 2575 | { AR_SREV_VERSION_9271, "9271" }, |
2804 | { AR_SREV_VERSION_9300, "9300" }, | 2576 | { AR_SREV_VERSION_9300, "9300" }, |
2577 | { AR_SREV_VERSION_9485, "9485" }, | ||
2805 | }; | 2578 | }; |
2806 | 2579 | ||
2807 | /* For devices with external radios */ | 2580 | /* For devices with external radios */ |
@@ -2854,7 +2627,7 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len) | |||
2854 | int used; | 2627 | int used; |
2855 | 2628 | ||
2856 | /* chipsets >= AR9280 are single-chip */ | 2629 | /* chipsets >= AR9280 are single-chip */ |
2857 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 2630 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
2858 | used = snprintf(hw_name, len, | 2631 | used = snprintf(hw_name, len, |
2859 | "Atheros AR%s Rev:%x", | 2632 | "Atheros AR%s Rev:%x", |
2860 | ath9k_hw_mac_bb_name(ah->hw_version.macVersion), | 2633 | ath9k_hw_mac_bb_name(ah->hw_version.macVersion), |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 399f7c1283cd..4b157c53d1a8 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2010 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -30,7 +30,6 @@ | |||
30 | #include "btcoex.h" | 30 | #include "btcoex.h" |
31 | 31 | ||
32 | #include "../regd.h" | 32 | #include "../regd.h" |
33 | #include "../debug.h" | ||
34 | 33 | ||
35 | #define ATHEROS_VENDOR_ID 0x168c | 34 | #define ATHEROS_VENDOR_ID 0x168c |
36 | 35 | ||
@@ -44,6 +43,8 @@ | |||
44 | #define AR9287_DEVID_PCI 0x002d | 43 | #define AR9287_DEVID_PCI 0x002d |
45 | #define AR9287_DEVID_PCIE 0x002e | 44 | #define AR9287_DEVID_PCIE 0x002e |
46 | #define AR9300_DEVID_PCIE 0x0030 | 45 | #define AR9300_DEVID_PCIE 0x0030 |
46 | #define AR9300_DEVID_AR9340 0x0031 | ||
47 | #define AR9300_DEVID_AR9485_PCIE 0x0032 | ||
47 | 48 | ||
48 | #define AR5416_AR9100_DEVID 0x000b | 49 | #define AR5416_AR9100_DEVID 0x000b |
49 | 50 | ||
@@ -55,64 +56,62 @@ | |||
55 | #define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa | 56 | #define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa |
56 | #define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab | 57 | #define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab |
57 | 58 | ||
59 | #define AR9300_NUM_BT_WEIGHTS 4 | ||
60 | #define AR9300_NUM_WLAN_WEIGHTS 4 | ||
61 | |||
58 | #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) | 62 | #define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) |
59 | 63 | ||
60 | #define ATH_DEFAULT_NOISE_FLOOR -95 | 64 | #define ATH_DEFAULT_NOISE_FLOOR -95 |
61 | 65 | ||
62 | #define ATH9K_RSSI_BAD -128 | 66 | #define ATH9K_RSSI_BAD -128 |
63 | 67 | ||
68 | #define ATH9K_NUM_CHANNELS 38 | ||
69 | |||
64 | /* Register read/write primitives */ | 70 | /* Register read/write primitives */ |
65 | #define REG_WRITE(_ah, _reg, _val) \ | 71 | #define REG_WRITE(_ah, _reg, _val) \ |
66 | ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg)) | 72 | (_ah)->reg_ops.write((_ah), (_val), (_reg)) |
67 | 73 | ||
68 | #define REG_READ(_ah, _reg) \ | 74 | #define REG_READ(_ah, _reg) \ |
69 | ath9k_hw_common(_ah)->ops->read((_ah), (_reg)) | 75 | (_ah)->reg_ops.read((_ah), (_reg)) |
70 | 76 | ||
71 | #define ENABLE_REGWRITE_BUFFER(_ah) \ | 77 | #define REG_READ_MULTI(_ah, _addr, _val, _cnt) \ |
72 | do { \ | 78 | (_ah)->reg_ops.multi_read((_ah), (_addr), (_val), (_cnt)) |
73 | if (AR_SREV_9271(_ah)) \ | 79 | |
74 | ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \ | 80 | #define REG_RMW(_ah, _reg, _set, _clr) \ |
75 | } while (0) | 81 | (_ah)->reg_ops.rmw((_ah), (_reg), (_set), (_clr)) |
76 | 82 | ||
77 | #define DISABLE_REGWRITE_BUFFER(_ah) \ | 83 | #define ENABLE_REGWRITE_BUFFER(_ah) \ |
78 | do { \ | 84 | do { \ |
79 | if (AR_SREV_9271(_ah)) \ | 85 | if ((_ah)->reg_ops.enable_write_buffer) \ |
80 | ath9k_hw_common(_ah)->ops->disable_write_buffer((_ah)); \ | 86 | (_ah)->reg_ops.enable_write_buffer((_ah)); \ |
81 | } while (0) | 87 | } while (0) |
82 | 88 | ||
83 | #define REGWRITE_BUFFER_FLUSH(_ah) \ | 89 | #define REGWRITE_BUFFER_FLUSH(_ah) \ |
84 | do { \ | 90 | do { \ |
85 | if (AR_SREV_9271(_ah)) \ | 91 | if ((_ah)->reg_ops.write_flush) \ |
86 | ath9k_hw_common(_ah)->ops->write_flush((_ah)); \ | 92 | (_ah)->reg_ops.write_flush((_ah)); \ |
87 | } while (0) | 93 | } while (0) |
88 | 94 | ||
89 | #define SM(_v, _f) (((_v) << _f##_S) & _f) | 95 | #define SM(_v, _f) (((_v) << _f##_S) & _f) |
90 | #define MS(_v, _f) (((_v) & _f) >> _f##_S) | 96 | #define MS(_v, _f) (((_v) & _f) >> _f##_S) |
91 | #define REG_RMW(_a, _r, _set, _clr) \ | ||
92 | REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set)) | ||
93 | #define REG_RMW_FIELD(_a, _r, _f, _v) \ | 97 | #define REG_RMW_FIELD(_a, _r, _f, _v) \ |
94 | REG_WRITE(_a, _r, \ | 98 | REG_RMW(_a, _r, (((_v) << _f##_S) & _f), (_f)) |
95 | (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) | ||
96 | #define REG_READ_FIELD(_a, _r, _f) \ | 99 | #define REG_READ_FIELD(_a, _r, _f) \ |
97 | (((REG_READ(_a, _r) & _f) >> _f##_S)) | 100 | (((REG_READ(_a, _r) & _f) >> _f##_S)) |
98 | #define REG_SET_BIT(_a, _r, _f) \ | 101 | #define REG_SET_BIT(_a, _r, _f) \ |
99 | REG_WRITE(_a, _r, REG_READ(_a, _r) | _f) | 102 | REG_RMW(_a, _r, (_f), 0) |
100 | #define REG_CLR_BIT(_a, _r, _f) \ | 103 | #define REG_CLR_BIT(_a, _r, _f) \ |
101 | REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) | 104 | REG_RMW(_a, _r, 0, (_f)) |
102 | 105 | ||
103 | #define DO_DELAY(x) do { \ | 106 | #define DO_DELAY(x) do { \ |
104 | if ((++(x) % 64) == 0) \ | 107 | if (((++(x) % 64) == 0) && \ |
105 | udelay(1); \ | 108 | (ath9k_hw_common(ah)->bus_ops->ath_bus_type \ |
109 | != ATH_USB)) \ | ||
110 | udelay(1); \ | ||
106 | } while (0) | 111 | } while (0) |
107 | 112 | ||
108 | #define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ | 113 | #define REG_WRITE_ARRAY(iniarray, column, regWr) \ |
109 | int r; \ | 114 | ath9k_hw_write_array(ah, iniarray, column, &(regWr)) |
110 | for (r = 0; r < ((iniarray)->ia_rows); r++) { \ | ||
111 | REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ | ||
112 | INI_RA((iniarray), r, (column))); \ | ||
113 | DO_DELAY(regWr); \ | ||
114 | } \ | ||
115 | } while (0) | ||
116 | 115 | ||
117 | #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 | 116 | #define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 |
118 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 | 117 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 |
@@ -126,7 +125,7 @@ | |||
126 | #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) | 125 | #define AR_GPIO_BIT(_gpio) (1 << (_gpio)) |
127 | 126 | ||
128 | #define BASE_ACTIVATE_DELAY 100 | 127 | #define BASE_ACTIVATE_DELAY 100 |
129 | #define RTC_PLL_SETTLE_DELAY 100 | 128 | #define RTC_PLL_SETTLE_DELAY (AR_SREV_9340(ah) ? 1000 : 100) |
130 | #define COEF_SCALE_S 24 | 129 | #define COEF_SCALE_S 24 |
131 | #define HT40_CHANNEL_CENTER_SHIFT 10 | 130 | #define HT40_CHANNEL_CENTER_SHIFT 10 |
132 | 131 | ||
@@ -161,6 +160,13 @@ | |||
161 | #define PAPRD_GAIN_TABLE_ENTRIES 32 | 160 | #define PAPRD_GAIN_TABLE_ENTRIES 32 |
162 | #define PAPRD_TABLE_SZ 24 | 161 | #define PAPRD_TABLE_SZ 24 |
163 | 162 | ||
163 | enum ath_hw_txq_subtype { | ||
164 | ATH_TXQ_AC_BE = 0, | ||
165 | ATH_TXQ_AC_BK = 1, | ||
166 | ATH_TXQ_AC_VI = 2, | ||
167 | ATH_TXQ_AC_VO = 3, | ||
168 | }; | ||
169 | |||
164 | enum ath_ini_subsys { | 170 | enum ath_ini_subsys { |
165 | ATH_INI_PRE = 0, | 171 | ATH_INI_PRE = 0, |
166 | ATH_INI_CORE, | 172 | ATH_INI_CORE, |
@@ -168,64 +174,39 @@ enum ath_ini_subsys { | |||
168 | ATH_INI_NUM_SPLIT, | 174 | ATH_INI_NUM_SPLIT, |
169 | }; | 175 | }; |
170 | 176 | ||
171 | enum wireless_mode { | ||
172 | ATH9K_MODE_11A = 0, | ||
173 | ATH9K_MODE_11G, | ||
174 | ATH9K_MODE_11NA_HT20, | ||
175 | ATH9K_MODE_11NG_HT20, | ||
176 | ATH9K_MODE_11NA_HT40PLUS, | ||
177 | ATH9K_MODE_11NA_HT40MINUS, | ||
178 | ATH9K_MODE_11NG_HT40PLUS, | ||
179 | ATH9K_MODE_11NG_HT40MINUS, | ||
180 | ATH9K_MODE_MAX, | ||
181 | }; | ||
182 | |||
183 | enum ath9k_hw_caps { | 177 | enum ath9k_hw_caps { |
184 | ATH9K_HW_CAP_MIC_AESCCM = BIT(0), | 178 | ATH9K_HW_CAP_HT = BIT(0), |
185 | ATH9K_HW_CAP_MIC_CKIP = BIT(1), | 179 | ATH9K_HW_CAP_RFSILENT = BIT(1), |
186 | ATH9K_HW_CAP_MIC_TKIP = BIT(2), | 180 | ATH9K_HW_CAP_CST = BIT(2), |
187 | ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3), | 181 | ATH9K_HW_CAP_AUTOSLEEP = BIT(4), |
188 | ATH9K_HW_CAP_CIPHER_CKIP = BIT(4), | 182 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(5), |
189 | ATH9K_HW_CAP_CIPHER_TKIP = BIT(5), | 183 | ATH9K_HW_CAP_EDMA = BIT(6), |
190 | ATH9K_HW_CAP_VEOL = BIT(6), | 184 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(7), |
191 | ATH9K_HW_CAP_BSSIDMASK = BIT(7), | 185 | ATH9K_HW_CAP_LDPC = BIT(8), |
192 | ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8), | 186 | ATH9K_HW_CAP_FASTCLOCK = BIT(9), |
193 | ATH9K_HW_CAP_HT = BIT(9), | 187 | ATH9K_HW_CAP_SGI_20 = BIT(10), |
194 | ATH9K_HW_CAP_GTT = BIT(10), | 188 | ATH9K_HW_CAP_PAPRD = BIT(11), |
195 | ATH9K_HW_CAP_FASTCC = BIT(11), | 189 | ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), |
196 | ATH9K_HW_CAP_RFSILENT = BIT(12), | 190 | ATH9K_HW_CAP_2GHZ = BIT(13), |
197 | ATH9K_HW_CAP_CST = BIT(13), | 191 | ATH9K_HW_CAP_5GHZ = BIT(14), |
198 | ATH9K_HW_CAP_ENHANCEDPM = BIT(14), | 192 | ATH9K_HW_CAP_APM = BIT(15), |
199 | ATH9K_HW_CAP_AUTOSLEEP = BIT(15), | ||
200 | ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), | ||
201 | ATH9K_HW_CAP_EDMA = BIT(17), | ||
202 | ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18), | ||
203 | ATH9K_HW_CAP_LDPC = BIT(19), | ||
204 | ATH9K_HW_CAP_FASTCLOCK = BIT(20), | ||
205 | ATH9K_HW_CAP_SGI_20 = BIT(21), | ||
206 | ATH9K_HW_CAP_PAPRD = BIT(22), | ||
207 | }; | 193 | }; |
208 | 194 | ||
209 | struct ath9k_hw_capabilities { | 195 | struct ath9k_hw_capabilities { |
210 | u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ | 196 | u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ |
211 | DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */ | ||
212 | u16 total_queues; | ||
213 | u16 keycache_size; | ||
214 | u16 low_5ghz_chan, high_5ghz_chan; | ||
215 | u16 low_2ghz_chan, high_2ghz_chan; | ||
216 | u16 rts_aggr_limit; | 197 | u16 rts_aggr_limit; |
217 | u8 tx_chainmask; | 198 | u8 tx_chainmask; |
218 | u8 rx_chainmask; | 199 | u8 rx_chainmask; |
219 | u16 tx_triglevel_max; | 200 | u8 max_txchains; |
220 | u16 reg_cap; | 201 | u8 max_rxchains; |
221 | u8 num_gpio_pins; | 202 | u8 num_gpio_pins; |
222 | u8 num_antcfg_2ghz; | ||
223 | u8 num_antcfg_5ghz; | ||
224 | u8 rx_hp_qdepth; | 203 | u8 rx_hp_qdepth; |
225 | u8 rx_lp_qdepth; | 204 | u8 rx_lp_qdepth; |
226 | u8 rx_status_len; | 205 | u8 rx_status_len; |
227 | u8 tx_desc_len; | 206 | u8 tx_desc_len; |
228 | u8 txs_len; | 207 | u8 txs_len; |
208 | u16 pcie_lcr_offset; | ||
209 | bool pcie_lcr_extsync_en; | ||
229 | }; | 210 | }; |
230 | 211 | ||
231 | struct ath9k_ops_config { | 212 | struct ath9k_ops_config { |
@@ -239,7 +220,7 @@ struct ath9k_ops_config { | |||
239 | u8 pcie_clock_req; | 220 | u8 pcie_clock_req; |
240 | u32 pcie_waen; | 221 | u32 pcie_waen; |
241 | u8 analog_shiftreg; | 222 | u8 analog_shiftreg; |
242 | u8 ht_enable; | 223 | u8 paprd_disable; |
243 | u32 ofdm_trig_low; | 224 | u32 ofdm_trig_low; |
244 | u32 ofdm_trig_high; | 225 | u32 ofdm_trig_high; |
245 | u32 cck_trig_high; | 226 | u32 cck_trig_high; |
@@ -251,7 +232,6 @@ struct ath9k_ops_config { | |||
251 | #define SPUR_DISABLE 0 | 232 | #define SPUR_DISABLE 0 |
252 | #define SPUR_ENABLE_IOCTL 1 | 233 | #define SPUR_ENABLE_IOCTL 1 |
253 | #define SPUR_ENABLE_EEPROM 2 | 234 | #define SPUR_ENABLE_EEPROM 2 |
254 | #define AR_EEPROM_MODAL_SPURS 5 | ||
255 | #define AR_SPUR_5413_1 1640 | 235 | #define AR_SPUR_5413_1 1640 |
256 | #define AR_SPUR_5413_2 1200 | 236 | #define AR_SPUR_5413_2 1200 |
257 | #define AR_NO_SPUR 0x8000 | 237 | #define AR_NO_SPUR 0x8000 |
@@ -352,9 +332,9 @@ struct ath9k_hw_cal_data { | |||
352 | int32_t CalValid; | 332 | int32_t CalValid; |
353 | int8_t iCoff; | 333 | int8_t iCoff; |
354 | int8_t qCoff; | 334 | int8_t qCoff; |
355 | int16_t rawNoiseFloor; | ||
356 | bool paprd_done; | 335 | bool paprd_done; |
357 | bool nfcal_pending; | 336 | bool nfcal_pending; |
337 | bool nfcal_interference; | ||
358 | u16 small_signal_gain[AR9300_MAX_CHAINS]; | 338 | u16 small_signal_gain[AR9300_MAX_CHAINS]; |
359 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; | 339 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; |
360 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | 340 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |
@@ -362,9 +342,11 @@ struct ath9k_hw_cal_data { | |||
362 | 342 | ||
363 | struct ath9k_channel { | 343 | struct ath9k_channel { |
364 | struct ieee80211_channel *chan; | 344 | struct ieee80211_channel *chan; |
345 | struct ar5416AniState ani; | ||
365 | u16 channel; | 346 | u16 channel; |
366 | u32 channelFlags; | 347 | u32 channelFlags; |
367 | u32 chanmode; | 348 | u32 chanmode; |
349 | s16 noisefloor; | ||
368 | }; | 350 | }; |
369 | 351 | ||
370 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ | 352 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ |
@@ -422,8 +404,6 @@ struct ath9k_beacon_state { | |||
422 | u32 bs_nextdtim; | 404 | u32 bs_nextdtim; |
423 | u32 bs_intval; | 405 | u32 bs_intval; |
424 | #define ATH9K_BEACON_PERIOD 0x0000ffff | 406 | #define ATH9K_BEACON_PERIOD 0x0000ffff |
425 | #define ATH9K_BEACON_ENA 0x00800000 | ||
426 | #define ATH9K_BEACON_RESET_TSF 0x01000000 | ||
427 | #define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ | 407 | #define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ |
428 | u32 bs_dtimperiod; | 408 | u32 bs_dtimperiod; |
429 | u16 bs_cfpperiod; | 409 | u16 bs_cfpperiod; |
@@ -457,6 +437,7 @@ struct ath9k_hw_version { | |||
457 | u16 analog5GhzRev; | 437 | u16 analog5GhzRev; |
458 | u16 analog2GhzRev; | 438 | u16 analog2GhzRev; |
459 | u16 subsysid; | 439 | u16 subsysid; |
440 | enum ath_usb_dev usbdev; | ||
460 | }; | 441 | }; |
461 | 442 | ||
462 | /* Generic TSF timer definitions */ | 443 | /* Generic TSF timer definitions */ |
@@ -494,6 +475,50 @@ struct ath_gen_timer_table { | |||
494 | } timer_mask; | 475 | } timer_mask; |
495 | }; | 476 | }; |
496 | 477 | ||
478 | struct ath_hw_antcomb_conf { | ||
479 | u8 main_lna_conf; | ||
480 | u8 alt_lna_conf; | ||
481 | u8 fast_div_bias; | ||
482 | u8 main_gaintb; | ||
483 | u8 alt_gaintb; | ||
484 | int lna1_lna2_delta; | ||
485 | u8 div_group; | ||
486 | }; | ||
487 | |||
488 | /** | ||
489 | * struct ath_hw_radar_conf - radar detection initialization parameters | ||
490 | * | ||
491 | * @pulse_inband: threshold for checking the ratio of in-band power | ||
492 | * to total power for short radar pulses (half dB steps) | ||
493 | * @pulse_inband_step: threshold for checking an in-band power to total | ||
494 | * power ratio increase for short radar pulses (half dB steps) | ||
495 | * @pulse_height: threshold for detecting the beginning of a short | ||
496 | * radar pulse (dB step) | ||
497 | * @pulse_rssi: threshold for detecting if a short radar pulse is | ||
498 | * gone (dB step) | ||
499 | * @pulse_maxlen: maximum pulse length (0.8 us steps) | ||
500 | * | ||
501 | * @radar_rssi: RSSI threshold for starting long radar detection (dB steps) | ||
502 | * @radar_inband: threshold for checking the ratio of in-band power | ||
503 | * to total power for long radar pulses (half dB steps) | ||
504 | * @fir_power: threshold for detecting the end of a long radar pulse (dB) | ||
505 | * | ||
506 | * @ext_channel: enable extension channel radar detection | ||
507 | */ | ||
508 | struct ath_hw_radar_conf { | ||
509 | unsigned int pulse_inband; | ||
510 | unsigned int pulse_inband_step; | ||
511 | unsigned int pulse_height; | ||
512 | unsigned int pulse_rssi; | ||
513 | unsigned int pulse_maxlen; | ||
514 | |||
515 | unsigned int radar_rssi; | ||
516 | unsigned int radar_inband; | ||
517 | int fir_power; | ||
518 | |||
519 | bool ext_channel; | ||
520 | }; | ||
521 | |||
497 | /** | 522 | /** |
498 | * struct ath_hw_private_ops - callbacks used internally by hardware code | 523 | * struct ath_hw_private_ops - callbacks used internally by hardware code |
499 | * | 524 | * |
@@ -505,7 +530,6 @@ struct ath_gen_timer_table { | |||
505 | * | 530 | * |
506 | * @init_mode_regs: Initializes mode registers | 531 | * @init_mode_regs: Initializes mode registers |
507 | * @init_mode_gain_regs: Initialize TX/RX gain registers | 532 | * @init_mode_gain_regs: Initialize TX/RX gain registers |
508 | * @macversion_supported: If this specific mac revision is supported | ||
509 | * | 533 | * |
510 | * @rf_set_freq: change frequency | 534 | * @rf_set_freq: change frequency |
511 | * @spur_mitigate_freq: spur mitigation | 535 | * @spur_mitigate_freq: spur mitigation |
@@ -517,14 +541,6 @@ struct ath_gen_timer_table { | |||
517 | * @setup_calibration: set up calibration | 541 | * @setup_calibration: set up calibration |
518 | * @iscal_supported: used to query if a type of calibration is supported | 542 | * @iscal_supported: used to query if a type of calibration is supported |
519 | * | 543 | * |
520 | * @ani_reset: reset ANI parameters to default values | ||
521 | * @ani_lower_immunity: lower the noise immunity level. The level controls | ||
522 | * the power-based packet detection on hardware. If a power jump is | ||
523 | * detected the adapter takes it as an indication that a packet has | ||
524 | * arrived. The level ranges from 0-5. Each level corresponds to a | ||
525 | * few dB more of noise immunity. If you have a strong time-varying | ||
526 | * interference that is causing false detections (OFDM timing errors or | ||
527 | * CCK timing errors) the level can be increased. | ||
528 | * @ani_cache_ini_regs: cache the values for ANI from the initial | 544 | * @ani_cache_ini_regs: cache the values for ANI from the initial |
529 | * register settings through the register initialization. | 545 | * register settings through the register initialization. |
530 | */ | 546 | */ |
@@ -535,11 +551,8 @@ struct ath_hw_private_ops { | |||
535 | 551 | ||
536 | void (*init_mode_regs)(struct ath_hw *ah); | 552 | void (*init_mode_regs)(struct ath_hw *ah); |
537 | void (*init_mode_gain_regs)(struct ath_hw *ah); | 553 | void (*init_mode_gain_regs)(struct ath_hw *ah); |
538 | bool (*macversion_supported)(u32 macversion); | ||
539 | void (*setup_calibration)(struct ath_hw *ah, | 554 | void (*setup_calibration)(struct ath_hw *ah, |
540 | struct ath9k_cal_list *currCal); | 555 | struct ath9k_cal_list *currCal); |
541 | bool (*iscal_supported)(struct ath_hw *ah, | ||
542 | enum ath9k_cal_types calType); | ||
543 | 556 | ||
544 | /* PHY ops */ | 557 | /* PHY ops */ |
545 | int (*rf_set_freq)(struct ath_hw *ah, | 558 | int (*rf_set_freq)(struct ath_hw *ah, |
@@ -561,7 +574,6 @@ struct ath_hw_private_ops { | |||
561 | void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan); | 574 | void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan); |
562 | bool (*rfbus_req)(struct ath_hw *ah); | 575 | bool (*rfbus_req)(struct ath_hw *ah); |
563 | void (*rfbus_done)(struct ath_hw *ah); | 576 | void (*rfbus_done)(struct ath_hw *ah); |
564 | void (*enable_rfkill)(struct ath_hw *ah); | ||
565 | void (*restore_chainmask)(struct ath_hw *ah); | 577 | void (*restore_chainmask)(struct ath_hw *ah); |
566 | void (*set_diversity)(struct ath_hw *ah, bool value); | 578 | void (*set_diversity)(struct ath_hw *ah, bool value); |
567 | u32 (*compute_pll_control)(struct ath_hw *ah, | 579 | u32 (*compute_pll_control)(struct ath_hw *ah, |
@@ -569,10 +581,10 @@ struct ath_hw_private_ops { | |||
569 | bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, | 581 | bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd, |
570 | int param); | 582 | int param); |
571 | void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); | 583 | void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]); |
584 | void (*set_radar_params)(struct ath_hw *ah, | ||
585 | struct ath_hw_radar_conf *conf); | ||
572 | 586 | ||
573 | /* ANI */ | 587 | /* ANI */ |
574 | void (*ani_reset)(struct ath_hw *ah, bool is_scanning); | ||
575 | void (*ani_lower_immunity)(struct ath_hw *ah); | ||
576 | void (*ani_cache_ini_regs)(struct ath_hw *ah); | 588 | void (*ani_cache_ini_regs)(struct ath_hw *ah); |
577 | }; | 589 | }; |
578 | 590 | ||
@@ -584,11 +596,6 @@ struct ath_hw_private_ops { | |||
584 | * | 596 | * |
585 | * @config_pci_powersave: | 597 | * @config_pci_powersave: |
586 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC | 598 | * @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC |
587 | * | ||
588 | * @ani_proc_mib_event: process MIB events, this would happen upon specific ANI | ||
589 | * thresholds being reached or having overflowed. | ||
590 | * @ani_monitor: called periodically by the core driver to collect | ||
591 | * MIB stats and adjust ANI if specific thresholds have been reached. | ||
592 | */ | 599 | */ |
593 | struct ath_hw_ops { | 600 | struct ath_hw_ops { |
594 | void (*config_pci_powersave)(struct ath_hw *ah, | 601 | void (*config_pci_powersave)(struct ath_hw *ah, |
@@ -625,13 +632,12 @@ struct ath_hw_ops { | |||
625 | u32 numDelims); | 632 | u32 numDelims); |
626 | void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); | 633 | void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); |
627 | void (*clr11n_aggr)(struct ath_hw *ah, void *ds); | 634 | void (*clr11n_aggr)(struct ath_hw *ah, void *ds); |
628 | void (*set11n_burstduration)(struct ath_hw *ah, void *ds, | 635 | void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); |
629 | u32 burstDuration); | 636 | void (*antdiv_comb_conf_get)(struct ath_hw *ah, |
630 | void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds, | 637 | struct ath_hw_antcomb_conf *antconf); |
631 | u32 vmf); | 638 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, |
639 | struct ath_hw_antcomb_conf *antconf); | ||
632 | 640 | ||
633 | void (*ani_proc_mib_event)(struct ath_hw *ah); | ||
634 | void (*ani_monitor)(struct ath_hw *ah, struct ath9k_channel *chan); | ||
635 | }; | 641 | }; |
636 | 642 | ||
637 | struct ath_nf_limits { | 643 | struct ath_nf_limits { |
@@ -640,13 +646,19 @@ struct ath_nf_limits { | |||
640 | s16 nominal; | 646 | s16 nominal; |
641 | }; | 647 | }; |
642 | 648 | ||
649 | /* ah_flags */ | ||
650 | #define AH_USE_EEPROM 0x1 | ||
651 | #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ | ||
652 | |||
643 | struct ath_hw { | 653 | struct ath_hw { |
654 | struct ath_ops reg_ops; | ||
655 | |||
644 | struct ieee80211_hw *hw; | 656 | struct ieee80211_hw *hw; |
645 | struct ath_common common; | 657 | struct ath_common common; |
646 | struct ath9k_hw_version hw_version; | 658 | struct ath9k_hw_version hw_version; |
647 | struct ath9k_ops_config config; | 659 | struct ath9k_ops_config config; |
648 | struct ath9k_hw_capabilities caps; | 660 | struct ath9k_hw_capabilities caps; |
649 | struct ath9k_channel channels[38]; | 661 | struct ath9k_channel channels[ATH9K_NUM_CHANNELS]; |
650 | struct ath9k_channel *curchan; | 662 | struct ath9k_channel *curchan; |
651 | 663 | ||
652 | union { | 664 | union { |
@@ -659,6 +671,7 @@ struct ath_hw { | |||
659 | 671 | ||
660 | bool sw_mgmt_crypto; | 672 | bool sw_mgmt_crypto; |
661 | bool is_pciexpress; | 673 | bool is_pciexpress; |
674 | bool is_monitoring; | ||
662 | bool need_an_top2_fixup; | 675 | bool need_an_top2_fixup; |
663 | u16 tx_trig_level; | 676 | u16 tx_trig_level; |
664 | 677 | ||
@@ -692,10 +705,9 @@ struct ath_hw { | |||
692 | u32 atim_window; | 705 | u32 atim_window; |
693 | 706 | ||
694 | /* Calibration */ | 707 | /* Calibration */ |
695 | enum ath9k_cal_types supp_cals; | 708 | u32 supp_cals; |
696 | struct ath9k_cal_list iq_caldata; | 709 | struct ath9k_cal_list iq_caldata; |
697 | struct ath9k_cal_list adcgain_caldata; | 710 | struct ath9k_cal_list adcgain_caldata; |
698 | struct ath9k_cal_list adcdc_calinitdata; | ||
699 | struct ath9k_cal_list adcdc_caldata; | 711 | struct ath9k_cal_list adcdc_caldata; |
700 | struct ath9k_cal_list tempCompCalData; | 712 | struct ath9k_cal_list tempCompCalData; |
701 | struct ath9k_cal_list *cal_list; | 713 | struct ath9k_cal_list *cal_list; |
@@ -755,17 +767,13 @@ struct ath_hw { | |||
755 | u32 *bank6Temp; | 767 | u32 *bank6Temp; |
756 | 768 | ||
757 | u8 txpower_limit; | 769 | u8 txpower_limit; |
758 | int16_t txpower_indexoffset; | ||
759 | int coverage_class; | 770 | int coverage_class; |
760 | u32 beacon_interval; | ||
761 | u32 slottime; | 771 | u32 slottime; |
762 | u32 globaltxtimeout; | 772 | u32 globaltxtimeout; |
763 | 773 | ||
764 | /* ANI */ | 774 | /* ANI */ |
765 | u32 proc_phyerr; | 775 | u32 proc_phyerr; |
766 | u32 aniperiod; | 776 | u32 aniperiod; |
767 | struct ar5416AniState *curani; | ||
768 | struct ar5416AniState ani[255]; | ||
769 | int totalSizeDesired[5]; | 777 | int totalSizeDesired[5]; |
770 | int coarse_high[5]; | 778 | int coarse_high[5]; |
771 | int coarse_low[5]; | 779 | int coarse_low[5]; |
@@ -774,15 +782,21 @@ struct ath_hw { | |||
774 | 782 | ||
775 | /* Bluetooth coexistance */ | 783 | /* Bluetooth coexistance */ |
776 | struct ath_btcoex_hw btcoex_hw; | 784 | struct ath_btcoex_hw btcoex_hw; |
785 | u32 bt_coex_bt_weight[AR9300_NUM_BT_WEIGHTS]; | ||
786 | u32 bt_coex_wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; | ||
777 | 787 | ||
778 | u32 intr_txqs; | 788 | u32 intr_txqs; |
779 | u8 txchainmask; | 789 | u8 txchainmask; |
780 | u8 rxchainmask; | 790 | u8 rxchainmask; |
781 | 791 | ||
792 | struct ath_hw_radar_conf radar_conf; | ||
793 | |||
782 | u32 originalGain[22]; | 794 | u32 originalGain[22]; |
783 | int initPDADC; | 795 | int initPDADC; |
784 | int PDADCdelta; | 796 | int PDADCdelta; |
785 | u8 led_pin; | 797 | int led_pin; |
798 | u32 gpio_mask; | ||
799 | u32 gpio_val; | ||
786 | 800 | ||
787 | struct ar5416IniArray iniModes; | 801 | struct ar5416IniArray iniModes; |
788 | struct ar5416IniArray iniCommon; | 802 | struct ar5416IniArray iniCommon; |
@@ -798,6 +812,7 @@ struct ath_hw { | |||
798 | struct ar5416IniArray iniPcieSerdes; | 812 | struct ar5416IniArray iniPcieSerdes; |
799 | struct ar5416IniArray iniPcieSerdesLowPower; | 813 | struct ar5416IniArray iniPcieSerdesLowPower; |
800 | struct ar5416IniArray iniModesAdditional; | 814 | struct ar5416IniArray iniModesAdditional; |
815 | struct ar5416IniArray iniModesAdditional_40M; | ||
801 | struct ar5416IniArray iniModesRxGain; | 816 | struct ar5416IniArray iniModesRxGain; |
802 | struct ar5416IniArray iniModesTxGain; | 817 | struct ar5416IniArray iniModesTxGain; |
803 | struct ar5416IniArray iniModes_9271_1_0_only; | 818 | struct ar5416IniArray iniModes_9271_1_0_only; |
@@ -827,7 +842,13 @@ struct ath_hw { | |||
827 | 842 | ||
828 | u32 bb_watchdog_last_status; | 843 | u32 bb_watchdog_last_status; |
829 | u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ | 844 | u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */ |
845 | u8 bb_hang_rx_ofdm; /* true if bb hang due to rx_ofdm */ | ||
830 | 846 | ||
847 | unsigned int paprd_target_power; | ||
848 | unsigned int paprd_training_power; | ||
849 | unsigned int paprd_ratemask; | ||
850 | unsigned int paprd_ratemask_ht40; | ||
851 | bool paprd_table_write_done; | ||
831 | u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; | 852 | u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES]; |
832 | u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; | 853 | u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES]; |
833 | /* | 854 | /* |
@@ -836,6 +857,19 @@ struct ath_hw { | |||
836 | * this register when in sleep states. | 857 | * this register when in sleep states. |
837 | */ | 858 | */ |
838 | u32 WARegVal; | 859 | u32 WARegVal; |
860 | |||
861 | /* Enterprise mode cap */ | ||
862 | u32 ent_mode; | ||
863 | |||
864 | bool is_clk_25mhz; | ||
865 | }; | ||
866 | |||
867 | struct ath_bus_ops { | ||
868 | enum ath_bus_type ath_bus_type; | ||
869 | void (*read_cachesize)(struct ath_common *common, int *csz); | ||
870 | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); | ||
871 | void (*bt_coex_prep)(struct ath_common *common); | ||
872 | void (*extn_synch_en)(struct ath_common *common); | ||
839 | }; | 873 | }; |
840 | 874 | ||
841 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) | 875 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) |
@@ -858,10 +892,9 @@ static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah) | |||
858 | return &ah->ops; | 892 | return &ah->ops; |
859 | } | 893 | } |
860 | 894 | ||
861 | static inline int sign_extend(int val, const int nbits) | 895 | static inline u8 get_streams(int mask) |
862 | { | 896 | { |
863 | int order = BIT(nbits-1); | 897 | return !!(mask & BIT(0)) + !!(mask & BIT(1)) + !!(mask & BIT(2)); |
864 | return (val ^ order) - order; | ||
865 | } | 898 | } |
866 | 899 | ||
867 | /* Initialization, Detach, Reset */ | 900 | /* Initialization, Detach, Reset */ |
@@ -873,12 +906,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
873 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); | 906 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); |
874 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); | 907 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); |
875 | 908 | ||
876 | /* Key Cache Management */ | ||
877 | bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); | ||
878 | bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, | ||
879 | const struct ath9k_keyval *k, | ||
880 | const u8 *mac); | ||
881 | |||
882 | /* GPIO / RFKILL / Antennae */ | 909 | /* GPIO / RFKILL / Antennae */ |
883 | void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); | 910 | void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); |
884 | u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); | 911 | u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); |
@@ -890,8 +917,9 @@ void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); | |||
890 | 917 | ||
891 | /* General Operation */ | 918 | /* General Operation */ |
892 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); | 919 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); |
920 | void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array, | ||
921 | int column, unsigned int *writecnt); | ||
893 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); | 922 | u32 ath9k_hw_reverse_bits(u32 val, u32 n); |
894 | bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); | ||
895 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, | 923 | u16 ath9k_hw_computetxtime(struct ath_hw *ah, |
896 | u8 phy, int kbps, | 924 | u8 phy, int kbps, |
897 | u32 frameLen, u16 rateix, bool shortPreamble); | 925 | u32 frameLen, u16 rateix, bool shortPreamble); |
@@ -902,16 +930,18 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah); | |||
902 | void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); | 930 | void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); |
903 | bool ath9k_hw_phy_disable(struct ath_hw *ah); | 931 | bool ath9k_hw_phy_disable(struct ath_hw *ah); |
904 | bool ath9k_hw_disable(struct ath_hw *ah); | 932 | bool ath9k_hw_disable(struct ath_hw *ah); |
905 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); | 933 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test); |
906 | void ath9k_hw_setopmode(struct ath_hw *ah); | 934 | void ath9k_hw_setopmode(struct ath_hw *ah); |
907 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); | 935 | void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); |
908 | void ath9k_hw_setbssidmask(struct ath_hw *ah); | 936 | void ath9k_hw_setbssidmask(struct ath_hw *ah); |
909 | void ath9k_hw_write_associd(struct ath_hw *ah); | 937 | void ath9k_hw_write_associd(struct ath_hw *ah); |
938 | u32 ath9k_hw_gettsf32(struct ath_hw *ah); | ||
910 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); | 939 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); |
911 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); | 940 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); |
912 | void ath9k_hw_reset_tsf(struct ath_hw *ah); | 941 | void ath9k_hw_reset_tsf(struct ath_hw *ah); |
913 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); | 942 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); |
914 | void ath9k_hw_init_global_settings(struct ath_hw *ah); | 943 | void ath9k_hw_init_global_settings(struct ath_hw *ah); |
944 | u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); | ||
915 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); | 945 | void ath9k_hw_set11nmac2040(struct ath_hw *ah); |
916 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); | 946 | void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); |
917 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | 947 | void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, |
@@ -934,7 +964,6 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); | |||
934 | 964 | ||
935 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); | 965 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); |
936 | void ath_gen_timer_isr(struct ath_hw *hw); | 966 | void ath_gen_timer_isr(struct ath_hw *hw); |
937 | u32 ath9k_hw_gettsf32(struct ath_hw *ah); | ||
938 | 967 | ||
939 | void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); | 968 | void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); |
940 | 969 | ||
@@ -962,6 +991,7 @@ void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah); | |||
962 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); | 991 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah); |
963 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); | 992 | void ar9003_hw_bb_watchdog_read(struct ath_hw *ah); |
964 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); | 993 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); |
994 | void ar9003_hw_disable_phy_restart(struct ath_hw *ah); | ||
965 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); | 995 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); |
966 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, | 996 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, |
967 | struct ath9k_hw_cal_data *caldata, | 997 | struct ath9k_hw_cal_data *caldata, |
@@ -984,6 +1014,7 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah); | |||
984 | void ar9002_hw_attach_ops(struct ath_hw *ah); | 1014 | void ar9002_hw_attach_ops(struct ath_hw *ah); |
985 | void ar9003_hw_attach_ops(struct ath_hw *ah); | 1015 | void ar9003_hw_attach_ops(struct ath_hw *ah); |
986 | 1016 | ||
1017 | void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan); | ||
987 | /* | 1018 | /* |
988 | * ANI work can be shared between all families but a next | 1019 | * ANI work can be shared between all families but a next |
989 | * generation implementation of ANI will be used only for AR9003 only | 1020 | * generation implementation of ANI will be used only for AR9003 only |
@@ -992,8 +1023,9 @@ void ar9003_hw_attach_ops(struct ath_hw *ah); | |||
992 | * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani. | 1023 | * older families (AR5008, AR9001, AR9002) by using modparam_force_new_ani. |
993 | */ | 1024 | */ |
994 | extern int modparam_force_new_ani; | 1025 | extern int modparam_force_new_ani; |
995 | void ath9k_hw_attach_ani_ops_old(struct ath_hw *ah); | 1026 | void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning); |
996 | void ath9k_hw_attach_ani_ops_new(struct ath_hw *ah); | 1027 | void ath9k_hw_proc_mib_event(struct ath_hw *ah); |
1028 | void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); | ||
997 | 1029 | ||
998 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 | 1030 | #define ATH_PCIE_CAP_LINK_CTRL 0x70 |
999 | #define ATH_PCIE_CAP_LINK_L0S 1 | 1031 | #define ATH_PCIE_CAP_LINK_L0S 1 |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 243c1775f343..45c585a337e9 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/ath9k_platform.h> | ||
18 | 19 | ||
19 | #include "ath9k.h" | 20 | #include "ath9k.h" |
20 | 21 | ||
@@ -29,17 +30,23 @@ static unsigned int ath9k_debug = ATH_DBG_DEFAULT; | |||
29 | module_param_named(debug, ath9k_debug, uint, 0); | 30 | module_param_named(debug, ath9k_debug, uint, 0); |
30 | MODULE_PARM_DESC(debug, "Debugging mask"); | 31 | MODULE_PARM_DESC(debug, "Debugging mask"); |
31 | 32 | ||
32 | int modparam_nohwcrypt; | 33 | int ath9k_modparam_nohwcrypt; |
33 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); | 34 | module_param_named(nohwcrypt, ath9k_modparam_nohwcrypt, int, 0444); |
34 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | 35 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); |
35 | 36 | ||
36 | int led_blink = 1; | 37 | int led_blink; |
37 | module_param_named(blink, led_blink, int, 0444); | 38 | module_param_named(blink, led_blink, int, 0444); |
38 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | 39 | MODULE_PARM_DESC(blink, "Enable LED blink on activity"); |
39 | 40 | ||
41 | static int ath9k_btcoex_enable; | ||
42 | module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444); | ||
43 | MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence"); | ||
44 | |||
45 | bool is_ath9k_unloaded; | ||
40 | /* We use the hw_value as an index into our private channel structure */ | 46 | /* We use the hw_value as an index into our private channel structure */ |
41 | 47 | ||
42 | #define CHAN2G(_freq, _idx) { \ | 48 | #define CHAN2G(_freq, _idx) { \ |
49 | .band = IEEE80211_BAND_2GHZ, \ | ||
43 | .center_freq = (_freq), \ | 50 | .center_freq = (_freq), \ |
44 | .hw_value = (_idx), \ | 51 | .hw_value = (_idx), \ |
45 | .max_power = 20, \ | 52 | .max_power = 20, \ |
@@ -56,7 +63,7 @@ MODULE_PARM_DESC(blink, "Enable LED blink on activity"); | |||
56 | * on 5 MHz steps, we support the channels which we know | 63 | * on 5 MHz steps, we support the channels which we know |
57 | * we have calibration data for all cards though to make | 64 | * we have calibration data for all cards though to make |
58 | * this static */ | 65 | * this static */ |
59 | static struct ieee80211_channel ath9k_2ghz_chantable[] = { | 66 | static const struct ieee80211_channel ath9k_2ghz_chantable[] = { |
60 | CHAN2G(2412, 0), /* Channel 1 */ | 67 | CHAN2G(2412, 0), /* Channel 1 */ |
61 | CHAN2G(2417, 1), /* Channel 2 */ | 68 | CHAN2G(2417, 1), /* Channel 2 */ |
62 | CHAN2G(2422, 2), /* Channel 3 */ | 69 | CHAN2G(2422, 2), /* Channel 3 */ |
@@ -77,7 +84,7 @@ static struct ieee80211_channel ath9k_2ghz_chantable[] = { | |||
77 | * on 5 MHz steps, we support the channels which we know | 84 | * on 5 MHz steps, we support the channels which we know |
78 | * we have calibration data for all cards though to make | 85 | * we have calibration data for all cards though to make |
79 | * this static */ | 86 | * this static */ |
80 | static struct ieee80211_channel ath9k_5ghz_chantable[] = { | 87 | static const struct ieee80211_channel ath9k_5ghz_chantable[] = { |
81 | /* _We_ call this UNII 1 */ | 88 | /* _We_ call this UNII 1 */ |
82 | CHAN5G(5180, 14), /* Channel 36 */ | 89 | CHAN5G(5180, 14), /* Channel 36 */ |
83 | CHAN5G(5200, 15), /* Channel 40 */ | 90 | CHAN5G(5200, 15), /* Channel 40 */ |
@@ -134,6 +141,21 @@ static struct ieee80211_rate ath9k_legacy_rates[] = { | |||
134 | RATE(540, 0x0c, 0), | 141 | RATE(540, 0x0c, 0), |
135 | }; | 142 | }; |
136 | 143 | ||
144 | #ifdef CONFIG_MAC80211_LEDS | ||
145 | static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = { | ||
146 | { .throughput = 0 * 1024, .blink_time = 334 }, | ||
147 | { .throughput = 1 * 1024, .blink_time = 260 }, | ||
148 | { .throughput = 5 * 1024, .blink_time = 220 }, | ||
149 | { .throughput = 10 * 1024, .blink_time = 190 }, | ||
150 | { .throughput = 20 * 1024, .blink_time = 170 }, | ||
151 | { .throughput = 50 * 1024, .blink_time = 150 }, | ||
152 | { .throughput = 70 * 1024, .blink_time = 130 }, | ||
153 | { .throughput = 100 * 1024, .blink_time = 110 }, | ||
154 | { .throughput = 200 * 1024, .blink_time = 80 }, | ||
155 | { .throughput = 300 * 1024, .blink_time = 50 }, | ||
156 | }; | ||
157 | #endif | ||
158 | |||
137 | static void ath9k_deinit_softc(struct ath_softc *sc); | 159 | static void ath9k_deinit_softc(struct ath_softc *sc); |
138 | 160 | ||
139 | /* | 161 | /* |
@@ -174,10 +196,27 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset) | |||
174 | return val; | 196 | return val; |
175 | } | 197 | } |
176 | 198 | ||
177 | static const struct ath_ops ath9k_common_ops = { | 199 | static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 clr) |
178 | .read = ath9k_ioread32, | 200 | { |
179 | .write = ath9k_iowrite32, | 201 | struct ath_hw *ah = (struct ath_hw *) hw_priv; |
180 | }; | 202 | struct ath_common *common = ath9k_hw_common(ah); |
203 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
204 | unsigned long uninitialized_var(flags); | ||
205 | u32 val; | ||
206 | |||
207 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) | ||
208 | spin_lock_irqsave(&sc->sc_serial_rw, flags); | ||
209 | |||
210 | val = ioread32(sc->mem + reg_offset); | ||
211 | val &= ~clr; | ||
212 | val |= set; | ||
213 | iowrite32(val, sc->mem + reg_offset); | ||
214 | |||
215 | if (ah->config.serialize_regmode == SER_REG_MODE_ON) | ||
216 | spin_unlock_irqrestore(&sc->sc_serial_rw, flags); | ||
217 | |||
218 | return val; | ||
219 | } | ||
181 | 220 | ||
182 | /**************************/ | 221 | /**************************/ |
183 | /* Initialization */ | 222 | /* Initialization */ |
@@ -206,12 +245,14 @@ static void setup_ht_cap(struct ath_softc *sc, | |||
206 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; | 245 | ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; |
207 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; | 246 | ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; |
208 | 247 | ||
209 | if (AR_SREV_9300_20_OR_LATER(ah)) | 248 | if (AR_SREV_9485(ah)) |
249 | max_streams = 1; | ||
250 | else if (AR_SREV_9300_20_OR_LATER(ah)) | ||
210 | max_streams = 3; | 251 | max_streams = 3; |
211 | else | 252 | else |
212 | max_streams = 2; | 253 | max_streams = 2; |
213 | 254 | ||
214 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 255 | if (AR_SREV_9280_20_OR_LATER(ah)) { |
215 | if (max_streams >= 2) | 256 | if (max_streams >= 2) |
216 | ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; | 257 | ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; |
217 | ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); | 258 | ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); |
@@ -222,9 +263,9 @@ static void setup_ht_cap(struct ath_softc *sc, | |||
222 | tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams); | 263 | tx_streams = ath9k_cmn_count_streams(common->tx_chainmask, max_streams); |
223 | rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams); | 264 | rx_streams = ath9k_cmn_count_streams(common->rx_chainmask, max_streams); |
224 | 265 | ||
225 | ath_print(common, ATH_DBG_CONFIG, | 266 | ath_dbg(common, ATH_DBG_CONFIG, |
226 | "TX streams %d, RX streams: %d\n", | 267 | "TX streams %d, RX streams: %d\n", |
227 | tx_streams, rx_streams); | 268 | tx_streams, rx_streams); |
228 | 269 | ||
229 | if (tx_streams != rx_streams) { | 270 | if (tx_streams != rx_streams) { |
230 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; | 271 | ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; |
@@ -242,8 +283,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, | |||
242 | struct regulatory_request *request) | 283 | struct regulatory_request *request) |
243 | { | 284 | { |
244 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 285 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
245 | struct ath_wiphy *aphy = hw->priv; | 286 | struct ath_softc *sc = hw->priv; |
246 | struct ath_softc *sc = aphy->sc; | ||
247 | struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); | 287 | struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah); |
248 | 288 | ||
249 | return ath_reg_notifier_apply(wiphy, request, reg); | 289 | return ath_reg_notifier_apply(wiphy, request, reg); |
@@ -267,8 +307,8 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
267 | struct ath_buf *bf; | 307 | struct ath_buf *bf; |
268 | int i, bsize, error, desc_len; | 308 | int i, bsize, error, desc_len; |
269 | 309 | ||
270 | ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", | 310 | ath_dbg(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", |
271 | name, nbuf, ndesc); | 311 | name, nbuf, ndesc); |
272 | 312 | ||
273 | INIT_LIST_HEAD(head); | 313 | INIT_LIST_HEAD(head); |
274 | 314 | ||
@@ -279,8 +319,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
279 | 319 | ||
280 | /* ath_desc must be a multiple of DWORDs */ | 320 | /* ath_desc must be a multiple of DWORDs */ |
281 | if ((desc_len % 4) != 0) { | 321 | if ((desc_len % 4) != 0) { |
282 | ath_print(common, ATH_DBG_FATAL, | 322 | ath_err(common, "ath_desc not DWORD aligned\n"); |
283 | "ath_desc not DWORD aligned\n"); | ||
284 | BUG_ON((desc_len % 4) != 0); | 323 | BUG_ON((desc_len % 4) != 0); |
285 | error = -ENOMEM; | 324 | error = -ENOMEM; |
286 | goto fail; | 325 | goto fail; |
@@ -314,9 +353,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
314 | goto fail; | 353 | goto fail; |
315 | } | 354 | } |
316 | ds = (u8 *) dd->dd_desc; | 355 | ds = (u8 *) dd->dd_desc; |
317 | ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", | 356 | ath_dbg(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", |
318 | name, ds, (u32) dd->dd_desc_len, | 357 | name, ds, (u32) dd->dd_desc_len, |
319 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); | 358 | ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); |
320 | 359 | ||
321 | /* allocate buffers */ | 360 | /* allocate buffers */ |
322 | bsize = sizeof(struct ath_buf) * nbuf; | 361 | bsize = sizeof(struct ath_buf) * nbuf; |
@@ -362,26 +401,20 @@ fail: | |||
362 | #undef DS2PHYS | 401 | #undef DS2PHYS |
363 | } | 402 | } |
364 | 403 | ||
365 | static void ath9k_init_crypto(struct ath_softc *sc) | 404 | void ath9k_init_crypto(struct ath_softc *sc) |
366 | { | 405 | { |
367 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 406 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
368 | int i = 0; | 407 | int i = 0; |
369 | 408 | ||
370 | /* Get the hardware key cache size. */ | 409 | /* Get the hardware key cache size. */ |
371 | common->keymax = sc->sc_ah->caps.keycache_size; | 410 | common->keymax = AR_KEYTABLE_SIZE; |
372 | if (common->keymax > ATH_KEYMAX) { | ||
373 | ath_print(common, ATH_DBG_ANY, | ||
374 | "Warning, using only %u entries in %u key cache\n", | ||
375 | ATH_KEYMAX, common->keymax); | ||
376 | common->keymax = ATH_KEYMAX; | ||
377 | } | ||
378 | 411 | ||
379 | /* | 412 | /* |
380 | * Reset the key cache since some parts do not | 413 | * Reset the key cache since some parts do not |
381 | * reset the contents on initial power up. | 414 | * reset the contents on initial power up. |
382 | */ | 415 | */ |
383 | for (i = 0; i < common->keymax; i++) | 416 | for (i = 0; i < common->keymax; i++) |
384 | ath9k_hw_keyreset(sc->sc_ah, (u16) i); | 417 | ath_hw_keyreset(common, (u16) i); |
385 | 418 | ||
386 | /* | 419 | /* |
387 | * Check whether the separate key cache entries | 420 | * Check whether the separate key cache entries |
@@ -389,13 +422,14 @@ static void ath9k_init_crypto(struct ath_softc *sc) | |||
389 | * With split mic keys the number of stations is limited | 422 | * With split mic keys the number of stations is limited |
390 | * to 27 otherwise 59. | 423 | * to 27 otherwise 59. |
391 | */ | 424 | */ |
392 | if (!(sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)) | 425 | if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) |
393 | common->splitmic = 1; | 426 | common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; |
394 | } | 427 | } |
395 | 428 | ||
396 | static int ath9k_init_btcoex(struct ath_softc *sc) | 429 | static int ath9k_init_btcoex(struct ath_softc *sc) |
397 | { | 430 | { |
398 | int r, qnum; | 431 | struct ath_txq *txq; |
432 | int r; | ||
399 | 433 | ||
400 | switch (sc->sc_ah->btcoex_hw.scheme) { | 434 | switch (sc->sc_ah->btcoex_hw.scheme) { |
401 | case ATH_BTCOEX_CFG_NONE: | 435 | case ATH_BTCOEX_CFG_NONE: |
@@ -408,8 +442,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc) | |||
408 | r = ath_init_btcoex_timer(sc); | 442 | r = ath_init_btcoex_timer(sc); |
409 | if (r) | 443 | if (r) |
410 | return -1; | 444 | return -1; |
411 | qnum = sc->tx.hwq_map[WME_AC_BE]; | 445 | txq = sc->tx.txq_map[WME_AC_BE]; |
412 | ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum); | 446 | ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); |
413 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | 447 | sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; |
414 | break; | 448 | break; |
415 | default: | 449 | default: |
@@ -422,65 +456,36 @@ static int ath9k_init_btcoex(struct ath_softc *sc) | |||
422 | 456 | ||
423 | static int ath9k_init_queues(struct ath_softc *sc) | 457 | static int ath9k_init_queues(struct ath_softc *sc) |
424 | { | 458 | { |
425 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
426 | int i = 0; | 459 | int i = 0; |
427 | 460 | ||
428 | for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) | ||
429 | sc->tx.hwq_map[i] = -1; | ||
430 | |||
431 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); | 461 | sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah); |
432 | if (sc->beacon.beaconq == -1) { | ||
433 | ath_print(common, ATH_DBG_FATAL, | ||
434 | "Unable to setup a beacon xmit queue\n"); | ||
435 | goto err; | ||
436 | } | ||
437 | |||
438 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); | 462 | sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); |
439 | if (sc->beacon.cabq == NULL) { | ||
440 | ath_print(common, ATH_DBG_FATAL, | ||
441 | "Unable to setup CAB xmit queue\n"); | ||
442 | goto err; | ||
443 | } | ||
444 | 463 | ||
445 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; | 464 | sc->config.cabqReadytime = ATH_CABQ_READY_TIME; |
446 | ath_cabq_update(sc); | 465 | ath_cabq_update(sc); |
447 | 466 | ||
448 | if (!ath_tx_setup(sc, WME_AC_BK)) { | 467 | for (i = 0; i < WME_NUM_AC; i++) { |
449 | ath_print(common, ATH_DBG_FATAL, | 468 | sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i); |
450 | "Unable to setup xmit queue for BK traffic\n"); | 469 | sc->tx.txq_map[i]->mac80211_qnum = i; |
451 | goto err; | ||
452 | } | ||
453 | |||
454 | if (!ath_tx_setup(sc, WME_AC_BE)) { | ||
455 | ath_print(common, ATH_DBG_FATAL, | ||
456 | "Unable to setup xmit queue for BE traffic\n"); | ||
457 | goto err; | ||
458 | } | ||
459 | if (!ath_tx_setup(sc, WME_AC_VI)) { | ||
460 | ath_print(common, ATH_DBG_FATAL, | ||
461 | "Unable to setup xmit queue for VI traffic\n"); | ||
462 | goto err; | ||
463 | } | ||
464 | if (!ath_tx_setup(sc, WME_AC_VO)) { | ||
465 | ath_print(common, ATH_DBG_FATAL, | ||
466 | "Unable to setup xmit queue for VO traffic\n"); | ||
467 | goto err; | ||
468 | } | 470 | } |
469 | |||
470 | return 0; | 471 | return 0; |
471 | |||
472 | err: | ||
473 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||
474 | if (ATH_TXQ_SETUP(sc, i)) | ||
475 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | ||
476 | |||
477 | return -EIO; | ||
478 | } | 472 | } |
479 | 473 | ||
480 | static void ath9k_init_channels_rates(struct ath_softc *sc) | 474 | static int ath9k_init_channels_rates(struct ath_softc *sc) |
481 | { | 475 | { |
482 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { | 476 | void *channels; |
483 | sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; | 477 | |
478 | BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) + | ||
479 | ARRAY_SIZE(ath9k_5ghz_chantable) != | ||
480 | ATH9K_NUM_CHANNELS); | ||
481 | |||
482 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { | ||
483 | channels = kmemdup(ath9k_2ghz_chantable, | ||
484 | sizeof(ath9k_2ghz_chantable), GFP_KERNEL); | ||
485 | if (!channels) | ||
486 | return -ENOMEM; | ||
487 | |||
488 | sc->sbands[IEEE80211_BAND_2GHZ].channels = channels; | ||
484 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; | 489 | sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; |
485 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = | 490 | sc->sbands[IEEE80211_BAND_2GHZ].n_channels = |
486 | ARRAY_SIZE(ath9k_2ghz_chantable); | 491 | ARRAY_SIZE(ath9k_2ghz_chantable); |
@@ -489,8 +494,16 @@ static void ath9k_init_channels_rates(struct ath_softc *sc) | |||
489 | ARRAY_SIZE(ath9k_legacy_rates); | 494 | ARRAY_SIZE(ath9k_legacy_rates); |
490 | } | 495 | } |
491 | 496 | ||
492 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { | 497 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { |
493 | sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; | 498 | channels = kmemdup(ath9k_5ghz_chantable, |
499 | sizeof(ath9k_5ghz_chantable), GFP_KERNEL); | ||
500 | if (!channels) { | ||
501 | if (sc->sbands[IEEE80211_BAND_2GHZ].channels) | ||
502 | kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); | ||
503 | return -ENOMEM; | ||
504 | } | ||
505 | |||
506 | sc->sbands[IEEE80211_BAND_5GHZ].channels = channels; | ||
494 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; | 507 | sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; |
495 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = | 508 | sc->sbands[IEEE80211_BAND_5GHZ].n_channels = |
496 | ARRAY_SIZE(ath9k_5ghz_chantable); | 509 | ARRAY_SIZE(ath9k_5ghz_chantable); |
@@ -499,6 +512,7 @@ static void ath9k_init_channels_rates(struct ath_softc *sc) | |||
499 | sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = | 512 | sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates = |
500 | ARRAY_SIZE(ath9k_legacy_rates) - 4; | 513 | ARRAY_SIZE(ath9k_legacy_rates) - 4; |
501 | } | 514 | } |
515 | return 0; | ||
502 | } | 516 | } |
503 | 517 | ||
504 | static void ath9k_init_misc(struct ath_softc *sc) | 518 | static void ath9k_init_misc(struct ath_softc *sc) |
@@ -506,7 +520,6 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
506 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 520 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
507 | int i = 0; | 521 | int i = 0; |
508 | 522 | ||
509 | common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; | ||
510 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); | 523 | setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); |
511 | 524 | ||
512 | sc->config.txpowlimit = ATH_TXPOWER_MAX; | 525 | sc->config.txpowlimit = ATH_TXPOWER_MAX; |
@@ -522,20 +535,21 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
522 | ath9k_hw_set_diversity(sc->sc_ah, true); | 535 | ath9k_hw_set_diversity(sc->sc_ah, true); |
523 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); | 536 | sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah); |
524 | 537 | ||
525 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 538 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); |
526 | memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); | ||
527 | 539 | ||
528 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; | 540 | sc->beacon.slottime = ATH9K_SLOT_TIME_9; |
529 | 541 | ||
530 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | 542 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) |
531 | sc->beacon.bslot[i] = NULL; | 543 | sc->beacon.bslot[i] = NULL; |
532 | sc->beacon.bslot_aphy[i] = NULL; | 544 | |
533 | } | 545 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) |
546 | sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; | ||
534 | } | 547 | } |
535 | 548 | ||
536 | static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | 549 | static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, |
537 | const struct ath_bus_ops *bus_ops) | 550 | const struct ath_bus_ops *bus_ops) |
538 | { | 551 | { |
552 | struct ath9k_platform_data *pdata = sc->dev->platform_data; | ||
539 | struct ath_hw *ah = NULL; | 553 | struct ath_hw *ah = NULL; |
540 | struct ath_common *common; | 554 | struct ath_common *common; |
541 | int ret = 0, i; | 555 | int ret = 0, i; |
@@ -545,23 +559,41 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
545 | if (!ah) | 559 | if (!ah) |
546 | return -ENOMEM; | 560 | return -ENOMEM; |
547 | 561 | ||
562 | ah->hw = sc->hw; | ||
548 | ah->hw_version.devid = devid; | 563 | ah->hw_version.devid = devid; |
549 | ah->hw_version.subsysid = subsysid; | 564 | ah->hw_version.subsysid = subsysid; |
565 | ah->reg_ops.read = ath9k_ioread32; | ||
566 | ah->reg_ops.write = ath9k_iowrite32; | ||
567 | ah->reg_ops.rmw = ath9k_reg_rmw; | ||
550 | sc->sc_ah = ah; | 568 | sc->sc_ah = ah; |
551 | 569 | ||
570 | if (!pdata) { | ||
571 | ah->ah_flags |= AH_USE_EEPROM; | ||
572 | sc->sc_ah->led_pin = -1; | ||
573 | } else { | ||
574 | sc->sc_ah->gpio_mask = pdata->gpio_mask; | ||
575 | sc->sc_ah->gpio_val = pdata->gpio_val; | ||
576 | sc->sc_ah->led_pin = pdata->led_pin; | ||
577 | ah->is_clk_25mhz = pdata->is_clk_25mhz; | ||
578 | } | ||
579 | |||
552 | common = ath9k_hw_common(ah); | 580 | common = ath9k_hw_common(ah); |
553 | common->ops = &ath9k_common_ops; | 581 | common->ops = &ah->reg_ops; |
554 | common->bus_ops = bus_ops; | 582 | common->bus_ops = bus_ops; |
555 | common->ah = ah; | 583 | common->ah = ah; |
556 | common->hw = sc->hw; | 584 | common->hw = sc->hw; |
557 | common->priv = sc; | 585 | common->priv = sc; |
558 | common->debug_mask = ath9k_debug; | 586 | common->debug_mask = ath9k_debug; |
587 | common->btcoex_enabled = ath9k_btcoex_enable == 1; | ||
588 | spin_lock_init(&common->cc_lock); | ||
559 | 589 | ||
560 | spin_lock_init(&sc->wiphy_lock); | ||
561 | spin_lock_init(&sc->sc_resetlock); | ||
562 | spin_lock_init(&sc->sc_serial_rw); | 590 | spin_lock_init(&sc->sc_serial_rw); |
563 | spin_lock_init(&sc->sc_pm_lock); | 591 | spin_lock_init(&sc->sc_pm_lock); |
564 | mutex_init(&sc->mutex); | 592 | mutex_init(&sc->mutex); |
593 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
594 | spin_lock_init(&sc->nodes_lock); | ||
595 | INIT_LIST_HEAD(&sc->nodes); | ||
596 | #endif | ||
565 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | 597 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); |
566 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, | 598 | tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, |
567 | (unsigned long)sc); | 599 | (unsigned long)sc); |
@@ -578,12 +610,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
578 | if (ret) | 610 | if (ret) |
579 | goto err_hw; | 611 | goto err_hw; |
580 | 612 | ||
581 | ret = ath9k_init_debug(ah); | 613 | if (pdata && pdata->macaddr) |
582 | if (ret) { | 614 | memcpy(common->macaddr, pdata->macaddr, ETH_ALEN); |
583 | ath_print(common, ATH_DBG_FATAL, | ||
584 | "Unable to create debugfs files\n"); | ||
585 | goto err_debug; | ||
586 | } | ||
587 | 615 | ||
588 | ret = ath9k_init_queues(sc); | 616 | ret = ath9k_init_queues(sc); |
589 | if (ret) | 617 | if (ret) |
@@ -593,8 +621,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
593 | if (ret) | 621 | if (ret) |
594 | goto err_btcoex; | 622 | goto err_btcoex; |
595 | 623 | ||
624 | ret = ath9k_init_channels_rates(sc); | ||
625 | if (ret) | ||
626 | goto err_btcoex; | ||
627 | |||
596 | ath9k_init_crypto(sc); | 628 | ath9k_init_crypto(sc); |
597 | ath9k_init_channels_rates(sc); | ||
598 | ath9k_init_misc(sc); | 629 | ath9k_init_misc(sc); |
599 | 630 | ||
600 | return 0; | 631 | return 0; |
@@ -604,12 +635,8 @@ err_btcoex: | |||
604 | if (ATH_TXQ_SETUP(sc, i)) | 635 | if (ATH_TXQ_SETUP(sc, i)) |
605 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 636 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
606 | err_queues: | 637 | err_queues: |
607 | ath9k_exit_debug(ah); | ||
608 | err_debug: | ||
609 | ath9k_hw_deinit(ah); | 638 | ath9k_hw_deinit(ah); |
610 | err_hw: | 639 | err_hw: |
611 | tasklet_kill(&sc->intr_tq); | ||
612 | tasklet_kill(&sc->bcon_tasklet); | ||
613 | 640 | ||
614 | kfree(ah); | 641 | kfree(ah); |
615 | sc->sc_ah = NULL; | 642 | sc->sc_ah = NULL; |
@@ -617,6 +644,37 @@ err_hw: | |||
617 | return ret; | 644 | return ret; |
618 | } | 645 | } |
619 | 646 | ||
647 | static void ath9k_init_band_txpower(struct ath_softc *sc, int band) | ||
648 | { | ||
649 | struct ieee80211_supported_band *sband; | ||
650 | struct ieee80211_channel *chan; | ||
651 | struct ath_hw *ah = sc->sc_ah; | ||
652 | struct ath_regulatory *reg = ath9k_hw_regulatory(ah); | ||
653 | int i; | ||
654 | |||
655 | sband = &sc->sbands[band]; | ||
656 | for (i = 0; i < sband->n_channels; i++) { | ||
657 | chan = &sband->channels[i]; | ||
658 | ah->curchan = &ah->channels[chan->hw_value]; | ||
659 | ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20); | ||
660 | ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); | ||
661 | chan->max_power = reg->max_power_level / 2; | ||
662 | } | ||
663 | } | ||
664 | |||
665 | static void ath9k_init_txpower_limits(struct ath_softc *sc) | ||
666 | { | ||
667 | struct ath_hw *ah = sc->sc_ah; | ||
668 | struct ath9k_channel *curchan = ah->curchan; | ||
669 | |||
670 | if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) | ||
671 | ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ); | ||
672 | if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) | ||
673 | ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ); | ||
674 | |||
675 | ah->curchan = curchan; | ||
676 | } | ||
677 | |||
620 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | 678 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
621 | { | 679 | { |
622 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 680 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -632,16 +690,22 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
632 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 690 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
633 | hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; | 691 | hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; |
634 | 692 | ||
635 | if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) | 693 | if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt) |
636 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; | 694 | hw->flags |= IEEE80211_HW_MFP_CAPABLE; |
637 | 695 | ||
638 | hw->wiphy->interface_modes = | 696 | hw->wiphy->interface_modes = |
697 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
698 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
639 | BIT(NL80211_IFTYPE_AP) | | 699 | BIT(NL80211_IFTYPE_AP) | |
700 | BIT(NL80211_IFTYPE_WDS) | | ||
640 | BIT(NL80211_IFTYPE_STATION) | | 701 | BIT(NL80211_IFTYPE_STATION) | |
641 | BIT(NL80211_IFTYPE_ADHOC) | | 702 | BIT(NL80211_IFTYPE_ADHOC) | |
642 | BIT(NL80211_IFTYPE_MESH_POINT); | 703 | BIT(NL80211_IFTYPE_MESH_POINT); |
643 | 704 | ||
644 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 705 | if (AR_SREV_5416(sc->sc_ah)) |
706 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
707 | |||
708 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | ||
645 | 709 | ||
646 | hw->queues = 4; | 710 | hw->queues = 4; |
647 | hw->max_rates = 4; | 711 | hw->max_rates = 4; |
@@ -651,19 +715,21 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
651 | hw->sta_data_size = sizeof(struct ath_node); | 715 | hw->sta_data_size = sizeof(struct ath_node); |
652 | hw->vif_data_size = sizeof(struct ath_vif); | 716 | hw->vif_data_size = sizeof(struct ath_vif); |
653 | 717 | ||
718 | #ifdef CONFIG_ATH9K_RATE_CONTROL | ||
654 | hw->rate_control_algorithm = "ath9k_rate_control"; | 719 | hw->rate_control_algorithm = "ath9k_rate_control"; |
720 | #endif | ||
655 | 721 | ||
656 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) | 722 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) |
657 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = | 723 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = |
658 | &sc->sbands[IEEE80211_BAND_2GHZ]; | 724 | &sc->sbands[IEEE80211_BAND_2GHZ]; |
659 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) | 725 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) |
660 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 726 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
661 | &sc->sbands[IEEE80211_BAND_5GHZ]; | 727 | &sc->sbands[IEEE80211_BAND_5GHZ]; |
662 | 728 | ||
663 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | 729 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { |
664 | if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) | 730 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) |
665 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | 731 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); |
666 | if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) | 732 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) |
667 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); | 733 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); |
668 | } | 734 | } |
669 | 735 | ||
@@ -706,11 +772,26 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
706 | if (error != 0) | 772 | if (error != 0) |
707 | goto error_rx; | 773 | goto error_rx; |
708 | 774 | ||
775 | ath9k_init_txpower_limits(sc); | ||
776 | |||
777 | #ifdef CONFIG_MAC80211_LEDS | ||
778 | /* must be initialized before ieee80211_register_hw */ | ||
779 | sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, | ||
780 | IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, | ||
781 | ARRAY_SIZE(ath9k_tpt_blink)); | ||
782 | #endif | ||
783 | |||
709 | /* Register with mac80211 */ | 784 | /* Register with mac80211 */ |
710 | error = ieee80211_register_hw(hw); | 785 | error = ieee80211_register_hw(hw); |
711 | if (error) | 786 | if (error) |
712 | goto error_register; | 787 | goto error_register; |
713 | 788 | ||
789 | error = ath9k_init_debug(ah); | ||
790 | if (error) { | ||
791 | ath_err(common, "Unable to create debugfs files\n"); | ||
792 | goto error_world; | ||
793 | } | ||
794 | |||
714 | /* Handle world regulatory */ | 795 | /* Handle world regulatory */ |
715 | if (!ath_is_world_regd(reg)) { | 796 | if (!ath_is_world_regd(reg)) { |
716 | error = regulatory_hint(hw->wiphy, reg->alpha2); | 797 | error = regulatory_hint(hw->wiphy, reg->alpha2); |
@@ -720,9 +801,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
720 | 801 | ||
721 | INIT_WORK(&sc->hw_check_work, ath_hw_check); | 802 | INIT_WORK(&sc->hw_check_work, ath_hw_check); |
722 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); | 803 | INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); |
723 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | 804 | INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); |
724 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | 805 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; |
725 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | ||
726 | 806 | ||
727 | ath_init_leds(sc); | 807 | ath_init_leds(sc); |
728 | ath_start_rfkill_poll(sc); | 808 | ath_start_rfkill_poll(sc); |
@@ -751,6 +831,12 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
751 | { | 831 | { |
752 | int i = 0; | 832 | int i = 0; |
753 | 833 | ||
834 | if (sc->sbands[IEEE80211_BAND_2GHZ].channels) | ||
835 | kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels); | ||
836 | |||
837 | if (sc->sbands[IEEE80211_BAND_5GHZ].channels) | ||
838 | kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels); | ||
839 | |||
754 | if ((sc->btcoex.no_stomp_timer) && | 840 | if ((sc->btcoex.no_stomp_timer) && |
755 | sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 841 | sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
756 | ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); | 842 | ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); |
@@ -759,12 +845,8 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
759 | if (ATH_TXQ_SETUP(sc, i)) | 845 | if (ATH_TXQ_SETUP(sc, i)) |
760 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 846 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
761 | 847 | ||
762 | ath9k_exit_debug(sc->sc_ah); | ||
763 | ath9k_hw_deinit(sc->sc_ah); | 848 | ath9k_hw_deinit(sc->sc_ah); |
764 | 849 | ||
765 | tasklet_kill(&sc->intr_tq); | ||
766 | tasklet_kill(&sc->bcon_tasklet); | ||
767 | |||
768 | kfree(sc->sc_ah); | 850 | kfree(sc->sc_ah); |
769 | sc->sc_ah = NULL; | 851 | sc->sc_ah = NULL; |
770 | } | 852 | } |
@@ -772,27 +854,18 @@ static void ath9k_deinit_softc(struct ath_softc *sc) | |||
772 | void ath9k_deinit_device(struct ath_softc *sc) | 854 | void ath9k_deinit_device(struct ath_softc *sc) |
773 | { | 855 | { |
774 | struct ieee80211_hw *hw = sc->hw; | 856 | struct ieee80211_hw *hw = sc->hw; |
775 | int i = 0; | ||
776 | 857 | ||
777 | ath9k_ps_wakeup(sc); | 858 | ath9k_ps_wakeup(sc); |
778 | 859 | ||
779 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | 860 | wiphy_rfkill_stop_polling(sc->hw->wiphy); |
780 | ath_deinit_leds(sc); | 861 | ath_deinit_leds(sc); |
781 | 862 | ||
782 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 863 | ath9k_ps_restore(sc); |
783 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
784 | if (aphy == NULL) | ||
785 | continue; | ||
786 | sc->sec_wiphy[i] = NULL; | ||
787 | ieee80211_unregister_hw(aphy->hw); | ||
788 | ieee80211_free_hw(aphy->hw); | ||
789 | } | ||
790 | 864 | ||
791 | ieee80211_unregister_hw(hw); | 865 | ieee80211_unregister_hw(hw); |
792 | ath_rx_cleanup(sc); | 866 | ath_rx_cleanup(sc); |
793 | ath_tx_cleanup(sc); | 867 | ath_tx_cleanup(sc); |
794 | ath9k_deinit_softc(sc); | 868 | ath9k_deinit_softc(sc); |
795 | kfree(sc->sec_wiphy); | ||
796 | } | 869 | } |
797 | 870 | ||
798 | void ath_descdma_cleanup(struct ath_softc *sc, | 871 | void ath_descdma_cleanup(struct ath_softc *sc, |
@@ -825,20 +898,12 @@ static int __init ath9k_init(void) | |||
825 | goto err_out; | 898 | goto err_out; |
826 | } | 899 | } |
827 | 900 | ||
828 | error = ath9k_debug_create_root(); | ||
829 | if (error) { | ||
830 | printk(KERN_ERR | ||
831 | "ath9k: Unable to create debugfs root: %d\n", | ||
832 | error); | ||
833 | goto err_rate_unregister; | ||
834 | } | ||
835 | |||
836 | error = ath_pci_init(); | 901 | error = ath_pci_init(); |
837 | if (error < 0) { | 902 | if (error < 0) { |
838 | printk(KERN_ERR | 903 | printk(KERN_ERR |
839 | "ath9k: No PCI devices found, driver not installed.\n"); | 904 | "ath9k: No PCI devices found, driver not installed.\n"); |
840 | error = -ENODEV; | 905 | error = -ENODEV; |
841 | goto err_remove_root; | 906 | goto err_rate_unregister; |
842 | } | 907 | } |
843 | 908 | ||
844 | error = ath_ahb_init(); | 909 | error = ath_ahb_init(); |
@@ -852,8 +917,6 @@ static int __init ath9k_init(void) | |||
852 | err_pci_exit: | 917 | err_pci_exit: |
853 | ath_pci_exit(); | 918 | ath_pci_exit(); |
854 | 919 | ||
855 | err_remove_root: | ||
856 | ath9k_debug_remove_root(); | ||
857 | err_rate_unregister: | 920 | err_rate_unregister: |
858 | ath_rate_control_unregister(); | 921 | ath_rate_control_unregister(); |
859 | err_out: | 922 | err_out: |
@@ -863,9 +926,9 @@ module_init(ath9k_init); | |||
863 | 926 | ||
864 | static void __exit ath9k_exit(void) | 927 | static void __exit ath9k_exit(void) |
865 | { | 928 | { |
929 | is_ath9k_unloaded = true; | ||
866 | ath_ahb_exit(); | 930 | ath_ahb_exit(); |
867 | ath_pci_exit(); | 931 | ath_pci_exit(); |
868 | ath9k_debug_remove_root(); | ||
869 | ath_rate_control_unregister(); | 932 | ath_rate_control_unregister(); |
870 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); | 933 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); |
871 | } | 934 | } |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index e955bb9d98cb..c2091f1f4096 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -20,11 +20,11 @@ | |||
20 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | 20 | static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, |
21 | struct ath9k_tx_queue_info *qi) | 21 | struct ath9k_tx_queue_info *qi) |
22 | { | 22 | { |
23 | ath_print(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, | 23 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_INTERRUPT, |
24 | "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", | 24 | "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", |
25 | ah->txok_interrupt_mask, ah->txerr_interrupt_mask, | 25 | ah->txok_interrupt_mask, ah->txerr_interrupt_mask, |
26 | ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, | 26 | ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, |
27 | ah->txurn_interrupt_mask); | 27 | ah->txurn_interrupt_mask); |
28 | 28 | ||
29 | ENABLE_REGWRITE_BUFFER(ah); | 29 | ENABLE_REGWRITE_BUFFER(ah); |
30 | 30 | ||
@@ -40,7 +40,6 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, | |||
40 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); | 40 | REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg); |
41 | 41 | ||
42 | REGWRITE_BUFFER_FLUSH(ah); | 42 | REGWRITE_BUFFER_FLUSH(ah); |
43 | DISABLE_REGWRITE_BUFFER(ah); | ||
44 | } | 43 | } |
45 | 44 | ||
46 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) | 45 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) |
@@ -57,8 +56,8 @@ EXPORT_SYMBOL(ath9k_hw_puttxbuf); | |||
57 | 56 | ||
58 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q) | 57 | void ath9k_hw_txstart(struct ath_hw *ah, u32 q) |
59 | { | 58 | { |
60 | ath_print(ath9k_hw_common(ah), ATH_DBG_QUEUE, | 59 | ath_dbg(ath9k_hw_common(ah), ATH_DBG_QUEUE, |
61 | "Enable TXE on queue: %u\n", q); | 60 | "Enable TXE on queue: %u\n", q); |
62 | REG_WRITE(ah, AR_Q_TXE, 1 << q); | 61 | REG_WRITE(ah, AR_Q_TXE, 1 << q); |
63 | } | 62 | } |
64 | EXPORT_SYMBOL(ath9k_hw_txstart); | 63 | EXPORT_SYMBOL(ath9k_hw_txstart); |
@@ -118,12 +117,11 @@ EXPORT_SYMBOL(ath9k_hw_numtxpending); | |||
118 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | 117 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) |
119 | { | 118 | { |
120 | u32 txcfg, curLevel, newLevel; | 119 | u32 txcfg, curLevel, newLevel; |
121 | enum ath9k_int omask; | ||
122 | 120 | ||
123 | if (ah->tx_trig_level >= ah->config.max_txtrig_level) | 121 | if (ah->tx_trig_level >= ah->config.max_txtrig_level) |
124 | return false; | 122 | return false; |
125 | 123 | ||
126 | omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL); | 124 | ath9k_hw_disable_interrupts(ah); |
127 | 125 | ||
128 | txcfg = REG_READ(ah, AR_TXCFG); | 126 | txcfg = REG_READ(ah, AR_TXCFG); |
129 | curLevel = MS(txcfg, AR_FTRIG); | 127 | curLevel = MS(txcfg, AR_FTRIG); |
@@ -137,7 +135,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | |||
137 | REG_WRITE(ah, AR_TXCFG, | 135 | REG_WRITE(ah, AR_TXCFG, |
138 | (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); | 136 | (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); |
139 | 137 | ||
140 | ath9k_hw_set_interrupts(ah, omask); | 138 | ath9k_hw_enable_interrupts(ah); |
141 | 139 | ||
142 | ah->tx_trig_level = newLevel; | 140 | ah->tx_trig_level = newLevel; |
143 | 141 | ||
@@ -145,85 +143,59 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | |||
145 | } | 143 | } |
146 | EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel); | 144 | EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel); |
147 | 145 | ||
148 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) | 146 | void ath9k_hw_abort_tx_dma(struct ath_hw *ah) |
149 | { | 147 | { |
150 | #define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ | 148 | int i, q; |
151 | #define ATH9K_TIME_QUANTUM 100 /* usec */ | ||
152 | struct ath_common *common = ath9k_hw_common(ah); | ||
153 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
154 | struct ath9k_tx_queue_info *qi; | ||
155 | u32 tsfLow, j, wait; | ||
156 | u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; | ||
157 | 149 | ||
158 | if (q >= pCap->total_queues) { | 150 | REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M); |
159 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " | ||
160 | "invalid queue: %u\n", q); | ||
161 | return false; | ||
162 | } | ||
163 | 151 | ||
164 | qi = &ah->txq[q]; | 152 | REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); |
165 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 153 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); |
166 | ath_print(common, ATH_DBG_QUEUE, "Stopping TX DMA, " | 154 | REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); |
167 | "inactive queue: %u\n", q); | ||
168 | return false; | ||
169 | } | ||
170 | 155 | ||
171 | REG_WRITE(ah, AR_Q_TXD, 1 << q); | 156 | for (q = 0; q < AR_NUM_QCU; q++) { |
157 | for (i = 0; i < 1000; i++) { | ||
158 | if (i) | ||
159 | udelay(5); | ||
172 | 160 | ||
173 | for (wait = wait_time; wait != 0; wait--) { | 161 | if (!ath9k_hw_numtxpending(ah, q)) |
174 | if (ath9k_hw_numtxpending(ah, q) == 0) | 162 | break; |
175 | break; | 163 | } |
176 | udelay(ATH9K_TIME_QUANTUM); | ||
177 | } | 164 | } |
178 | 165 | ||
179 | if (ath9k_hw_numtxpending(ah, q)) { | 166 | REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); |
180 | ath_print(common, ATH_DBG_QUEUE, | 167 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); |
181 | "%s: Num of pending TX Frames %d on Q %d\n", | 168 | REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); |
182 | __func__, ath9k_hw_numtxpending(ah, q), q); | ||
183 | |||
184 | for (j = 0; j < 2; j++) { | ||
185 | tsfLow = REG_READ(ah, AR_TSF_L32); | ||
186 | REG_WRITE(ah, AR_QUIET2, | ||
187 | SM(10, AR_QUIET2_QUIET_DUR)); | ||
188 | REG_WRITE(ah, AR_QUIET_PERIOD, 100); | ||
189 | REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); | ||
190 | REG_SET_BIT(ah, AR_TIMER_MODE, | ||
191 | AR_QUIET_TIMER_EN); | ||
192 | |||
193 | if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) | ||
194 | break; | ||
195 | 169 | ||
196 | ath_print(common, ATH_DBG_QUEUE, | 170 | REG_WRITE(ah, AR_Q_TXD, 0); |
197 | "TSF has moved while trying to set " | 171 | } |
198 | "quiet time TSF: 0x%08x\n", tsfLow); | 172 | EXPORT_SYMBOL(ath9k_hw_abort_tx_dma); |
199 | } | ||
200 | 173 | ||
201 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | 174 | bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q) |
175 | { | ||
176 | #define ATH9K_TX_STOP_DMA_TIMEOUT 1000 /* usec */ | ||
177 | #define ATH9K_TIME_QUANTUM 100 /* usec */ | ||
178 | int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; | ||
179 | int wait; | ||
202 | 180 | ||
203 | udelay(200); | 181 | REG_WRITE(ah, AR_Q_TXD, 1 << q); |
204 | REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); | ||
205 | 182 | ||
206 | wait = wait_time; | 183 | for (wait = wait_time; wait != 0; wait--) { |
207 | while (ath9k_hw_numtxpending(ah, q)) { | 184 | if (wait != wait_time) |
208 | if ((--wait) == 0) { | ||
209 | ath_print(common, ATH_DBG_FATAL, | ||
210 | "Failed to stop TX DMA in 100 " | ||
211 | "msec after killing last frame\n"); | ||
212 | break; | ||
213 | } | ||
214 | udelay(ATH9K_TIME_QUANTUM); | 185 | udelay(ATH9K_TIME_QUANTUM); |
215 | } | ||
216 | 186 | ||
217 | REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); | 187 | if (ath9k_hw_numtxpending(ah, q) == 0) |
188 | break; | ||
218 | } | 189 | } |
219 | 190 | ||
220 | REG_WRITE(ah, AR_Q_TXD, 0); | 191 | REG_WRITE(ah, AR_Q_TXD, 0); |
192 | |||
221 | return wait != 0; | 193 | return wait != 0; |
222 | 194 | ||
223 | #undef ATH9K_TX_STOP_DMA_TIMEOUT | 195 | #undef ATH9K_TX_STOP_DMA_TIMEOUT |
224 | #undef ATH9K_TIME_QUANTUM | 196 | #undef ATH9K_TIME_QUANTUM |
225 | } | 197 | } |
226 | EXPORT_SYMBOL(ath9k_hw_stoptxdma); | 198 | EXPORT_SYMBOL(ath9k_hw_stop_dma_queue); |
227 | 199 | ||
228 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) | 200 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) |
229 | { | 201 | { |
@@ -237,23 +209,16 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, | |||
237 | { | 209 | { |
238 | u32 cw; | 210 | u32 cw; |
239 | struct ath_common *common = ath9k_hw_common(ah); | 211 | struct ath_common *common = ath9k_hw_common(ah); |
240 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
241 | struct ath9k_tx_queue_info *qi; | 212 | struct ath9k_tx_queue_info *qi; |
242 | 213 | ||
243 | if (q >= pCap->total_queues) { | ||
244 | ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " | ||
245 | "invalid queue: %u\n", q); | ||
246 | return false; | ||
247 | } | ||
248 | |||
249 | qi = &ah->txq[q]; | 214 | qi = &ah->txq[q]; |
250 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 215 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
251 | ath_print(common, ATH_DBG_QUEUE, "Set TXQ properties, " | 216 | ath_dbg(common, ATH_DBG_QUEUE, |
252 | "inactive queue: %u\n", q); | 217 | "Set TXQ properties, inactive queue: %u\n", q); |
253 | return false; | 218 | return false; |
254 | } | 219 | } |
255 | 220 | ||
256 | ath_print(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); | 221 | ath_dbg(common, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); |
257 | 222 | ||
258 | qi->tqi_ver = qinfo->tqi_ver; | 223 | qi->tqi_ver = qinfo->tqi_ver; |
259 | qi->tqi_subtype = qinfo->tqi_subtype; | 224 | qi->tqi_subtype = qinfo->tqi_subtype; |
@@ -308,19 +273,12 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, | |||
308 | struct ath9k_tx_queue_info *qinfo) | 273 | struct ath9k_tx_queue_info *qinfo) |
309 | { | 274 | { |
310 | struct ath_common *common = ath9k_hw_common(ah); | 275 | struct ath_common *common = ath9k_hw_common(ah); |
311 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
312 | struct ath9k_tx_queue_info *qi; | 276 | struct ath9k_tx_queue_info *qi; |
313 | 277 | ||
314 | if (q >= pCap->total_queues) { | ||
315 | ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " | ||
316 | "invalid queue: %u\n", q); | ||
317 | return false; | ||
318 | } | ||
319 | |||
320 | qi = &ah->txq[q]; | 278 | qi = &ah->txq[q]; |
321 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 279 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
322 | ath_print(common, ATH_DBG_QUEUE, "Get TXQ properties, " | 280 | ath_dbg(common, ATH_DBG_QUEUE, |
323 | "inactive queue: %u\n", q); | 281 | "Get TXQ properties, inactive queue: %u\n", q); |
324 | return false; | 282 | return false; |
325 | } | 283 | } |
326 | 284 | ||
@@ -348,45 +306,41 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, | |||
348 | { | 306 | { |
349 | struct ath_common *common = ath9k_hw_common(ah); | 307 | struct ath_common *common = ath9k_hw_common(ah); |
350 | struct ath9k_tx_queue_info *qi; | 308 | struct ath9k_tx_queue_info *qi; |
351 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
352 | int q; | 309 | int q; |
353 | 310 | ||
354 | switch (type) { | 311 | switch (type) { |
355 | case ATH9K_TX_QUEUE_BEACON: | 312 | case ATH9K_TX_QUEUE_BEACON: |
356 | q = pCap->total_queues - 1; | 313 | q = ATH9K_NUM_TX_QUEUES - 1; |
357 | break; | 314 | break; |
358 | case ATH9K_TX_QUEUE_CAB: | 315 | case ATH9K_TX_QUEUE_CAB: |
359 | q = pCap->total_queues - 2; | 316 | q = ATH9K_NUM_TX_QUEUES - 2; |
360 | break; | 317 | break; |
361 | case ATH9K_TX_QUEUE_PSPOLL: | 318 | case ATH9K_TX_QUEUE_PSPOLL: |
362 | q = 1; | 319 | q = 1; |
363 | break; | 320 | break; |
364 | case ATH9K_TX_QUEUE_UAPSD: | 321 | case ATH9K_TX_QUEUE_UAPSD: |
365 | q = pCap->total_queues - 3; | 322 | q = ATH9K_NUM_TX_QUEUES - 3; |
366 | break; | 323 | break; |
367 | case ATH9K_TX_QUEUE_DATA: | 324 | case ATH9K_TX_QUEUE_DATA: |
368 | for (q = 0; q < pCap->total_queues; q++) | 325 | for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++) |
369 | if (ah->txq[q].tqi_type == | 326 | if (ah->txq[q].tqi_type == |
370 | ATH9K_TX_QUEUE_INACTIVE) | 327 | ATH9K_TX_QUEUE_INACTIVE) |
371 | break; | 328 | break; |
372 | if (q == pCap->total_queues) { | 329 | if (q == ATH9K_NUM_TX_QUEUES) { |
373 | ath_print(common, ATH_DBG_FATAL, | 330 | ath_err(common, "No available TX queue\n"); |
374 | "No available TX queue\n"); | ||
375 | return -1; | 331 | return -1; |
376 | } | 332 | } |
377 | break; | 333 | break; |
378 | default: | 334 | default: |
379 | ath_print(common, ATH_DBG_FATAL, | 335 | ath_err(common, "Invalid TX queue type: %u\n", type); |
380 | "Invalid TX queue type: %u\n", type); | ||
381 | return -1; | 336 | return -1; |
382 | } | 337 | } |
383 | 338 | ||
384 | ath_print(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); | 339 | ath_dbg(common, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); |
385 | 340 | ||
386 | qi = &ah->txq[q]; | 341 | qi = &ah->txq[q]; |
387 | if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { | 342 | if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { |
388 | ath_print(common, ATH_DBG_FATAL, | 343 | ath_err(common, "TX queue: %u already active\n", q); |
389 | "TX queue: %u already active\n", q); | ||
390 | return -1; | 344 | return -1; |
391 | } | 345 | } |
392 | memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); | 346 | memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); |
@@ -413,23 +367,17 @@ EXPORT_SYMBOL(ath9k_hw_setuptxqueue); | |||
413 | 367 | ||
414 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) | 368 | bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) |
415 | { | 369 | { |
416 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
417 | struct ath_common *common = ath9k_hw_common(ah); | 370 | struct ath_common *common = ath9k_hw_common(ah); |
418 | struct ath9k_tx_queue_info *qi; | 371 | struct ath9k_tx_queue_info *qi; |
419 | 372 | ||
420 | if (q >= pCap->total_queues) { | ||
421 | ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " | ||
422 | "invalid queue: %u\n", q); | ||
423 | return false; | ||
424 | } | ||
425 | qi = &ah->txq[q]; | 373 | qi = &ah->txq[q]; |
426 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 374 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
427 | ath_print(common, ATH_DBG_QUEUE, "Release TXQ, " | 375 | ath_dbg(common, ATH_DBG_QUEUE, |
428 | "inactive queue: %u\n", q); | 376 | "Release TXQ, inactive queue: %u\n", q); |
429 | return false; | 377 | return false; |
430 | } | 378 | } |
431 | 379 | ||
432 | ath_print(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); | 380 | ath_dbg(common, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); |
433 | 381 | ||
434 | qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; | 382 | qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; |
435 | ah->txok_interrupt_mask &= ~(1 << q); | 383 | ah->txok_interrupt_mask &= ~(1 << q); |
@@ -445,26 +393,19 @@ EXPORT_SYMBOL(ath9k_hw_releasetxqueue); | |||
445 | 393 | ||
446 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | 394 | bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) |
447 | { | 395 | { |
448 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
449 | struct ath_common *common = ath9k_hw_common(ah); | 396 | struct ath_common *common = ath9k_hw_common(ah); |
450 | struct ath9k_channel *chan = ah->curchan; | 397 | struct ath9k_channel *chan = ah->curchan; |
451 | struct ath9k_tx_queue_info *qi; | 398 | struct ath9k_tx_queue_info *qi; |
452 | u32 cwMin, chanCwMin, value; | 399 | u32 cwMin, chanCwMin, value; |
453 | 400 | ||
454 | if (q >= pCap->total_queues) { | ||
455 | ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " | ||
456 | "invalid queue: %u\n", q); | ||
457 | return false; | ||
458 | } | ||
459 | |||
460 | qi = &ah->txq[q]; | 401 | qi = &ah->txq[q]; |
461 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { | 402 | if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { |
462 | ath_print(common, ATH_DBG_QUEUE, "Reset TXQ, " | 403 | ath_dbg(common, ATH_DBG_QUEUE, |
463 | "inactive queue: %u\n", q); | 404 | "Reset TXQ, inactive queue: %u\n", q); |
464 | return true; | 405 | return true; |
465 | } | 406 | } |
466 | 407 | ||
467 | ath_print(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); | 408 | ath_dbg(common, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); |
468 | 409 | ||
469 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { | 410 | if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { |
470 | if (chan && IS_CHAN_B(chan)) | 411 | if (chan && IS_CHAN_B(chan)) |
@@ -489,19 +430,21 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
489 | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); | 430 | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); |
490 | 431 | ||
491 | REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); | 432 | REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); |
492 | REG_WRITE(ah, AR_DMISC(q), | ||
493 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); | ||
494 | 433 | ||
495 | REGWRITE_BUFFER_FLUSH(ah); | 434 | if (AR_SREV_9340(ah)) |
435 | REG_WRITE(ah, AR_DMISC(q), | ||
436 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1); | ||
437 | else | ||
438 | REG_WRITE(ah, AR_DMISC(q), | ||
439 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); | ||
496 | 440 | ||
497 | if (qi->tqi_cbrPeriod) { | 441 | if (qi->tqi_cbrPeriod) { |
498 | REG_WRITE(ah, AR_QCBRCFG(q), | 442 | REG_WRITE(ah, AR_QCBRCFG(q), |
499 | SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | | 443 | SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | |
500 | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH)); | 444 | SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH)); |
501 | REG_WRITE(ah, AR_QMISC(q), | 445 | REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_FSP_CBR | |
502 | REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | | 446 | (qi->tqi_cbrOverflowLimit ? |
503 | (qi->tqi_cbrOverflowLimit ? | 447 | AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); |
504 | AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); | ||
505 | } | 448 | } |
506 | if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { | 449 | if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { |
507 | REG_WRITE(ah, AR_QRDYTIMECFG(q), | 450 | REG_WRITE(ah, AR_QRDYTIMECFG(q), |
@@ -509,51 +452,38 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
509 | AR_Q_RDYTIMECFG_EN); | 452 | AR_Q_RDYTIMECFG_EN); |
510 | } | 453 | } |
511 | 454 | ||
512 | REGWRITE_BUFFER_FLUSH(ah); | ||
513 | |||
514 | REG_WRITE(ah, AR_DCHNTIME(q), | 455 | REG_WRITE(ah, AR_DCHNTIME(q), |
515 | SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | | 456 | SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | |
516 | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); | 457 | (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); |
517 | 458 | ||
518 | if (qi->tqi_burstTime | 459 | if (qi->tqi_burstTime |
519 | && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) { | 460 | && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) |
520 | REG_WRITE(ah, AR_QMISC(q), | 461 | REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_RDYTIME_EXP_POLICY); |
521 | REG_READ(ah, AR_QMISC(q)) | | ||
522 | AR_Q_MISC_RDYTIME_EXP_POLICY); | ||
523 | 462 | ||
524 | } | 463 | if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) |
525 | 464 | REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS); | |
526 | if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) { | ||
527 | REG_WRITE(ah, AR_DMISC(q), | ||
528 | REG_READ(ah, AR_DMISC(q)) | | ||
529 | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
530 | } | ||
531 | 465 | ||
532 | REGWRITE_BUFFER_FLUSH(ah); | 466 | REGWRITE_BUFFER_FLUSH(ah); |
533 | DISABLE_REGWRITE_BUFFER(ah); | ||
534 | 467 | ||
535 | if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { | 468 | if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) |
536 | REG_WRITE(ah, AR_DMISC(q), | 469 | REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_FRAG_BKOFF_EN); |
537 | REG_READ(ah, AR_DMISC(q)) | | 470 | |
538 | AR_D_MISC_FRAG_BKOFF_EN); | ||
539 | } | ||
540 | switch (qi->tqi_type) { | 471 | switch (qi->tqi_type) { |
541 | case ATH9K_TX_QUEUE_BEACON: | 472 | case ATH9K_TX_QUEUE_BEACON: |
542 | ENABLE_REGWRITE_BUFFER(ah); | 473 | ENABLE_REGWRITE_BUFFER(ah); |
543 | 474 | ||
544 | REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) | 475 | REG_SET_BIT(ah, AR_QMISC(q), |
545 | | AR_Q_MISC_FSP_DBA_GATED | 476 | AR_Q_MISC_FSP_DBA_GATED |
546 | | AR_Q_MISC_BEACON_USE | 477 | | AR_Q_MISC_BEACON_USE |
547 | | AR_Q_MISC_CBR_INCR_DIS1); | 478 | | AR_Q_MISC_CBR_INCR_DIS1); |
548 | 479 | ||
549 | REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | 480 | REG_SET_BIT(ah, AR_DMISC(q), |
550 | | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << | 481 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << |
551 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S) | 482 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S) |
552 | | AR_D_MISC_BEACON_USE | 483 | | AR_D_MISC_BEACON_USE |
553 | | AR_D_MISC_POST_FR_BKOFF_DIS); | 484 | | AR_D_MISC_POST_FR_BKOFF_DIS); |
554 | 485 | ||
555 | REGWRITE_BUFFER_FLUSH(ah); | 486 | REGWRITE_BUFFER_FLUSH(ah); |
556 | DISABLE_REGWRITE_BUFFER(ah); | ||
557 | 487 | ||
558 | /* | 488 | /* |
559 | * cwmin and cwmax should be 0 for beacon queue | 489 | * cwmin and cwmax should be 0 for beacon queue |
@@ -570,42 +500,38 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
570 | case ATH9K_TX_QUEUE_CAB: | 500 | case ATH9K_TX_QUEUE_CAB: |
571 | ENABLE_REGWRITE_BUFFER(ah); | 501 | ENABLE_REGWRITE_BUFFER(ah); |
572 | 502 | ||
573 | REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) | 503 | REG_SET_BIT(ah, AR_QMISC(q), |
574 | | AR_Q_MISC_FSP_DBA_GATED | 504 | AR_Q_MISC_FSP_DBA_GATED |
575 | | AR_Q_MISC_CBR_INCR_DIS1 | 505 | | AR_Q_MISC_CBR_INCR_DIS1 |
576 | | AR_Q_MISC_CBR_INCR_DIS0); | 506 | | AR_Q_MISC_CBR_INCR_DIS0); |
577 | value = (qi->tqi_readyTime - | 507 | value = (qi->tqi_readyTime - |
578 | (ah->config.sw_beacon_response_time - | 508 | (ah->config.sw_beacon_response_time - |
579 | ah->config.dma_beacon_response_time) - | 509 | ah->config.dma_beacon_response_time) - |
580 | ah->config.additional_swba_backoff) * 1024; | 510 | ah->config.additional_swba_backoff) * 1024; |
581 | REG_WRITE(ah, AR_QRDYTIMECFG(q), | 511 | REG_WRITE(ah, AR_QRDYTIMECFG(q), |
582 | value | AR_Q_RDYTIMECFG_EN); | 512 | value | AR_Q_RDYTIMECFG_EN); |
583 | REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | 513 | REG_SET_BIT(ah, AR_DMISC(q), |
584 | | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << | 514 | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << |
585 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); | 515 | AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); |
586 | 516 | ||
587 | REGWRITE_BUFFER_FLUSH(ah); | 517 | REGWRITE_BUFFER_FLUSH(ah); |
588 | DISABLE_REGWRITE_BUFFER(ah); | ||
589 | 518 | ||
590 | break; | 519 | break; |
591 | case ATH9K_TX_QUEUE_PSPOLL: | 520 | case ATH9K_TX_QUEUE_PSPOLL: |
592 | REG_WRITE(ah, AR_QMISC(q), | 521 | REG_SET_BIT(ah, AR_QMISC(q), AR_Q_MISC_CBR_INCR_DIS1); |
593 | REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); | ||
594 | break; | 522 | break; |
595 | case ATH9K_TX_QUEUE_UAPSD: | 523 | case ATH9K_TX_QUEUE_UAPSD: |
596 | REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | | 524 | REG_SET_BIT(ah, AR_DMISC(q), AR_D_MISC_POST_FR_BKOFF_DIS); |
597 | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
598 | break; | 525 | break; |
599 | default: | 526 | default: |
600 | break; | 527 | break; |
601 | } | 528 | } |
602 | 529 | ||
603 | if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { | 530 | if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { |
604 | REG_WRITE(ah, AR_DMISC(q), | 531 | REG_SET_BIT(ah, AR_DMISC(q), |
605 | REG_READ(ah, AR_DMISC(q)) | | 532 | SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, |
606 | SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, | 533 | AR_D_MISC_ARB_LOCKOUT_CNTRL) | |
607 | AR_D_MISC_ARB_LOCKOUT_CNTRL) | | 534 | AR_D_MISC_POST_FR_BKOFF_DIS); |
608 | AR_D_MISC_POST_FR_BKOFF_DIS); | ||
609 | } | 535 | } |
610 | 536 | ||
611 | if (AR_SREV_9300_20_OR_LATER(ah)) | 537 | if (AR_SREV_9300_20_OR_LATER(ah)) |
@@ -703,6 +629,12 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
703 | rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; | 629 | rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY; |
704 | 630 | ||
705 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { | 631 | if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { |
632 | /* | ||
633 | * Treat these errors as mutually exclusive to avoid spurious | ||
634 | * extra error reports from the hardware. If a CRC error is | ||
635 | * reported, then decryption and MIC errors are irrelevant, | ||
636 | * the frame is going to be dropped either way | ||
637 | */ | ||
706 | if (ads.ds_rxstatus8 & AR_CRCErr) | 638 | if (ads.ds_rxstatus8 & AR_CRCErr) |
707 | rs->rs_status |= ATH9K_RXERR_CRC; | 639 | rs->rs_status |= ATH9K_RXERR_CRC; |
708 | else if (ads.ds_rxstatus8 & AR_PHYErr) { | 640 | else if (ads.ds_rxstatus8 & AR_PHYErr) { |
@@ -713,6 +645,9 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
713 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | 645 | rs->rs_status |= ATH9K_RXERR_DECRYPT; |
714 | else if (ads.ds_rxstatus8 & AR_MichaelErr) | 646 | else if (ads.ds_rxstatus8 & AR_MichaelErr) |
715 | rs->rs_status |= ATH9K_RXERR_MIC; | 647 | rs->rs_status |= ATH9K_RXERR_MIC; |
648 | |||
649 | if (ads.ds_rxstatus8 & AR_KeyMiss) | ||
650 | rs->rs_status |= ATH9K_RXERR_DECRYPT; | ||
716 | } | 651 | } |
717 | 652 | ||
718 | return 0; | 653 | return 0; |
@@ -741,9 +676,9 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) | |||
741 | AR_DIAG_RX_ABORT)); | 676 | AR_DIAG_RX_ABORT)); |
742 | 677 | ||
743 | reg = REG_READ(ah, AR_OBS_BUS_1); | 678 | reg = REG_READ(ah, AR_OBS_BUS_1); |
744 | ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, | 679 | ath_err(ath9k_hw_common(ah), |
745 | "RX failed to go idle in 10 ms RXSM=0x%x\n", | 680 | "RX failed to go idle in 10 ms RXSM=0x%x\n", |
746 | reg); | 681 | reg); |
747 | 682 | ||
748 | return false; | 683 | return false; |
749 | } | 684 | } |
@@ -772,14 +707,6 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning) | |||
772 | } | 707 | } |
773 | EXPORT_SYMBOL(ath9k_hw_startpcureceive); | 708 | EXPORT_SYMBOL(ath9k_hw_startpcureceive); |
774 | 709 | ||
775 | void ath9k_hw_stoppcurecv(struct ath_hw *ah) | ||
776 | { | ||
777 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); | ||
778 | |||
779 | ath9k_hw_disable_mib_counters(ah); | ||
780 | } | ||
781 | EXPORT_SYMBOL(ath9k_hw_stoppcurecv); | ||
782 | |||
783 | void ath9k_hw_abortpcurecv(struct ath_hw *ah) | 710 | void ath9k_hw_abortpcurecv(struct ath_hw *ah) |
784 | { | 711 | { |
785 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); | 712 | REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS); |
@@ -788,35 +715,51 @@ void ath9k_hw_abortpcurecv(struct ath_hw *ah) | |||
788 | } | 715 | } |
789 | EXPORT_SYMBOL(ath9k_hw_abortpcurecv); | 716 | EXPORT_SYMBOL(ath9k_hw_abortpcurecv); |
790 | 717 | ||
791 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah) | 718 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset) |
792 | { | 719 | { |
793 | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ | 720 | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ |
794 | #define AH_RX_TIME_QUANTUM 100 /* usec */ | ||
795 | struct ath_common *common = ath9k_hw_common(ah); | 721 | struct ath_common *common = ath9k_hw_common(ah); |
722 | u32 mac_status, last_mac_status = 0; | ||
796 | int i; | 723 | int i; |
797 | 724 | ||
725 | /* Enable access to the DMA observation bus */ | ||
726 | REG_WRITE(ah, AR_MACMISC, | ||
727 | ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | | ||
728 | (AR_MACMISC_MISC_OBS_BUS_1 << | ||
729 | AR_MACMISC_MISC_OBS_BUS_MSB_S))); | ||
730 | |||
798 | REG_WRITE(ah, AR_CR, AR_CR_RXD); | 731 | REG_WRITE(ah, AR_CR, AR_CR_RXD); |
799 | 732 | ||
800 | /* Wait for rx enable bit to go low */ | 733 | /* Wait for rx enable bit to go low */ |
801 | for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { | 734 | for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { |
802 | if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) | 735 | if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) |
803 | break; | 736 | break; |
737 | |||
738 | if (!AR_SREV_9300_20_OR_LATER(ah)) { | ||
739 | mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0; | ||
740 | if (mac_status == 0x1c0 && mac_status == last_mac_status) { | ||
741 | *reset = true; | ||
742 | break; | ||
743 | } | ||
744 | |||
745 | last_mac_status = mac_status; | ||
746 | } | ||
747 | |||
804 | udelay(AH_TIME_QUANTUM); | 748 | udelay(AH_TIME_QUANTUM); |
805 | } | 749 | } |
806 | 750 | ||
807 | if (i == 0) { | 751 | if (i == 0) { |
808 | ath_print(common, ATH_DBG_FATAL, | 752 | ath_err(common, |
809 | "DMA failed to stop in %d ms " | 753 | "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n", |
810 | "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", | 754 | AH_RX_STOP_DMA_TIMEOUT / 1000, |
811 | AH_RX_STOP_DMA_TIMEOUT / 1000, | 755 | REG_READ(ah, AR_CR), |
812 | REG_READ(ah, AR_CR), | 756 | REG_READ(ah, AR_DIAG_SW), |
813 | REG_READ(ah, AR_DIAG_SW)); | 757 | REG_READ(ah, AR_DMADBG_7)); |
814 | return false; | 758 | return false; |
815 | } else { | 759 | } else { |
816 | return true; | 760 | return true; |
817 | } | 761 | } |
818 | 762 | ||
819 | #undef AH_RX_TIME_QUANTUM | ||
820 | #undef AH_RX_STOP_DMA_TIMEOUT | 763 | #undef AH_RX_STOP_DMA_TIMEOUT |
821 | } | 764 | } |
822 | EXPORT_SYMBOL(ath9k_hw_stopdmarecv); | 765 | EXPORT_SYMBOL(ath9k_hw_stopdmarecv); |
@@ -854,28 +797,61 @@ bool ath9k_hw_intrpend(struct ath_hw *ah) | |||
854 | } | 797 | } |
855 | EXPORT_SYMBOL(ath9k_hw_intrpend); | 798 | EXPORT_SYMBOL(ath9k_hw_intrpend); |
856 | 799 | ||
857 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, | 800 | void ath9k_hw_disable_interrupts(struct ath_hw *ah) |
858 | enum ath9k_int ints) | 801 | { |
802 | struct ath_common *common = ath9k_hw_common(ah); | ||
803 | |||
804 | ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n"); | ||
805 | REG_WRITE(ah, AR_IER, AR_IER_DISABLE); | ||
806 | (void) REG_READ(ah, AR_IER); | ||
807 | if (!AR_SREV_9100(ah)) { | ||
808 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); | ||
809 | (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); | ||
810 | |||
811 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); | ||
812 | (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); | ||
813 | } | ||
814 | } | ||
815 | EXPORT_SYMBOL(ath9k_hw_disable_interrupts); | ||
816 | |||
817 | void ath9k_hw_enable_interrupts(struct ath_hw *ah) | ||
818 | { | ||
819 | struct ath_common *common = ath9k_hw_common(ah); | ||
820 | u32 sync_default = AR_INTR_SYNC_DEFAULT; | ||
821 | |||
822 | if (!(ah->imask & ATH9K_INT_GLOBAL)) | ||
823 | return; | ||
824 | |||
825 | if (AR_SREV_9340(ah)) | ||
826 | sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; | ||
827 | |||
828 | ath_dbg(common, ATH_DBG_INTERRUPT, "enable IER\n"); | ||
829 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); | ||
830 | if (!AR_SREV_9100(ah)) { | ||
831 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, | ||
832 | AR_INTR_MAC_IRQ); | ||
833 | REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); | ||
834 | |||
835 | |||
836 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, sync_default); | ||
837 | REG_WRITE(ah, AR_INTR_SYNC_MASK, sync_default); | ||
838 | } | ||
839 | ath_dbg(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", | ||
840 | REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); | ||
841 | } | ||
842 | EXPORT_SYMBOL(ath9k_hw_enable_interrupts); | ||
843 | |||
844 | void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) | ||
859 | { | 845 | { |
860 | enum ath9k_int omask = ah->imask; | 846 | enum ath9k_int omask = ah->imask; |
861 | u32 mask, mask2; | 847 | u32 mask, mask2; |
862 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 848 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
863 | struct ath_common *common = ath9k_hw_common(ah); | 849 | struct ath_common *common = ath9k_hw_common(ah); |
864 | 850 | ||
865 | ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); | 851 | if (!(ints & ATH9K_INT_GLOBAL)) |
866 | 852 | ath9k_hw_disable_interrupts(ah); | |
867 | if (omask & ATH9K_INT_GLOBAL) { | ||
868 | ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n"); | ||
869 | REG_WRITE(ah, AR_IER, AR_IER_DISABLE); | ||
870 | (void) REG_READ(ah, AR_IER); | ||
871 | if (!AR_SREV_9100(ah)) { | ||
872 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); | ||
873 | (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); | ||
874 | 853 | ||
875 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); | 854 | ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); |
876 | (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); | ||
877 | } | ||
878 | } | ||
879 | 855 | ||
880 | /* TODO: global int Ref count */ | 856 | /* TODO: global int Ref count */ |
881 | mask = ints & ATH9K_INT_COMMON; | 857 | mask = ints & ATH9K_INT_COMMON; |
@@ -914,6 +890,9 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, | |||
914 | mask |= AR_IMR_GENTMR; | 890 | mask |= AR_IMR_GENTMR; |
915 | } | 891 | } |
916 | 892 | ||
893 | if (ints & ATH9K_INT_GENTIMER) | ||
894 | mask |= AR_IMR_GENTMR; | ||
895 | |||
917 | if (ints & (ATH9K_INT_BMISC)) { | 896 | if (ints & (ATH9K_INT_BMISC)) { |
918 | mask |= AR_IMR_BCNMISC; | 897 | mask |= AR_IMR_BCNMISC; |
919 | if (ints & ATH9K_INT_TIM) | 898 | if (ints & ATH9K_INT_TIM) |
@@ -936,7 +915,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, | |||
936 | mask2 |= AR_IMR_S2_CST; | 915 | mask2 |= AR_IMR_S2_CST; |
937 | } | 916 | } |
938 | 917 | ||
939 | ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); | 918 | ath_dbg(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); |
940 | REG_WRITE(ah, AR_IMR, mask); | 919 | REG_WRITE(ah, AR_IMR, mask); |
941 | ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | | 920 | ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC | |
942 | AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | | 921 | AR_IMR_S2_CABEND | AR_IMR_S2_CABTO | |
@@ -951,24 +930,9 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, | |||
951 | REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); | 930 | REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); |
952 | } | 931 | } |
953 | 932 | ||
954 | if (ints & ATH9K_INT_GLOBAL) { | 933 | if (ints & ATH9K_INT_GLOBAL) |
955 | ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n"); | 934 | ath9k_hw_enable_interrupts(ah); |
956 | REG_WRITE(ah, AR_IER, AR_IER_ENABLE); | ||
957 | if (!AR_SREV_9100(ah)) { | ||
958 | REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, | ||
959 | AR_INTR_MAC_IRQ); | ||
960 | REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); | ||
961 | |||
962 | |||
963 | REG_WRITE(ah, AR_INTR_SYNC_ENABLE, | ||
964 | AR_INTR_SYNC_DEFAULT); | ||
965 | REG_WRITE(ah, AR_INTR_SYNC_MASK, | ||
966 | AR_INTR_SYNC_DEFAULT); | ||
967 | } | ||
968 | ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", | ||
969 | REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); | ||
970 | } | ||
971 | 935 | ||
972 | return omask; | 936 | return; |
973 | } | 937 | } |
974 | EXPORT_SYMBOL(ath9k_hw_set_interrupts); | 938 | EXPORT_SYMBOL(ath9k_hw_set_interrupts); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 2633896d3998..8e848c4d16ba 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -104,13 +104,11 @@ struct ath_tx_status { | |||
104 | u32 ts_tstamp; | 104 | u32 ts_tstamp; |
105 | u16 ts_seqnum; | 105 | u16 ts_seqnum; |
106 | u8 ts_status; | 106 | u8 ts_status; |
107 | u8 ts_ratecode; | ||
108 | u8 ts_rateindex; | 107 | u8 ts_rateindex; |
109 | int8_t ts_rssi; | 108 | int8_t ts_rssi; |
110 | u8 ts_shortretry; | 109 | u8 ts_shortretry; |
111 | u8 ts_longretry; | 110 | u8 ts_longretry; |
112 | u8 ts_virtcol; | 111 | u8 ts_virtcol; |
113 | u8 ts_antenna; | ||
114 | u8 ts_flags; | 112 | u8 ts_flags; |
115 | int8_t ts_rssi_ctl0; | 113 | int8_t ts_rssi_ctl0; |
116 | int8_t ts_rssi_ctl1; | 114 | int8_t ts_rssi_ctl1; |
@@ -121,7 +119,6 @@ struct ath_tx_status { | |||
121 | u8 qid; | 119 | u8 qid; |
122 | u16 desc_id; | 120 | u16 desc_id; |
123 | u8 tid; | 121 | u8 tid; |
124 | u8 pad[2]; | ||
125 | u32 ba_low; | 122 | u32 ba_low; |
126 | u32 ba_high; | 123 | u32 ba_high; |
127 | u32 evm0; | 124 | u32 evm0; |
@@ -240,9 +237,8 @@ struct ath_desc { | |||
240 | u32 ds_ctl1; | 237 | u32 ds_ctl1; |
241 | u32 ds_hw[20]; | 238 | u32 ds_hw[20]; |
242 | void *ds_vdata; | 239 | void *ds_vdata; |
243 | } __packed; | 240 | } __packed __aligned(4); |
244 | 241 | ||
245 | #define ATH9K_TXDESC_CLRDMASK 0x0001 | ||
246 | #define ATH9K_TXDESC_NOACK 0x0002 | 242 | #define ATH9K_TXDESC_NOACK 0x0002 |
247 | #define ATH9K_TXDESC_RTSENA 0x0004 | 243 | #define ATH9K_TXDESC_RTSENA 0x0004 |
248 | #define ATH9K_TXDESC_CTSENA 0x0008 | 244 | #define ATH9K_TXDESC_CTSENA 0x0008 |
@@ -310,7 +306,7 @@ struct ar5416_desc { | |||
310 | u32 status8; | 306 | u32 status8; |
311 | } rx; | 307 | } rx; |
312 | } u; | 308 | } u; |
313 | } __packed; | 309 | } __packed __aligned(4); |
314 | 310 | ||
315 | #define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) | 311 | #define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) |
316 | #define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) | 312 | #define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) |
@@ -642,6 +638,8 @@ enum ath9k_rx_filter { | |||
642 | ATH9K_RX_FILTER_PHYERR = 0x00000100, | 638 | ATH9K_RX_FILTER_PHYERR = 0x00000100, |
643 | ATH9K_RX_FILTER_MYBEACON = 0x00000200, | 639 | ATH9K_RX_FILTER_MYBEACON = 0x00000200, |
644 | ATH9K_RX_FILTER_COMP_BAR = 0x00000400, | 640 | ATH9K_RX_FILTER_COMP_BAR = 0x00000400, |
641 | ATH9K_RX_FILTER_COMP_BA = 0x00000800, | ||
642 | ATH9K_RX_FILTER_UNCOMP_BA_BAR = 0x00001000, | ||
645 | ATH9K_RX_FILTER_PSPOLL = 0x00004000, | 643 | ATH9K_RX_FILTER_PSPOLL = 0x00004000, |
646 | ATH9K_RX_FILTER_PHYRADAR = 0x00002000, | 644 | ATH9K_RX_FILTER_PHYRADAR = 0x00002000, |
647 | ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, | 645 | ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, |
@@ -660,17 +658,6 @@ struct ath9k_11n_rate_series { | |||
660 | u32 RateFlags; | 658 | u32 RateFlags; |
661 | }; | 659 | }; |
662 | 660 | ||
663 | struct ath9k_keyval { | ||
664 | u8 kv_type; | ||
665 | u8 kv_pad; | ||
666 | u16 kv_len; | ||
667 | u8 kv_val[16]; /* TK */ | ||
668 | u8 kv_mic[8]; /* Michael MIC key */ | ||
669 | u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware | ||
670 | * supports both MIC keys in the same key cache entry; | ||
671 | * in that case, kv_mic is the RX key) */ | ||
672 | }; | ||
673 | |||
674 | enum ath9k_key_type { | 661 | enum ath9k_key_type { |
675 | ATH9K_KEY_TYPE_CLEAR, | 662 | ATH9K_KEY_TYPE_CLEAR, |
676 | ATH9K_KEY_TYPE_WEP, | 663 | ATH9K_KEY_TYPE_WEP, |
@@ -678,18 +665,9 @@ enum ath9k_key_type { | |||
678 | ATH9K_KEY_TYPE_TKIP, | 665 | ATH9K_KEY_TYPE_TKIP, |
679 | }; | 666 | }; |
680 | 667 | ||
681 | enum ath9k_cipher { | ||
682 | ATH9K_CIPHER_WEP = 0, | ||
683 | ATH9K_CIPHER_AES_OCB = 1, | ||
684 | ATH9K_CIPHER_AES_CCM = 2, | ||
685 | ATH9K_CIPHER_CKIP = 3, | ||
686 | ATH9K_CIPHER_TKIP = 4, | ||
687 | ATH9K_CIPHER_CLR = 5, | ||
688 | ATH9K_CIPHER_MIC = 127 | ||
689 | }; | ||
690 | |||
691 | struct ath_hw; | 668 | struct ath_hw; |
692 | struct ath9k_channel; | 669 | struct ath9k_channel; |
670 | enum ath9k_int; | ||
693 | 671 | ||
694 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); | 672 | u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); |
695 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); | 673 | void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); |
@@ -697,7 +675,8 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q); | |||
697 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds); | 675 | void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds); |
698 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); | 676 | u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); |
699 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); | 677 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); |
700 | bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); | 678 | bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q); |
679 | void ath9k_hw_abort_tx_dma(struct ath_hw *ah); | ||
701 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); | 680 | void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); |
702 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, | 681 | bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, |
703 | const struct ath9k_tx_queue_info *qinfo); | 682 | const struct ath9k_tx_queue_info *qinfo); |
@@ -714,15 +693,15 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | |||
714 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); | 693 | bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); |
715 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); | 694 | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); |
716 | void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); | 695 | void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); |
717 | void ath9k_hw_stoppcurecv(struct ath_hw *ah); | ||
718 | void ath9k_hw_abortpcurecv(struct ath_hw *ah); | 696 | void ath9k_hw_abortpcurecv(struct ath_hw *ah); |
719 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah); | 697 | bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset); |
720 | int ath9k_hw_beaconq_setup(struct ath_hw *ah); | 698 | int ath9k_hw_beaconq_setup(struct ath_hw *ah); |
721 | 699 | ||
722 | /* Interrupt Handling */ | 700 | /* Interrupt Handling */ |
723 | bool ath9k_hw_intrpend(struct ath_hw *ah); | 701 | bool ath9k_hw_intrpend(struct ath_hw *ah); |
724 | enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, | 702 | void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); |
725 | enum ath9k_int ints); | 703 | void ath9k_hw_enable_interrupts(struct ath_hw *ah); |
704 | void ath9k_hw_disable_interrupts(struct ath_hw *ah); | ||
726 | 705 | ||
727 | void ar9002_hw_attach_mac_ops(struct ath_hw *ah); | 706 | void ar9002_hw_attach_mac_ops(struct ath_hw *ah); |
728 | 707 | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3caa32316e7b..2ca351fe6d3c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -15,50 +15,10 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/nl80211.h> | 17 | #include <linux/nl80211.h> |
18 | #include <linux/delay.h> | ||
18 | #include "ath9k.h" | 19 | #include "ath9k.h" |
19 | #include "btcoex.h" | 20 | #include "btcoex.h" |
20 | 21 | ||
21 | static void ath_cache_conf_rate(struct ath_softc *sc, | ||
22 | struct ieee80211_conf *conf) | ||
23 | { | ||
24 | switch (conf->channel->band) { | ||
25 | case IEEE80211_BAND_2GHZ: | ||
26 | if (conf_is_ht20(conf)) | ||
27 | sc->cur_rate_mode = ATH9K_MODE_11NG_HT20; | ||
28 | else if (conf_is_ht40_minus(conf)) | ||
29 | sc->cur_rate_mode = ATH9K_MODE_11NG_HT40MINUS; | ||
30 | else if (conf_is_ht40_plus(conf)) | ||
31 | sc->cur_rate_mode = ATH9K_MODE_11NG_HT40PLUS; | ||
32 | else | ||
33 | sc->cur_rate_mode = ATH9K_MODE_11G; | ||
34 | break; | ||
35 | case IEEE80211_BAND_5GHZ: | ||
36 | if (conf_is_ht20(conf)) | ||
37 | sc->cur_rate_mode = ATH9K_MODE_11NA_HT20; | ||
38 | else if (conf_is_ht40_minus(conf)) | ||
39 | sc->cur_rate_mode = ATH9K_MODE_11NA_HT40MINUS; | ||
40 | else if (conf_is_ht40_plus(conf)) | ||
41 | sc->cur_rate_mode = ATH9K_MODE_11NA_HT40PLUS; | ||
42 | else | ||
43 | sc->cur_rate_mode = ATH9K_MODE_11A; | ||
44 | break; | ||
45 | default: | ||
46 | BUG_ON(1); | ||
47 | break; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static void ath_update_txpow(struct ath_softc *sc) | ||
52 | { | ||
53 | struct ath_hw *ah = sc->sc_ah; | ||
54 | |||
55 | if (sc->curtxpow != sc->config.txpowlimit) { | ||
56 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); | ||
57 | /* read back in case value is clamped */ | ||
58 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | static u8 parse_mpdudensity(u8 mpdudensity) | 22 | static u8 parse_mpdudensity(u8 mpdudensity) |
63 | { | 23 | { |
64 | /* | 24 | /* |
@@ -94,17 +54,19 @@ static u8 parse_mpdudensity(u8 mpdudensity) | |||
94 | } | 54 | } |
95 | } | 55 | } |
96 | 56 | ||
97 | static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, | 57 | static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq) |
98 | struct ieee80211_hw *hw) | ||
99 | { | 58 | { |
100 | struct ieee80211_channel *curchan = hw->conf.channel; | 59 | bool pending = false; |
101 | struct ath9k_channel *channel; | 60 | |
102 | u8 chan_idx; | 61 | spin_lock_bh(&txq->axq_lock); |
62 | |||
63 | if (txq->axq_depth || !list_empty(&txq->axq_acq)) | ||
64 | pending = true; | ||
65 | else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | ||
66 | pending = !list_empty(&txq->txq_fifo_pending); | ||
103 | 67 | ||
104 | chan_idx = curchan->hw_value; | 68 | spin_unlock_bh(&txq->axq_lock); |
105 | channel = &sc->sc_ah->channels[chan_idx]; | 69 | return pending; |
106 | ath9k_update_ichannel(sc, hw, channel); | ||
107 | return channel; | ||
108 | } | 70 | } |
109 | 71 | ||
110 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) | 72 | bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) |
@@ -121,26 +83,46 @@ bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) | |||
121 | 83 | ||
122 | void ath9k_ps_wakeup(struct ath_softc *sc) | 84 | void ath9k_ps_wakeup(struct ath_softc *sc) |
123 | { | 85 | { |
86 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
124 | unsigned long flags; | 87 | unsigned long flags; |
88 | enum ath9k_power_mode power_mode; | ||
125 | 89 | ||
126 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 90 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
127 | if (++sc->ps_usecount != 1) | 91 | if (++sc->ps_usecount != 1) |
128 | goto unlock; | 92 | goto unlock; |
129 | 93 | ||
94 | power_mode = sc->sc_ah->power_mode; | ||
130 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); | 95 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); |
131 | 96 | ||
97 | /* | ||
98 | * While the hardware is asleep, the cycle counters contain no | ||
99 | * useful data. Better clear them now so that they don't mess up | ||
100 | * survey data results. | ||
101 | */ | ||
102 | if (power_mode != ATH9K_PM_AWAKE) { | ||
103 | spin_lock(&common->cc_lock); | ||
104 | ath_hw_cycle_counters_update(common); | ||
105 | memset(&common->cc_survey, 0, sizeof(common->cc_survey)); | ||
106 | spin_unlock(&common->cc_lock); | ||
107 | } | ||
108 | |||
132 | unlock: | 109 | unlock: |
133 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 110 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
134 | } | 111 | } |
135 | 112 | ||
136 | void ath9k_ps_restore(struct ath_softc *sc) | 113 | void ath9k_ps_restore(struct ath_softc *sc) |
137 | { | 114 | { |
115 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
138 | unsigned long flags; | 116 | unsigned long flags; |
139 | 117 | ||
140 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 118 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
141 | if (--sc->ps_usecount != 0) | 119 | if (--sc->ps_usecount != 0) |
142 | goto unlock; | 120 | goto unlock; |
143 | 121 | ||
122 | spin_lock(&common->cc_lock); | ||
123 | ath_hw_cycle_counters_update(common); | ||
124 | spin_unlock(&common->cc_lock); | ||
125 | |||
144 | if (sc->ps_idle) | 126 | if (sc->ps_idle) |
145 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); | 127 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); |
146 | else if (sc->ps_enabled && | 128 | else if (sc->ps_enabled && |
@@ -175,6 +157,63 @@ static void ath_start_ani(struct ath_common *common) | |||
175 | msecs_to_jiffies((u32)ah->config.ani_poll_interval)); | 157 | msecs_to_jiffies((u32)ah->config.ani_poll_interval)); |
176 | } | 158 | } |
177 | 159 | ||
160 | static void ath_update_survey_nf(struct ath_softc *sc, int channel) | ||
161 | { | ||
162 | struct ath_hw *ah = sc->sc_ah; | ||
163 | struct ath9k_channel *chan = &ah->channels[channel]; | ||
164 | struct survey_info *survey = &sc->survey[channel]; | ||
165 | |||
166 | if (chan->noisefloor) { | ||
167 | survey->filled |= SURVEY_INFO_NOISE_DBM; | ||
168 | survey->noise = chan->noisefloor; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Updates the survey statistics and returns the busy time since last | ||
174 | * update in %, if the measurement duration was long enough for the | ||
175 | * result to be useful, -1 otherwise. | ||
176 | */ | ||
177 | static int ath_update_survey_stats(struct ath_softc *sc) | ||
178 | { | ||
179 | struct ath_hw *ah = sc->sc_ah; | ||
180 | struct ath_common *common = ath9k_hw_common(ah); | ||
181 | int pos = ah->curchan - &ah->channels[0]; | ||
182 | struct survey_info *survey = &sc->survey[pos]; | ||
183 | struct ath_cycle_counters *cc = &common->cc_survey; | ||
184 | unsigned int div = common->clockrate * 1000; | ||
185 | int ret = 0; | ||
186 | |||
187 | if (!ah->curchan) | ||
188 | return -1; | ||
189 | |||
190 | if (ah->power_mode == ATH9K_PM_AWAKE) | ||
191 | ath_hw_cycle_counters_update(common); | ||
192 | |||
193 | if (cc->cycles > 0) { | ||
194 | survey->filled |= SURVEY_INFO_CHANNEL_TIME | | ||
195 | SURVEY_INFO_CHANNEL_TIME_BUSY | | ||
196 | SURVEY_INFO_CHANNEL_TIME_RX | | ||
197 | SURVEY_INFO_CHANNEL_TIME_TX; | ||
198 | survey->channel_time += cc->cycles / div; | ||
199 | survey->channel_time_busy += cc->rx_busy / div; | ||
200 | survey->channel_time_rx += cc->rx_frame / div; | ||
201 | survey->channel_time_tx += cc->tx_frame / div; | ||
202 | } | ||
203 | |||
204 | if (cc->cycles < div) | ||
205 | return -1; | ||
206 | |||
207 | if (cc->cycles > 0) | ||
208 | ret = cc->rx_busy * 100 / cc->cycles; | ||
209 | |||
210 | memset(cc, 0, sizeof(*cc)); | ||
211 | |||
212 | ath_update_survey_nf(sc, pos); | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | |||
178 | /* | 217 | /* |
179 | * Set/change channels. If the channel is really being changed, it's done | 218 | * Set/change channels. If the channel is really being changed, it's done |
180 | * by reseting the chip. To accomplish this we must first cleanup any pending | 219 | * by reseting the chip. To accomplish this we must first cleanup any pending |
@@ -183,7 +222,6 @@ static void ath_start_ani(struct ath_common *common) | |||
183 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | 222 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, |
184 | struct ath9k_channel *hchan) | 223 | struct ath9k_channel *hchan) |
185 | { | 224 | { |
186 | struct ath_wiphy *aphy = hw->priv; | ||
187 | struct ath_hw *ah = sc->sc_ah; | 225 | struct ath_hw *ah = sc->sc_ah; |
188 | struct ath_common *common = ath9k_hw_common(ah); | 226 | struct ath_common *common = ath9k_hw_common(ah); |
189 | struct ieee80211_conf *conf = &common->hw->conf; | 227 | struct ieee80211_conf *conf = &common->hw->conf; |
@@ -195,13 +233,18 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
195 | if (sc->sc_flags & SC_OP_INVALID) | 233 | if (sc->sc_flags & SC_OP_INVALID) |
196 | return -EIO; | 234 | return -EIO; |
197 | 235 | ||
236 | sc->hw_busy_count = 0; | ||
237 | |||
198 | del_timer_sync(&common->ani.timer); | 238 | del_timer_sync(&common->ani.timer); |
199 | cancel_work_sync(&sc->paprd_work); | 239 | cancel_work_sync(&sc->paprd_work); |
200 | cancel_work_sync(&sc->hw_check_work); | 240 | cancel_work_sync(&sc->hw_check_work); |
201 | cancel_delayed_work_sync(&sc->tx_complete_work); | 241 | cancel_delayed_work_sync(&sc->tx_complete_work); |
242 | cancel_delayed_work_sync(&sc->hw_pll_work); | ||
202 | 243 | ||
203 | ath9k_ps_wakeup(sc); | 244 | ath9k_ps_wakeup(sc); |
204 | 245 | ||
246 | spin_lock_bh(&sc->sc_pcu_lock); | ||
247 | |||
205 | /* | 248 | /* |
206 | * This is only performed if the channel settings have | 249 | * This is only performed if the channel settings have |
207 | * actually changed. | 250 | * actually changed. |
@@ -211,9 +254,14 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
211 | * hardware at the new frequency, and then re-enable | 254 | * hardware at the new frequency, and then re-enable |
212 | * the relevant bits of the h/w. | 255 | * the relevant bits of the h/w. |
213 | */ | 256 | */ |
214 | ath9k_hw_set_interrupts(ah, 0); | 257 | ath9k_hw_disable_interrupts(ah); |
215 | ath_drain_all_txq(sc, false); | 258 | stopped = ath_drain_all_txq(sc, false); |
216 | stopped = ath_stoprecv(sc); | 259 | |
260 | if (!ath_stoprecv(sc)) | ||
261 | stopped = false; | ||
262 | |||
263 | if (!ath9k_hw_check_alive(ah)) | ||
264 | stopped = false; | ||
217 | 265 | ||
218 | /* XXX: do not flush receive queue here. We don't want | 266 | /* XXX: do not flush receive queue here. We don't want |
219 | * to flush data frames already in queue because of | 267 | * to flush data frames already in queue because of |
@@ -223,44 +271,45 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
223 | fastcc = false; | 271 | fastcc = false; |
224 | 272 | ||
225 | if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) | 273 | if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) |
226 | caldata = &aphy->caldata; | 274 | caldata = &sc->caldata; |
227 | |||
228 | ath_print(common, ATH_DBG_CONFIG, | ||
229 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", | ||
230 | sc->sc_ah->curchan->channel, | ||
231 | channel->center_freq, conf_is_ht40(conf)); | ||
232 | 275 | ||
233 | spin_lock_bh(&sc->sc_resetlock); | 276 | ath_dbg(common, ATH_DBG_CONFIG, |
277 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", | ||
278 | sc->sc_ah->curchan->channel, | ||
279 | channel->center_freq, conf_is_ht40(conf), | ||
280 | fastcc); | ||
234 | 281 | ||
235 | r = ath9k_hw_reset(ah, hchan, caldata, fastcc); | 282 | r = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
236 | if (r) { | 283 | if (r) { |
237 | ath_print(common, ATH_DBG_FATAL, | 284 | ath_err(common, |
238 | "Unable to reset channel (%u MHz), " | 285 | "Unable to reset channel (%u MHz), reset status %d\n", |
239 | "reset status %d\n", | 286 | channel->center_freq, r); |
240 | channel->center_freq, r); | ||
241 | spin_unlock_bh(&sc->sc_resetlock); | ||
242 | goto ps_restore; | 287 | goto ps_restore; |
243 | } | 288 | } |
244 | spin_unlock_bh(&sc->sc_resetlock); | ||
245 | 289 | ||
246 | if (ath_startrecv(sc) != 0) { | 290 | if (ath_startrecv(sc) != 0) { |
247 | ath_print(common, ATH_DBG_FATAL, | 291 | ath_err(common, "Unable to restart recv logic\n"); |
248 | "Unable to restart recv logic\n"); | ||
249 | r = -EIO; | 292 | r = -EIO; |
250 | goto ps_restore; | 293 | goto ps_restore; |
251 | } | 294 | } |
252 | 295 | ||
253 | ath_cache_conf_rate(sc, &hw->conf); | 296 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
254 | ath_update_txpow(sc); | 297 | sc->config.txpowlimit, &sc->curtxpow); |
255 | ath9k_hw_set_interrupts(ah, ah->imask); | 298 | ath9k_hw_set_interrupts(ah, ah->imask); |
256 | 299 | ||
257 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) { | 300 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { |
258 | ath_start_ani(common); | 301 | if (sc->sc_flags & SC_OP_BEACONS) |
302 | ath_set_beacon(sc); | ||
259 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 303 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
260 | ath_beacon_config(sc, NULL); | 304 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); |
305 | ath_start_ani(common); | ||
261 | } | 306 | } |
262 | 307 | ||
263 | ps_restore: | 308 | ps_restore: |
309 | ieee80211_wake_queues(hw); | ||
310 | |||
311 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
312 | |||
264 | ath9k_ps_restore(sc); | 313 | ath9k_ps_restore(sc); |
265 | return r; | 314 | return r; |
266 | } | 315 | } |
@@ -269,6 +318,7 @@ static void ath_paprd_activate(struct ath_softc *sc) | |||
269 | { | 318 | { |
270 | struct ath_hw *ah = sc->sc_ah; | 319 | struct ath_hw *ah = sc->sc_ah; |
271 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 320 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
321 | struct ath_common *common = ath9k_hw_common(ah); | ||
272 | int chain; | 322 | int chain; |
273 | 323 | ||
274 | if (!caldata || !caldata->paprd_done) | 324 | if (!caldata || !caldata->paprd_done) |
@@ -277,7 +327,7 @@ static void ath_paprd_activate(struct ath_softc *sc) | |||
277 | ath9k_ps_wakeup(sc); | 327 | ath9k_ps_wakeup(sc); |
278 | ar9003_paprd_enable(ah, false); | 328 | ar9003_paprd_enable(ah, false); |
279 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | 329 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
280 | if (!(ah->caps.tx_chainmask & BIT(chain))) | 330 | if (!(common->tx_chainmask & BIT(chain))) |
281 | continue; | 331 | continue; |
282 | 332 | ||
283 | ar9003_paprd_populate_single_table(ah, caldata, chain); | 333 | ar9003_paprd_populate_single_table(ah, caldata, chain); |
@@ -287,6 +337,46 @@ static void ath_paprd_activate(struct ath_softc *sc) | |||
287 | ath9k_ps_restore(sc); | 337 | ath9k_ps_restore(sc); |
288 | } | 338 | } |
289 | 339 | ||
340 | static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain) | ||
341 | { | ||
342 | struct ieee80211_hw *hw = sc->hw; | ||
343 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
344 | struct ath_hw *ah = sc->sc_ah; | ||
345 | struct ath_common *common = ath9k_hw_common(ah); | ||
346 | struct ath_tx_control txctl; | ||
347 | int time_left; | ||
348 | |||
349 | memset(&txctl, 0, sizeof(txctl)); | ||
350 | txctl.txq = sc->tx.txq_map[WME_AC_BE]; | ||
351 | |||
352 | memset(tx_info, 0, sizeof(*tx_info)); | ||
353 | tx_info->band = hw->conf.channel->band; | ||
354 | tx_info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
355 | tx_info->control.rates[0].idx = 0; | ||
356 | tx_info->control.rates[0].count = 1; | ||
357 | tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS; | ||
358 | tx_info->control.rates[1].idx = -1; | ||
359 | |||
360 | init_completion(&sc->paprd_complete); | ||
361 | txctl.paprd = BIT(chain); | ||
362 | |||
363 | if (ath_tx_start(hw, skb, &txctl) != 0) { | ||
364 | ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n"); | ||
365 | dev_kfree_skb_any(skb); | ||
366 | return false; | ||
367 | } | ||
368 | |||
369 | time_left = wait_for_completion_timeout(&sc->paprd_complete, | ||
370 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); | ||
371 | |||
372 | if (!time_left) | ||
373 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE, | ||
374 | "Timeout waiting for paprd training on TX chain %d\n", | ||
375 | chain); | ||
376 | |||
377 | return !!time_left; | ||
378 | } | ||
379 | |||
290 | void ath_paprd_calibrate(struct work_struct *work) | 380 | void ath_paprd_calibrate(struct work_struct *work) |
291 | { | 381 | { |
292 | struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); | 382 | struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work); |
@@ -294,27 +384,23 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
294 | struct ath_hw *ah = sc->sc_ah; | 384 | struct ath_hw *ah = sc->sc_ah; |
295 | struct ieee80211_hdr *hdr; | 385 | struct ieee80211_hdr *hdr; |
296 | struct sk_buff *skb = NULL; | 386 | struct sk_buff *skb = NULL; |
297 | struct ieee80211_tx_info *tx_info; | ||
298 | int band = hw->conf.channel->band; | ||
299 | struct ieee80211_supported_band *sband = &sc->sbands[band]; | ||
300 | struct ath_tx_control txctl; | ||
301 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 387 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
302 | int qnum, ftype; | 388 | struct ath_common *common = ath9k_hw_common(ah); |
389 | int ftype; | ||
303 | int chain_ok = 0; | 390 | int chain_ok = 0; |
304 | int chain; | 391 | int chain; |
305 | int len = 1800; | 392 | int len = 1800; |
306 | int time_left; | ||
307 | int i; | ||
308 | 393 | ||
309 | if (!caldata) | 394 | if (!caldata) |
310 | return; | 395 | return; |
311 | 396 | ||
397 | if (ar9003_paprd_init_table(ah) < 0) | ||
398 | return; | ||
399 | |||
312 | skb = alloc_skb(len, GFP_KERNEL); | 400 | skb = alloc_skb(len, GFP_KERNEL); |
313 | if (!skb) | 401 | if (!skb) |
314 | return; | 402 | return; |
315 | 403 | ||
316 | tx_info = IEEE80211_SKB_CB(skb); | ||
317 | |||
318 | skb_put(skb, len); | 404 | skb_put(skb, len); |
319 | memset(skb->data, 0, len); | 405 | memset(skb->data, 0, len); |
320 | hdr = (struct ieee80211_hdr *)skb->data; | 406 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -325,40 +411,25 @@ void ath_paprd_calibrate(struct work_struct *work) | |||
325 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | 411 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); |
326 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | 412 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); |
327 | 413 | ||
328 | memset(&txctl, 0, sizeof(txctl)); | ||
329 | qnum = sc->tx.hwq_map[WME_AC_BE]; | ||
330 | txctl.txq = &sc->tx.txq[qnum]; | ||
331 | |||
332 | ath9k_ps_wakeup(sc); | 414 | ath9k_ps_wakeup(sc); |
333 | ar9003_paprd_init_table(ah); | ||
334 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | 415 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
335 | if (!(ah->caps.tx_chainmask & BIT(chain))) | 416 | if (!(common->tx_chainmask & BIT(chain))) |
336 | continue; | 417 | continue; |
337 | 418 | ||
338 | chain_ok = 0; | 419 | chain_ok = 0; |
339 | memset(tx_info, 0, sizeof(*tx_info)); | ||
340 | tx_info->band = band; | ||
341 | 420 | ||
342 | for (i = 0; i < 4; i++) { | 421 | ath_dbg(common, ATH_DBG_CALIBRATE, |
343 | tx_info->control.rates[i].idx = sband->n_bitrates - 1; | 422 | "Sending PAPRD frame for thermal measurement " |
344 | tx_info->control.rates[i].count = 6; | 423 | "on chain %d\n", chain); |
345 | } | 424 | if (!ath_paprd_send_frame(sc, skb, chain)) |
425 | goto fail_paprd; | ||
346 | 426 | ||
347 | init_completion(&sc->paprd_complete); | ||
348 | ar9003_paprd_setup_gain_table(ah, chain); | 427 | ar9003_paprd_setup_gain_table(ah, chain); |
349 | txctl.paprd = BIT(chain); | ||
350 | if (ath_tx_start(hw, skb, &txctl) != 0) | ||
351 | break; | ||
352 | 428 | ||
353 | time_left = wait_for_completion_timeout(&sc->paprd_complete, | 429 | ath_dbg(common, ATH_DBG_CALIBRATE, |
354 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT)); | 430 | "Sending PAPRD training frame on chain %d\n", chain); |
355 | if (!time_left) { | 431 | if (!ath_paprd_send_frame(sc, skb, chain)) |
356 | ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, | ||
357 | "Timeout waiting for paprd training on " | ||
358 | "TX chain %d\n", | ||
359 | chain); | ||
360 | goto fail_paprd; | 432 | goto fail_paprd; |
361 | } | ||
362 | 433 | ||
363 | if (!ar9003_paprd_is_done(ah)) | 434 | if (!ar9003_paprd_is_done(ah)) |
364 | break; | 435 | break; |
@@ -395,7 +466,13 @@ void ath_ani_calibrate(unsigned long data) | |||
395 | bool shortcal = false; | 466 | bool shortcal = false; |
396 | bool aniflag = false; | 467 | bool aniflag = false; |
397 | unsigned int timestamp = jiffies_to_msecs(jiffies); | 468 | unsigned int timestamp = jiffies_to_msecs(jiffies); |
398 | u32 cal_interval, short_cal_interval; | 469 | u32 cal_interval, short_cal_interval, long_cal_interval; |
470 | unsigned long flags; | ||
471 | |||
472 | if (ah->caldata && ah->caldata->nfcal_interference) | ||
473 | long_cal_interval = ATH_LONG_CALINTERVAL_INT; | ||
474 | else | ||
475 | long_cal_interval = ATH_LONG_CALINTERVAL; | ||
399 | 476 | ||
400 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? | 477 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? |
401 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | 478 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; |
@@ -407,9 +484,9 @@ void ath_ani_calibrate(unsigned long data) | |||
407 | ath9k_ps_wakeup(sc); | 484 | ath9k_ps_wakeup(sc); |
408 | 485 | ||
409 | /* Long calibration runs independently of short calibration. */ | 486 | /* Long calibration runs independently of short calibration. */ |
410 | if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { | 487 | if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { |
411 | longcal = true; | 488 | longcal = true; |
412 | ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); | 489 | ath_dbg(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); |
413 | common->ani.longcal_timer = timestamp; | 490 | common->ani.longcal_timer = timestamp; |
414 | } | 491 | } |
415 | 492 | ||
@@ -417,8 +494,8 @@ void ath_ani_calibrate(unsigned long data) | |||
417 | if (!common->ani.caldone) { | 494 | if (!common->ani.caldone) { |
418 | if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { | 495 | if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) { |
419 | shortcal = true; | 496 | shortcal = true; |
420 | ath_print(common, ATH_DBG_ANI, | 497 | ath_dbg(common, ATH_DBG_ANI, |
421 | "shortcal @%lu\n", jiffies); | 498 | "shortcal @%lu\n", jiffies); |
422 | common->ani.shortcal_timer = timestamp; | 499 | common->ani.shortcal_timer = timestamp; |
423 | common->ani.resetcal_timer = timestamp; | 500 | common->ani.resetcal_timer = timestamp; |
424 | } | 501 | } |
@@ -441,8 +518,12 @@ void ath_ani_calibrate(unsigned long data) | |||
441 | /* Skip all processing if there's nothing to do. */ | 518 | /* Skip all processing if there's nothing to do. */ |
442 | if (longcal || shortcal || aniflag) { | 519 | if (longcal || shortcal || aniflag) { |
443 | /* Call ANI routine if necessary */ | 520 | /* Call ANI routine if necessary */ |
444 | if (aniflag) | 521 | if (aniflag) { |
522 | spin_lock_irqsave(&common->cc_lock, flags); | ||
445 | ath9k_hw_ani_monitor(ah, ah->curchan); | 523 | ath9k_hw_ani_monitor(ah, ah->curchan); |
524 | ath_update_survey_stats(sc); | ||
525 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
526 | } | ||
446 | 527 | ||
447 | /* Perform calibration if necessary */ | 528 | /* Perform calibration if necessary */ |
448 | if (longcal || shortcal) { | 529 | if (longcal || shortcal) { |
@@ -451,16 +532,6 @@ void ath_ani_calibrate(unsigned long data) | |||
451 | ah->curchan, | 532 | ah->curchan, |
452 | common->rx_chainmask, | 533 | common->rx_chainmask, |
453 | longcal); | 534 | longcal); |
454 | |||
455 | if (longcal) | ||
456 | common->ani.noise_floor = ath9k_hw_getchan_noise(ah, | ||
457 | ah->curchan); | ||
458 | |||
459 | ath_print(common, ATH_DBG_ANI, | ||
460 | " calibrate chan %u/%x nf: %d\n", | ||
461 | ah->curchan->channel, | ||
462 | ah->curchan->channelFlags, | ||
463 | common->ani.noise_floor); | ||
464 | } | 535 | } |
465 | } | 536 | } |
466 | 537 | ||
@@ -483,49 +554,31 @@ set_timer: | |||
483 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { | 554 | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { |
484 | if (!ah->caldata->paprd_done) | 555 | if (!ah->caldata->paprd_done) |
485 | ieee80211_queue_work(sc->hw, &sc->paprd_work); | 556 | ieee80211_queue_work(sc->hw, &sc->paprd_work); |
486 | else | 557 | else if (!ah->paprd_table_write_done) |
487 | ath_paprd_activate(sc); | 558 | ath_paprd_activate(sc); |
488 | } | 559 | } |
489 | } | 560 | } |
490 | 561 | ||
491 | /* | ||
492 | * Update tx/rx chainmask. For legacy association, | ||
493 | * hard code chainmask to 1x1, for 11n association, use | ||
494 | * the chainmask configuration, for bt coexistence, use | ||
495 | * the chainmask configuration even in legacy mode. | ||
496 | */ | ||
497 | void ath_update_chainmask(struct ath_softc *sc, int is_ht) | ||
498 | { | ||
499 | struct ath_hw *ah = sc->sc_ah; | ||
500 | struct ath_common *common = ath9k_hw_common(ah); | ||
501 | |||
502 | if ((sc->sc_flags & SC_OP_OFFCHANNEL) || is_ht || | ||
503 | (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { | ||
504 | common->tx_chainmask = ah->caps.tx_chainmask; | ||
505 | common->rx_chainmask = ah->caps.rx_chainmask; | ||
506 | } else { | ||
507 | common->tx_chainmask = 1; | ||
508 | common->rx_chainmask = 1; | ||
509 | } | ||
510 | |||
511 | ath_print(common, ATH_DBG_CONFIG, | ||
512 | "tx chmask: %d, rx chmask: %d\n", | ||
513 | common->tx_chainmask, | ||
514 | common->rx_chainmask); | ||
515 | } | ||
516 | |||
517 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) | 562 | static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) |
518 | { | 563 | { |
519 | struct ath_node *an; | 564 | struct ath_node *an; |
520 | 565 | struct ath_hw *ah = sc->sc_ah; | |
521 | an = (struct ath_node *)sta->drv_priv; | 566 | an = (struct ath_node *)sta->drv_priv; |
522 | 567 | ||
568 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
569 | spin_lock(&sc->nodes_lock); | ||
570 | list_add(&an->list, &sc->nodes); | ||
571 | spin_unlock(&sc->nodes_lock); | ||
572 | an->sta = sta; | ||
573 | #endif | ||
574 | if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) | ||
575 | sc->sc_flags |= SC_OP_ENABLE_APM; | ||
576 | |||
523 | if (sc->sc_flags & SC_OP_TXAGGR) { | 577 | if (sc->sc_flags & SC_OP_TXAGGR) { |
524 | ath_tx_node_init(sc, an); | 578 | ath_tx_node_init(sc, an); |
525 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | 579 | an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + |
526 | sta->ht_cap.ampdu_factor); | 580 | sta->ht_cap.ampdu_factor); |
527 | an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); | 581 | an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); |
528 | an->last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
529 | } | 582 | } |
530 | } | 583 | } |
531 | 584 | ||
@@ -533,6 +586,13 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
533 | { | 586 | { |
534 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 587 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
535 | 588 | ||
589 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
590 | spin_lock(&sc->nodes_lock); | ||
591 | list_del(&an->list); | ||
592 | spin_unlock(&sc->nodes_lock); | ||
593 | an->sta = NULL; | ||
594 | #endif | ||
595 | |||
536 | if (sc->sc_flags & SC_OP_TXAGGR) | 596 | if (sc->sc_flags & SC_OP_TXAGGR) |
537 | ath_tx_node_cleanup(sc, an); | 597 | ath_tx_node_cleanup(sc, an); |
538 | } | 598 | } |
@@ -540,22 +600,67 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) | |||
540 | void ath_hw_check(struct work_struct *work) | 600 | void ath_hw_check(struct work_struct *work) |
541 | { | 601 | { |
542 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); | 602 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); |
543 | int i; | 603 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
604 | unsigned long flags; | ||
605 | int busy; | ||
544 | 606 | ||
545 | ath9k_ps_wakeup(sc); | 607 | ath9k_ps_wakeup(sc); |
608 | if (ath9k_hw_check_alive(sc->sc_ah)) | ||
609 | goto out; | ||
546 | 610 | ||
547 | for (i = 0; i < 3; i++) { | 611 | spin_lock_irqsave(&common->cc_lock, flags); |
548 | if (ath9k_hw_check_alive(sc->sc_ah)) | 612 | busy = ath_update_survey_stats(sc); |
549 | goto out; | 613 | spin_unlock_irqrestore(&common->cc_lock, flags); |
550 | 614 | ||
551 | msleep(1); | 615 | ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " |
552 | } | 616 | "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); |
553 | ath_reset(sc, false); | 617 | if (busy >= 99) { |
618 | if (++sc->hw_busy_count >= 3) | ||
619 | ath_reset(sc, true); | ||
620 | } else if (busy >= 0) | ||
621 | sc->hw_busy_count = 0; | ||
554 | 622 | ||
555 | out: | 623 | out: |
556 | ath9k_ps_restore(sc); | 624 | ath9k_ps_restore(sc); |
557 | } | 625 | } |
558 | 626 | ||
627 | static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) | ||
628 | { | ||
629 | static int count; | ||
630 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
631 | |||
632 | if (pll_sqsum >= 0x40000) { | ||
633 | count++; | ||
634 | if (count == 3) { | ||
635 | /* Rx is hung for more than 500ms. Reset it */ | ||
636 | ath_dbg(common, ATH_DBG_RESET, | ||
637 | "Possible RX hang, resetting"); | ||
638 | ath_reset(sc, true); | ||
639 | count = 0; | ||
640 | } | ||
641 | } else | ||
642 | count = 0; | ||
643 | } | ||
644 | |||
645 | void ath_hw_pll_work(struct work_struct *work) | ||
646 | { | ||
647 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
648 | hw_pll_work.work); | ||
649 | u32 pll_sqsum; | ||
650 | |||
651 | if (AR_SREV_9485(sc->sc_ah)) { | ||
652 | |||
653 | ath9k_ps_wakeup(sc); | ||
654 | pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); | ||
655 | ath9k_ps_restore(sc); | ||
656 | |||
657 | ath_hw_pll_rx_hang_check(sc, pll_sqsum); | ||
658 | |||
659 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); | ||
660 | } | ||
661 | } | ||
662 | |||
663 | |||
559 | void ath9k_tasklet(unsigned long data) | 664 | void ath9k_tasklet(unsigned long data) |
560 | { | 665 | { |
561 | struct ath_softc *sc = (struct ath_softc *)data; | 666 | struct ath_softc *sc = (struct ath_softc *)data; |
@@ -565,17 +670,37 @@ void ath9k_tasklet(unsigned long data) | |||
565 | u32 status = sc->intrstatus; | 670 | u32 status = sc->intrstatus; |
566 | u32 rxmask; | 671 | u32 rxmask; |
567 | 672 | ||
568 | ath9k_ps_wakeup(sc); | 673 | if ((status & ATH9K_INT_FATAL) || |
569 | 674 | (status & ATH9K_INT_BB_WATCHDOG)) { | |
570 | if (status & ATH9K_INT_FATAL) { | 675 | ath_reset(sc, true); |
571 | ath_reset(sc, false); | ||
572 | ath9k_ps_restore(sc); | ||
573 | return; | 676 | return; |
574 | } | 677 | } |
575 | 678 | ||
576 | if (!ath9k_hw_check_alive(ah)) | 679 | ath9k_ps_wakeup(sc); |
680 | spin_lock(&sc->sc_pcu_lock); | ||
681 | |||
682 | /* | ||
683 | * Only run the baseband hang check if beacons stop working in AP or | ||
684 | * IBSS mode, because it has a high false positive rate. For station | ||
685 | * mode it should not be necessary, since the upper layers will detect | ||
686 | * this through a beacon miss automatically and the following channel | ||
687 | * change will trigger a hardware reset anyway | ||
688 | */ | ||
689 | if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0 && | ||
690 | !ath9k_hw_check_alive(ah)) | ||
577 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | 691 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); |
578 | 692 | ||
693 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { | ||
694 | /* | ||
695 | * TSF sync does not look correct; remain awake to sync with | ||
696 | * the next Beacon. | ||
697 | */ | ||
698 | ath_dbg(common, ATH_DBG_PS, | ||
699 | "TSFOOR - Sync with next Beacon\n"); | ||
700 | sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC | | ||
701 | PS_TSFOOR_SYNC; | ||
702 | } | ||
703 | |||
579 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 704 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
580 | rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | | 705 | rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | |
581 | ATH9K_INT_RXORN); | 706 | ATH9K_INT_RXORN); |
@@ -583,15 +708,12 @@ void ath9k_tasklet(unsigned long data) | |||
583 | rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); | 708 | rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN); |
584 | 709 | ||
585 | if (status & rxmask) { | 710 | if (status & rxmask) { |
586 | spin_lock_bh(&sc->rx.rxflushlock); | ||
587 | |||
588 | /* Check for high priority Rx first */ | 711 | /* Check for high priority Rx first */ |
589 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && | 712 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && |
590 | (status & ATH9K_INT_RXHP)) | 713 | (status & ATH9K_INT_RXHP)) |
591 | ath_rx_tasklet(sc, 0, true); | 714 | ath_rx_tasklet(sc, 0, true); |
592 | 715 | ||
593 | ath_rx_tasklet(sc, 0, false); | 716 | ath_rx_tasklet(sc, 0, false); |
594 | spin_unlock_bh(&sc->rx.rxflushlock); | ||
595 | } | 717 | } |
596 | 718 | ||
597 | if (status & ATH9K_INT_TX) { | 719 | if (status & ATH9K_INT_TX) { |
@@ -601,22 +723,14 @@ void ath9k_tasklet(unsigned long data) | |||
601 | ath_tx_tasklet(sc); | 723 | ath_tx_tasklet(sc); |
602 | } | 724 | } |
603 | 725 | ||
604 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { | ||
605 | /* | ||
606 | * TSF sync does not look correct; remain awake to sync with | ||
607 | * the next Beacon. | ||
608 | */ | ||
609 | ath_print(common, ATH_DBG_PS, | ||
610 | "TSFOOR - Sync with next Beacon\n"); | ||
611 | sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; | ||
612 | } | ||
613 | |||
614 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 726 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
615 | if (status & ATH9K_INT_GENTIMER) | 727 | if (status & ATH9K_INT_GENTIMER) |
616 | ath_gen_timer_isr(sc->sc_ah); | 728 | ath_gen_timer_isr(sc->sc_ah); |
617 | 729 | ||
618 | /* re-enable hardware interrupt */ | 730 | /* re-enable hardware interrupt */ |
619 | ath9k_hw_set_interrupts(ah, ah->imask); | 731 | ath9k_hw_enable_interrupts(ah); |
732 | |||
733 | spin_unlock(&sc->sc_pcu_lock); | ||
620 | ath9k_ps_restore(sc); | 734 | ath9k_ps_restore(sc); |
621 | } | 735 | } |
622 | 736 | ||
@@ -624,6 +738,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
624 | { | 738 | { |
625 | #define SCHED_INTR ( \ | 739 | #define SCHED_INTR ( \ |
626 | ATH9K_INT_FATAL | \ | 740 | ATH9K_INT_FATAL | \ |
741 | ATH9K_INT_BB_WATCHDOG | \ | ||
627 | ATH9K_INT_RXORN | \ | 742 | ATH9K_INT_RXORN | \ |
628 | ATH9K_INT_RXEOL | \ | 743 | ATH9K_INT_RXEOL | \ |
629 | ATH9K_INT_RX | \ | 744 | ATH9K_INT_RX | \ |
@@ -637,6 +752,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
637 | 752 | ||
638 | struct ath_softc *sc = dev; | 753 | struct ath_softc *sc = dev; |
639 | struct ath_hw *ah = sc->sc_ah; | 754 | struct ath_hw *ah = sc->sc_ah; |
755 | struct ath_common *common = ath9k_hw_common(ah); | ||
640 | enum ath9k_int status; | 756 | enum ath9k_int status; |
641 | bool sched = false; | 757 | bool sched = false; |
642 | 758 | ||
@@ -686,7 +802,12 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
686 | 802 | ||
687 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && | 803 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && |
688 | (status & ATH9K_INT_BB_WATCHDOG)) { | 804 | (status & ATH9K_INT_BB_WATCHDOG)) { |
805 | |||
806 | spin_lock(&common->cc_lock); | ||
807 | ath_hw_cycle_counters_update(common); | ||
689 | ar9003_hw_bb_watchdog_dbg_info(ah); | 808 | ar9003_hw_bb_watchdog_dbg_info(ah); |
809 | spin_unlock(&common->cc_lock); | ||
810 | |||
690 | goto chip_reset; | 811 | goto chip_reset; |
691 | } | 812 | } |
692 | 813 | ||
@@ -709,18 +830,22 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
709 | * interrupt; otherwise it will continue to | 830 | * interrupt; otherwise it will continue to |
710 | * fire. | 831 | * fire. |
711 | */ | 832 | */ |
712 | ath9k_hw_set_interrupts(ah, 0); | 833 | ath9k_hw_disable_interrupts(ah); |
713 | /* | 834 | /* |
714 | * Let the hal handle the event. We assume | 835 | * Let the hal handle the event. We assume |
715 | * it will clear whatever condition caused | 836 | * it will clear whatever condition caused |
716 | * the interrupt. | 837 | * the interrupt. |
717 | */ | 838 | */ |
718 | ath9k_hw_procmibevent(ah); | 839 | spin_lock(&common->cc_lock); |
719 | ath9k_hw_set_interrupts(ah, ah->imask); | 840 | ath9k_hw_proc_mib_event(ah); |
841 | spin_unlock(&common->cc_lock); | ||
842 | ath9k_hw_enable_interrupts(ah); | ||
720 | } | 843 | } |
721 | 844 | ||
722 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 845 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
723 | if (status & ATH9K_INT_TIM_TIMER) { | 846 | if (status & ATH9K_INT_TIM_TIMER) { |
847 | if (ATH_DBG_WARN_ON_ONCE(sc->ps_idle)) | ||
848 | goto chip_reset; | ||
724 | /* Clear RxAbort bit so that we can | 849 | /* Clear RxAbort bit so that we can |
725 | * receive frames */ | 850 | * receive frames */ |
726 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | 851 | ath9k_setpower(sc, ATH9K_PM_AWAKE); |
@@ -733,8 +858,8 @@ chip_reset: | |||
733 | ath_debug_stat_interrupt(sc, status); | 858 | ath_debug_stat_interrupt(sc, status); |
734 | 859 | ||
735 | if (sched) { | 860 | if (sched) { |
736 | /* turn off every interrupt except SWBA */ | 861 | /* turn off every interrupt */ |
737 | ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA)); | 862 | ath9k_hw_disable_interrupts(ah); |
738 | tasklet_schedule(&sc->intr_tq); | 863 | tasklet_schedule(&sc->intr_tq); |
739 | } | 864 | } |
740 | 865 | ||
@@ -743,88 +868,6 @@ chip_reset: | |||
743 | #undef SCHED_INTR | 868 | #undef SCHED_INTR |
744 | } | 869 | } |
745 | 870 | ||
746 | static u32 ath_get_extchanmode(struct ath_softc *sc, | ||
747 | struct ieee80211_channel *chan, | ||
748 | enum nl80211_channel_type channel_type) | ||
749 | { | ||
750 | u32 chanmode = 0; | ||
751 | |||
752 | switch (chan->band) { | ||
753 | case IEEE80211_BAND_2GHZ: | ||
754 | switch(channel_type) { | ||
755 | case NL80211_CHAN_NO_HT: | ||
756 | case NL80211_CHAN_HT20: | ||
757 | chanmode = CHANNEL_G_HT20; | ||
758 | break; | ||
759 | case NL80211_CHAN_HT40PLUS: | ||
760 | chanmode = CHANNEL_G_HT40PLUS; | ||
761 | break; | ||
762 | case NL80211_CHAN_HT40MINUS: | ||
763 | chanmode = CHANNEL_G_HT40MINUS; | ||
764 | break; | ||
765 | } | ||
766 | break; | ||
767 | case IEEE80211_BAND_5GHZ: | ||
768 | switch(channel_type) { | ||
769 | case NL80211_CHAN_NO_HT: | ||
770 | case NL80211_CHAN_HT20: | ||
771 | chanmode = CHANNEL_A_HT20; | ||
772 | break; | ||
773 | case NL80211_CHAN_HT40PLUS: | ||
774 | chanmode = CHANNEL_A_HT40PLUS; | ||
775 | break; | ||
776 | case NL80211_CHAN_HT40MINUS: | ||
777 | chanmode = CHANNEL_A_HT40MINUS; | ||
778 | break; | ||
779 | } | ||
780 | break; | ||
781 | default: | ||
782 | break; | ||
783 | } | ||
784 | |||
785 | return chanmode; | ||
786 | } | ||
787 | |||
788 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | ||
789 | struct ieee80211_vif *vif, | ||
790 | struct ieee80211_bss_conf *bss_conf) | ||
791 | { | ||
792 | struct ath_hw *ah = sc->sc_ah; | ||
793 | struct ath_common *common = ath9k_hw_common(ah); | ||
794 | |||
795 | if (bss_conf->assoc) { | ||
796 | ath_print(common, ATH_DBG_CONFIG, | ||
797 | "Bss Info ASSOC %d, bssid: %pM\n", | ||
798 | bss_conf->aid, common->curbssid); | ||
799 | |||
800 | /* New association, store aid */ | ||
801 | common->curaid = bss_conf->aid; | ||
802 | ath9k_hw_write_associd(ah); | ||
803 | |||
804 | /* | ||
805 | * Request a re-configuration of Beacon related timers | ||
806 | * on the receipt of the first Beacon frame (i.e., | ||
807 | * after time sync with the AP). | ||
808 | */ | ||
809 | sc->ps_flags |= PS_BEACON_SYNC; | ||
810 | |||
811 | /* Configure the beacon */ | ||
812 | ath_beacon_config(sc, vif); | ||
813 | |||
814 | /* Reset rssi stats */ | ||
815 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | ||
816 | |||
817 | sc->sc_flags |= SC_OP_ANI_RUN; | ||
818 | ath_start_ani(common); | ||
819 | } else { | ||
820 | ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); | ||
821 | common->curaid = 0; | ||
822 | /* Stop ANI */ | ||
823 | sc->sc_flags &= ~SC_OP_ANI_RUN; | ||
824 | del_timer_sync(&common->ani.timer); | ||
825 | } | ||
826 | } | ||
827 | |||
828 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | 871 | void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) |
829 | { | 872 | { |
830 | struct ath_hw *ah = sc->sc_ah; | 873 | struct ath_hw *ah = sc->sc_ah; |
@@ -833,30 +876,28 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
833 | int r; | 876 | int r; |
834 | 877 | ||
835 | ath9k_ps_wakeup(sc); | 878 | ath9k_ps_wakeup(sc); |
879 | spin_lock_bh(&sc->sc_pcu_lock); | ||
880 | |||
836 | ath9k_hw_configpcipowersave(ah, 0, 0); | 881 | ath9k_hw_configpcipowersave(ah, 0, 0); |
837 | 882 | ||
838 | if (!ah->curchan) | 883 | if (!ah->curchan) |
839 | ah->curchan = ath_get_curchannel(sc, sc->hw); | 884 | ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah); |
840 | 885 | ||
841 | spin_lock_bh(&sc->sc_resetlock); | ||
842 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | 886 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
843 | if (r) { | 887 | if (r) { |
844 | ath_print(common, ATH_DBG_FATAL, | 888 | ath_err(common, |
845 | "Unable to reset channel (%u MHz), " | 889 | "Unable to reset channel (%u MHz), reset status %d\n", |
846 | "reset status %d\n", | 890 | channel->center_freq, r); |
847 | channel->center_freq, r); | ||
848 | } | 891 | } |
849 | spin_unlock_bh(&sc->sc_resetlock); | ||
850 | 892 | ||
851 | ath_update_txpow(sc); | 893 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
894 | sc->config.txpowlimit, &sc->curtxpow); | ||
852 | if (ath_startrecv(sc) != 0) { | 895 | if (ath_startrecv(sc) != 0) { |
853 | ath_print(common, ATH_DBG_FATAL, | 896 | ath_err(common, "Unable to restart recv logic\n"); |
854 | "Unable to restart recv logic\n"); | 897 | goto out; |
855 | return; | ||
856 | } | 898 | } |
857 | |||
858 | if (sc->sc_flags & SC_OP_BEACONS) | 899 | if (sc->sc_flags & SC_OP_BEACONS) |
859 | ath_beacon_config(sc, NULL); /* restart beacons */ | 900 | ath_set_beacon(sc); /* restart beacons */ |
860 | 901 | ||
861 | /* Re-Enable interrupts */ | 902 | /* Re-Enable interrupts */ |
862 | ath9k_hw_set_interrupts(ah, ah->imask); | 903 | ath9k_hw_set_interrupts(ah, ah->imask); |
@@ -867,6 +908,11 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
867 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | 908 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); |
868 | 909 | ||
869 | ieee80211_wake_queues(hw); | 910 | ieee80211_wake_queues(hw); |
911 | ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2); | ||
912 | |||
913 | out: | ||
914 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
915 | |||
870 | ath9k_ps_restore(sc); | 916 | ath9k_ps_restore(sc); |
871 | } | 917 | } |
872 | 918 | ||
@@ -877,6 +923,10 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
877 | int r; | 923 | int r; |
878 | 924 | ||
879 | ath9k_ps_wakeup(sc); | 925 | ath9k_ps_wakeup(sc); |
926 | cancel_delayed_work_sync(&sc->hw_pll_work); | ||
927 | |||
928 | spin_lock_bh(&sc->sc_pcu_lock); | ||
929 | |||
880 | ieee80211_stop_queues(hw); | 930 | ieee80211_stop_queues(hw); |
881 | 931 | ||
882 | /* | 932 | /* |
@@ -889,29 +939,29 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
889 | } | 939 | } |
890 | 940 | ||
891 | /* Disable interrupts */ | 941 | /* Disable interrupts */ |
892 | ath9k_hw_set_interrupts(ah, 0); | 942 | ath9k_hw_disable_interrupts(ah); |
893 | 943 | ||
894 | ath_drain_all_txq(sc, false); /* clear pending tx frames */ | 944 | ath_drain_all_txq(sc, false); /* clear pending tx frames */ |
945 | |||
895 | ath_stoprecv(sc); /* turn off frame recv */ | 946 | ath_stoprecv(sc); /* turn off frame recv */ |
896 | ath_flushrecv(sc); /* flush recv queue */ | 947 | ath_flushrecv(sc); /* flush recv queue */ |
897 | 948 | ||
898 | if (!ah->curchan) | 949 | if (!ah->curchan) |
899 | ah->curchan = ath_get_curchannel(sc, hw); | 950 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
900 | 951 | ||
901 | spin_lock_bh(&sc->sc_resetlock); | ||
902 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | 952 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
903 | if (r) { | 953 | if (r) { |
904 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 954 | ath_err(ath9k_hw_common(sc->sc_ah), |
905 | "Unable to reset channel (%u MHz), " | 955 | "Unable to reset channel (%u MHz), reset status %d\n", |
906 | "reset status %d\n", | 956 | channel->center_freq, r); |
907 | channel->center_freq, r); | ||
908 | } | 957 | } |
909 | spin_unlock_bh(&sc->sc_resetlock); | ||
910 | 958 | ||
911 | ath9k_hw_phy_disable(ah); | 959 | ath9k_hw_phy_disable(ah); |
960 | |||
912 | ath9k_hw_configpcipowersave(ah, 1, 1); | 961 | ath9k_hw_configpcipowersave(ah, 1, 1); |
962 | |||
963 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
913 | ath9k_ps_restore(sc); | 964 | ath9k_ps_restore(sc); |
914 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); | ||
915 | } | 965 | } |
916 | 966 | ||
917 | int ath_reset(struct ath_softc *sc, bool retry_tx) | 967 | int ath_reset(struct ath_softc *sc, bool retry_tx) |
@@ -921,38 +971,40 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
921 | struct ieee80211_hw *hw = sc->hw; | 971 | struct ieee80211_hw *hw = sc->hw; |
922 | int r; | 972 | int r; |
923 | 973 | ||
974 | sc->hw_busy_count = 0; | ||
975 | |||
924 | /* Stop ANI */ | 976 | /* Stop ANI */ |
925 | del_timer_sync(&common->ani.timer); | 977 | del_timer_sync(&common->ani.timer); |
926 | 978 | ||
979 | ath9k_ps_wakeup(sc); | ||
980 | spin_lock_bh(&sc->sc_pcu_lock); | ||
981 | |||
927 | ieee80211_stop_queues(hw); | 982 | ieee80211_stop_queues(hw); |
928 | 983 | ||
929 | ath9k_hw_set_interrupts(ah, 0); | 984 | ath9k_hw_disable_interrupts(ah); |
930 | ath_drain_all_txq(sc, retry_tx); | 985 | ath_drain_all_txq(sc, retry_tx); |
986 | |||
931 | ath_stoprecv(sc); | 987 | ath_stoprecv(sc); |
932 | ath_flushrecv(sc); | 988 | ath_flushrecv(sc); |
933 | 989 | ||
934 | spin_lock_bh(&sc->sc_resetlock); | ||
935 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); | 990 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); |
936 | if (r) | 991 | if (r) |
937 | ath_print(common, ATH_DBG_FATAL, | 992 | ath_err(common, |
938 | "Unable to reset hardware; reset status %d\n", r); | 993 | "Unable to reset hardware; reset status %d\n", r); |
939 | spin_unlock_bh(&sc->sc_resetlock); | ||
940 | 994 | ||
941 | if (ath_startrecv(sc) != 0) | 995 | if (ath_startrecv(sc) != 0) |
942 | ath_print(common, ATH_DBG_FATAL, | 996 | ath_err(common, "Unable to start recv logic\n"); |
943 | "Unable to start recv logic\n"); | ||
944 | 997 | ||
945 | /* | 998 | /* |
946 | * We may be doing a reset in response to a request | 999 | * We may be doing a reset in response to a request |
947 | * that changes the channel so update any state that | 1000 | * that changes the channel so update any state that |
948 | * might change as a result. | 1001 | * might change as a result. |
949 | */ | 1002 | */ |
950 | ath_cache_conf_rate(sc, &hw->conf); | 1003 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
1004 | sc->config.txpowlimit, &sc->curtxpow); | ||
951 | 1005 | ||
952 | ath_update_txpow(sc); | 1006 | if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) |
953 | 1007 | ath_set_beacon(sc); /* restart beacons */ | |
954 | if (sc->sc_flags & SC_OP_BEACONS) | ||
955 | ath_beacon_config(sc, NULL); /* restart beacons */ | ||
956 | 1008 | ||
957 | ath9k_hw_set_interrupts(ah, ah->imask); | 1009 | ath9k_hw_set_interrupts(ah, ah->imask); |
958 | 1010 | ||
@@ -968,133 +1020,40 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
968 | } | 1020 | } |
969 | 1021 | ||
970 | ieee80211_wake_queues(hw); | 1022 | ieee80211_wake_queues(hw); |
1023 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
971 | 1024 | ||
972 | /* Start ANI */ | 1025 | /* Start ANI */ |
973 | ath_start_ani(common); | 1026 | ath_start_ani(common); |
1027 | ath9k_ps_restore(sc); | ||
974 | 1028 | ||
975 | return r; | 1029 | return r; |
976 | } | 1030 | } |
977 | 1031 | ||
978 | static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) | ||
979 | { | ||
980 | int qnum; | ||
981 | |||
982 | switch (queue) { | ||
983 | case 0: | ||
984 | qnum = sc->tx.hwq_map[WME_AC_VO]; | ||
985 | break; | ||
986 | case 1: | ||
987 | qnum = sc->tx.hwq_map[WME_AC_VI]; | ||
988 | break; | ||
989 | case 2: | ||
990 | qnum = sc->tx.hwq_map[WME_AC_BE]; | ||
991 | break; | ||
992 | case 3: | ||
993 | qnum = sc->tx.hwq_map[WME_AC_BK]; | ||
994 | break; | ||
995 | default: | ||
996 | qnum = sc->tx.hwq_map[WME_AC_BE]; | ||
997 | break; | ||
998 | } | ||
999 | |||
1000 | return qnum; | ||
1001 | } | ||
1002 | |||
1003 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) | ||
1004 | { | ||
1005 | int qnum; | ||
1006 | |||
1007 | switch (queue) { | ||
1008 | case WME_AC_VO: | ||
1009 | qnum = 0; | ||
1010 | break; | ||
1011 | case WME_AC_VI: | ||
1012 | qnum = 1; | ||
1013 | break; | ||
1014 | case WME_AC_BE: | ||
1015 | qnum = 2; | ||
1016 | break; | ||
1017 | case WME_AC_BK: | ||
1018 | qnum = 3; | ||
1019 | break; | ||
1020 | default: | ||
1021 | qnum = -1; | ||
1022 | break; | ||
1023 | } | ||
1024 | |||
1025 | return qnum; | ||
1026 | } | ||
1027 | |||
1028 | /* XXX: Remove me once we don't depend on ath9k_channel for all | ||
1029 | * this redundant data */ | ||
1030 | void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, | ||
1031 | struct ath9k_channel *ichan) | ||
1032 | { | ||
1033 | struct ieee80211_channel *chan = hw->conf.channel; | ||
1034 | struct ieee80211_conf *conf = &hw->conf; | ||
1035 | |||
1036 | ichan->channel = chan->center_freq; | ||
1037 | ichan->chan = chan; | ||
1038 | |||
1039 | if (chan->band == IEEE80211_BAND_2GHZ) { | ||
1040 | ichan->chanmode = CHANNEL_G; | ||
1041 | ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; | ||
1042 | } else { | ||
1043 | ichan->chanmode = CHANNEL_A; | ||
1044 | ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; | ||
1045 | } | ||
1046 | |||
1047 | if (conf_is_ht(conf)) | ||
1048 | ichan->chanmode = ath_get_extchanmode(sc, chan, | ||
1049 | conf->channel_type); | ||
1050 | } | ||
1051 | |||
1052 | /**********************/ | 1032 | /**********************/ |
1053 | /* mac80211 callbacks */ | 1033 | /* mac80211 callbacks */ |
1054 | /**********************/ | 1034 | /**********************/ |
1055 | 1035 | ||
1056 | static int ath9k_start(struct ieee80211_hw *hw) | 1036 | static int ath9k_start(struct ieee80211_hw *hw) |
1057 | { | 1037 | { |
1058 | struct ath_wiphy *aphy = hw->priv; | 1038 | struct ath_softc *sc = hw->priv; |
1059 | struct ath_softc *sc = aphy->sc; | ||
1060 | struct ath_hw *ah = sc->sc_ah; | 1039 | struct ath_hw *ah = sc->sc_ah; |
1061 | struct ath_common *common = ath9k_hw_common(ah); | 1040 | struct ath_common *common = ath9k_hw_common(ah); |
1062 | struct ieee80211_channel *curchan = hw->conf.channel; | 1041 | struct ieee80211_channel *curchan = hw->conf.channel; |
1063 | struct ath9k_channel *init_channel; | 1042 | struct ath9k_channel *init_channel; |
1064 | int r; | 1043 | int r; |
1065 | 1044 | ||
1066 | ath_print(common, ATH_DBG_CONFIG, | 1045 | ath_dbg(common, ATH_DBG_CONFIG, |
1067 | "Starting driver with initial channel: %d MHz\n", | 1046 | "Starting driver with initial channel: %d MHz\n", |
1068 | curchan->center_freq); | 1047 | curchan->center_freq); |
1069 | 1048 | ||
1070 | mutex_lock(&sc->mutex); | 1049 | ath9k_ps_wakeup(sc); |
1071 | 1050 | ||
1072 | if (ath9k_wiphy_started(sc)) { | 1051 | mutex_lock(&sc->mutex); |
1073 | if (sc->chan_idx == curchan->hw_value) { | ||
1074 | /* | ||
1075 | * Already on the operational channel, the new wiphy | ||
1076 | * can be marked active. | ||
1077 | */ | ||
1078 | aphy->state = ATH_WIPHY_ACTIVE; | ||
1079 | ieee80211_wake_queues(hw); | ||
1080 | } else { | ||
1081 | /* | ||
1082 | * Another wiphy is on another channel, start the new | ||
1083 | * wiphy in paused state. | ||
1084 | */ | ||
1085 | aphy->state = ATH_WIPHY_PAUSED; | ||
1086 | ieee80211_stop_queues(hw); | ||
1087 | } | ||
1088 | mutex_unlock(&sc->mutex); | ||
1089 | return 0; | ||
1090 | } | ||
1091 | aphy->state = ATH_WIPHY_ACTIVE; | ||
1092 | 1052 | ||
1093 | /* setup initial channel */ | 1053 | /* setup initial channel */ |
1094 | |||
1095 | sc->chan_idx = curchan->hw_value; | 1054 | sc->chan_idx = curchan->hw_value; |
1096 | 1055 | ||
1097 | init_channel = ath_get_curchannel(sc, hw); | 1056 | init_channel = ath9k_cmn_get_curchannel(hw, ah); |
1098 | 1057 | ||
1099 | /* Reset SERDES registers */ | 1058 | /* Reset SERDES registers */ |
1100 | ath9k_hw_configpcipowersave(ah, 0, 0); | 1059 | ath9k_hw_configpcipowersave(ah, 0, 0); |
@@ -1106,23 +1065,22 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1106 | * be followed by initialization of the appropriate bits | 1065 | * be followed by initialization of the appropriate bits |
1107 | * and then setup of the interrupt mask. | 1066 | * and then setup of the interrupt mask. |
1108 | */ | 1067 | */ |
1109 | spin_lock_bh(&sc->sc_resetlock); | 1068 | spin_lock_bh(&sc->sc_pcu_lock); |
1110 | r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); | 1069 | r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
1111 | if (r) { | 1070 | if (r) { |
1112 | ath_print(common, ATH_DBG_FATAL, | 1071 | ath_err(common, |
1113 | "Unable to reset hardware; reset status %d " | 1072 | "Unable to reset hardware; reset status %d (freq %u MHz)\n", |
1114 | "(freq %u MHz)\n", r, | 1073 | r, curchan->center_freq); |
1115 | curchan->center_freq); | 1074 | spin_unlock_bh(&sc->sc_pcu_lock); |
1116 | spin_unlock_bh(&sc->sc_resetlock); | ||
1117 | goto mutex_unlock; | 1075 | goto mutex_unlock; |
1118 | } | 1076 | } |
1119 | spin_unlock_bh(&sc->sc_resetlock); | ||
1120 | 1077 | ||
1121 | /* | 1078 | /* |
1122 | * This is needed only to setup initial state | 1079 | * This is needed only to setup initial state |
1123 | * but it's best done after a reset. | 1080 | * but it's best done after a reset. |
1124 | */ | 1081 | */ |
1125 | ath_update_txpow(sc); | 1082 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
1083 | sc->config.txpowlimit, &sc->curtxpow); | ||
1126 | 1084 | ||
1127 | /* | 1085 | /* |
1128 | * Setup the hardware after reset: | 1086 | * Setup the hardware after reset: |
@@ -1132,11 +1090,12 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1132 | * here except setup the interrupt mask. | 1090 | * here except setup the interrupt mask. |
1133 | */ | 1091 | */ |
1134 | if (ath_startrecv(sc) != 0) { | 1092 | if (ath_startrecv(sc) != 0) { |
1135 | ath_print(common, ATH_DBG_FATAL, | 1093 | ath_err(common, "Unable to start recv logic\n"); |
1136 | "Unable to start recv logic\n"); | ||
1137 | r = -EIO; | 1094 | r = -EIO; |
1095 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
1138 | goto mutex_unlock; | 1096 | goto mutex_unlock; |
1139 | } | 1097 | } |
1098 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
1140 | 1099 | ||
1141 | /* Setup our intr mask. */ | 1100 | /* Setup our intr mask. */ |
1142 | ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | | 1101 | ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | |
@@ -1150,15 +1109,13 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1150 | else | 1109 | else |
1151 | ah->imask |= ATH9K_INT_RX; | 1110 | ah->imask |= ATH9K_INT_RX; |
1152 | 1111 | ||
1153 | if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT) | 1112 | ah->imask |= ATH9K_INT_GTT; |
1154 | ah->imask |= ATH9K_INT_GTT; | ||
1155 | 1113 | ||
1156 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) | 1114 | if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) |
1157 | ah->imask |= ATH9K_INT_CST; | 1115 | ah->imask |= ATH9K_INT_CST; |
1158 | 1116 | ||
1159 | ath_cache_conf_rate(sc, &hw->conf); | ||
1160 | |||
1161 | sc->sc_flags &= ~SC_OP_INVALID; | 1117 | sc->sc_flags &= ~SC_OP_INVALID; |
1118 | sc->sc_ah->is_monitoring = false; | ||
1162 | 1119 | ||
1163 | /* Disable BMISS interrupt when we're not associated */ | 1120 | /* Disable BMISS interrupt when we're not associated */ |
1164 | ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | 1121 | ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); |
@@ -1180,30 +1137,23 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1180 | ath9k_btcoex_timer_resume(sc); | 1137 | ath9k_btcoex_timer_resume(sc); |
1181 | } | 1138 | } |
1182 | 1139 | ||
1140 | if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en) | ||
1141 | common->bus_ops->extn_synch_en(common); | ||
1142 | |||
1183 | mutex_unlock: | 1143 | mutex_unlock: |
1184 | mutex_unlock(&sc->mutex); | 1144 | mutex_unlock(&sc->mutex); |
1185 | 1145 | ||
1146 | ath9k_ps_restore(sc); | ||
1147 | |||
1186 | return r; | 1148 | return r; |
1187 | } | 1149 | } |
1188 | 1150 | ||
1189 | static int ath9k_tx(struct ieee80211_hw *hw, | 1151 | static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
1190 | struct sk_buff *skb) | ||
1191 | { | 1152 | { |
1192 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1153 | struct ath_softc *sc = hw->priv; |
1193 | struct ath_wiphy *aphy = hw->priv; | ||
1194 | struct ath_softc *sc = aphy->sc; | ||
1195 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1154 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1196 | struct ath_tx_control txctl; | 1155 | struct ath_tx_control txctl; |
1197 | int padpos, padsize; | ||
1198 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1156 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1199 | int qnum; | ||
1200 | |||
1201 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { | ||
1202 | ath_print(common, ATH_DBG_XMIT, | ||
1203 | "ath9k: %s: TX in unexpected wiphy state " | ||
1204 | "%d\n", wiphy_name(hw->wiphy), aphy->state); | ||
1205 | goto exit; | ||
1206 | } | ||
1207 | 1157 | ||
1208 | if (sc->ps_enabled) { | 1158 | if (sc->ps_enabled) { |
1209 | /* | 1159 | /* |
@@ -1213,8 +1163,8 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
1213 | if (ieee80211_is_data(hdr->frame_control) && | 1163 | if (ieee80211_is_data(hdr->frame_control) && |
1214 | !ieee80211_is_nullfunc(hdr->frame_control) && | 1164 | !ieee80211_is_nullfunc(hdr->frame_control) && |
1215 | !ieee80211_has_pm(hdr->frame_control)) { | 1165 | !ieee80211_has_pm(hdr->frame_control)) { |
1216 | ath_print(common, ATH_DBG_PS, "Add PM=1 for a TX frame " | 1166 | ath_dbg(common, ATH_DBG_PS, |
1217 | "while in PS mode\n"); | 1167 | "Add PM=1 for a TX frame while in PS mode\n"); |
1218 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); | 1168 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
1219 | } | 1169 | } |
1220 | } | 1170 | } |
@@ -1229,12 +1179,12 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
1229 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 1179 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
1230 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 1180 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
1231 | if (ieee80211_is_pspoll(hdr->frame_control)) { | 1181 | if (ieee80211_is_pspoll(hdr->frame_control)) { |
1232 | ath_print(common, ATH_DBG_PS, | 1182 | ath_dbg(common, ATH_DBG_PS, |
1233 | "Sending PS-Poll to pick a buffered frame\n"); | 1183 | "Sending PS-Poll to pick a buffered frame\n"); |
1234 | sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA; | 1184 | sc->ps_flags |= PS_WAIT_FOR_PSPOLL_DATA; |
1235 | } else { | 1185 | } else { |
1236 | ath_print(common, ATH_DBG_PS, | 1186 | ath_dbg(common, ATH_DBG_PS, |
1237 | "Wake up to complete TX\n"); | 1187 | "Wake up to complete TX\n"); |
1238 | sc->ps_flags |= PS_WAIT_FOR_TX_ACK; | 1188 | sc->ps_flags |= PS_WAIT_FOR_TX_ACK; |
1239 | } | 1189 | } |
1240 | /* | 1190 | /* |
@@ -1246,85 +1196,39 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
1246 | } | 1196 | } |
1247 | 1197 | ||
1248 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | 1198 | memset(&txctl, 0, sizeof(struct ath_tx_control)); |
1199 | txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)]; | ||
1249 | 1200 | ||
1250 | /* | 1201 | ath_dbg(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); |
1251 | * As a temporary workaround, assign seq# here; this will likely need | ||
1252 | * to be cleaned up to work better with Beacon transmission and virtual | ||
1253 | * BSSes. | ||
1254 | */ | ||
1255 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
1256 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
1257 | sc->tx.seq_no += 0x10; | ||
1258 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
1259 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | ||
1260 | } | ||
1261 | |||
1262 | /* Add the padding after the header if this is not already done */ | ||
1263 | padpos = ath9k_cmn_padpos(hdr->frame_control); | ||
1264 | padsize = padpos & 3; | ||
1265 | if (padsize && skb->len>padpos) { | ||
1266 | if (skb_headroom(skb) < padsize) | ||
1267 | return -1; | ||
1268 | skb_push(skb, padsize); | ||
1269 | memmove(skb->data, skb->data + padsize, padpos); | ||
1270 | } | ||
1271 | |||
1272 | qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); | ||
1273 | txctl.txq = &sc->tx.txq[qnum]; | ||
1274 | |||
1275 | ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); | ||
1276 | 1202 | ||
1277 | if (ath_tx_start(hw, skb, &txctl) != 0) { | 1203 | if (ath_tx_start(hw, skb, &txctl) != 0) { |
1278 | ath_print(common, ATH_DBG_XMIT, "TX failed\n"); | 1204 | ath_dbg(common, ATH_DBG_XMIT, "TX failed\n"); |
1279 | goto exit; | 1205 | goto exit; |
1280 | } | 1206 | } |
1281 | 1207 | ||
1282 | return 0; | 1208 | return; |
1283 | exit: | 1209 | exit: |
1284 | dev_kfree_skb_any(skb); | 1210 | dev_kfree_skb_any(skb); |
1285 | return 0; | ||
1286 | } | 1211 | } |
1287 | 1212 | ||
1288 | static void ath9k_stop(struct ieee80211_hw *hw) | 1213 | static void ath9k_stop(struct ieee80211_hw *hw) |
1289 | { | 1214 | { |
1290 | struct ath_wiphy *aphy = hw->priv; | 1215 | struct ath_softc *sc = hw->priv; |
1291 | struct ath_softc *sc = aphy->sc; | ||
1292 | struct ath_hw *ah = sc->sc_ah; | 1216 | struct ath_hw *ah = sc->sc_ah; |
1293 | struct ath_common *common = ath9k_hw_common(ah); | 1217 | struct ath_common *common = ath9k_hw_common(ah); |
1294 | int i; | ||
1295 | 1218 | ||
1296 | mutex_lock(&sc->mutex); | 1219 | mutex_lock(&sc->mutex); |
1297 | 1220 | ||
1298 | aphy->state = ATH_WIPHY_INACTIVE; | ||
1299 | |||
1300 | if (led_blink) | ||
1301 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
1302 | |||
1303 | cancel_delayed_work_sync(&sc->tx_complete_work); | 1221 | cancel_delayed_work_sync(&sc->tx_complete_work); |
1222 | cancel_delayed_work_sync(&sc->hw_pll_work); | ||
1304 | cancel_work_sync(&sc->paprd_work); | 1223 | cancel_work_sync(&sc->paprd_work); |
1305 | cancel_work_sync(&sc->hw_check_work); | 1224 | cancel_work_sync(&sc->hw_check_work); |
1306 | 1225 | ||
1307 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
1308 | if (sc->sec_wiphy[i]) | ||
1309 | break; | ||
1310 | } | ||
1311 | |||
1312 | if (i == sc->num_sec_wiphy) { | ||
1313 | cancel_delayed_work_sync(&sc->wiphy_work); | ||
1314 | cancel_work_sync(&sc->chan_work); | ||
1315 | } | ||
1316 | |||
1317 | if (sc->sc_flags & SC_OP_INVALID) { | 1226 | if (sc->sc_flags & SC_OP_INVALID) { |
1318 | ath_print(common, ATH_DBG_ANY, "Device not present\n"); | 1227 | ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); |
1319 | mutex_unlock(&sc->mutex); | 1228 | mutex_unlock(&sc->mutex); |
1320 | return; | 1229 | return; |
1321 | } | 1230 | } |
1322 | 1231 | ||
1323 | if (ath9k_wiphy_started(sc)) { | ||
1324 | mutex_unlock(&sc->mutex); | ||
1325 | return; /* another wiphy still in use */ | ||
1326 | } | ||
1327 | |||
1328 | /* Ensure HW is awake when we try to shut it down. */ | 1232 | /* Ensure HW is awake when we try to shut it down. */ |
1329 | ath9k_ps_wakeup(sc); | 1233 | ath9k_ps_wakeup(sc); |
1330 | 1234 | ||
@@ -1334,9 +1238,14 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1334 | ath9k_btcoex_timer_pause(sc); | 1238 | ath9k_btcoex_timer_pause(sc); |
1335 | } | 1239 | } |
1336 | 1240 | ||
1241 | spin_lock_bh(&sc->sc_pcu_lock); | ||
1242 | |||
1243 | /* prevent tasklets to enable interrupts once we disable them */ | ||
1244 | ah->imask &= ~ATH9K_INT_GLOBAL; | ||
1245 | |||
1337 | /* make sure h/w will not generate any interrupt | 1246 | /* make sure h/w will not generate any interrupt |
1338 | * before setting the invalid flag. */ | 1247 | * before setting the invalid flag. */ |
1339 | ath9k_hw_set_interrupts(ah, 0); | 1248 | ath9k_hw_disable_interrupts(ah); |
1340 | 1249 | ||
1341 | if (!(sc->sc_flags & SC_OP_INVALID)) { | 1250 | if (!(sc->sc_flags & SC_OP_INVALID)) { |
1342 | ath_drain_all_txq(sc, false); | 1251 | ath_drain_all_txq(sc, false); |
@@ -1345,153 +1254,325 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1345 | } else | 1254 | } else |
1346 | sc->rx.rxlink = NULL; | 1255 | sc->rx.rxlink = NULL; |
1347 | 1256 | ||
1257 | if (sc->rx.frag) { | ||
1258 | dev_kfree_skb_any(sc->rx.frag); | ||
1259 | sc->rx.frag = NULL; | ||
1260 | } | ||
1261 | |||
1348 | /* disable HAL and put h/w to sleep */ | 1262 | /* disable HAL and put h/w to sleep */ |
1349 | ath9k_hw_disable(ah); | 1263 | ath9k_hw_disable(ah); |
1350 | ath9k_hw_configpcipowersave(ah, 1, 1); | 1264 | ath9k_hw_configpcipowersave(ah, 1, 1); |
1265 | |||
1266 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
1267 | |||
1268 | /* we can now sync irq and kill any running tasklets, since we already | ||
1269 | * disabled interrupts and not holding a spin lock */ | ||
1270 | synchronize_irq(sc->irq); | ||
1271 | tasklet_kill(&sc->intr_tq); | ||
1272 | tasklet_kill(&sc->bcon_tasklet); | ||
1273 | |||
1351 | ath9k_ps_restore(sc); | 1274 | ath9k_ps_restore(sc); |
1352 | 1275 | ||
1353 | /* Finally, put the chip in FULL SLEEP mode */ | 1276 | sc->ps_idle = true; |
1354 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); | 1277 | ath_radio_disable(sc, hw); |
1355 | 1278 | ||
1356 | sc->sc_flags |= SC_OP_INVALID; | 1279 | sc->sc_flags |= SC_OP_INVALID; |
1357 | 1280 | ||
1358 | mutex_unlock(&sc->mutex); | 1281 | mutex_unlock(&sc->mutex); |
1359 | 1282 | ||
1360 | ath_print(common, ATH_DBG_CONFIG, "Driver halt\n"); | 1283 | ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); |
1361 | } | 1284 | } |
1362 | 1285 | ||
1363 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 1286 | bool ath9k_uses_beacons(int type) |
1364 | struct ieee80211_vif *vif) | 1287 | { |
1288 | switch (type) { | ||
1289 | case NL80211_IFTYPE_AP: | ||
1290 | case NL80211_IFTYPE_ADHOC: | ||
1291 | case NL80211_IFTYPE_MESH_POINT: | ||
1292 | return true; | ||
1293 | default: | ||
1294 | return false; | ||
1295 | } | ||
1296 | } | ||
1297 | |||
1298 | static void ath9k_reclaim_beacon(struct ath_softc *sc, | ||
1299 | struct ieee80211_vif *vif) | ||
1365 | { | 1300 | { |
1366 | struct ath_wiphy *aphy = hw->priv; | ||
1367 | struct ath_softc *sc = aphy->sc; | ||
1368 | struct ath_hw *ah = sc->sc_ah; | ||
1369 | struct ath_common *common = ath9k_hw_common(ah); | ||
1370 | struct ath_vif *avp = (void *)vif->drv_priv; | 1301 | struct ath_vif *avp = (void *)vif->drv_priv; |
1371 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; | ||
1372 | int ret = 0; | ||
1373 | 1302 | ||
1374 | mutex_lock(&sc->mutex); | 1303 | ath9k_set_beaconing_status(sc, false); |
1304 | ath_beacon_return(sc, avp); | ||
1305 | ath9k_set_beaconing_status(sc, true); | ||
1306 | sc->sc_flags &= ~SC_OP_BEACONS; | ||
1307 | } | ||
1375 | 1308 | ||
1376 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && | 1309 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) |
1377 | sc->nvifs > 0) { | 1310 | { |
1378 | ret = -ENOBUFS; | 1311 | struct ath9k_vif_iter_data *iter_data = data; |
1379 | goto out; | 1312 | int i; |
1380 | } | 1313 | |
1314 | if (iter_data->hw_macaddr) | ||
1315 | for (i = 0; i < ETH_ALEN; i++) | ||
1316 | iter_data->mask[i] &= | ||
1317 | ~(iter_data->hw_macaddr[i] ^ mac[i]); | ||
1381 | 1318 | ||
1382 | switch (vif->type) { | 1319 | switch (vif->type) { |
1320 | case NL80211_IFTYPE_AP: | ||
1321 | iter_data->naps++; | ||
1322 | break; | ||
1383 | case NL80211_IFTYPE_STATION: | 1323 | case NL80211_IFTYPE_STATION: |
1384 | ic_opmode = NL80211_IFTYPE_STATION; | 1324 | iter_data->nstations++; |
1385 | break; | 1325 | break; |
1386 | case NL80211_IFTYPE_ADHOC: | 1326 | case NL80211_IFTYPE_ADHOC: |
1387 | case NL80211_IFTYPE_AP: | 1327 | iter_data->nadhocs++; |
1328 | break; | ||
1388 | case NL80211_IFTYPE_MESH_POINT: | 1329 | case NL80211_IFTYPE_MESH_POINT: |
1389 | if (sc->nbcnvifs >= ATH_BCBUF) { | 1330 | iter_data->nmeshes++; |
1390 | ret = -ENOBUFS; | 1331 | break; |
1391 | goto out; | 1332 | case NL80211_IFTYPE_WDS: |
1392 | } | 1333 | iter_data->nwds++; |
1393 | ic_opmode = vif->type; | ||
1394 | break; | 1334 | break; |
1395 | default: | 1335 | default: |
1396 | ath_print(common, ATH_DBG_FATAL, | 1336 | iter_data->nothers++; |
1397 | "Interface type %d not yet supported\n", vif->type); | 1337 | break; |
1398 | ret = -EOPNOTSUPP; | ||
1399 | goto out; | ||
1400 | } | 1338 | } |
1339 | } | ||
1401 | 1340 | ||
1402 | ath_print(common, ATH_DBG_CONFIG, | 1341 | /* Called with sc->mutex held. */ |
1403 | "Attach a VIF of type: %d\n", ic_opmode); | 1342 | void ath9k_calculate_iter_data(struct ieee80211_hw *hw, |
1343 | struct ieee80211_vif *vif, | ||
1344 | struct ath9k_vif_iter_data *iter_data) | ||
1345 | { | ||
1346 | struct ath_softc *sc = hw->priv; | ||
1347 | struct ath_hw *ah = sc->sc_ah; | ||
1348 | struct ath_common *common = ath9k_hw_common(ah); | ||
1349 | |||
1350 | /* | ||
1351 | * Use the hardware MAC address as reference, the hardware uses it | ||
1352 | * together with the BSSID mask when matching addresses. | ||
1353 | */ | ||
1354 | memset(iter_data, 0, sizeof(*iter_data)); | ||
1355 | iter_data->hw_macaddr = common->macaddr; | ||
1356 | memset(&iter_data->mask, 0xff, ETH_ALEN); | ||
1404 | 1357 | ||
1405 | /* Set the VIF opmode */ | 1358 | if (vif) |
1406 | avp->av_opmode = ic_opmode; | 1359 | ath9k_vif_iter(iter_data, vif->addr, vif); |
1407 | avp->av_bslot = -1; | ||
1408 | 1360 | ||
1409 | sc->nvifs++; | 1361 | /* Get list of all active MAC addresses */ |
1362 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, | ||
1363 | iter_data); | ||
1364 | } | ||
1365 | |||
1366 | /* Called with sc->mutex held. */ | ||
1367 | static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | ||
1368 | struct ieee80211_vif *vif) | ||
1369 | { | ||
1370 | struct ath_softc *sc = hw->priv; | ||
1371 | struct ath_hw *ah = sc->sc_ah; | ||
1372 | struct ath_common *common = ath9k_hw_common(ah); | ||
1373 | struct ath9k_vif_iter_data iter_data; | ||
1410 | 1374 | ||
1411 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 1375 | ath9k_calculate_iter_data(hw, vif, &iter_data); |
1412 | ath9k_set_bssid_mask(hw); | ||
1413 | 1376 | ||
1414 | if (sc->nvifs > 1) | 1377 | /* Set BSSID mask. */ |
1415 | goto out; /* skip global settings for secondary vif */ | 1378 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); |
1379 | ath_hw_setbssidmask(common); | ||
1416 | 1380 | ||
1417 | if (ic_opmode == NL80211_IFTYPE_AP) { | 1381 | /* Set op-mode & TSF */ |
1382 | if (iter_data.naps > 0) { | ||
1418 | ath9k_hw_set_tsfadjust(ah, 1); | 1383 | ath9k_hw_set_tsfadjust(ah, 1); |
1419 | sc->sc_flags |= SC_OP_TSF_RESET; | 1384 | sc->sc_flags |= SC_OP_TSF_RESET; |
1385 | ah->opmode = NL80211_IFTYPE_AP; | ||
1386 | } else { | ||
1387 | ath9k_hw_set_tsfadjust(ah, 0); | ||
1388 | sc->sc_flags &= ~SC_OP_TSF_RESET; | ||
1389 | |||
1390 | if (iter_data.nmeshes) | ||
1391 | ah->opmode = NL80211_IFTYPE_MESH_POINT; | ||
1392 | else if (iter_data.nwds) | ||
1393 | ah->opmode = NL80211_IFTYPE_AP; | ||
1394 | else if (iter_data.nadhocs) | ||
1395 | ah->opmode = NL80211_IFTYPE_ADHOC; | ||
1396 | else | ||
1397 | ah->opmode = NL80211_IFTYPE_STATION; | ||
1420 | } | 1398 | } |
1421 | 1399 | ||
1422 | /* Set the device opmode */ | ||
1423 | ah->opmode = ic_opmode; | ||
1424 | |||
1425 | /* | 1400 | /* |
1426 | * Enable MIB interrupts when there are hardware phy counters. | 1401 | * Enable MIB interrupts when there are hardware phy counters. |
1427 | * Note we only do this (at the moment) for station mode. | ||
1428 | */ | 1402 | */ |
1429 | if ((vif->type == NL80211_IFTYPE_STATION) || | 1403 | if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) { |
1430 | (vif->type == NL80211_IFTYPE_ADHOC) || | ||
1431 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { | ||
1432 | if (ah->config.enable_ani) | 1404 | if (ah->config.enable_ani) |
1433 | ah->imask |= ATH9K_INT_MIB; | 1405 | ah->imask |= ATH9K_INT_MIB; |
1434 | ah->imask |= ATH9K_INT_TSFOOR; | 1406 | ah->imask |= ATH9K_INT_TSFOOR; |
1407 | } else { | ||
1408 | ah->imask &= ~ATH9K_INT_MIB; | ||
1409 | ah->imask &= ~ATH9K_INT_TSFOOR; | ||
1435 | } | 1410 | } |
1436 | 1411 | ||
1437 | ath9k_hw_set_interrupts(ah, ah->imask); | 1412 | ath9k_hw_set_interrupts(ah, ah->imask); |
1438 | 1413 | ||
1439 | if (vif->type == NL80211_IFTYPE_AP || | 1414 | /* Set up ANI */ |
1440 | vif->type == NL80211_IFTYPE_ADHOC || | 1415 | if ((iter_data.naps + iter_data.nadhocs) > 0) { |
1441 | vif->type == NL80211_IFTYPE_MONITOR) { | 1416 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; |
1442 | sc->sc_flags |= SC_OP_ANI_RUN; | 1417 | sc->sc_flags |= SC_OP_ANI_RUN; |
1443 | ath_start_ani(common); | 1418 | ath_start_ani(common); |
1419 | } else { | ||
1420 | sc->sc_flags &= ~SC_OP_ANI_RUN; | ||
1421 | del_timer_sync(&common->ani.timer); | ||
1444 | } | 1422 | } |
1423 | } | ||
1424 | |||
1425 | /* Called with sc->mutex held, vif counts set up properly. */ | ||
1426 | static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw, | ||
1427 | struct ieee80211_vif *vif) | ||
1428 | { | ||
1429 | struct ath_softc *sc = hw->priv; | ||
1430 | |||
1431 | ath9k_calculate_summary_state(hw, vif); | ||
1432 | |||
1433 | if (ath9k_uses_beacons(vif->type)) { | ||
1434 | int error; | ||
1435 | /* This may fail because upper levels do not have beacons | ||
1436 | * properly configured yet. That's OK, we assume it | ||
1437 | * will be properly configured and then we will be notified | ||
1438 | * in the info_changed method and set up beacons properly | ||
1439 | * there. | ||
1440 | */ | ||
1441 | ath9k_set_beaconing_status(sc, false); | ||
1442 | error = ath_beacon_alloc(sc, vif); | ||
1443 | if (!error) | ||
1444 | ath_beacon_config(sc, vif); | ||
1445 | ath9k_set_beaconing_status(sc, true); | ||
1446 | } | ||
1447 | } | ||
1445 | 1448 | ||
1449 | |||
1450 | static int ath9k_add_interface(struct ieee80211_hw *hw, | ||
1451 | struct ieee80211_vif *vif) | ||
1452 | { | ||
1453 | struct ath_softc *sc = hw->priv; | ||
1454 | struct ath_hw *ah = sc->sc_ah; | ||
1455 | struct ath_common *common = ath9k_hw_common(ah); | ||
1456 | int ret = 0; | ||
1457 | |||
1458 | ath9k_ps_wakeup(sc); | ||
1459 | mutex_lock(&sc->mutex); | ||
1460 | |||
1461 | switch (vif->type) { | ||
1462 | case NL80211_IFTYPE_STATION: | ||
1463 | case NL80211_IFTYPE_WDS: | ||
1464 | case NL80211_IFTYPE_ADHOC: | ||
1465 | case NL80211_IFTYPE_AP: | ||
1466 | case NL80211_IFTYPE_MESH_POINT: | ||
1467 | break; | ||
1468 | default: | ||
1469 | ath_err(common, "Interface type %d not yet supported\n", | ||
1470 | vif->type); | ||
1471 | ret = -EOPNOTSUPP; | ||
1472 | goto out; | ||
1473 | } | ||
1474 | |||
1475 | if (ath9k_uses_beacons(vif->type)) { | ||
1476 | if (sc->nbcnvifs >= ATH_BCBUF) { | ||
1477 | ath_err(common, "Not enough beacon buffers when adding" | ||
1478 | " new interface of type: %i\n", | ||
1479 | vif->type); | ||
1480 | ret = -ENOBUFS; | ||
1481 | goto out; | ||
1482 | } | ||
1483 | } | ||
1484 | |||
1485 | if ((ah->opmode == NL80211_IFTYPE_ADHOC) || | ||
1486 | ((vif->type == NL80211_IFTYPE_ADHOC) && | ||
1487 | sc->nvifs > 0)) { | ||
1488 | ath_err(common, "Cannot create ADHOC interface when other" | ||
1489 | " interfaces already exist.\n"); | ||
1490 | ret = -EINVAL; | ||
1491 | goto out; | ||
1492 | } | ||
1493 | |||
1494 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1495 | "Attach a VIF of type: %d\n", vif->type); | ||
1496 | |||
1497 | sc->nvifs++; | ||
1498 | |||
1499 | ath9k_do_vif_add_setup(hw, vif); | ||
1446 | out: | 1500 | out: |
1447 | mutex_unlock(&sc->mutex); | 1501 | mutex_unlock(&sc->mutex); |
1502 | ath9k_ps_restore(sc); | ||
1448 | return ret; | 1503 | return ret; |
1449 | } | 1504 | } |
1450 | 1505 | ||
1451 | static void ath9k_remove_interface(struct ieee80211_hw *hw, | 1506 | static int ath9k_change_interface(struct ieee80211_hw *hw, |
1452 | struct ieee80211_vif *vif) | 1507 | struct ieee80211_vif *vif, |
1508 | enum nl80211_iftype new_type, | ||
1509 | bool p2p) | ||
1453 | { | 1510 | { |
1454 | struct ath_wiphy *aphy = hw->priv; | 1511 | struct ath_softc *sc = hw->priv; |
1455 | struct ath_softc *sc = aphy->sc; | ||
1456 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1512 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1457 | struct ath_vif *avp = (void *)vif->drv_priv; | 1513 | int ret = 0; |
1458 | int i; | ||
1459 | |||
1460 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); | ||
1461 | 1514 | ||
1515 | ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n"); | ||
1462 | mutex_lock(&sc->mutex); | 1516 | mutex_lock(&sc->mutex); |
1517 | ath9k_ps_wakeup(sc); | ||
1463 | 1518 | ||
1464 | /* Stop ANI */ | 1519 | /* See if new interface type is valid. */ |
1465 | sc->sc_flags &= ~SC_OP_ANI_RUN; | 1520 | if ((new_type == NL80211_IFTYPE_ADHOC) && |
1466 | del_timer_sync(&common->ani.timer); | 1521 | (sc->nvifs > 1)) { |
1467 | 1522 | ath_err(common, "When using ADHOC, it must be the only" | |
1468 | /* Reclaim beacon resources */ | 1523 | " interface.\n"); |
1469 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || | 1524 | ret = -EINVAL; |
1470 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || | 1525 | goto out; |
1471 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { | ||
1472 | ath9k_ps_wakeup(sc); | ||
1473 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | ||
1474 | ath9k_ps_restore(sc); | ||
1475 | } | 1526 | } |
1476 | 1527 | ||
1477 | ath_beacon_return(sc, avp); | 1528 | if (ath9k_uses_beacons(new_type) && |
1478 | sc->sc_flags &= ~SC_OP_BEACONS; | 1529 | !ath9k_uses_beacons(vif->type)) { |
1479 | 1530 | if (sc->nbcnvifs >= ATH_BCBUF) { | |
1480 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | 1531 | ath_err(common, "No beacon slot available\n"); |
1481 | if (sc->beacon.bslot[i] == vif) { | 1532 | ret = -ENOBUFS; |
1482 | printk(KERN_DEBUG "%s: vif had allocated beacon " | 1533 | goto out; |
1483 | "slot\n", __func__); | ||
1484 | sc->beacon.bslot[i] = NULL; | ||
1485 | sc->beacon.bslot_aphy[i] = NULL; | ||
1486 | } | 1534 | } |
1487 | } | 1535 | } |
1488 | 1536 | ||
1537 | /* Clean up old vif stuff */ | ||
1538 | if (ath9k_uses_beacons(vif->type)) | ||
1539 | ath9k_reclaim_beacon(sc, vif); | ||
1540 | |||
1541 | /* Add new settings */ | ||
1542 | vif->type = new_type; | ||
1543 | vif->p2p = p2p; | ||
1544 | |||
1545 | ath9k_do_vif_add_setup(hw, vif); | ||
1546 | out: | ||
1547 | ath9k_ps_restore(sc); | ||
1548 | mutex_unlock(&sc->mutex); | ||
1549 | return ret; | ||
1550 | } | ||
1551 | |||
1552 | static void ath9k_remove_interface(struct ieee80211_hw *hw, | ||
1553 | struct ieee80211_vif *vif) | ||
1554 | { | ||
1555 | struct ath_softc *sc = hw->priv; | ||
1556 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1557 | |||
1558 | ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); | ||
1559 | |||
1560 | ath9k_ps_wakeup(sc); | ||
1561 | mutex_lock(&sc->mutex); | ||
1562 | |||
1489 | sc->nvifs--; | 1563 | sc->nvifs--; |
1490 | 1564 | ||
1565 | /* Reclaim beacon resources */ | ||
1566 | if (ath9k_uses_beacons(vif->type)) | ||
1567 | ath9k_reclaim_beacon(sc, vif); | ||
1568 | |||
1569 | ath9k_calculate_summary_state(hw, NULL); | ||
1570 | |||
1491 | mutex_unlock(&sc->mutex); | 1571 | mutex_unlock(&sc->mutex); |
1572 | ath9k_ps_restore(sc); | ||
1492 | } | 1573 | } |
1493 | 1574 | ||
1494 | void ath9k_enable_ps(struct ath_softc *sc) | 1575 | static void ath9k_enable_ps(struct ath_softc *sc) |
1495 | { | 1576 | { |
1496 | struct ath_hw *ah = sc->sc_ah; | 1577 | struct ath_hw *ah = sc->sc_ah; |
1497 | 1578 | ||
@@ -1505,14 +1586,33 @@ void ath9k_enable_ps(struct ath_softc *sc) | |||
1505 | } | 1586 | } |
1506 | } | 1587 | } |
1507 | 1588 | ||
1589 | static void ath9k_disable_ps(struct ath_softc *sc) | ||
1590 | { | ||
1591 | struct ath_hw *ah = sc->sc_ah; | ||
1592 | |||
1593 | sc->ps_enabled = false; | ||
1594 | ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); | ||
1595 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { | ||
1596 | ath9k_hw_setrxabort(ah, 0); | ||
1597 | sc->ps_flags &= ~(PS_WAIT_FOR_BEACON | | ||
1598 | PS_WAIT_FOR_CAB | | ||
1599 | PS_WAIT_FOR_PSPOLL_DATA | | ||
1600 | PS_WAIT_FOR_TX_ACK); | ||
1601 | if (ah->imask & ATH9K_INT_TIM_TIMER) { | ||
1602 | ah->imask &= ~ATH9K_INT_TIM_TIMER; | ||
1603 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
1604 | } | ||
1605 | } | ||
1606 | |||
1607 | } | ||
1608 | |||
1508 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 1609 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
1509 | { | 1610 | { |
1510 | struct ath_wiphy *aphy = hw->priv; | 1611 | struct ath_softc *sc = hw->priv; |
1511 | struct ath_softc *sc = aphy->sc; | ||
1512 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1513 | struct ieee80211_conf *conf = &hw->conf; | ||
1514 | struct ath_hw *ah = sc->sc_ah; | 1612 | struct ath_hw *ah = sc->sc_ah; |
1515 | bool disable_radio; | 1613 | struct ath_common *common = ath9k_hw_common(ah); |
1614 | struct ieee80211_conf *conf = &hw->conf; | ||
1615 | bool disable_radio = false; | ||
1516 | 1616 | ||
1517 | mutex_lock(&sc->mutex); | 1617 | mutex_lock(&sc->mutex); |
1518 | 1618 | ||
@@ -1523,29 +1623,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1523 | * the end. | 1623 | * the end. |
1524 | */ | 1624 | */ |
1525 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { | 1625 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1526 | bool enable_radio; | 1626 | sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
1527 | bool all_wiphys_idle; | 1627 | if (!sc->ps_idle) { |
1528 | bool idle = !!(conf->flags & IEEE80211_CONF_IDLE); | ||
1529 | |||
1530 | spin_lock_bh(&sc->wiphy_lock); | ||
1531 | all_wiphys_idle = ath9k_all_wiphys_idle(sc); | ||
1532 | ath9k_set_wiphy_idle(aphy, idle); | ||
1533 | |||
1534 | enable_radio = (!idle && all_wiphys_idle); | ||
1535 | |||
1536 | /* | ||
1537 | * After we unlock here its possible another wiphy | ||
1538 | * can be re-renabled so to account for that we will | ||
1539 | * only disable the radio toward the end of this routine | ||
1540 | * if by then all wiphys are still idle. | ||
1541 | */ | ||
1542 | spin_unlock_bh(&sc->wiphy_lock); | ||
1543 | |||
1544 | if (enable_radio) { | ||
1545 | sc->ps_idle = false; | ||
1546 | ath_radio_enable(sc, hw); | 1628 | ath_radio_enable(sc, hw); |
1547 | ath_print(common, ATH_DBG_CONFIG, | 1629 | ath_dbg(common, ATH_DBG_CONFIG, |
1548 | "not-idle: enabling radio\n"); | 1630 | "not-idle: enabling radio\n"); |
1631 | } else { | ||
1632 | disable_radio = true; | ||
1549 | } | 1633 | } |
1550 | } | 1634 | } |
1551 | 1635 | ||
@@ -1556,96 +1640,100 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1556 | * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode. | 1640 | * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode. |
1557 | */ | 1641 | */ |
1558 | if (changed & IEEE80211_CONF_CHANGE_PS) { | 1642 | if (changed & IEEE80211_CONF_CHANGE_PS) { |
1559 | if (conf->flags & IEEE80211_CONF_PS) { | 1643 | unsigned long flags; |
1560 | sc->ps_flags |= PS_ENABLED; | 1644 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
1561 | /* | 1645 | if (conf->flags & IEEE80211_CONF_PS) |
1562 | * At this point we know hardware has received an ACK | 1646 | ath9k_enable_ps(sc); |
1563 | * of a previously sent null data frame. | 1647 | else |
1564 | */ | 1648 | ath9k_disable_ps(sc); |
1565 | if ((sc->ps_flags & PS_NULLFUNC_COMPLETED)) { | 1649 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
1566 | sc->ps_flags &= ~PS_NULLFUNC_COMPLETED; | ||
1567 | ath9k_enable_ps(sc); | ||
1568 | } | ||
1569 | } else { | ||
1570 | sc->ps_enabled = false; | ||
1571 | sc->ps_flags &= ~(PS_ENABLED | | ||
1572 | PS_NULLFUNC_COMPLETED); | ||
1573 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | ||
1574 | if (!(ah->caps.hw_caps & | ||
1575 | ATH9K_HW_CAP_AUTOSLEEP)) { | ||
1576 | ath9k_hw_setrxabort(sc->sc_ah, 0); | ||
1577 | sc->ps_flags &= ~(PS_WAIT_FOR_BEACON | | ||
1578 | PS_WAIT_FOR_CAB | | ||
1579 | PS_WAIT_FOR_PSPOLL_DATA | | ||
1580 | PS_WAIT_FOR_TX_ACK); | ||
1581 | if (ah->imask & ATH9K_INT_TIM_TIMER) { | ||
1582 | ah->imask &= ~ATH9K_INT_TIM_TIMER; | ||
1583 | ath9k_hw_set_interrupts(sc->sc_ah, | ||
1584 | ah->imask); | ||
1585 | } | ||
1586 | } | ||
1587 | } | ||
1588 | } | 1650 | } |
1589 | 1651 | ||
1590 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | 1652 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { |
1591 | if (conf->flags & IEEE80211_CONF_MONITOR) { | 1653 | if (conf->flags & IEEE80211_CONF_MONITOR) { |
1592 | ath_print(common, ATH_DBG_CONFIG, | 1654 | ath_dbg(common, ATH_DBG_CONFIG, |
1593 | "HW opmode set to Monitor mode\n"); | 1655 | "Monitor mode is enabled\n"); |
1594 | sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; | 1656 | sc->sc_ah->is_monitoring = true; |
1657 | } else { | ||
1658 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1659 | "Monitor mode is disabled\n"); | ||
1660 | sc->sc_ah->is_monitoring = false; | ||
1595 | } | 1661 | } |
1596 | } | 1662 | } |
1597 | 1663 | ||
1598 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1664 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
1599 | struct ieee80211_channel *curchan = hw->conf.channel; | 1665 | struct ieee80211_channel *curchan = hw->conf.channel; |
1600 | int pos = curchan->hw_value; | 1666 | int pos = curchan->hw_value; |
1667 | int old_pos = -1; | ||
1668 | unsigned long flags; | ||
1669 | |||
1670 | if (ah->curchan) | ||
1671 | old_pos = ah->curchan - &ah->channels[0]; | ||
1601 | 1672 | ||
1602 | aphy->chan_idx = pos; | ||
1603 | aphy->chan_is_ht = conf_is_ht(conf); | ||
1604 | if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) | 1673 | if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) |
1605 | sc->sc_flags |= SC_OP_OFFCHANNEL; | 1674 | sc->sc_flags |= SC_OP_OFFCHANNEL; |
1606 | else | 1675 | else |
1607 | sc->sc_flags &= ~SC_OP_OFFCHANNEL; | 1676 | sc->sc_flags &= ~SC_OP_OFFCHANNEL; |
1608 | 1677 | ||
1609 | if (aphy->state == ATH_WIPHY_SCAN || | 1678 | ath_dbg(common, ATH_DBG_CONFIG, |
1610 | aphy->state == ATH_WIPHY_ACTIVE) | 1679 | "Set channel: %d MHz type: %d\n", |
1611 | ath9k_wiphy_pause_all_forced(sc, aphy); | 1680 | curchan->center_freq, conf->channel_type); |
1612 | else { | ||
1613 | /* | ||
1614 | * Do not change operational channel based on a paused | ||
1615 | * wiphy changes. | ||
1616 | */ | ||
1617 | goto skip_chan_change; | ||
1618 | } | ||
1619 | 1681 | ||
1620 | ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", | 1682 | ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], |
1621 | curchan->center_freq); | 1683 | curchan, conf->channel_type); |
1622 | 1684 | ||
1623 | /* XXX: remove me eventualy */ | 1685 | /* update survey stats for the old channel before switching */ |
1624 | ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); | 1686 | spin_lock_irqsave(&common->cc_lock, flags); |
1687 | ath_update_survey_stats(sc); | ||
1688 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
1625 | 1689 | ||
1626 | ath_update_chainmask(sc, conf_is_ht(conf)); | 1690 | /* |
1691 | * If the operating channel changes, change the survey in-use flags | ||
1692 | * along with it. | ||
1693 | * Reset the survey data for the new channel, unless we're switching | ||
1694 | * back to the operating channel from an off-channel operation. | ||
1695 | */ | ||
1696 | if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && | ||
1697 | sc->cur_survey != &sc->survey[pos]) { | ||
1698 | |||
1699 | if (sc->cur_survey) | ||
1700 | sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; | ||
1701 | |||
1702 | sc->cur_survey = &sc->survey[pos]; | ||
1703 | |||
1704 | memset(sc->cur_survey, 0, sizeof(struct survey_info)); | ||
1705 | sc->cur_survey->filled |= SURVEY_INFO_IN_USE; | ||
1706 | } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { | ||
1707 | memset(&sc->survey[pos], 0, sizeof(struct survey_info)); | ||
1708 | } | ||
1627 | 1709 | ||
1628 | if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { | 1710 | if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { |
1629 | ath_print(common, ATH_DBG_FATAL, | 1711 | ath_err(common, "Unable to set channel\n"); |
1630 | "Unable to set channel\n"); | ||
1631 | mutex_unlock(&sc->mutex); | 1712 | mutex_unlock(&sc->mutex); |
1632 | return -EINVAL; | 1713 | return -EINVAL; |
1633 | } | 1714 | } |
1715 | |||
1716 | /* | ||
1717 | * The most recent snapshot of channel->noisefloor for the old | ||
1718 | * channel is only available after the hardware reset. Copy it to | ||
1719 | * the survey stats now. | ||
1720 | */ | ||
1721 | if (old_pos >= 0) | ||
1722 | ath_update_survey_nf(sc, old_pos); | ||
1634 | } | 1723 | } |
1635 | 1724 | ||
1636 | skip_chan_change: | ||
1637 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1725 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
1726 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1727 | "Set power: %d\n", conf->power_level); | ||
1638 | sc->config.txpowlimit = 2 * conf->power_level; | 1728 | sc->config.txpowlimit = 2 * conf->power_level; |
1639 | ath_update_txpow(sc); | 1729 | ath9k_ps_wakeup(sc); |
1730 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | ||
1731 | sc->config.txpowlimit, &sc->curtxpow); | ||
1732 | ath9k_ps_restore(sc); | ||
1640 | } | 1733 | } |
1641 | 1734 | ||
1642 | spin_lock_bh(&sc->wiphy_lock); | ||
1643 | disable_radio = ath9k_all_wiphys_idle(sc); | ||
1644 | spin_unlock_bh(&sc->wiphy_lock); | ||
1645 | |||
1646 | if (disable_radio) { | 1735 | if (disable_radio) { |
1647 | ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); | 1736 | ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n"); |
1648 | sc->ps_idle = true; | ||
1649 | ath_radio_disable(sc, hw); | 1737 | ath_radio_disable(sc, hw); |
1650 | } | 1738 | } |
1651 | 1739 | ||
@@ -1661,6 +1749,7 @@ skip_chan_change: | |||
1661 | FIF_PSPOLL | \ | 1749 | FIF_PSPOLL | \ |
1662 | FIF_OTHER_BSS | \ | 1750 | FIF_OTHER_BSS | \ |
1663 | FIF_BCN_PRBRESP_PROMISC | \ | 1751 | FIF_BCN_PRBRESP_PROMISC | \ |
1752 | FIF_PROBE_REQ | \ | ||
1664 | FIF_FCSFAIL) | 1753 | FIF_FCSFAIL) |
1665 | 1754 | ||
1666 | /* FIXME: sc->sc_full_reset ? */ | 1755 | /* FIXME: sc->sc_full_reset ? */ |
@@ -1669,8 +1758,7 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, | |||
1669 | unsigned int *total_flags, | 1758 | unsigned int *total_flags, |
1670 | u64 multicast) | 1759 | u64 multicast) |
1671 | { | 1760 | { |
1672 | struct ath_wiphy *aphy = hw->priv; | 1761 | struct ath_softc *sc = hw->priv; |
1673 | struct ath_softc *sc = aphy->sc; | ||
1674 | u32 rfilt; | 1762 | u32 rfilt; |
1675 | 1763 | ||
1676 | changed_flags &= SUPPORTED_FILTERS; | 1764 | changed_flags &= SUPPORTED_FILTERS; |
@@ -1682,46 +1770,92 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw, | |||
1682 | ath9k_hw_setrxfilter(sc->sc_ah, rfilt); | 1770 | ath9k_hw_setrxfilter(sc->sc_ah, rfilt); |
1683 | ath9k_ps_restore(sc); | 1771 | ath9k_ps_restore(sc); |
1684 | 1772 | ||
1685 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, | 1773 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, |
1686 | "Set HW RX filter: 0x%x\n", rfilt); | 1774 | "Set HW RX filter: 0x%x\n", rfilt); |
1687 | } | 1775 | } |
1688 | 1776 | ||
1689 | static int ath9k_sta_add(struct ieee80211_hw *hw, | 1777 | static int ath9k_sta_add(struct ieee80211_hw *hw, |
1690 | struct ieee80211_vif *vif, | 1778 | struct ieee80211_vif *vif, |
1691 | struct ieee80211_sta *sta) | 1779 | struct ieee80211_sta *sta) |
1692 | { | 1780 | { |
1693 | struct ath_wiphy *aphy = hw->priv; | 1781 | struct ath_softc *sc = hw->priv; |
1694 | struct ath_softc *sc = aphy->sc; | 1782 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1783 | struct ath_node *an = (struct ath_node *) sta->drv_priv; | ||
1784 | struct ieee80211_key_conf ps_key = { }; | ||
1695 | 1785 | ||
1696 | ath_node_attach(sc, sta); | 1786 | ath_node_attach(sc, sta); |
1697 | 1787 | ||
1788 | if (vif->type != NL80211_IFTYPE_AP && | ||
1789 | vif->type != NL80211_IFTYPE_AP_VLAN) | ||
1790 | return 0; | ||
1791 | |||
1792 | an->ps_key = ath_key_config(common, vif, sta, &ps_key); | ||
1793 | |||
1698 | return 0; | 1794 | return 0; |
1699 | } | 1795 | } |
1700 | 1796 | ||
1797 | static void ath9k_del_ps_key(struct ath_softc *sc, | ||
1798 | struct ieee80211_vif *vif, | ||
1799 | struct ieee80211_sta *sta) | ||
1800 | { | ||
1801 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1802 | struct ath_node *an = (struct ath_node *) sta->drv_priv; | ||
1803 | struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key }; | ||
1804 | |||
1805 | if (!an->ps_key) | ||
1806 | return; | ||
1807 | |||
1808 | ath_key_delete(common, &ps_key); | ||
1809 | } | ||
1810 | |||
1701 | static int ath9k_sta_remove(struct ieee80211_hw *hw, | 1811 | static int ath9k_sta_remove(struct ieee80211_hw *hw, |
1702 | struct ieee80211_vif *vif, | 1812 | struct ieee80211_vif *vif, |
1703 | struct ieee80211_sta *sta) | 1813 | struct ieee80211_sta *sta) |
1704 | { | 1814 | { |
1705 | struct ath_wiphy *aphy = hw->priv; | 1815 | struct ath_softc *sc = hw->priv; |
1706 | struct ath_softc *sc = aphy->sc; | ||
1707 | 1816 | ||
1817 | ath9k_del_ps_key(sc, vif, sta); | ||
1708 | ath_node_detach(sc, sta); | 1818 | ath_node_detach(sc, sta); |
1709 | 1819 | ||
1710 | return 0; | 1820 | return 0; |
1711 | } | 1821 | } |
1712 | 1822 | ||
1823 | static void ath9k_sta_notify(struct ieee80211_hw *hw, | ||
1824 | struct ieee80211_vif *vif, | ||
1825 | enum sta_notify_cmd cmd, | ||
1826 | struct ieee80211_sta *sta) | ||
1827 | { | ||
1828 | struct ath_softc *sc = hw->priv; | ||
1829 | struct ath_node *an = (struct ath_node *) sta->drv_priv; | ||
1830 | |||
1831 | switch (cmd) { | ||
1832 | case STA_NOTIFY_SLEEP: | ||
1833 | an->sleeping = true; | ||
1834 | if (ath_tx_aggr_sleep(sc, an)) | ||
1835 | ieee80211_sta_set_tim(sta); | ||
1836 | break; | ||
1837 | case STA_NOTIFY_AWAKE: | ||
1838 | an->sleeping = false; | ||
1839 | ath_tx_aggr_wakeup(sc, an); | ||
1840 | break; | ||
1841 | } | ||
1842 | } | ||
1843 | |||
1713 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 1844 | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
1714 | const struct ieee80211_tx_queue_params *params) | 1845 | const struct ieee80211_tx_queue_params *params) |
1715 | { | 1846 | { |
1716 | struct ath_wiphy *aphy = hw->priv; | 1847 | struct ath_softc *sc = hw->priv; |
1717 | struct ath_softc *sc = aphy->sc; | ||
1718 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1848 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1849 | struct ath_txq *txq; | ||
1719 | struct ath9k_tx_queue_info qi; | 1850 | struct ath9k_tx_queue_info qi; |
1720 | int ret = 0, qnum; | 1851 | int ret = 0; |
1721 | 1852 | ||
1722 | if (queue >= WME_NUM_AC) | 1853 | if (queue >= WME_NUM_AC) |
1723 | return 0; | 1854 | return 0; |
1724 | 1855 | ||
1856 | txq = sc->tx.txq_map[queue]; | ||
1857 | |||
1858 | ath9k_ps_wakeup(sc); | ||
1725 | mutex_lock(&sc->mutex); | 1859 | mutex_lock(&sc->mutex); |
1726 | 1860 | ||
1727 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); | 1861 | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); |
@@ -1730,23 +1864,22 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1730 | qi.tqi_cwmin = params->cw_min; | 1864 | qi.tqi_cwmin = params->cw_min; |
1731 | qi.tqi_cwmax = params->cw_max; | 1865 | qi.tqi_cwmax = params->cw_max; |
1732 | qi.tqi_burstTime = params->txop; | 1866 | qi.tqi_burstTime = params->txop; |
1733 | qnum = ath_get_hal_qnum(queue, sc); | ||
1734 | 1867 | ||
1735 | ath_print(common, ATH_DBG_CONFIG, | 1868 | ath_dbg(common, ATH_DBG_CONFIG, |
1736 | "Configure tx [queue/halq] [%d/%d], " | 1869 | "Configure tx [queue/halq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", |
1737 | "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", | 1870 | queue, txq->axq_qnum, params->aifs, params->cw_min, |
1738 | queue, qnum, params->aifs, params->cw_min, | 1871 | params->cw_max, params->txop); |
1739 | params->cw_max, params->txop); | ||
1740 | 1872 | ||
1741 | ret = ath_txq_update(sc, qnum, &qi); | 1873 | ret = ath_txq_update(sc, txq->axq_qnum, &qi); |
1742 | if (ret) | 1874 | if (ret) |
1743 | ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); | 1875 | ath_err(common, "TXQ Update failed\n"); |
1744 | 1876 | ||
1745 | if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) | 1877 | if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) |
1746 | if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret) | 1878 | if (queue == WME_AC_BE && !ret) |
1747 | ath_beaconq_config(sc); | 1879 | ath_beaconq_config(sc); |
1748 | 1880 | ||
1749 | mutex_unlock(&sc->mutex); | 1881 | mutex_unlock(&sc->mutex); |
1882 | ath9k_ps_restore(sc); | ||
1750 | 1883 | ||
1751 | return ret; | 1884 | return ret; |
1752 | } | 1885 | } |
@@ -1757,34 +1890,51 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1757 | struct ieee80211_sta *sta, | 1890 | struct ieee80211_sta *sta, |
1758 | struct ieee80211_key_conf *key) | 1891 | struct ieee80211_key_conf *key) |
1759 | { | 1892 | { |
1760 | struct ath_wiphy *aphy = hw->priv; | 1893 | struct ath_softc *sc = hw->priv; |
1761 | struct ath_softc *sc = aphy->sc; | ||
1762 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1894 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1763 | int ret = 0; | 1895 | int ret = 0; |
1764 | 1896 | ||
1765 | if (modparam_nohwcrypt) | 1897 | if (ath9k_modparam_nohwcrypt) |
1766 | return -ENOSPC; | 1898 | return -ENOSPC; |
1767 | 1899 | ||
1900 | if (vif->type == NL80211_IFTYPE_ADHOC && | ||
1901 | (key->cipher == WLAN_CIPHER_SUITE_TKIP || | ||
1902 | key->cipher == WLAN_CIPHER_SUITE_CCMP) && | ||
1903 | !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { | ||
1904 | /* | ||
1905 | * For now, disable hw crypto for the RSN IBSS group keys. This | ||
1906 | * could be optimized in the future to use a modified key cache | ||
1907 | * design to support per-STA RX GTK, but until that gets | ||
1908 | * implemented, use of software crypto for group addressed | ||
1909 | * frames is a acceptable to allow RSN IBSS to be used. | ||
1910 | */ | ||
1911 | return -EOPNOTSUPP; | ||
1912 | } | ||
1913 | |||
1768 | mutex_lock(&sc->mutex); | 1914 | mutex_lock(&sc->mutex); |
1769 | ath9k_ps_wakeup(sc); | 1915 | ath9k_ps_wakeup(sc); |
1770 | ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); | 1916 | ath_dbg(common, ATH_DBG_CONFIG, "Set HW Key\n"); |
1771 | 1917 | ||
1772 | switch (cmd) { | 1918 | switch (cmd) { |
1773 | case SET_KEY: | 1919 | case SET_KEY: |
1774 | ret = ath9k_cmn_key_config(common, vif, sta, key); | 1920 | if (sta) |
1921 | ath9k_del_ps_key(sc, vif, sta); | ||
1922 | |||
1923 | ret = ath_key_config(common, vif, sta, key); | ||
1775 | if (ret >= 0) { | 1924 | if (ret >= 0) { |
1776 | key->hw_key_idx = ret; | 1925 | key->hw_key_idx = ret; |
1777 | /* push IV and Michael MIC generation to stack */ | 1926 | /* push IV and Michael MIC generation to stack */ |
1778 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1927 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1779 | if (key->alg == ALG_TKIP) | 1928 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
1780 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1929 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1781 | if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP) | 1930 | if (sc->sc_ah->sw_mgmt_crypto && |
1931 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | ||
1782 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | 1932 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; |
1783 | ret = 0; | 1933 | ret = 0; |
1784 | } | 1934 | } |
1785 | break; | 1935 | break; |
1786 | case DISABLE_KEY: | 1936 | case DISABLE_KEY: |
1787 | ath9k_cmn_key_delete(common, key); | 1937 | ath_key_delete(common, key); |
1788 | break; | 1938 | break; |
1789 | default: | 1939 | default: |
1790 | ret = -EINVAL; | 1940 | ret = -EINVAL; |
@@ -1795,51 +1945,123 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1795 | 1945 | ||
1796 | return ret; | 1946 | return ret; |
1797 | } | 1947 | } |
1948 | static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
1949 | { | ||
1950 | struct ath_softc *sc = data; | ||
1951 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1952 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
1953 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
1954 | |||
1955 | switch (sc->sc_ah->opmode) { | ||
1956 | case NL80211_IFTYPE_ADHOC: | ||
1957 | /* There can be only one vif available */ | ||
1958 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1959 | common->curaid = bss_conf->aid; | ||
1960 | ath9k_hw_write_associd(sc->sc_ah); | ||
1961 | /* configure beacon */ | ||
1962 | if (bss_conf->enable_beacon) | ||
1963 | ath_beacon_config(sc, vif); | ||
1964 | break; | ||
1965 | case NL80211_IFTYPE_STATION: | ||
1966 | /* | ||
1967 | * Skip iteration if primary station vif's bss info | ||
1968 | * was not changed | ||
1969 | */ | ||
1970 | if (sc->sc_flags & SC_OP_PRIM_STA_VIF) | ||
1971 | break; | ||
1972 | |||
1973 | if (bss_conf->assoc) { | ||
1974 | sc->sc_flags |= SC_OP_PRIM_STA_VIF; | ||
1975 | avp->primary_sta_vif = true; | ||
1976 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1977 | common->curaid = bss_conf->aid; | ||
1978 | ath9k_hw_write_associd(sc->sc_ah); | ||
1979 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1980 | "Bss Info ASSOC %d, bssid: %pM\n", | ||
1981 | bss_conf->aid, common->curbssid); | ||
1982 | ath_beacon_config(sc, vif); | ||
1983 | /* | ||
1984 | * Request a re-configuration of Beacon related timers | ||
1985 | * on the receipt of the first Beacon frame (i.e., | ||
1986 | * after time sync with the AP). | ||
1987 | */ | ||
1988 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | ||
1989 | /* Reset rssi stats */ | ||
1990 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
1991 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | ||
1992 | |||
1993 | sc->sc_flags |= SC_OP_ANI_RUN; | ||
1994 | ath_start_ani(common); | ||
1995 | } | ||
1996 | break; | ||
1997 | default: | ||
1998 | break; | ||
1999 | } | ||
2000 | } | ||
2001 | |||
2002 | static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif) | ||
2003 | { | ||
2004 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2005 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
2006 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
2007 | |||
2008 | /* Reconfigure bss info */ | ||
2009 | if (avp->primary_sta_vif && !bss_conf->assoc) { | ||
2010 | ath_dbg(common, ATH_DBG_CONFIG, | ||
2011 | "Bss Info DISASSOC %d, bssid %pM\n", | ||
2012 | common->curaid, common->curbssid); | ||
2013 | sc->sc_flags &= ~(SC_OP_PRIM_STA_VIF | SC_OP_BEACONS); | ||
2014 | avp->primary_sta_vif = false; | ||
2015 | memset(common->curbssid, 0, ETH_ALEN); | ||
2016 | common->curaid = 0; | ||
2017 | } | ||
2018 | |||
2019 | ieee80211_iterate_active_interfaces_atomic( | ||
2020 | sc->hw, ath9k_bss_iter, sc); | ||
2021 | |||
2022 | /* | ||
2023 | * None of station vifs are associated. | ||
2024 | * Clear bssid & aid | ||
2025 | */ | ||
2026 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && | ||
2027 | !(sc->sc_flags & SC_OP_PRIM_STA_VIF)) { | ||
2028 | ath9k_hw_write_associd(sc->sc_ah); | ||
2029 | /* Stop ANI */ | ||
2030 | sc->sc_flags &= ~SC_OP_ANI_RUN; | ||
2031 | del_timer_sync(&common->ani.timer); | ||
2032 | } | ||
2033 | } | ||
1798 | 2034 | ||
1799 | static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | 2035 | static void ath9k_bss_info_changed(struct ieee80211_hw *hw, |
1800 | struct ieee80211_vif *vif, | 2036 | struct ieee80211_vif *vif, |
1801 | struct ieee80211_bss_conf *bss_conf, | 2037 | struct ieee80211_bss_conf *bss_conf, |
1802 | u32 changed) | 2038 | u32 changed) |
1803 | { | 2039 | { |
1804 | struct ath_wiphy *aphy = hw->priv; | 2040 | struct ath_softc *sc = hw->priv; |
1805 | struct ath_softc *sc = aphy->sc; | ||
1806 | struct ath_hw *ah = sc->sc_ah; | 2041 | struct ath_hw *ah = sc->sc_ah; |
1807 | struct ath_common *common = ath9k_hw_common(ah); | 2042 | struct ath_common *common = ath9k_hw_common(ah); |
1808 | struct ath_vif *avp = (void *)vif->drv_priv; | 2043 | struct ath_vif *avp = (void *)vif->drv_priv; |
1809 | int slottime; | 2044 | int slottime; |
1810 | int error; | 2045 | int error; |
1811 | 2046 | ||
2047 | ath9k_ps_wakeup(sc); | ||
1812 | mutex_lock(&sc->mutex); | 2048 | mutex_lock(&sc->mutex); |
1813 | 2049 | ||
1814 | if (changed & BSS_CHANGED_BSSID) { | 2050 | if (changed & BSS_CHANGED_BSSID) { |
1815 | /* Set BSSID */ | 2051 | ath9k_config_bss(sc, vif); |
1816 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
1817 | memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); | ||
1818 | common->curaid = 0; | ||
1819 | ath9k_hw_write_associd(ah); | ||
1820 | |||
1821 | /* Set aggregation protection mode parameters */ | ||
1822 | sc->config.ath_aggr_prot = 0; | ||
1823 | 2052 | ||
1824 | /* Only legacy IBSS for now */ | 2053 | ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", |
1825 | if (vif->type == NL80211_IFTYPE_ADHOC) | 2054 | common->curbssid, common->curaid); |
1826 | ath_update_chainmask(sc, 0); | ||
1827 | |||
1828 | ath_print(common, ATH_DBG_CONFIG, | ||
1829 | "BSSID: %pM aid: 0x%x\n", | ||
1830 | common->curbssid, common->curaid); | ||
1831 | |||
1832 | /* need to reconfigure the beacon */ | ||
1833 | sc->sc_flags &= ~SC_OP_BEACONS ; | ||
1834 | } | 2055 | } |
1835 | 2056 | ||
1836 | /* Enable transmission of beacons (AP, IBSS, MESH) */ | 2057 | /* Enable transmission of beacons (AP, IBSS, MESH) */ |
1837 | if ((changed & BSS_CHANGED_BEACON) || | 2058 | if ((changed & BSS_CHANGED_BEACON) || |
1838 | ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) { | 2059 | ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) { |
1839 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 2060 | ath9k_set_beaconing_status(sc, false); |
1840 | error = ath_beacon_alloc(aphy, vif); | 2061 | error = ath_beacon_alloc(sc, vif); |
1841 | if (!error) | 2062 | if (!error) |
1842 | ath_beacon_config(sc, vif); | 2063 | ath_beacon_config(sc, vif); |
2064 | ath9k_set_beaconing_status(sc, true); | ||
1843 | } | 2065 | } |
1844 | 2066 | ||
1845 | if (changed & BSS_CHANGED_ERP_SLOT) { | 2067 | if (changed & BSS_CHANGED_ERP_SLOT) { |
@@ -1862,29 +2084,32 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1862 | } | 2084 | } |
1863 | 2085 | ||
1864 | /* Disable transmission of beacons */ | 2086 | /* Disable transmission of beacons */ |
1865 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) | 2087 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && |
1866 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 2088 | !bss_conf->enable_beacon) { |
2089 | ath9k_set_beaconing_status(sc, false); | ||
2090 | avp->is_bslot_active = false; | ||
2091 | ath9k_set_beaconing_status(sc, true); | ||
2092 | } | ||
1867 | 2093 | ||
1868 | if (changed & BSS_CHANGED_BEACON_INT) { | 2094 | if (changed & BSS_CHANGED_BEACON_INT) { |
1869 | sc->beacon_interval = bss_conf->beacon_int; | ||
1870 | /* | 2095 | /* |
1871 | * In case of AP mode, the HW TSF has to be reset | 2096 | * In case of AP mode, the HW TSF has to be reset |
1872 | * when the beacon interval changes. | 2097 | * when the beacon interval changes. |
1873 | */ | 2098 | */ |
1874 | if (vif->type == NL80211_IFTYPE_AP) { | 2099 | if (vif->type == NL80211_IFTYPE_AP) { |
1875 | sc->sc_flags |= SC_OP_TSF_RESET; | 2100 | sc->sc_flags |= SC_OP_TSF_RESET; |
1876 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 2101 | ath9k_set_beaconing_status(sc, false); |
1877 | error = ath_beacon_alloc(aphy, vif); | 2102 | error = ath_beacon_alloc(sc, vif); |
1878 | if (!error) | 2103 | if (!error) |
1879 | ath_beacon_config(sc, vif); | 2104 | ath_beacon_config(sc, vif); |
1880 | } else { | 2105 | ath9k_set_beaconing_status(sc, true); |
2106 | } else | ||
1881 | ath_beacon_config(sc, vif); | 2107 | ath_beacon_config(sc, vif); |
1882 | } | ||
1883 | } | 2108 | } |
1884 | 2109 | ||
1885 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 2110 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
1886 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", | 2111 | ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", |
1887 | bss_conf->use_short_preamble); | 2112 | bss_conf->use_short_preamble); |
1888 | if (bss_conf->use_short_preamble) | 2113 | if (bss_conf->use_short_preamble) |
1889 | sc->sc_flags |= SC_OP_PREAMBLE_SHORT; | 2114 | sc->sc_flags |= SC_OP_PREAMBLE_SHORT; |
1890 | else | 2115 | else |
@@ -1892,8 +2117,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1892 | } | 2117 | } |
1893 | 2118 | ||
1894 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 2119 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
1895 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", | 2120 | ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", |
1896 | bss_conf->use_cts_prot); | 2121 | bss_conf->use_cts_prot); |
1897 | if (bss_conf->use_cts_prot && | 2122 | if (bss_conf->use_cts_prot && |
1898 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) | 2123 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) |
1899 | sc->sc_flags |= SC_OP_PROTECT_ENABLE; | 2124 | sc->sc_flags |= SC_OP_PROTECT_ENABLE; |
@@ -1901,23 +2126,19 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1901 | sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; | 2126 | sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; |
1902 | } | 2127 | } |
1903 | 2128 | ||
1904 | if (changed & BSS_CHANGED_ASSOC) { | ||
1905 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", | ||
1906 | bss_conf->assoc); | ||
1907 | ath9k_bss_assoc_info(sc, vif, bss_conf); | ||
1908 | } | ||
1909 | |||
1910 | mutex_unlock(&sc->mutex); | 2129 | mutex_unlock(&sc->mutex); |
2130 | ath9k_ps_restore(sc); | ||
1911 | } | 2131 | } |
1912 | 2132 | ||
1913 | static u64 ath9k_get_tsf(struct ieee80211_hw *hw) | 2133 | static u64 ath9k_get_tsf(struct ieee80211_hw *hw) |
1914 | { | 2134 | { |
2135 | struct ath_softc *sc = hw->priv; | ||
1915 | u64 tsf; | 2136 | u64 tsf; |
1916 | struct ath_wiphy *aphy = hw->priv; | ||
1917 | struct ath_softc *sc = aphy->sc; | ||
1918 | 2137 | ||
1919 | mutex_lock(&sc->mutex); | 2138 | mutex_lock(&sc->mutex); |
2139 | ath9k_ps_wakeup(sc); | ||
1920 | tsf = ath9k_hw_gettsf64(sc->sc_ah); | 2140 | tsf = ath9k_hw_gettsf64(sc->sc_ah); |
2141 | ath9k_ps_restore(sc); | ||
1921 | mutex_unlock(&sc->mutex); | 2142 | mutex_unlock(&sc->mutex); |
1922 | 2143 | ||
1923 | return tsf; | 2144 | return tsf; |
@@ -1925,18 +2146,18 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw) | |||
1925 | 2146 | ||
1926 | static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | 2147 | static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) |
1927 | { | 2148 | { |
1928 | struct ath_wiphy *aphy = hw->priv; | 2149 | struct ath_softc *sc = hw->priv; |
1929 | struct ath_softc *sc = aphy->sc; | ||
1930 | 2150 | ||
1931 | mutex_lock(&sc->mutex); | 2151 | mutex_lock(&sc->mutex); |
2152 | ath9k_ps_wakeup(sc); | ||
1932 | ath9k_hw_settsf64(sc->sc_ah, tsf); | 2153 | ath9k_hw_settsf64(sc->sc_ah, tsf); |
2154 | ath9k_ps_restore(sc); | ||
1933 | mutex_unlock(&sc->mutex); | 2155 | mutex_unlock(&sc->mutex); |
1934 | } | 2156 | } |
1935 | 2157 | ||
1936 | static void ath9k_reset_tsf(struct ieee80211_hw *hw) | 2158 | static void ath9k_reset_tsf(struct ieee80211_hw *hw) |
1937 | { | 2159 | { |
1938 | struct ath_wiphy *aphy = hw->priv; | 2160 | struct ath_softc *sc = hw->priv; |
1939 | struct ath_softc *sc = aphy->sc; | ||
1940 | 2161 | ||
1941 | mutex_lock(&sc->mutex); | 2162 | mutex_lock(&sc->mutex); |
1942 | 2163 | ||
@@ -1951,10 +2172,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1951 | struct ieee80211_vif *vif, | 2172 | struct ieee80211_vif *vif, |
1952 | enum ieee80211_ampdu_mlme_action action, | 2173 | enum ieee80211_ampdu_mlme_action action, |
1953 | struct ieee80211_sta *sta, | 2174 | struct ieee80211_sta *sta, |
1954 | u16 tid, u16 *ssn) | 2175 | u16 tid, u16 *ssn, u8 buf_size) |
1955 | { | 2176 | { |
1956 | struct ath_wiphy *aphy = hw->priv; | 2177 | struct ath_softc *sc = hw->priv; |
1957 | struct ath_softc *sc = aphy->sc; | ||
1958 | int ret = 0; | 2178 | int ret = 0; |
1959 | 2179 | ||
1960 | local_bh_disable(); | 2180 | local_bh_disable(); |
@@ -1967,9 +2187,13 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1967 | case IEEE80211_AMPDU_RX_STOP: | 2187 | case IEEE80211_AMPDU_RX_STOP: |
1968 | break; | 2188 | break; |
1969 | case IEEE80211_AMPDU_TX_START: | 2189 | case IEEE80211_AMPDU_TX_START: |
2190 | if (!(sc->sc_flags & SC_OP_TXAGGR)) | ||
2191 | return -EOPNOTSUPP; | ||
2192 | |||
1970 | ath9k_ps_wakeup(sc); | 2193 | ath9k_ps_wakeup(sc); |
1971 | ath_tx_aggr_start(sc, sta, tid, ssn); | 2194 | ret = ath_tx_aggr_start(sc, sta, tid, ssn); |
1972 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 2195 | if (!ret) |
2196 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
1973 | ath9k_ps_restore(sc); | 2197 | ath9k_ps_restore(sc); |
1974 | break; | 2198 | break; |
1975 | case IEEE80211_AMPDU_TX_STOP: | 2199 | case IEEE80211_AMPDU_TX_STOP: |
@@ -1984,8 +2208,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1984 | ath9k_ps_restore(sc); | 2208 | ath9k_ps_restore(sc); |
1985 | break; | 2209 | break; |
1986 | default: | 2210 | default: |
1987 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 2211 | ath_err(ath9k_hw_common(sc->sc_ah), "Unknown AMPDU action\n"); |
1988 | "Unknown AMPDU action\n"); | ||
1989 | } | 2212 | } |
1990 | 2213 | ||
1991 | local_bh_enable(); | 2214 | local_bh_enable(); |
@@ -1996,71 +2219,158 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1996 | static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, | 2219 | static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, |
1997 | struct survey_info *survey) | 2220 | struct survey_info *survey) |
1998 | { | 2221 | { |
1999 | struct ath_wiphy *aphy = hw->priv; | 2222 | struct ath_softc *sc = hw->priv; |
2000 | struct ath_softc *sc = aphy->sc; | 2223 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2001 | struct ath_hw *ah = sc->sc_ah; | 2224 | struct ieee80211_supported_band *sband; |
2002 | struct ath_common *common = ath9k_hw_common(ah); | 2225 | struct ieee80211_channel *chan; |
2003 | struct ieee80211_conf *conf = &hw->conf; | 2226 | unsigned long flags; |
2227 | int pos; | ||
2004 | 2228 | ||
2005 | if (idx != 0) | 2229 | spin_lock_irqsave(&common->cc_lock, flags); |
2230 | if (idx == 0) | ||
2231 | ath_update_survey_stats(sc); | ||
2232 | |||
2233 | sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
2234 | if (sband && idx >= sband->n_channels) { | ||
2235 | idx -= sband->n_channels; | ||
2236 | sband = NULL; | ||
2237 | } | ||
2238 | |||
2239 | if (!sband) | ||
2240 | sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ]; | ||
2241 | |||
2242 | if (!sband || idx >= sband->n_channels) { | ||
2243 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
2006 | return -ENOENT; | 2244 | return -ENOENT; |
2245 | } | ||
2007 | 2246 | ||
2008 | survey->channel = conf->channel; | 2247 | chan = &sband->channels[idx]; |
2009 | survey->filled = SURVEY_INFO_NOISE_DBM; | 2248 | pos = chan->hw_value; |
2010 | survey->noise = common->ani.noise_floor; | 2249 | memcpy(survey, &sc->survey[pos], sizeof(*survey)); |
2250 | survey->channel = chan; | ||
2251 | spin_unlock_irqrestore(&common->cc_lock, flags); | ||
2011 | 2252 | ||
2012 | return 0; | 2253 | return 0; |
2013 | } | 2254 | } |
2014 | 2255 | ||
2015 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | 2256 | static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) |
2016 | { | 2257 | { |
2017 | struct ath_wiphy *aphy = hw->priv; | 2258 | struct ath_softc *sc = hw->priv; |
2018 | struct ath_softc *sc = aphy->sc; | 2259 | struct ath_hw *ah = sc->sc_ah; |
2019 | 2260 | ||
2020 | mutex_lock(&sc->mutex); | 2261 | mutex_lock(&sc->mutex); |
2021 | if (ath9k_wiphy_scanning(sc)) { | 2262 | ah->coverage_class = coverage_class; |
2022 | /* | 2263 | ath9k_hw_init_global_settings(ah); |
2023 | * There is a race here in mac80211 but fixing it requires | 2264 | mutex_unlock(&sc->mutex); |
2024 | * we revisit how we handle the scan complete callback. | 2265 | } |
2025 | * After mac80211 fixes we will not have configured hardware | 2266 | |
2026 | * to the home channel nor would we have configured the RX | 2267 | static void ath9k_flush(struct ieee80211_hw *hw, bool drop) |
2027 | * filter yet. | 2268 | { |
2028 | */ | 2269 | struct ath_softc *sc = hw->priv; |
2270 | struct ath_hw *ah = sc->sc_ah; | ||
2271 | struct ath_common *common = ath9k_hw_common(ah); | ||
2272 | int timeout = 200; /* ms */ | ||
2273 | int i, j; | ||
2274 | bool drain_txq; | ||
2275 | |||
2276 | mutex_lock(&sc->mutex); | ||
2277 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
2278 | |||
2279 | if (sc->sc_flags & SC_OP_INVALID) { | ||
2280 | ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); | ||
2029 | mutex_unlock(&sc->mutex); | 2281 | mutex_unlock(&sc->mutex); |
2030 | return; | 2282 | return; |
2031 | } | 2283 | } |
2032 | 2284 | ||
2033 | aphy->state = ATH_WIPHY_SCAN; | 2285 | if (drop) |
2034 | ath9k_wiphy_pause_all_forced(sc, aphy); | 2286 | timeout = 1; |
2035 | sc->sc_flags |= SC_OP_SCANNING; | 2287 | |
2288 | for (j = 0; j < timeout; j++) { | ||
2289 | bool npend = false; | ||
2290 | |||
2291 | if (j) | ||
2292 | usleep_range(1000, 2000); | ||
2293 | |||
2294 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
2295 | if (!ATH_TXQ_SETUP(sc, i)) | ||
2296 | continue; | ||
2297 | |||
2298 | npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); | ||
2299 | |||
2300 | if (npend) | ||
2301 | break; | ||
2302 | } | ||
2303 | |||
2304 | if (!npend) | ||
2305 | goto out; | ||
2306 | } | ||
2307 | |||
2308 | ath9k_ps_wakeup(sc); | ||
2309 | spin_lock_bh(&sc->sc_pcu_lock); | ||
2310 | drain_txq = ath_drain_all_txq(sc, false); | ||
2311 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
2312 | if (!drain_txq) | ||
2313 | ath_reset(sc, false); | ||
2314 | ath9k_ps_restore(sc); | ||
2315 | ieee80211_wake_queues(hw); | ||
2316 | |||
2317 | out: | ||
2318 | ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); | ||
2036 | mutex_unlock(&sc->mutex); | 2319 | mutex_unlock(&sc->mutex); |
2037 | } | 2320 | } |
2038 | 2321 | ||
2039 | /* | 2322 | static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) |
2040 | * XXX: this requires a revisit after the driver | ||
2041 | * scan_complete gets moved to another place/removed in mac80211. | ||
2042 | */ | ||
2043 | static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | ||
2044 | { | 2323 | { |
2045 | struct ath_wiphy *aphy = hw->priv; | 2324 | struct ath_softc *sc = hw->priv; |
2046 | struct ath_softc *sc = aphy->sc; | 2325 | int i; |
2047 | 2326 | ||
2048 | mutex_lock(&sc->mutex); | 2327 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { |
2049 | aphy->state = ATH_WIPHY_ACTIVE; | 2328 | if (!ATH_TXQ_SETUP(sc, i)) |
2050 | sc->sc_flags &= ~SC_OP_SCANNING; | 2329 | continue; |
2051 | mutex_unlock(&sc->mutex); | 2330 | |
2331 | if (ath9k_has_pending_frames(sc, &sc->tx.txq[i])) | ||
2332 | return true; | ||
2333 | } | ||
2334 | return false; | ||
2052 | } | 2335 | } |
2053 | 2336 | ||
2054 | static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class) | 2337 | int ath9k_tx_last_beacon(struct ieee80211_hw *hw) |
2055 | { | 2338 | { |
2056 | struct ath_wiphy *aphy = hw->priv; | 2339 | struct ath_softc *sc = hw->priv; |
2057 | struct ath_softc *sc = aphy->sc; | ||
2058 | struct ath_hw *ah = sc->sc_ah; | 2340 | struct ath_hw *ah = sc->sc_ah; |
2341 | struct ieee80211_vif *vif; | ||
2342 | struct ath_vif *avp; | ||
2343 | struct ath_buf *bf; | ||
2344 | struct ath_tx_status ts; | ||
2345 | int status; | ||
2346 | |||
2347 | vif = sc->beacon.bslot[0]; | ||
2348 | if (!vif) | ||
2349 | return 0; | ||
2059 | 2350 | ||
2060 | mutex_lock(&sc->mutex); | 2351 | avp = (void *)vif->drv_priv; |
2061 | ah->coverage_class = coverage_class; | 2352 | if (!avp->is_bslot_active) |
2062 | ath9k_hw_init_global_settings(ah); | 2353 | return 0; |
2063 | mutex_unlock(&sc->mutex); | 2354 | |
2355 | if (!sc->beacon.tx_processed) { | ||
2356 | tasklet_disable(&sc->bcon_tasklet); | ||
2357 | |||
2358 | bf = avp->av_bcbuf; | ||
2359 | if (!bf || !bf->bf_mpdu) | ||
2360 | goto skip; | ||
2361 | |||
2362 | status = ath9k_hw_txprocdesc(ah, bf->bf_desc, &ts); | ||
2363 | if (status == -EINPROGRESS) | ||
2364 | goto skip; | ||
2365 | |||
2366 | sc->beacon.tx_processed = true; | ||
2367 | sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK); | ||
2368 | |||
2369 | skip: | ||
2370 | tasklet_enable(&sc->bcon_tasklet); | ||
2371 | } | ||
2372 | |||
2373 | return sc->beacon.tx_last; | ||
2064 | } | 2374 | } |
2065 | 2375 | ||
2066 | struct ieee80211_ops ath9k_ops = { | 2376 | struct ieee80211_ops ath9k_ops = { |
@@ -2068,11 +2378,13 @@ struct ieee80211_ops ath9k_ops = { | |||
2068 | .start = ath9k_start, | 2378 | .start = ath9k_start, |
2069 | .stop = ath9k_stop, | 2379 | .stop = ath9k_stop, |
2070 | .add_interface = ath9k_add_interface, | 2380 | .add_interface = ath9k_add_interface, |
2381 | .change_interface = ath9k_change_interface, | ||
2071 | .remove_interface = ath9k_remove_interface, | 2382 | .remove_interface = ath9k_remove_interface, |
2072 | .config = ath9k_config, | 2383 | .config = ath9k_config, |
2073 | .configure_filter = ath9k_configure_filter, | 2384 | .configure_filter = ath9k_configure_filter, |
2074 | .sta_add = ath9k_sta_add, | 2385 | .sta_add = ath9k_sta_add, |
2075 | .sta_remove = ath9k_sta_remove, | 2386 | .sta_remove = ath9k_sta_remove, |
2387 | .sta_notify = ath9k_sta_notify, | ||
2076 | .conf_tx = ath9k_conf_tx, | 2388 | .conf_tx = ath9k_conf_tx, |
2077 | .bss_info_changed = ath9k_bss_info_changed, | 2389 | .bss_info_changed = ath9k_bss_info_changed, |
2078 | .set_key = ath9k_set_key, | 2390 | .set_key = ath9k_set_key, |
@@ -2081,8 +2393,9 @@ struct ieee80211_ops ath9k_ops = { | |||
2081 | .reset_tsf = ath9k_reset_tsf, | 2393 | .reset_tsf = ath9k_reset_tsf, |
2082 | .ampdu_action = ath9k_ampdu_action, | 2394 | .ampdu_action = ath9k_ampdu_action, |
2083 | .get_survey = ath9k_get_survey, | 2395 | .get_survey = ath9k_get_survey, |
2084 | .sw_scan_start = ath9k_sw_scan_start, | ||
2085 | .sw_scan_complete = ath9k_sw_scan_complete, | ||
2086 | .rfkill_poll = ath9k_rfkill_poll_state, | 2396 | .rfkill_poll = ath9k_rfkill_poll_state, |
2087 | .set_coverage_class = ath9k_set_coverage_class, | 2397 | .set_coverage_class = ath9k_set_coverage_class, |
2398 | .flush = ath9k_flush, | ||
2399 | .tx_frames_pending = ath9k_tx_frames_pending, | ||
2400 | .tx_last_beacon = ath9k_tx_last_beacon, | ||
2088 | }; | 2401 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index b5b651413e77..3bad0b2cf9a3 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/nl80211.h> | 17 | #include <linux/nl80211.h> |
18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
19 | #include <linux/ath9k_platform.h> | ||
19 | #include "ath9k.h" | 20 | #include "ath9k.h" |
20 | 21 | ||
21 | static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | 22 | static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { |
@@ -29,6 +30,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
29 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ | 30 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ |
30 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ | 31 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ |
31 | { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ | 32 | { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ |
33 | { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ | ||
32 | { 0 } | 34 | { 0 } |
33 | }; | 35 | }; |
34 | 36 | ||
@@ -42,7 +44,7 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz) | |||
42 | *csz = (int)u8tmp; | 44 | *csz = (int)u8tmp; |
43 | 45 | ||
44 | /* | 46 | /* |
45 | * This check was put in to avoid "unplesant" consequences if | 47 | * This check was put in to avoid "unpleasant" consequences if |
46 | * the bootrom has not fully initialized all PCI devices. | 48 | * the bootrom has not fully initialized all PCI devices. |
47 | * Sometimes the cache line size register is not set | 49 | * Sometimes the cache line size register is not set |
48 | */ | 50 | */ |
@@ -53,21 +55,35 @@ static void ath_pci_read_cachesize(struct ath_common *common, int *csz) | |||
53 | 55 | ||
54 | static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) | 56 | static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) |
55 | { | 57 | { |
56 | struct ath_hw *ah = (struct ath_hw *) common->ah; | 58 | struct ath_softc *sc = (struct ath_softc *) common->priv; |
57 | 59 | struct ath9k_platform_data *pdata = sc->dev->platform_data; | |
58 | common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); | 60 | |
59 | 61 | if (pdata) { | |
60 | if (!ath9k_hw_wait(ah, | 62 | if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { |
61 | AR_EEPROM_STATUS_DATA, | 63 | ath_err(common, |
62 | AR_EEPROM_STATUS_DATA_BUSY | | 64 | "%s: eeprom read failed, offset %08x is out of range\n", |
63 | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, | 65 | __func__, off); |
64 | AH_WAIT_TIMEOUT)) { | 66 | } |
65 | return false; | 67 | |
68 | *data = pdata->eeprom_data[off]; | ||
69 | } else { | ||
70 | struct ath_hw *ah = (struct ath_hw *) common->ah; | ||
71 | |||
72 | common->ops->read(ah, AR5416_EEPROM_OFFSET + | ||
73 | (off << AR5416_EEPROM_S)); | ||
74 | |||
75 | if (!ath9k_hw_wait(ah, | ||
76 | AR_EEPROM_STATUS_DATA, | ||
77 | AR_EEPROM_STATUS_DATA_BUSY | | ||
78 | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, | ||
79 | AH_WAIT_TIMEOUT)) { | ||
80 | return false; | ||
81 | } | ||
82 | |||
83 | *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), | ||
84 | AR_EEPROM_STATUS_DATA_VAL); | ||
66 | } | 85 | } |
67 | 86 | ||
68 | *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), | ||
69 | AR_EEPROM_STATUS_DATA_VAL); | ||
70 | |||
71 | return true; | 87 | return true; |
72 | } | 88 | } |
73 | 89 | ||
@@ -80,7 +96,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) | |||
80 | struct pci_dev *pdev = to_pci_dev(sc->dev); | 96 | struct pci_dev *pdev = to_pci_dev(sc->dev); |
81 | u8 aspm; | 97 | u8 aspm; |
82 | 98 | ||
83 | if (!pdev->is_pcie) | 99 | if (!pci_is_pcie(pdev)) |
84 | return; | 100 | return; |
85 | 101 | ||
86 | pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); | 102 | pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); |
@@ -88,17 +104,28 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) | |||
88 | pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); | 104 | pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); |
89 | } | 105 | } |
90 | 106 | ||
107 | static void ath_pci_extn_synch_enable(struct ath_common *common) | ||
108 | { | ||
109 | struct ath_softc *sc = (struct ath_softc *) common->priv; | ||
110 | struct pci_dev *pdev = to_pci_dev(sc->dev); | ||
111 | u8 lnkctl; | ||
112 | |||
113 | pci_read_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, &lnkctl); | ||
114 | lnkctl |= PCI_EXP_LNKCTL_ES; | ||
115 | pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl); | ||
116 | } | ||
117 | |||
91 | static const struct ath_bus_ops ath_pci_bus_ops = { | 118 | static const struct ath_bus_ops ath_pci_bus_ops = { |
92 | .ath_bus_type = ATH_PCI, | 119 | .ath_bus_type = ATH_PCI, |
93 | .read_cachesize = ath_pci_read_cachesize, | 120 | .read_cachesize = ath_pci_read_cachesize, |
94 | .eeprom_read = ath_pci_eeprom_read, | 121 | .eeprom_read = ath_pci_eeprom_read, |
95 | .bt_coex_prep = ath_pci_bt_coex_prep, | 122 | .bt_coex_prep = ath_pci_bt_coex_prep, |
123 | .extn_synch_en = ath_pci_extn_synch_enable, | ||
96 | }; | 124 | }; |
97 | 125 | ||
98 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 126 | static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
99 | { | 127 | { |
100 | void __iomem *mem; | 128 | void __iomem *mem; |
101 | struct ath_wiphy *aphy; | ||
102 | struct ath_softc *sc; | 129 | struct ath_softc *sc; |
103 | struct ieee80211_hw *hw; | 130 | struct ieee80211_hw *hw; |
104 | u8 csz; | 131 | u8 csz; |
@@ -170,8 +197,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
170 | goto err_iomap; | 197 | goto err_iomap; |
171 | } | 198 | } |
172 | 199 | ||
173 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + | 200 | hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); |
174 | sizeof(struct ath_softc), &ath9k_ops); | ||
175 | if (!hw) { | 201 | if (!hw) { |
176 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); | 202 | dev_err(&pdev->dev, "No memory for ieee80211_hw\n"); |
177 | ret = -ENOMEM; | 203 | ret = -ENOMEM; |
@@ -181,11 +207,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
181 | SET_IEEE80211_DEV(hw, &pdev->dev); | 207 | SET_IEEE80211_DEV(hw, &pdev->dev); |
182 | pci_set_drvdata(pdev, hw); | 208 | pci_set_drvdata(pdev, hw); |
183 | 209 | ||
184 | aphy = hw->priv; | 210 | sc = hw->priv; |
185 | sc = (struct ath_softc *) (aphy + 1); | ||
186 | aphy->sc = sc; | ||
187 | aphy->hw = hw; | ||
188 | sc->pri_wiphy = aphy; | ||
189 | sc->hw = hw; | 211 | sc->hw = hw; |
190 | sc->dev = &pdev->dev; | 212 | sc->dev = &pdev->dev; |
191 | sc->mem = mem; | 213 | sc->mem = mem; |
@@ -232,10 +254,11 @@ err_dma: | |||
232 | static void ath_pci_remove(struct pci_dev *pdev) | 254 | static void ath_pci_remove(struct pci_dev *pdev) |
233 | { | 255 | { |
234 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 256 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
235 | struct ath_wiphy *aphy = hw->priv; | 257 | struct ath_softc *sc = hw->priv; |
236 | struct ath_softc *sc = aphy->sc; | ||
237 | void __iomem *mem = sc->mem; | 258 | void __iomem *mem = sc->mem; |
238 | 259 | ||
260 | if (!is_ath9k_unloaded) | ||
261 | sc->sc_ah->ah_flags |= AH_UNPLUGGED; | ||
239 | ath9k_deinit_device(sc); | 262 | ath9k_deinit_device(sc); |
240 | free_irq(sc->irq, sc); | 263 | free_irq(sc->irq, sc); |
241 | ieee80211_free_hw(sc->hw); | 264 | ieee80211_free_hw(sc->hw); |
@@ -247,34 +270,29 @@ static void ath_pci_remove(struct pci_dev *pdev) | |||
247 | 270 | ||
248 | #ifdef CONFIG_PM | 271 | #ifdef CONFIG_PM |
249 | 272 | ||
250 | static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) | 273 | static int ath_pci_suspend(struct device *device) |
251 | { | 274 | { |
275 | struct pci_dev *pdev = to_pci_dev(device); | ||
252 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 276 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
253 | struct ath_wiphy *aphy = hw->priv; | 277 | struct ath_softc *sc = hw->priv; |
254 | struct ath_softc *sc = aphy->sc; | ||
255 | 278 | ||
256 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | 279 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
257 | 280 | ||
258 | pci_save_state(pdev); | 281 | /* The device has to be moved to FULLSLEEP forcibly. |
259 | pci_disable_device(pdev); | 282 | * Otherwise the chip never moved to full sleep, |
260 | pci_set_power_state(pdev, PCI_D3hot); | 283 | * when no interface is up. |
284 | */ | ||
285 | ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); | ||
261 | 286 | ||
262 | return 0; | 287 | return 0; |
263 | } | 288 | } |
264 | 289 | ||
265 | static int ath_pci_resume(struct pci_dev *pdev) | 290 | static int ath_pci_resume(struct device *device) |
266 | { | 291 | { |
292 | struct pci_dev *pdev = to_pci_dev(device); | ||
267 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 293 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
268 | struct ath_wiphy *aphy = hw->priv; | 294 | struct ath_softc *sc = hw->priv; |
269 | struct ath_softc *sc = aphy->sc; | ||
270 | u32 val; | 295 | u32 val; |
271 | int err; | ||
272 | |||
273 | pci_restore_state(pdev); | ||
274 | |||
275 | err = pci_enable_device(pdev); | ||
276 | if (err) | ||
277 | return err; | ||
278 | 296 | ||
279 | /* | 297 | /* |
280 | * Suspend/Resume resets the PCI configuration space, so we have to | 298 | * Suspend/Resume resets the PCI configuration space, so we have to |
@@ -290,10 +308,37 @@ static int ath_pci_resume(struct pci_dev *pdev) | |||
290 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 308 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
291 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | 309 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
292 | 310 | ||
311 | /* | ||
312 | * Reset key cache to sane defaults (all entries cleared) instead of | ||
313 | * semi-random values after suspend/resume. | ||
314 | */ | ||
315 | ath9k_ps_wakeup(sc); | ||
316 | ath9k_init_crypto(sc); | ||
317 | ath9k_ps_restore(sc); | ||
318 | |||
319 | sc->ps_idle = true; | ||
320 | ath_radio_disable(sc, hw); | ||
321 | |||
293 | return 0; | 322 | return 0; |
294 | } | 323 | } |
295 | 324 | ||
296 | #endif /* CONFIG_PM */ | 325 | static const struct dev_pm_ops ath9k_pm_ops = { |
326 | .suspend = ath_pci_suspend, | ||
327 | .resume = ath_pci_resume, | ||
328 | .freeze = ath_pci_suspend, | ||
329 | .thaw = ath_pci_resume, | ||
330 | .poweroff = ath_pci_suspend, | ||
331 | .restore = ath_pci_resume, | ||
332 | }; | ||
333 | |||
334 | #define ATH9K_PM_OPS (&ath9k_pm_ops) | ||
335 | |||
336 | #else /* !CONFIG_PM */ | ||
337 | |||
338 | #define ATH9K_PM_OPS NULL | ||
339 | |||
340 | #endif /* !CONFIG_PM */ | ||
341 | |||
297 | 342 | ||
298 | MODULE_DEVICE_TABLE(pci, ath_pci_id_table); | 343 | MODULE_DEVICE_TABLE(pci, ath_pci_id_table); |
299 | 344 | ||
@@ -302,10 +347,7 @@ static struct pci_driver ath_pci_driver = { | |||
302 | .id_table = ath_pci_id_table, | 347 | .id_table = ath_pci_id_table, |
303 | .probe = ath_pci_probe, | 348 | .probe = ath_pci_probe, |
304 | .remove = ath_pci_remove, | 349 | .remove = ath_pci_remove, |
305 | #ifdef CONFIG_PM | 350 | .driver.pm = ATH9K_PM_OPS, |
306 | .suspend = ath_pci_suspend, | ||
307 | .resume = ath_pci_resume, | ||
308 | #endif /* CONFIG_PM */ | ||
309 | }; | 351 | }; |
310 | 352 | ||
311 | int ath_pci_init(void) | 353 | int ath_pci_init(void) |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index e724c2c1ae2a..8b380305b0fc 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -37,29 +37,15 @@ | |||
37 | #define AR_PHY_CLC_Q0 0x0000ffd0 | 37 | #define AR_PHY_CLC_Q0 0x0000ffd0 |
38 | #define AR_PHY_CLC_Q0_S 5 | 38 | #define AR_PHY_CLC_Q0_S 5 |
39 | 39 | ||
40 | #define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ | ||
41 | int r; \ | ||
42 | for (r = 0; r < ((iniarray)->ia_rows); r++) { \ | ||
43 | REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ | ||
44 | DO_DELAY(regWr); \ | ||
45 | } \ | ||
46 | } while (0) | ||
47 | |||
48 | #define ATH9K_IS_MIC_ENABLED(ah) \ | ||
49 | ((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE) | ||
50 | |||
51 | #define ANTSWAP_AB 0x0001 | 40 | #define ANTSWAP_AB 0x0001 |
52 | #define REDUCE_CHAIN_0 0x00000050 | 41 | #define REDUCE_CHAIN_0 0x00000050 |
53 | #define REDUCE_CHAIN_1 0x00000051 | 42 | #define REDUCE_CHAIN_1 0x00000051 |
54 | #define AR_PHY_CHIP_ID 0x9818 | 43 | #define AR_PHY_CHIP_ID 0x9818 |
55 | 44 | ||
56 | #define RF_BANK_SETUP(_bank, _iniarray, _col) do { \ | ||
57 | int i; \ | ||
58 | for (i = 0; i < (_iniarray)->ia_rows; i++) \ | ||
59 | (_bank)[i] = INI_RA((_iniarray), i, _col);; \ | ||
60 | } while (0) | ||
61 | |||
62 | #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 | 45 | #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 |
63 | #define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 | 46 | #define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 |
64 | 47 | ||
48 | #define AR_PHY_PLL_CONTROL 0x16180 | ||
49 | #define AR_PHY_PLL_MODE 0x16184 | ||
50 | |||
65 | #endif | 51 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index e49be733d546..ba7f36ab0a74 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 Video54 Technologies, Inc. | 2 | * Copyright (c) 2004 Video54 Technologies, Inc. |
3 | * Copyright (c) 2004-2009 Atheros Communications, Inc. | 3 | * Copyright (c) 2004-2011 Atheros Communications, Inc. |
4 | * | 4 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -302,7 +302,7 @@ static const struct ath_rate_table ar5416_11ng_ratetable = { | |||
302 | [64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, | 302 | [64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, |
303 | 205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */ | 303 | 205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */ |
304 | [65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, | 304 | [65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, |
305 | 224700, 20, 20, 8, 64, 65, 65 }, /* 170 Mb */ | 305 | 224700, 20, 20, 8, 64, 65, 65 }, /* 270 Mb */ |
306 | [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, | 306 | [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, |
307 | 263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */ | 307 | 263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */ |
308 | [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, | 308 | [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, |
@@ -378,39 +378,9 @@ static const struct ath_rate_table ar5416_11g_ratetable = { | |||
378 | 0, /* Phy rates allowed initially */ | 378 | 0, /* Phy rates allowed initially */ |
379 | }; | 379 | }; |
380 | 380 | ||
381 | static const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX] = { | ||
382 | [ATH9K_MODE_11A] = &ar5416_11a_ratetable, | ||
383 | [ATH9K_MODE_11G] = &ar5416_11g_ratetable, | ||
384 | [ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable, | ||
385 | [ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable, | ||
386 | [ATH9K_MODE_11NA_HT40PLUS] = &ar5416_11na_ratetable, | ||
387 | [ATH9K_MODE_11NA_HT40MINUS] = &ar5416_11na_ratetable, | ||
388 | [ATH9K_MODE_11NG_HT40PLUS] = &ar5416_11ng_ratetable, | ||
389 | [ATH9K_MODE_11NG_HT40MINUS] = &ar5416_11ng_ratetable, | ||
390 | }; | ||
391 | |||
392 | static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, | 381 | static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, |
393 | struct ieee80211_tx_rate *rate); | 382 | struct ieee80211_tx_rate *rate); |
394 | 383 | ||
395 | static inline int8_t median(int8_t a, int8_t b, int8_t c) | ||
396 | { | ||
397 | if (a >= b) { | ||
398 | if (b >= c) | ||
399 | return b; | ||
400 | else if (a > c) | ||
401 | return c; | ||
402 | else | ||
403 | return a; | ||
404 | } else { | ||
405 | if (a >= c) | ||
406 | return a; | ||
407 | else if (b >= c) | ||
408 | return c; | ||
409 | else | ||
410 | return b; | ||
411 | } | ||
412 | } | ||
413 | |||
414 | static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, | 384 | static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, |
415 | struct ath_rate_priv *ath_rc_priv) | 385 | struct ath_rate_priv *ath_rc_priv) |
416 | { | 386 | { |
@@ -430,7 +400,7 @@ static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, | |||
430 | } | 400 | } |
431 | } | 401 | } |
432 | 402 | ||
433 | static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv) | 403 | static void ath_rc_init_valid_rate_idx(struct ath_rate_priv *ath_rc_priv) |
434 | { | 404 | { |
435 | u8 i; | 405 | u8 i; |
436 | 406 | ||
@@ -438,7 +408,7 @@ static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv) | |||
438 | ath_rc_priv->valid_rate_index[i] = 0; | 408 | ath_rc_priv->valid_rate_index[i] = 0; |
439 | } | 409 | } |
440 | 410 | ||
441 | static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, | 411 | static inline void ath_rc_set_valid_rate_idx(struct ath_rate_priv *ath_rc_priv, |
442 | u8 index, int valid_tx_rate) | 412 | u8 index, int valid_tx_rate) |
443 | { | 413 | { |
444 | BUG_ON(index > ath_rc_priv->rate_table_size); | 414 | BUG_ON(index > ath_rc_priv->rate_table_size); |
@@ -519,7 +489,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, | |||
519 | 489 | ||
520 | ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; | 490 | ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; |
521 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; | 491 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; |
522 | ath_rc_set_valid_txmask(ath_rc_priv, i, 1); | 492 | ath_rc_set_valid_rate_idx(ath_rc_priv, i, 1); |
523 | hi = i; | 493 | hi = i; |
524 | } | 494 | } |
525 | } | 495 | } |
@@ -538,7 +508,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, | |||
538 | for (i = 0; i < rateset->rs_nrates; i++) { | 508 | for (i = 0; i < rateset->rs_nrates; i++) { |
539 | for (j = 0; j < rate_table->rate_cnt; j++) { | 509 | for (j = 0; j < rate_table->rate_cnt; j++) { |
540 | u32 phy = rate_table->info[j].phy; | 510 | u32 phy = rate_table->info[j].phy; |
541 | u16 rate_flags = rate_table->info[i].rate_flags; | 511 | u16 rate_flags = rate_table->info[j].rate_flags; |
542 | u8 rate = rateset->rs_rates[i]; | 512 | u8 rate = rateset->rs_rates[i]; |
543 | u8 dot11rate = rate_table->info[j].dot11rate; | 513 | u8 dot11rate = rate_table->info[j].dot11rate; |
544 | 514 | ||
@@ -562,7 +532,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, | |||
562 | ath_rc_priv->valid_phy_rateidx[phy] | 532 | ath_rc_priv->valid_phy_rateidx[phy] |
563 | [valid_rate_count] = j; | 533 | [valid_rate_count] = j; |
564 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; | 534 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; |
565 | ath_rc_set_valid_txmask(ath_rc_priv, j, 1); | 535 | ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); |
566 | hi = A_MAX(hi, j); | 536 | hi = A_MAX(hi, j); |
567 | } | 537 | } |
568 | } | 538 | } |
@@ -598,7 +568,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, | |||
598 | ath_rc_priv->valid_phy_rateidx[phy] | 568 | ath_rc_priv->valid_phy_rateidx[phy] |
599 | [ath_rc_priv->valid_phy_ratecnt[phy]] = j; | 569 | [ath_rc_priv->valid_phy_ratecnt[phy]] = j; |
600 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; | 570 | ath_rc_priv->valid_phy_ratecnt[phy] += 1; |
601 | ath_rc_set_valid_txmask(ath_rc_priv, j, 1); | 571 | ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1); |
602 | hi = A_MAX(hi, j); | 572 | hi = A_MAX(hi, j); |
603 | } | 573 | } |
604 | } | 574 | } |
@@ -719,7 +689,8 @@ static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table, | |||
719 | 689 | ||
720 | if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) { | 690 | if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) { |
721 | rate->flags |= IEEE80211_TX_RC_MCS; | 691 | rate->flags |= IEEE80211_TX_RC_MCS; |
722 | if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) | 692 | if (WLAN_RC_PHY_40(rate_table->info[rix].phy) && |
693 | conf_is_ht40(&txrc->hw->conf)) | ||
723 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | 694 | rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
724 | if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) | 695 | if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) |
725 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; | 696 | rate->flags |= IEEE80211_TX_RC_SHORT_GI; |
@@ -791,7 +762,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
791 | */ | 762 | */ |
792 | try_per_rate = 4; | 763 | try_per_rate = 4; |
793 | 764 | ||
794 | rate_table = sc->cur_rate_table; | 765 | rate_table = ath_rc_priv->rate_table; |
795 | rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); | 766 | rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); |
796 | 767 | ||
797 | /* | 768 | /* |
@@ -822,7 +793,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
822 | 793 | ||
823 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 794 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
824 | } else { | 795 | } else { |
825 | /* Set the choosen rate. No RTS for first series entry. */ | 796 | /* Set the chosen rate. No RTS for first series entry. */ |
826 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 797 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
827 | try_per_rate, rix, 0); | 798 | try_per_rate, rix, 0); |
828 | } | 799 | } |
@@ -884,17 +855,16 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
884 | ath_rc_rate_set_rtscts(sc, rate_table, tx_info); | 855 | ath_rc_rate_set_rtscts(sc, rate_table, tx_info); |
885 | } | 856 | } |
886 | 857 | ||
887 | static bool ath_rc_update_per(struct ath_softc *sc, | 858 | static void ath_rc_update_per(struct ath_softc *sc, |
888 | const struct ath_rate_table *rate_table, | 859 | const struct ath_rate_table *rate_table, |
889 | struct ath_rate_priv *ath_rc_priv, | 860 | struct ath_rate_priv *ath_rc_priv, |
890 | struct ieee80211_tx_info *tx_info, | 861 | struct ieee80211_tx_info *tx_info, |
891 | int tx_rate, int xretries, int retries, | 862 | int tx_rate, int xretries, int retries, |
892 | u32 now_msec) | 863 | u32 now_msec) |
893 | { | 864 | { |
894 | bool state_change = false; | ||
895 | int count, n_bad_frames; | 865 | int count, n_bad_frames; |
896 | u8 last_per; | 866 | u8 last_per; |
897 | static u32 nretry_to_per_lookup[10] = { | 867 | static const u32 nretry_to_per_lookup[10] = { |
898 | 100 * 0 / 1, | 868 | 100 * 0 / 1, |
899 | 100 * 1 / 4, | 869 | 100 * 1 / 4, |
900 | 100 * 1 / 2, | 870 | 100 * 1 / 2, |
@@ -1022,8 +992,16 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
1022 | 992 | ||
1023 | } | 993 | } |
1024 | } | 994 | } |
995 | } | ||
1025 | 996 | ||
1026 | return state_change; | 997 | static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, |
998 | int xretries, int retries, u8 per) | ||
999 | { | ||
1000 | struct ath_rc_stats *stats = &rc->rcstats[rix]; | ||
1001 | |||
1002 | stats->xretries += xretries; | ||
1003 | stats->retries += retries; | ||
1004 | stats->per = per; | ||
1027 | } | 1005 | } |
1028 | 1006 | ||
1029 | /* Update PER, RSSI and whatever else that the code thinks it is doing. | 1007 | /* Update PER, RSSI and whatever else that the code thinks it is doing. |
@@ -1037,8 +1015,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1037 | u32 now_msec = jiffies_to_msecs(jiffies); | 1015 | u32 now_msec = jiffies_to_msecs(jiffies); |
1038 | int rate; | 1016 | int rate; |
1039 | u8 last_per; | 1017 | u8 last_per; |
1040 | bool state_change = false; | 1018 | const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; |
1041 | const struct ath_rate_table *rate_table = sc->cur_rate_table; | ||
1042 | int size = ath_rc_priv->rate_table_size; | 1019 | int size = ath_rc_priv->rate_table_size; |
1043 | 1020 | ||
1044 | if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) | 1021 | if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) |
@@ -1047,9 +1024,9 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1047 | last_per = ath_rc_priv->per[tx_rate]; | 1024 | last_per = ath_rc_priv->per[tx_rate]; |
1048 | 1025 | ||
1049 | /* Update PER first */ | 1026 | /* Update PER first */ |
1050 | state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, | 1027 | ath_rc_update_per(sc, rate_table, ath_rc_priv, |
1051 | tx_info, tx_rate, xretries, | 1028 | tx_info, tx_rate, xretries, |
1052 | retries, now_msec); | 1029 | retries, now_msec); |
1053 | 1030 | ||
1054 | /* | 1031 | /* |
1055 | * If this rate looks bad (high PER) then stop using it for | 1032 | * If this rate looks bad (high PER) then stop using it for |
@@ -1098,7 +1075,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1098 | ath_rc_priv->per_down_time = now_msec; | 1075 | ath_rc_priv->per_down_time = now_msec; |
1099 | } | 1076 | } |
1100 | 1077 | ||
1101 | ath_debug_stat_retries(sc, tx_rate, xretries, retries, | 1078 | ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries, |
1102 | ath_rc_priv->per[tx_rate]); | 1079 | ath_rc_priv->per[tx_rate]); |
1103 | 1080 | ||
1104 | } | 1081 | } |
@@ -1107,13 +1084,12 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, | |||
1107 | struct ieee80211_tx_rate *rate) | 1084 | struct ieee80211_tx_rate *rate) |
1108 | { | 1085 | { |
1109 | int rix = 0, i = 0; | 1086 | int rix = 0, i = 0; |
1110 | int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; | 1087 | static const int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 }; |
1111 | 1088 | ||
1112 | if (!(rate->flags & IEEE80211_TX_RC_MCS)) | 1089 | if (!(rate->flags & IEEE80211_TX_RC_MCS)) |
1113 | return rate->idx; | 1090 | return rate->idx; |
1114 | 1091 | ||
1115 | while (rate->idx > mcs_rix_off[i] && | 1092 | while (i < ARRAY_SIZE(mcs_rix_off) && rate->idx > mcs_rix_off[i]) { |
1116 | i < sizeof(mcs_rix_off)/sizeof(int)) { | ||
1117 | rix++; i++; | 1093 | rix++; i++; |
1118 | } | 1094 | } |
1119 | 1095 | ||
@@ -1140,7 +1116,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, | |||
1140 | u8 flags; | 1116 | u8 flags; |
1141 | u32 i = 0, rix; | 1117 | u32 i = 0, rix; |
1142 | 1118 | ||
1143 | rate_table = sc->cur_rate_table; | 1119 | rate_table = ath_rc_priv->rate_table; |
1144 | 1120 | ||
1145 | /* | 1121 | /* |
1146 | * If the first rate is not the final index, there | 1122 | * If the first rate is not the final index, there |
@@ -1190,39 +1166,23 @@ static void ath_rc_tx_status(struct ath_softc *sc, | |||
1190 | static const | 1166 | static const |
1191 | struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, | 1167 | struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, |
1192 | enum ieee80211_band band, | 1168 | enum ieee80211_band band, |
1193 | bool is_ht, | 1169 | bool is_ht) |
1194 | bool is_cw_40) | ||
1195 | { | 1170 | { |
1196 | int mode = 0; | ||
1197 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1171 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1198 | 1172 | ||
1199 | switch(band) { | 1173 | switch(band) { |
1200 | case IEEE80211_BAND_2GHZ: | 1174 | case IEEE80211_BAND_2GHZ: |
1201 | mode = ATH9K_MODE_11G; | ||
1202 | if (is_ht) | 1175 | if (is_ht) |
1203 | mode = ATH9K_MODE_11NG_HT20; | 1176 | return &ar5416_11ng_ratetable; |
1204 | if (is_cw_40) | 1177 | return &ar5416_11g_ratetable; |
1205 | mode = ATH9K_MODE_11NG_HT40PLUS; | ||
1206 | break; | ||
1207 | case IEEE80211_BAND_5GHZ: | 1178 | case IEEE80211_BAND_5GHZ: |
1208 | mode = ATH9K_MODE_11A; | ||
1209 | if (is_ht) | 1179 | if (is_ht) |
1210 | mode = ATH9K_MODE_11NA_HT20; | 1180 | return &ar5416_11na_ratetable; |
1211 | if (is_cw_40) | 1181 | return &ar5416_11a_ratetable; |
1212 | mode = ATH9K_MODE_11NA_HT40PLUS; | ||
1213 | break; | ||
1214 | default: | 1182 | default: |
1215 | ath_print(common, ATH_DBG_CONFIG, "Invalid band\n"); | 1183 | ath_dbg(common, ATH_DBG_CONFIG, "Invalid band\n"); |
1216 | return NULL; | 1184 | return NULL; |
1217 | } | 1185 | } |
1218 | |||
1219 | BUG_ON(mode >= ATH9K_MODE_MAX); | ||
1220 | |||
1221 | ath_print(common, ATH_DBG_CONFIG, | ||
1222 | "Choosing rate table for mode: %d\n", mode); | ||
1223 | |||
1224 | sc->cur_rate_mode = mode; | ||
1225 | return hw_rate_table[mode]; | ||
1226 | } | 1186 | } |
1227 | 1187 | ||
1228 | static void ath_rc_init(struct ath_softc *sc, | 1188 | static void ath_rc_init(struct ath_softc *sc, |
@@ -1246,7 +1206,7 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1246 | } | 1206 | } |
1247 | 1207 | ||
1248 | /* Determine the valid rates */ | 1208 | /* Determine the valid rates */ |
1249 | ath_rc_init_valid_txmask(ath_rc_priv); | 1209 | ath_rc_init_valid_rate_idx(ath_rc_priv); |
1250 | 1210 | ||
1251 | for (i = 0; i < WLAN_RC_PHY_MAX; i++) { | 1211 | for (i = 0; i < WLAN_RC_PHY_MAX; i++) { |
1252 | for (j = 0; j < MAX_TX_RATE_PHY; j++) | 1212 | for (j = 0; j < MAX_TX_RATE_PHY; j++) |
@@ -1293,11 +1253,11 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1293 | ath_rc_priv->max_valid_rate = k; | 1253 | ath_rc_priv->max_valid_rate = k; |
1294 | ath_rc_sort_validrates(rate_table, ath_rc_priv); | 1254 | ath_rc_sort_validrates(rate_table, ath_rc_priv); |
1295 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; | 1255 | ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; |
1296 | sc->cur_rate_table = rate_table; | 1256 | ath_rc_priv->rate_table = rate_table; |
1297 | 1257 | ||
1298 | ath_print(common, ATH_DBG_CONFIG, | 1258 | ath_dbg(common, ATH_DBG_CONFIG, |
1299 | "RC Initialized with capabilities: 0x%x\n", | 1259 | "RC Initialized with capabilities: 0x%x\n", |
1300 | ath_rc_priv->ht_cap); | 1260 | ath_rc_priv->ht_cap); |
1301 | } | 1261 | } |
1302 | 1262 | ||
1303 | static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, | 1263 | static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, |
@@ -1320,10 +1280,35 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1320 | return caps; | 1280 | return caps; |
1321 | } | 1281 | } |
1322 | 1282 | ||
1283 | static bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, | ||
1284 | u8 tidno) | ||
1285 | { | ||
1286 | struct ath_atx_tid *txtid; | ||
1287 | |||
1288 | if (!(sc->sc_flags & SC_OP_TXAGGR)) | ||
1289 | return false; | ||
1290 | |||
1291 | txtid = ATH_AN_2_TID(an, tidno); | ||
1292 | |||
1293 | if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS))) | ||
1294 | return true; | ||
1295 | return false; | ||
1296 | } | ||
1297 | |||
1298 | |||
1323 | /***********************************/ | 1299 | /***********************************/ |
1324 | /* mac80211 Rate Control callbacks */ | 1300 | /* mac80211 Rate Control callbacks */ |
1325 | /***********************************/ | 1301 | /***********************************/ |
1326 | 1302 | ||
1303 | static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) | ||
1304 | { | ||
1305 | struct ath_rc_stats *stats; | ||
1306 | |||
1307 | stats = &rc->rcstats[final_rate]; | ||
1308 | stats->success++; | ||
1309 | } | ||
1310 | |||
1311 | |||
1327 | static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | 1312 | static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, |
1328 | struct ieee80211_sta *sta, void *priv_sta, | 1313 | struct ieee80211_sta *sta, void *priv_sta, |
1329 | struct sk_buff *skb) | 1314 | struct sk_buff *skb) |
@@ -1332,14 +1317,14 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1332 | struct ath_rate_priv *ath_rc_priv = priv_sta; | 1317 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
1333 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1318 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1334 | struct ieee80211_hdr *hdr; | 1319 | struct ieee80211_hdr *hdr; |
1335 | int final_ts_idx = 0, tx_status = 0, is_underrun = 0; | 1320 | int final_ts_idx = 0, tx_status = 0; |
1336 | int long_retry = 0; | 1321 | int long_retry = 0; |
1337 | __le16 fc; | 1322 | __le16 fc; |
1338 | int i; | 1323 | int i; |
1339 | 1324 | ||
1340 | hdr = (struct ieee80211_hdr *)skb->data; | 1325 | hdr = (struct ieee80211_hdr *)skb->data; |
1341 | fc = hdr->frame_control; | 1326 | fc = hdr->frame_control; |
1342 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 1327 | for (i = 0; i < sc->hw->max_rates; i++) { |
1343 | struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; | 1328 | struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; |
1344 | if (!rate->count) | 1329 | if (!rate->count) |
1345 | break; | 1330 | break; |
@@ -1359,32 +1344,23 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1359 | if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) | 1344 | if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) |
1360 | return; | 1345 | return; |
1361 | 1346 | ||
1362 | /* | 1347 | if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) { |
1363 | * If an underrun error is seen assume it as an excessive retry only | 1348 | tx_info->status.ampdu_ack_len = |
1364 | * if max frame trigger level has been reached (2 KB for singel stream, | 1349 | (tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0); |
1365 | * and 4 KB for dual stream). Adjust the long retry as if the frame was | 1350 | tx_info->status.ampdu_len = 1; |
1366 | * tried hw->max_rate_tries times to affect how ratectrl updates PER for | ||
1367 | * the failed rate. In case of congestion on the bus penalizing these | ||
1368 | * type of underruns should help hardware actually transmit new frames | ||
1369 | * successfully by eventually preferring slower rates. This itself | ||
1370 | * should also alleviate congestion on the bus. | ||
1371 | */ | ||
1372 | if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) && | ||
1373 | (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) { | ||
1374 | tx_status = 1; | ||
1375 | is_underrun = 1; | ||
1376 | } | 1351 | } |
1377 | 1352 | ||
1378 | if (tx_info->pad[0] & ATH_TX_INFO_XRETRY) | 1353 | if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) |
1379 | tx_status = 1; | 1354 | tx_status = 1; |
1380 | 1355 | ||
1381 | ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, | 1356 | ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, |
1382 | (is_underrun) ? sc->hw->max_rate_tries : long_retry); | 1357 | long_retry); |
1383 | 1358 | ||
1384 | /* Check if aggregation has to be enabled for this tid */ | 1359 | /* Check if aggregation has to be enabled for this tid */ |
1385 | if (conf_is_ht(&sc->hw->conf) && | 1360 | if (conf_is_ht(&sc->hw->conf) && |
1386 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { | 1361 | !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { |
1387 | if (ieee80211_is_data_qos(fc)) { | 1362 | if (ieee80211_is_data_qos(fc) && |
1363 | skb_get_queue_mapping(skb) != IEEE80211_AC_VO) { | ||
1388 | u8 *qc, tid; | 1364 | u8 *qc, tid; |
1389 | struct ath_node *an; | 1365 | struct ath_node *an; |
1390 | 1366 | ||
@@ -1393,12 +1369,13 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1393 | an = (struct ath_node *)sta->drv_priv; | 1369 | an = (struct ath_node *)sta->drv_priv; |
1394 | 1370 | ||
1395 | if(ath_tx_aggr_check(sc, an, tid)) | 1371 | if(ath_tx_aggr_check(sc, an, tid)) |
1396 | ieee80211_start_tx_ba_session(sta, tid); | 1372 | ieee80211_start_tx_ba_session(sta, tid, 0); |
1397 | } | 1373 | } |
1398 | } | 1374 | } |
1399 | 1375 | ||
1400 | ath_debug_stat_rc(sc, ath_rc_get_rateindex(sc->cur_rate_table, | 1376 | ath_debug_stat_rc(ath_rc_priv, |
1401 | &tx_info->status.rates[final_ts_idx])); | 1377 | ath_rc_get_rateindex(ath_rc_priv->rate_table, |
1378 | &tx_info->status.rates[final_ts_idx])); | ||
1402 | } | 1379 | } |
1403 | 1380 | ||
1404 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | 1381 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, |
@@ -1429,23 +1406,17 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1429 | ath_rc_priv->neg_ht_rates.rs_nrates = j; | 1406 | ath_rc_priv->neg_ht_rates.rs_nrates = j; |
1430 | } | 1407 | } |
1431 | 1408 | ||
1432 | is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 1409 | is_cw40 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); |
1433 | 1410 | ||
1434 | if (is_cw40) | 1411 | if (is_cw40) |
1435 | is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; | 1412 | is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40); |
1436 | else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) | 1413 | else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) |
1437 | is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20; | 1414 | is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20); |
1438 | 1415 | ||
1439 | /* Choose rate table first */ | 1416 | /* Choose rate table first */ |
1440 | 1417 | ||
1441 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || | 1418 | rate_table = ath_choose_rate_table(sc, sband->band, |
1442 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || | 1419 | sta->ht_cap.ht_supported); |
1443 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { | ||
1444 | rate_table = ath_choose_rate_table(sc, sband->band, | ||
1445 | sta->ht_cap.ht_supported, is_cw40); | ||
1446 | } else { | ||
1447 | rate_table = hw_rate_table[sc->cur_rate_mode]; | ||
1448 | } | ||
1449 | 1420 | ||
1450 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi); | 1421 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi); |
1451 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); | 1422 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); |
@@ -1459,10 +1430,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | |||
1459 | struct ath_rate_priv *ath_rc_priv = priv_sta; | 1430 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
1460 | const struct ath_rate_table *rate_table = NULL; | 1431 | const struct ath_rate_table *rate_table = NULL; |
1461 | bool oper_cw40 = false, oper_sgi; | 1432 | bool oper_cw40 = false, oper_sgi; |
1462 | bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? | 1433 | bool local_cw40 = !!(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG); |
1463 | true : false; | 1434 | bool local_sgi = !!(ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG); |
1464 | bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? | ||
1465 | true : false; | ||
1466 | 1435 | ||
1467 | /* FIXME: Handle AP mode later when we support CWM */ | 1436 | /* FIXME: Handle AP mode later when we support CWM */ |
1468 | 1437 | ||
@@ -1485,24 +1454,109 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | |||
1485 | 1454 | ||
1486 | if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) { | 1455 | if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) { |
1487 | rate_table = ath_choose_rate_table(sc, sband->band, | 1456 | rate_table = ath_choose_rate_table(sc, sband->band, |
1488 | sta->ht_cap.ht_supported, | 1457 | sta->ht_cap.ht_supported); |
1489 | oper_cw40); | ||
1490 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, | 1458 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, |
1491 | oper_cw40, oper_sgi); | 1459 | oper_cw40, oper_sgi); |
1492 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); | 1460 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); |
1493 | 1461 | ||
1494 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, | 1462 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, |
1495 | "Operating HT Bandwidth changed to: %d\n", | 1463 | "Operating HT Bandwidth changed to: %d\n", |
1496 | sc->hw->conf.channel_type); | 1464 | sc->hw->conf.channel_type); |
1497 | sc->cur_rate_table = hw_rate_table[sc->cur_rate_mode]; | 1465 | } |
1466 | } | ||
1467 | } | ||
1468 | |||
1469 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
1470 | |||
1471 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | ||
1472 | { | ||
1473 | file->private_data = inode->i_private; | ||
1474 | return 0; | ||
1475 | } | ||
1476 | |||
1477 | static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | ||
1478 | size_t count, loff_t *ppos) | ||
1479 | { | ||
1480 | struct ath_rate_priv *rc = file->private_data; | ||
1481 | char *buf; | ||
1482 | unsigned int len = 0, max; | ||
1483 | int i = 0; | ||
1484 | ssize_t retval; | ||
1485 | |||
1486 | if (rc->rate_table == NULL) | ||
1487 | return 0; | ||
1488 | |||
1489 | max = 80 + rc->rate_table->rate_cnt * 1024 + 1; | ||
1490 | buf = kmalloc(max, GFP_KERNEL); | ||
1491 | if (buf == NULL) | ||
1492 | return -ENOMEM; | ||
1493 | |||
1494 | len += sprintf(buf, "%6s %6s %6s " | ||
1495 | "%10s %10s %10s %10s\n", | ||
1496 | "HT", "MCS", "Rate", | ||
1497 | "Success", "Retries", "XRetries", "PER"); | ||
1498 | |||
1499 | for (i = 0; i < rc->rate_table->rate_cnt; i++) { | ||
1500 | u32 ratekbps = rc->rate_table->info[i].ratekbps; | ||
1501 | struct ath_rc_stats *stats = &rc->rcstats[i]; | ||
1502 | char mcs[5]; | ||
1503 | char htmode[5]; | ||
1504 | int used_mcs = 0, used_htmode = 0; | ||
1505 | |||
1506 | if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) { | ||
1507 | used_mcs = snprintf(mcs, 5, "%d", | ||
1508 | rc->rate_table->info[i].ratecode); | ||
1509 | |||
1510 | if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy)) | ||
1511 | used_htmode = snprintf(htmode, 5, "HT40"); | ||
1512 | else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy)) | ||
1513 | used_htmode = snprintf(htmode, 5, "HT20"); | ||
1514 | else | ||
1515 | used_htmode = snprintf(htmode, 5, "????"); | ||
1498 | } | 1516 | } |
1517 | |||
1518 | mcs[used_mcs] = '\0'; | ||
1519 | htmode[used_htmode] = '\0'; | ||
1520 | |||
1521 | len += snprintf(buf + len, max - len, | ||
1522 | "%6s %6s %3u.%d: " | ||
1523 | "%10u %10u %10u %10u\n", | ||
1524 | htmode, | ||
1525 | mcs, | ||
1526 | ratekbps / 1000, | ||
1527 | (ratekbps % 1000) / 100, | ||
1528 | stats->success, | ||
1529 | stats->retries, | ||
1530 | stats->xretries, | ||
1531 | stats->per); | ||
1499 | } | 1532 | } |
1533 | |||
1534 | if (len > max) | ||
1535 | len = max; | ||
1536 | |||
1537 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1538 | kfree(buf); | ||
1539 | return retval; | ||
1500 | } | 1540 | } |
1501 | 1541 | ||
1542 | static const struct file_operations fops_rcstat = { | ||
1543 | .read = read_file_rcstat, | ||
1544 | .open = ath9k_debugfs_open, | ||
1545 | .owner = THIS_MODULE | ||
1546 | }; | ||
1547 | |||
1548 | static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta, | ||
1549 | struct dentry *dir) | ||
1550 | { | ||
1551 | struct ath_rate_priv *rc = priv_sta; | ||
1552 | debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat); | ||
1553 | } | ||
1554 | |||
1555 | #endif /* CONFIG_ATH9K_DEBUGFS */ | ||
1556 | |||
1502 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 1557 | static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
1503 | { | 1558 | { |
1504 | struct ath_wiphy *aphy = hw->priv; | 1559 | return hw->priv; |
1505 | return aphy->sc; | ||
1506 | } | 1560 | } |
1507 | 1561 | ||
1508 | static void ath_rate_free(void *priv) | 1562 | static void ath_rate_free(void *priv) |
@@ -1517,13 +1571,11 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp | |||
1517 | 1571 | ||
1518 | rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); | 1572 | rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); |
1519 | if (!rate_priv) { | 1573 | if (!rate_priv) { |
1520 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 1574 | ath_err(ath9k_hw_common(sc->sc_ah), |
1521 | "Unable to allocate private rc structure\n"); | 1575 | "Unable to allocate private rc structure\n"); |
1522 | return NULL; | 1576 | return NULL; |
1523 | } | 1577 | } |
1524 | 1578 | ||
1525 | rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max; | ||
1526 | |||
1527 | return rate_priv; | 1579 | return rate_priv; |
1528 | } | 1580 | } |
1529 | 1581 | ||
@@ -1545,6 +1597,9 @@ static struct rate_control_ops ath_rate_ops = { | |||
1545 | .free = ath_rate_free, | 1597 | .free = ath_rate_free, |
1546 | .alloc_sta = ath_rate_alloc_sta, | 1598 | .alloc_sta = ath_rate_alloc_sta, |
1547 | .free_sta = ath_rate_free_sta, | 1599 | .free_sta = ath_rate_free_sta, |
1600 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
1601 | .add_sta_debugfs = ath_rate_add_sta_debugfs, | ||
1602 | #endif | ||
1548 | }; | 1603 | }; |
1549 | 1604 | ||
1550 | int ath_rate_control_register(void) | 1605 | int ath_rate_control_register(void) |
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index dc1082654501..c3d850207bee 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 Sam Leffler, Errno Consulting | 2 | * Copyright (c) 2004 Sam Leffler, Errno Consulting |
3 | * Copyright (c) 2004 Video54 Technologies, Inc. | 3 | * Copyright (c) 2004 Video54 Technologies, Inc. |
4 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 4 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
5 | * | 5 | * |
6 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 7 | * purpose with or without fee is hereby granted, provided that the above |
@@ -135,20 +135,21 @@ enum { | |||
135 | 135 | ||
136 | /** | 136 | /** |
137 | * struct ath_rate_table - Rate Control table | 137 | * struct ath_rate_table - Rate Control table |
138 | * @valid: valid for use in rate control | 138 | * @rate_cnt: total number of rates for the given wireless mode |
139 | * @valid_single_stream: valid for use in rate control for | 139 | * @mcs_start: MCS rate index offset |
140 | * single stream operation | 140 | * @rate_flags: Rate Control flags |
141 | * @phy: CCK/OFDM | 141 | * @phy: CCK/OFDM/HT20/HT40 |
142 | * @ratekbps: rate in Kbits per second | 142 | * @ratekbps: rate in Kbits per second |
143 | * @user_ratekbps: user rate in Kbits per second | 143 | * @user_ratekbps: user rate in Kbits per second |
144 | * @ratecode: rate that goes into HW descriptors | 144 | * @ratecode: rate that goes into HW descriptors |
145 | * @short_preamble: Mask for enabling short preamble in ratecode for CCK | ||
146 | * @dot11rate: value that goes into supported | 145 | * @dot11rate: value that goes into supported |
147 | * rates info element of MLME | 146 | * rates info element of MLME |
148 | * @ctrl_rate: Index of next lower basic rate, used for duration computation | 147 | * @ctrl_rate: Index of next lower basic rate, used for duration computation |
149 | * @max_4ms_framelen: maximum frame length(bytes) for tx duration | 148 | * @cw40index: Index of rates having 40MHz channel width |
149 | * @sgi_index: Index of rates having Short Guard Interval | ||
150 | * @ht_index: high throughput rates having 40MHz channel width and | ||
151 | * Short Guard Interval | ||
150 | * @probe_interval: interval for rate control to probe for other rates | 152 | * @probe_interval: interval for rate control to probe for other rates |
151 | * @rssi_reduce_interval: interval for rate control to reduce rssi | ||
152 | * @initial_ratemax: initial ratemax value | 153 | * @initial_ratemax: initial ratemax value |
153 | */ | 154 | */ |
154 | struct ath_rate_table { | 155 | struct ath_rate_table { |
@@ -175,6 +176,13 @@ struct ath_rateset { | |||
175 | u8 rs_rates[ATH_RATE_MAX]; | 176 | u8 rs_rates[ATH_RATE_MAX]; |
176 | }; | 177 | }; |
177 | 178 | ||
179 | struct ath_rc_stats { | ||
180 | u32 success; | ||
181 | u32 retries; | ||
182 | u32 xretries; | ||
183 | u8 per; | ||
184 | }; | ||
185 | |||
178 | /** | 186 | /** |
179 | * struct ath_rate_priv - Rate Control priv data | 187 | * struct ath_rate_priv - Rate Control priv data |
180 | * @state: RC state | 188 | * @state: RC state |
@@ -187,7 +195,6 @@ struct ath_rateset { | |||
187 | * @rate_max_phy: phy index for the max rate | 195 | * @rate_max_phy: phy index for the max rate |
188 | * @per: PER for every valid rate in % | 196 | * @per: PER for every valid rate in % |
189 | * @probe_interval: interval for ratectrl to probe for other rates | 197 | * @probe_interval: interval for ratectrl to probe for other rates |
190 | * @prev_data_rix: rate idx of last data frame | ||
191 | * @ht_cap: HT capabilities | 198 | * @ht_cap: HT capabilities |
192 | * @neg_rates: Negotatied rates | 199 | * @neg_rates: Negotatied rates |
193 | * @neg_ht_rates: Negotiated HT rates | 200 | * @neg_ht_rates: Negotiated HT rates |
@@ -206,17 +213,13 @@ struct ath_rate_priv { | |||
206 | u32 probe_time; | 213 | u32 probe_time; |
207 | u32 per_down_time; | 214 | u32 per_down_time; |
208 | u32 probe_interval; | 215 | u32 probe_interval; |
209 | u32 prev_data_rix; | ||
210 | u32 tx_triglevel_max; | ||
211 | struct ath_rateset neg_rates; | 216 | struct ath_rateset neg_rates; |
212 | struct ath_rateset neg_ht_rates; | 217 | struct ath_rateset neg_ht_rates; |
213 | struct ath_rate_softc *asc; | 218 | const struct ath_rate_table *rate_table; |
214 | }; | ||
215 | 219 | ||
216 | #define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0) | 220 | struct dentry *debugfs_rcstats; |
217 | #define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1) | 221 | struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; |
218 | #define ATH_TX_INFO_XRETRY (1 << 3) | 222 | }; |
219 | #define ATH_TX_INFO_UNDERRUN (1 << 4) | ||
220 | 223 | ||
221 | enum ath9k_internal_frame_type { | 224 | enum ath9k_internal_frame_type { |
222 | ATH9K_IFT_NOT_INTERNAL, | 225 | ATH9K_IFT_NOT_INTERNAL, |
@@ -224,7 +227,18 @@ enum ath9k_internal_frame_type { | |||
224 | ATH9K_IFT_UNPAUSE | 227 | ATH9K_IFT_UNPAUSE |
225 | }; | 228 | }; |
226 | 229 | ||
230 | #ifdef CONFIG_ATH9K_RATE_CONTROL | ||
227 | int ath_rate_control_register(void); | 231 | int ath_rate_control_register(void); |
228 | void ath_rate_control_unregister(void); | 232 | void ath_rate_control_unregister(void); |
233 | #else | ||
234 | static inline int ath_rate_control_register(void) | ||
235 | { | ||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static inline void ath_rate_control_unregister(void) | ||
240 | { | ||
241 | } | ||
242 | #endif | ||
229 | 243 | ||
230 | #endif /* RC_H */ | 244 | #endif /* RC_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index a3fc987ebab0..07e35e59c9e3 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -19,31 +19,46 @@ | |||
19 | 19 | ||
20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) | 20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) |
21 | 21 | ||
22 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 22 | static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, |
23 | int mindelta, int main_rssi_avg, | ||
24 | int alt_rssi_avg, int pkt_count) | ||
23 | { | 25 | { |
24 | return sc->ps_enabled && | 26 | return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && |
25 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP); | 27 | (alt_rssi_avg > main_rssi_avg + maxdelta)) || |
28 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | ||
26 | } | 29 | } |
27 | 30 | ||
28 | static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, | 31 | static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, |
29 | struct ieee80211_hdr *hdr) | 32 | int curr_main_set, int curr_alt_set, |
33 | int alt_rssi_avg, int main_rssi_avg) | ||
30 | { | 34 | { |
31 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | 35 | bool result = false; |
32 | int i; | 36 | switch (div_group) { |
33 | 37 | case 0: | |
34 | spin_lock_bh(&sc->wiphy_lock); | 38 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) |
35 | for (i = 0; i < sc->num_sec_wiphy; i++) { | 39 | result = true; |
36 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | 40 | break; |
37 | if (aphy == NULL) | 41 | case 1: |
38 | continue; | 42 | if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && |
39 | if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr) | 43 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && |
40 | == 0) { | 44 | (alt_rssi_avg >= (main_rssi_avg - 5))) || |
41 | hw = aphy->hw; | 45 | ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && |
42 | break; | 46 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && |
43 | } | 47 | (alt_rssi_avg >= (main_rssi_avg - 2)))) && |
48 | (alt_rssi_avg >= 4)) | ||
49 | result = true; | ||
50 | else | ||
51 | result = false; | ||
52 | break; | ||
44 | } | 53 | } |
45 | spin_unlock_bh(&sc->wiphy_lock); | 54 | |
46 | return hw; | 55 | return result; |
56 | } | ||
57 | |||
58 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | ||
59 | { | ||
60 | return sc->ps_enabled && | ||
61 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP); | ||
47 | } | 62 | } |
48 | 63 | ||
49 | /* | 64 | /* |
@@ -87,7 +102,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) | |||
87 | *sc->rx.rxlink = bf->bf_daddr; | 102 | *sc->rx.rxlink = bf->bf_daddr; |
88 | 103 | ||
89 | sc->rx.rxlink = &ds->ds_link; | 104 | sc->rx.rxlink = &ds->ds_link; |
90 | ath9k_hw_rxena(ah); | ||
91 | } | 105 | } |
92 | 106 | ||
93 | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) | 107 | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) |
@@ -110,8 +124,7 @@ static void ath_opmode_init(struct ath_softc *sc) | |||
110 | ath9k_hw_setrxfilter(ah, rfilt); | 124 | ath9k_hw_setrxfilter(ah, rfilt); |
111 | 125 | ||
112 | /* configure bssid mask */ | 126 | /* configure bssid mask */ |
113 | if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) | 127 | ath_hw_setbssidmask(common); |
114 | ath_hw_setbssidmask(common); | ||
115 | 128 | ||
116 | /* configure operational mode */ | 129 | /* configure operational mode */ |
117 | ath9k_hw_setopmode(ah); | 130 | ath9k_hw_setopmode(ah); |
@@ -157,7 +170,7 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc, | |||
157 | u32 nbuf = 0; | 170 | u32 nbuf = 0; |
158 | 171 | ||
159 | if (list_empty(&sc->rx.rxbuf)) { | 172 | if (list_empty(&sc->rx.rxbuf)) { |
160 | ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n"); | 173 | ath_dbg(common, ATH_DBG_QUEUE, "No free rx buf available\n"); |
161 | return; | 174 | return; |
162 | } | 175 | } |
163 | 176 | ||
@@ -222,11 +235,6 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
222 | int error = 0, i; | 235 | int error = 0, i; |
223 | u32 size; | 236 | u32 size; |
224 | 237 | ||
225 | |||
226 | common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN + | ||
227 | ah->caps.rx_status_len, | ||
228 | min(common->cachelsz, (u16)64)); | ||
229 | |||
230 | ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - | 238 | ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize - |
231 | ah->caps.rx_status_len); | 239 | ah->caps.rx_status_len); |
232 | 240 | ||
@@ -260,7 +268,8 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) | |||
260 | bf->bf_buf_addr))) { | 268 | bf->bf_buf_addr))) { |
261 | dev_kfree_skb_any(skb); | 269 | dev_kfree_skb_any(skb); |
262 | bf->bf_mpdu = NULL; | 270 | bf->bf_mpdu = NULL; |
263 | ath_print(common, ATH_DBG_FATAL, | 271 | bf->bf_buf_addr = 0; |
272 | ath_err(common, | ||
264 | "dma_mapping_error() on RX init\n"); | 273 | "dma_mapping_error() on RX init\n"); |
265 | error = -ENOMEM; | 274 | error = -ENOMEM; |
266 | goto rx_init_fail; | 275 | goto rx_init_fail; |
@@ -288,19 +297,17 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
288 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP, | 297 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP, |
289 | sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize); | 298 | sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize); |
290 | 299 | ||
291 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
292 | |||
293 | ath_opmode_init(sc); | 300 | ath_opmode_init(sc); |
294 | 301 | ||
295 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_SCANNING)); | 302 | ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); |
303 | |||
304 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
296 | } | 305 | } |
297 | 306 | ||
298 | static void ath_edma_stop_recv(struct ath_softc *sc) | 307 | static void ath_edma_stop_recv(struct ath_softc *sc) |
299 | { | 308 | { |
300 | spin_lock_bh(&sc->rx.rxbuflock); | ||
301 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); | 309 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP); |
302 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); | 310 | ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP); |
303 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
304 | } | 311 | } |
305 | 312 | ||
306 | int ath_rx_init(struct ath_softc *sc, int nbufs) | 313 | int ath_rx_init(struct ath_softc *sc, int nbufs) |
@@ -310,27 +317,27 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
310 | struct ath_buf *bf; | 317 | struct ath_buf *bf; |
311 | int error = 0; | 318 | int error = 0; |
312 | 319 | ||
313 | spin_lock_init(&sc->rx.rxflushlock); | 320 | spin_lock_init(&sc->sc_pcu_lock); |
314 | sc->sc_flags &= ~SC_OP_RXFLUSH; | 321 | sc->sc_flags &= ~SC_OP_RXFLUSH; |
315 | spin_lock_init(&sc->rx.rxbuflock); | 322 | spin_lock_init(&sc->rx.rxbuflock); |
316 | 323 | ||
324 | common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + | ||
325 | sc->sc_ah->caps.rx_status_len; | ||
326 | |||
317 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 327 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
318 | return ath_rx_edma_init(sc, nbufs); | 328 | return ath_rx_edma_init(sc, nbufs); |
319 | } else { | 329 | } else { |
320 | common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN, | 330 | ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", |
321 | min(common->cachelsz, (u16)64)); | 331 | common->cachelsz, common->rx_bufsize); |
322 | |||
323 | ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", | ||
324 | common->cachelsz, common->rx_bufsize); | ||
325 | 332 | ||
326 | /* Initialize rx descriptors */ | 333 | /* Initialize rx descriptors */ |
327 | 334 | ||
328 | error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, | 335 | error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, |
329 | "rx", nbufs, 1, 0); | 336 | "rx", nbufs, 1, 0); |
330 | if (error != 0) { | 337 | if (error != 0) { |
331 | ath_print(common, ATH_DBG_FATAL, | 338 | ath_err(common, |
332 | "failed to allocate rx descriptors: %d\n", | 339 | "failed to allocate rx descriptors: %d\n", |
333 | error); | 340 | error); |
334 | goto err; | 341 | goto err; |
335 | } | 342 | } |
336 | 343 | ||
@@ -350,12 +357,12 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
350 | bf->bf_buf_addr))) { | 357 | bf->bf_buf_addr))) { |
351 | dev_kfree_skb_any(skb); | 358 | dev_kfree_skb_any(skb); |
352 | bf->bf_mpdu = NULL; | 359 | bf->bf_mpdu = NULL; |
353 | ath_print(common, ATH_DBG_FATAL, | 360 | bf->bf_buf_addr = 0; |
354 | "dma_mapping_error() on RX init\n"); | 361 | ath_err(common, |
362 | "dma_mapping_error() on RX init\n"); | ||
355 | error = -ENOMEM; | 363 | error = -ENOMEM; |
356 | goto err; | 364 | goto err; |
357 | } | 365 | } |
358 | bf->bf_dmacontext = bf->bf_buf_addr; | ||
359 | } | 366 | } |
360 | sc->rx.rxlink = NULL; | 367 | sc->rx.rxlink = NULL; |
361 | } | 368 | } |
@@ -385,6 +392,8 @@ void ath_rx_cleanup(struct ath_softc *sc) | |||
385 | common->rx_bufsize, | 392 | common->rx_bufsize, |
386 | DMA_FROM_DEVICE); | 393 | DMA_FROM_DEVICE); |
387 | dev_kfree_skb(skb); | 394 | dev_kfree_skb(skb); |
395 | bf->bf_buf_addr = 0; | ||
396 | bf->bf_mpdu = NULL; | ||
388 | } | 397 | } |
389 | } | 398 | } |
390 | 399 | ||
@@ -422,8 +431,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
422 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | 431 | | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
423 | | ATH9K_RX_FILTER_MCAST; | 432 | | ATH9K_RX_FILTER_MCAST; |
424 | 433 | ||
425 | /* If not a STA, enable processing of Probe Requests */ | 434 | if (sc->rx.rxfilter & FIF_PROBE_REQ) |
426 | if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) | ||
427 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; | 435 | rfilt |= ATH9K_RX_FILTER_PROBEREQ; |
428 | 436 | ||
429 | /* | 437 | /* |
@@ -431,32 +439,27 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
431 | * mode interface or when in monitor mode. AP mode does not need this | 439 | * mode interface or when in monitor mode. AP mode does not need this |
432 | * since it receives all in-BSS frames anyway. | 440 | * since it receives all in-BSS frames anyway. |
433 | */ | 441 | */ |
434 | if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && | 442 | if (sc->sc_ah->is_monitoring) |
435 | (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || | ||
436 | (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR)) | ||
437 | rfilt |= ATH9K_RX_FILTER_PROM; | 443 | rfilt |= ATH9K_RX_FILTER_PROM; |
438 | 444 | ||
439 | if (sc->rx.rxfilter & FIF_CONTROL) | 445 | if (sc->rx.rxfilter & FIF_CONTROL) |
440 | rfilt |= ATH9K_RX_FILTER_CONTROL; | 446 | rfilt |= ATH9K_RX_FILTER_CONTROL; |
441 | 447 | ||
442 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && | 448 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && |
449 | (sc->nvifs <= 1) && | ||
443 | !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) | 450 | !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) |
444 | rfilt |= ATH9K_RX_FILTER_MYBEACON; | 451 | rfilt |= ATH9K_RX_FILTER_MYBEACON; |
445 | else | 452 | else |
446 | rfilt |= ATH9K_RX_FILTER_BEACON; | 453 | rfilt |= ATH9K_RX_FILTER_BEACON; |
447 | 454 | ||
448 | if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) || | 455 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || |
449 | AR_SREV_9285_10_OR_LATER(sc->sc_ah)) && | ||
450 | (sc->sc_ah->opmode == NL80211_IFTYPE_AP) && | ||
451 | (sc->rx.rxfilter & FIF_PSPOLL)) | 456 | (sc->rx.rxfilter & FIF_PSPOLL)) |
452 | rfilt |= ATH9K_RX_FILTER_PSPOLL; | 457 | rfilt |= ATH9K_RX_FILTER_PSPOLL; |
453 | 458 | ||
454 | if (conf_is_ht(&sc->hw->conf)) | 459 | if (conf_is_ht(&sc->hw->conf)) |
455 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | 460 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; |
456 | 461 | ||
457 | if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) { | 462 | if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) { |
458 | /* TODO: only needed if more than one BSSID is in use in | ||
459 | * station/adhoc mode */ | ||
460 | /* The following may also be needed for other older chips */ | 463 | /* The following may also be needed for other older chips */ |
461 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) | 464 | if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) |
462 | rfilt |= ATH9K_RX_FILTER_PROM; | 465 | rfilt |= ATH9K_RX_FILTER_PROM; |
@@ -496,9 +499,10 @@ int ath_startrecv(struct ath_softc *sc) | |||
496 | ath9k_hw_rxena(ah); | 499 | ath9k_hw_rxena(ah); |
497 | 500 | ||
498 | start_recv: | 501 | start_recv: |
499 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
500 | ath_opmode_init(sc); | 502 | ath_opmode_init(sc); |
501 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_SCANNING)); | 503 | ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL)); |
504 | |||
505 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
502 | 506 | ||
503 | return 0; | 507 | return 0; |
504 | } | 508 | } |
@@ -506,29 +510,36 @@ start_recv: | |||
506 | bool ath_stoprecv(struct ath_softc *sc) | 510 | bool ath_stoprecv(struct ath_softc *sc) |
507 | { | 511 | { |
508 | struct ath_hw *ah = sc->sc_ah; | 512 | struct ath_hw *ah = sc->sc_ah; |
509 | bool stopped; | 513 | bool stopped, reset = false; |
510 | 514 | ||
511 | ath9k_hw_stoppcurecv(ah); | 515 | spin_lock_bh(&sc->rx.rxbuflock); |
516 | ath9k_hw_abortpcurecv(ah); | ||
512 | ath9k_hw_setrxfilter(ah, 0); | 517 | ath9k_hw_setrxfilter(ah, 0); |
513 | stopped = ath9k_hw_stopdmarecv(ah); | 518 | stopped = ath9k_hw_stopdmarecv(ah, &reset); |
514 | 519 | ||
515 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 520 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
516 | ath_edma_stop_recv(sc); | 521 | ath_edma_stop_recv(sc); |
517 | else | 522 | else |
518 | sc->rx.rxlink = NULL; | 523 | sc->rx.rxlink = NULL; |
524 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
519 | 525 | ||
520 | return stopped; | 526 | if (!(ah->ah_flags & AH_UNPLUGGED) && |
527 | unlikely(!stopped)) { | ||
528 | ath_err(ath9k_hw_common(sc->sc_ah), | ||
529 | "Could not stop RX, we could be " | ||
530 | "confusing the DMA engine when we start RX up\n"); | ||
531 | ATH_DBG_WARN_ON_ONCE(!stopped); | ||
532 | } | ||
533 | return stopped && !reset; | ||
521 | } | 534 | } |
522 | 535 | ||
523 | void ath_flushrecv(struct ath_softc *sc) | 536 | void ath_flushrecv(struct ath_softc *sc) |
524 | { | 537 | { |
525 | spin_lock_bh(&sc->rx.rxflushlock); | ||
526 | sc->sc_flags |= SC_OP_RXFLUSH; | 538 | sc->sc_flags |= SC_OP_RXFLUSH; |
527 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 539 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
528 | ath_rx_tasklet(sc, 1, true); | 540 | ath_rx_tasklet(sc, 1, true); |
529 | ath_rx_tasklet(sc, 1, false); | 541 | ath_rx_tasklet(sc, 1, false); |
530 | sc->sc_flags &= ~SC_OP_RXFLUSH; | 542 | sc->sc_flags &= ~SC_OP_RXFLUSH; |
531 | spin_unlock_bh(&sc->rx.rxflushlock); | ||
532 | } | 543 | } |
533 | 544 | ||
534 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) | 545 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) |
@@ -572,17 +583,23 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
572 | return; | 583 | return; |
573 | 584 | ||
574 | mgmt = (struct ieee80211_mgmt *)skb->data; | 585 | mgmt = (struct ieee80211_mgmt *)skb->data; |
575 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) | 586 | if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) { |
587 | /* TODO: This doesn't work well if you have stations | ||
588 | * associated to two different APs because curbssid | ||
589 | * is just the last AP that any of the stations associated | ||
590 | * with. | ||
591 | */ | ||
576 | return; /* not from our current AP */ | 592 | return; /* not from our current AP */ |
593 | } | ||
577 | 594 | ||
578 | sc->ps_flags &= ~PS_WAIT_FOR_BEACON; | 595 | sc->ps_flags &= ~PS_WAIT_FOR_BEACON; |
579 | 596 | ||
580 | if (sc->ps_flags & PS_BEACON_SYNC) { | 597 | if (sc->ps_flags & PS_BEACON_SYNC) { |
581 | sc->ps_flags &= ~PS_BEACON_SYNC; | 598 | sc->ps_flags &= ~PS_BEACON_SYNC; |
582 | ath_print(common, ATH_DBG_PS, | 599 | ath_dbg(common, ATH_DBG_PS, |
583 | "Reconfigure Beacon timers based on " | 600 | "Reconfigure Beacon timers based on timestamp from the AP\n"); |
584 | "timestamp from the AP\n"); | 601 | ath_set_beacon(sc); |
585 | ath_beacon_config(sc, NULL); | 602 | sc->ps_flags &= ~PS_TSFOOR_SYNC; |
586 | } | 603 | } |
587 | 604 | ||
588 | if (ath_beacon_dtim_pending_cab(skb)) { | 605 | if (ath_beacon_dtim_pending_cab(skb)) { |
@@ -593,8 +610,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
593 | * a backup trigger for returning into NETWORK SLEEP state, | 610 | * a backup trigger for returning into NETWORK SLEEP state, |
594 | * so we are waiting for it as well. | 611 | * so we are waiting for it as well. |
595 | */ | 612 | */ |
596 | ath_print(common, ATH_DBG_PS, "Received DTIM beacon indicating " | 613 | ath_dbg(common, ATH_DBG_PS, |
597 | "buffered broadcast/multicast frame(s)\n"); | 614 | "Received DTIM beacon indicating buffered broadcast/multicast frame(s)\n"); |
598 | sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON; | 615 | sc->ps_flags |= PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON; |
599 | return; | 616 | return; |
600 | } | 617 | } |
@@ -606,8 +623,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
606 | * been delivered. | 623 | * been delivered. |
607 | */ | 624 | */ |
608 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; | 625 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; |
609 | ath_print(common, ATH_DBG_PS, | 626 | ath_dbg(common, ATH_DBG_PS, |
610 | "PS wait for CAB frames timed out\n"); | 627 | "PS wait for CAB frames timed out\n"); |
611 | } | 628 | } |
612 | } | 629 | } |
613 | 630 | ||
@@ -631,16 +648,15 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
631 | * No more broadcast/multicast frames to be received at this | 648 | * No more broadcast/multicast frames to be received at this |
632 | * point. | 649 | * point. |
633 | */ | 650 | */ |
634 | sc->ps_flags &= ~PS_WAIT_FOR_CAB; | 651 | sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON); |
635 | ath_print(common, ATH_DBG_PS, | 652 | ath_dbg(common, ATH_DBG_PS, |
636 | "All PS CAB frames received, back to sleep\n"); | 653 | "All PS CAB frames received, back to sleep\n"); |
637 | } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && | 654 | } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) && |
638 | !is_multicast_ether_addr(hdr->addr1) && | 655 | !is_multicast_ether_addr(hdr->addr1) && |
639 | !ieee80211_has_morefrags(hdr->frame_control)) { | 656 | !ieee80211_has_morefrags(hdr->frame_control)) { |
640 | sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA; | 657 | sc->ps_flags &= ~PS_WAIT_FOR_PSPOLL_DATA; |
641 | ath_print(common, ATH_DBG_PS, | 658 | ath_dbg(common, ATH_DBG_PS, |
642 | "Going back to sleep after having received " | 659 | "Going back to sleep after having received PS-Poll data (0x%lx)\n", |
643 | "PS-Poll data (0x%lx)\n", | ||
644 | sc->ps_flags & (PS_WAIT_FOR_BEACON | | 660 | sc->ps_flags & (PS_WAIT_FOR_BEACON | |
645 | PS_WAIT_FOR_CAB | | 661 | PS_WAIT_FOR_CAB | |
646 | PS_WAIT_FOR_PSPOLL_DATA | | 662 | PS_WAIT_FOR_PSPOLL_DATA | |
@@ -648,38 +664,6 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
648 | } | 664 | } |
649 | } | 665 | } |
650 | 666 | ||
651 | static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, | ||
652 | struct ath_softc *sc, struct sk_buff *skb, | ||
653 | struct ieee80211_rx_status *rxs) | ||
654 | { | ||
655 | struct ieee80211_hdr *hdr; | ||
656 | |||
657 | hdr = (struct ieee80211_hdr *)skb->data; | ||
658 | |||
659 | /* Send the frame to mac80211 */ | ||
660 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
661 | int i; | ||
662 | /* | ||
663 | * Deliver broadcast/multicast frames to all suitable | ||
664 | * virtual wiphys. | ||
665 | */ | ||
666 | /* TODO: filter based on channel configuration */ | ||
667 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
668 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
669 | struct sk_buff *nskb; | ||
670 | if (aphy == NULL) | ||
671 | continue; | ||
672 | nskb = skb_copy(skb, GFP_ATOMIC); | ||
673 | if (!nskb) | ||
674 | continue; | ||
675 | ieee80211_rx(aphy->hw, nskb); | ||
676 | } | ||
677 | ieee80211_rx(sc->hw, skb); | ||
678 | } else | ||
679 | /* Deliver unicast frames based on receiver address */ | ||
680 | ieee80211_rx(hw, skb); | ||
681 | } | ||
682 | |||
683 | static bool ath_edma_get_buffers(struct ath_softc *sc, | 667 | static bool ath_edma_get_buffers(struct ath_softc *sc, |
684 | enum ath9k_rx_qtype qtype) | 668 | enum ath9k_rx_qtype qtype) |
685 | { | 669 | { |
@@ -829,6 +813,10 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
829 | struct ath_rx_status *rx_stats, | 813 | struct ath_rx_status *rx_stats, |
830 | bool *decrypt_error) | 814 | bool *decrypt_error) |
831 | { | 815 | { |
816 | #define is_mc_or_valid_tkip_keyix ((is_mc || \ | ||
817 | (rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && \ | ||
818 | test_bit(rx_stats->rs_keyix, common->tkip_keymap)))) | ||
819 | |||
832 | struct ath_hw *ah = common->ah; | 820 | struct ath_hw *ah = common->ah; |
833 | __le16 fc; | 821 | __le16 fc; |
834 | u8 rx_status_len = ah->caps.rx_status_len; | 822 | u8 rx_status_len = ah->caps.rx_status_len; |
@@ -845,15 +833,9 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
845 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) | 833 | if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len)) |
846 | return false; | 834 | return false; |
847 | 835 | ||
848 | /* | 836 | /* Only use error bits from the last fragment */ |
849 | * rs_more indicates chained descriptors which can be used | ||
850 | * to link buffers together for a sort of scatter-gather | ||
851 | * operation. | ||
852 | * reject the frame, we don't support scatter-gather yet and | ||
853 | * the frame is probably corrupt anyway | ||
854 | */ | ||
855 | if (rx_stats->rs_more) | 837 | if (rx_stats->rs_more) |
856 | return false; | 838 | return true; |
857 | 839 | ||
858 | /* | 840 | /* |
859 | * The rx_stats->rs_status will not be set until the end of the | 841 | * The rx_stats->rs_status will not be set until the end of the |
@@ -870,22 +852,28 @@ static bool ath9k_rx_accept(struct ath_common *common, | |||
870 | if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { | 852 | if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { |
871 | *decrypt_error = true; | 853 | *decrypt_error = true; |
872 | } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { | 854 | } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { |
873 | if (ieee80211_is_ctl(fc)) | 855 | bool is_mc; |
874 | /* | 856 | /* |
875 | * Sometimes, we get invalid | 857 | * The MIC error bit is only valid if the frame |
876 | * MIC failures on valid control frames. | 858 | * is not a control frame or fragment, and it was |
877 | * Remove these mic errors. | 859 | * decrypted using a valid TKIP key. |
878 | */ | 860 | */ |
879 | rx_stats->rs_status &= ~ATH9K_RXERR_MIC; | 861 | is_mc = !!is_multicast_ether_addr(hdr->addr1); |
880 | else | 862 | |
863 | if (!ieee80211_is_ctl(fc) && | ||
864 | !ieee80211_has_morefrags(fc) && | ||
865 | !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && | ||
866 | is_mc_or_valid_tkip_keyix) | ||
881 | rxs->flag |= RX_FLAG_MMIC_ERROR; | 867 | rxs->flag |= RX_FLAG_MMIC_ERROR; |
868 | else | ||
869 | rx_stats->rs_status &= ~ATH9K_RXERR_MIC; | ||
882 | } | 870 | } |
883 | /* | 871 | /* |
884 | * Reject error frames with the exception of | 872 | * Reject error frames with the exception of |
885 | * decryption and MIC failures. For monitor mode, | 873 | * decryption and MIC failures. For monitor mode, |
886 | * we also ignore the CRC error. | 874 | * we also ignore the CRC error. |
887 | */ | 875 | */ |
888 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { | 876 | if (ah->is_monitoring) { |
889 | if (rx_stats->rs_status & | 877 | if (rx_stats->rs_status & |
890 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | | 878 | ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | |
891 | ATH9K_RXERR_CRC)) | 879 | ATH9K_RXERR_CRC)) |
@@ -939,8 +927,9 @@ static int ath9k_process_rate(struct ath_common *common, | |||
939 | * No valid hardware bitrate found -- we should not get here | 927 | * No valid hardware bitrate found -- we should not get here |
940 | * because hardware has already validated this frame as OK. | 928 | * because hardware has already validated this frame as OK. |
941 | */ | 929 | */ |
942 | ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " | 930 | ath_dbg(common, ATH_DBG_XMIT, |
943 | "0x%02x using 1 Mbit\n", rx_stats->rs_rate); | 931 | "unsupported hw bitrate detected 0x%02x using 1 Mbit\n", |
932 | rx_stats->rs_rate); | ||
944 | 933 | ||
945 | return -EINVAL; | 934 | return -EINVAL; |
946 | } | 935 | } |
@@ -950,32 +939,30 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
950 | struct ieee80211_hdr *hdr, | 939 | struct ieee80211_hdr *hdr, |
951 | struct ath_rx_status *rx_stats) | 940 | struct ath_rx_status *rx_stats) |
952 | { | 941 | { |
942 | struct ath_softc *sc = hw->priv; | ||
953 | struct ath_hw *ah = common->ah; | 943 | struct ath_hw *ah = common->ah; |
954 | struct ieee80211_sta *sta; | 944 | int last_rssi; |
955 | struct ath_node *an; | ||
956 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
957 | __le16 fc; | 945 | __le16 fc; |
958 | 946 | ||
959 | fc = hdr->frame_control; | 947 | if ((ah->opmode != NL80211_IFTYPE_STATION) && |
948 | (ah->opmode != NL80211_IFTYPE_ADHOC)) | ||
949 | return; | ||
960 | 950 | ||
961 | rcu_read_lock(); | 951 | fc = hdr->frame_control; |
962 | /* | 952 | if (!ieee80211_is_beacon(fc) || |
963 | * XXX: use ieee80211_find_sta! This requires quite a bit of work | 953 | compare_ether_addr(hdr->addr3, common->curbssid)) { |
964 | * under the current ath9k virtual wiphy implementation as we have | 954 | /* TODO: This doesn't work well if you have stations |
965 | * no way of tying a vif to wiphy. Typically vifs are attached to | 955 | * associated to two different APs because curbssid |
966 | * at least one sdata of a wiphy on mac80211 but with ath9k virtual | 956 | * is just the last AP that any of the stations associated |
967 | * wiphy you'd have to iterate over every wiphy and each sdata. | 957 | * with. |
968 | */ | 958 | */ |
969 | sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); | 959 | return; |
970 | if (sta) { | ||
971 | an = (struct ath_node *) sta->drv_priv; | ||
972 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && | ||
973 | !rx_stats->rs_moreaggr) | ||
974 | ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi); | ||
975 | last_rssi = an->last_rssi; | ||
976 | } | 960 | } |
977 | rcu_read_unlock(); | ||
978 | 961 | ||
962 | if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr) | ||
963 | ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi); | ||
964 | |||
965 | last_rssi = sc->last_rssi; | ||
979 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 966 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
980 | rx_stats->rs_rssi = ATH_EP_RND(last_rssi, | 967 | rx_stats->rs_rssi = ATH_EP_RND(last_rssi, |
981 | ATH_RSSI_EP_MULTIPLIER); | 968 | ATH_RSSI_EP_MULTIPLIER); |
@@ -983,8 +970,7 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
983 | rx_stats->rs_rssi = 0; | 970 | rx_stats->rs_rssi = 0; |
984 | 971 | ||
985 | /* Update Beacon RSSI, this is used by ANI. */ | 972 | /* Update Beacon RSSI, this is used by ANI. */ |
986 | if (ieee80211_is_beacon(fc)) | 973 | ah->stats.avgbrssi = rx_stats->rs_rssi; |
987 | ah->stats.avgbrssi = rx_stats->rs_rssi; | ||
988 | } | 974 | } |
989 | 975 | ||
990 | /* | 976 | /* |
@@ -1008,6 +994,10 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, | |||
1008 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) | 994 | if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error)) |
1009 | return -EINVAL; | 995 | return -EINVAL; |
1010 | 996 | ||
997 | /* Only use status info from the last fragment */ | ||
998 | if (rx_stats->rs_more) | ||
999 | return 0; | ||
1000 | |||
1011 | ath9k_process_rssi(common, hw, hdr, rx_stats); | 1001 | ath9k_process_rssi(common, hw, hdr, rx_stats); |
1012 | 1002 | ||
1013 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) | 1003 | if (ath9k_process_rate(common, hw, rx_stats, rx_status)) |
@@ -1017,7 +1007,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, | |||
1017 | rx_status->freq = hw->conf.channel->center_freq; | 1007 | rx_status->freq = hw->conf.channel->center_freq; |
1018 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; | 1008 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; |
1019 | rx_status->antenna = rx_stats->rs_antenna; | 1009 | rx_status->antenna = rx_stats->rs_antenna; |
1020 | rx_status->flag |= RX_FLAG_TSFT; | 1010 | rx_status->flag |= RX_FLAG_MACTIME_MPDU; |
1021 | 1011 | ||
1022 | return 0; | 1012 | return 0; |
1023 | } | 1013 | } |
@@ -1073,19 +1063,641 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, | |||
1073 | rxs->flag &= ~RX_FLAG_DECRYPTED; | 1063 | rxs->flag &= ~RX_FLAG_DECRYPTED; |
1074 | } | 1064 | } |
1075 | 1065 | ||
1066 | static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb, | ||
1067 | struct ath_hw_antcomb_conf ant_conf, | ||
1068 | int main_rssi_avg) | ||
1069 | { | ||
1070 | antcomb->quick_scan_cnt = 0; | ||
1071 | |||
1072 | if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1073 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1074 | else if (ant_conf.main_lna_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1075 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1076 | |||
1077 | switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) { | ||
1078 | case (0x10): /* LNA2 A-B */ | ||
1079 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1080 | antcomb->first_quick_scan_conf = | ||
1081 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1082 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1083 | break; | ||
1084 | case (0x20): /* LNA1 A-B */ | ||
1085 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1086 | antcomb->first_quick_scan_conf = | ||
1087 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1088 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1089 | break; | ||
1090 | case (0x21): /* LNA1 LNA2 */ | ||
1091 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1092 | antcomb->first_quick_scan_conf = | ||
1093 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1094 | antcomb->second_quick_scan_conf = | ||
1095 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1096 | break; | ||
1097 | case (0x12): /* LNA2 LNA1 */ | ||
1098 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1099 | antcomb->first_quick_scan_conf = | ||
1100 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1101 | antcomb->second_quick_scan_conf = | ||
1102 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1103 | break; | ||
1104 | case (0x13): /* LNA2 A+B */ | ||
1105 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1106 | antcomb->first_quick_scan_conf = | ||
1107 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1108 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1109 | break; | ||
1110 | case (0x23): /* LNA1 A+B */ | ||
1111 | antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1112 | antcomb->first_quick_scan_conf = | ||
1113 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1114 | antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1115 | break; | ||
1116 | default: | ||
1117 | break; | ||
1118 | } | ||
1119 | } | ||
1120 | |||
1121 | static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | ||
1122 | struct ath_hw_antcomb_conf *div_ant_conf, | ||
1123 | int main_rssi_avg, int alt_rssi_avg, | ||
1124 | int alt_ratio) | ||
1125 | { | ||
1126 | /* alt_good */ | ||
1127 | switch (antcomb->quick_scan_cnt) { | ||
1128 | case 0: | ||
1129 | /* set alt to main, and alt to first conf */ | ||
1130 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1131 | div_ant_conf->alt_lna_conf = antcomb->first_quick_scan_conf; | ||
1132 | break; | ||
1133 | case 1: | ||
1134 | /* set alt to main, and alt to first conf */ | ||
1135 | div_ant_conf->main_lna_conf = antcomb->main_conf; | ||
1136 | div_ant_conf->alt_lna_conf = antcomb->second_quick_scan_conf; | ||
1137 | antcomb->rssi_first = main_rssi_avg; | ||
1138 | antcomb->rssi_second = alt_rssi_avg; | ||
1139 | |||
1140 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1141 | /* main is LNA1 */ | ||
1142 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1143 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1144 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1145 | main_rssi_avg, alt_rssi_avg, | ||
1146 | antcomb->total_pkt_count)) | ||
1147 | antcomb->first_ratio = true; | ||
1148 | else | ||
1149 | antcomb->first_ratio = false; | ||
1150 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1151 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1152 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1153 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1154 | main_rssi_avg, alt_rssi_avg, | ||
1155 | antcomb->total_pkt_count)) | ||
1156 | antcomb->first_ratio = true; | ||
1157 | else | ||
1158 | antcomb->first_ratio = false; | ||
1159 | } else { | ||
1160 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1161 | (alt_rssi_avg > main_rssi_avg + | ||
1162 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1163 | (alt_rssi_avg > main_rssi_avg)) && | ||
1164 | (antcomb->total_pkt_count > 50)) | ||
1165 | antcomb->first_ratio = true; | ||
1166 | else | ||
1167 | antcomb->first_ratio = false; | ||
1168 | } | ||
1169 | break; | ||
1170 | case 2: | ||
1171 | antcomb->alt_good = false; | ||
1172 | antcomb->scan_not_start = false; | ||
1173 | antcomb->scan = false; | ||
1174 | antcomb->rssi_first = main_rssi_avg; | ||
1175 | antcomb->rssi_third = alt_rssi_avg; | ||
1176 | |||
1177 | if (antcomb->second_quick_scan_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1178 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1179 | else if (antcomb->second_quick_scan_conf == | ||
1180 | ATH_ANT_DIV_COMB_LNA2) | ||
1181 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1182 | else if (antcomb->second_quick_scan_conf == | ||
1183 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2) { | ||
1184 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) | ||
1185 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1186 | else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) | ||
1187 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1188 | } | ||
1189 | |||
1190 | if (antcomb->rssi_lna2 > antcomb->rssi_lna1 + | ||
1191 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA) | ||
1192 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1193 | else | ||
1194 | div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1; | ||
1195 | |||
1196 | if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) { | ||
1197 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1198 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI, | ||
1199 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1200 | main_rssi_avg, alt_rssi_avg, | ||
1201 | antcomb->total_pkt_count)) | ||
1202 | antcomb->second_ratio = true; | ||
1203 | else | ||
1204 | antcomb->second_ratio = false; | ||
1205 | } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) { | ||
1206 | if (ath_is_alt_ant_ratio_better(alt_ratio, | ||
1207 | ATH_ANT_DIV_COMB_LNA1_DELTA_MID, | ||
1208 | ATH_ANT_DIV_COMB_LNA1_DELTA_LOW, | ||
1209 | main_rssi_avg, alt_rssi_avg, | ||
1210 | antcomb->total_pkt_count)) | ||
1211 | antcomb->second_ratio = true; | ||
1212 | else | ||
1213 | antcomb->second_ratio = false; | ||
1214 | } else { | ||
1215 | if ((((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) && | ||
1216 | (alt_rssi_avg > main_rssi_avg + | ||
1217 | ATH_ANT_DIV_COMB_LNA1_DELTA_HI)) || | ||
1218 | (alt_rssi_avg > main_rssi_avg)) && | ||
1219 | (antcomb->total_pkt_count > 50)) | ||
1220 | antcomb->second_ratio = true; | ||
1221 | else | ||
1222 | antcomb->second_ratio = false; | ||
1223 | } | ||
1224 | |||
1225 | /* set alt to the conf with maximun ratio */ | ||
1226 | if (antcomb->first_ratio && antcomb->second_ratio) { | ||
1227 | if (antcomb->rssi_second > antcomb->rssi_third) { | ||
1228 | /* first alt*/ | ||
1229 | if ((antcomb->first_quick_scan_conf == | ||
1230 | ATH_ANT_DIV_COMB_LNA1) || | ||
1231 | (antcomb->first_quick_scan_conf == | ||
1232 | ATH_ANT_DIV_COMB_LNA2)) | ||
1233 | /* Set alt LNA1 or LNA2*/ | ||
1234 | if (div_ant_conf->main_lna_conf == | ||
1235 | ATH_ANT_DIV_COMB_LNA2) | ||
1236 | div_ant_conf->alt_lna_conf = | ||
1237 | ATH_ANT_DIV_COMB_LNA1; | ||
1238 | else | ||
1239 | div_ant_conf->alt_lna_conf = | ||
1240 | ATH_ANT_DIV_COMB_LNA2; | ||
1241 | else | ||
1242 | /* Set alt to A+B or A-B */ | ||
1243 | div_ant_conf->alt_lna_conf = | ||
1244 | antcomb->first_quick_scan_conf; | ||
1245 | } else if ((antcomb->second_quick_scan_conf == | ||
1246 | ATH_ANT_DIV_COMB_LNA1) || | ||
1247 | (antcomb->second_quick_scan_conf == | ||
1248 | ATH_ANT_DIV_COMB_LNA2)) { | ||
1249 | /* Set alt LNA1 or LNA2 */ | ||
1250 | if (div_ant_conf->main_lna_conf == | ||
1251 | ATH_ANT_DIV_COMB_LNA2) | ||
1252 | div_ant_conf->alt_lna_conf = | ||
1253 | ATH_ANT_DIV_COMB_LNA1; | ||
1254 | else | ||
1255 | div_ant_conf->alt_lna_conf = | ||
1256 | ATH_ANT_DIV_COMB_LNA2; | ||
1257 | } else { | ||
1258 | /* Set alt to A+B or A-B */ | ||
1259 | div_ant_conf->alt_lna_conf = | ||
1260 | antcomb->second_quick_scan_conf; | ||
1261 | } | ||
1262 | } else if (antcomb->first_ratio) { | ||
1263 | /* first alt */ | ||
1264 | if ((antcomb->first_quick_scan_conf == | ||
1265 | ATH_ANT_DIV_COMB_LNA1) || | ||
1266 | (antcomb->first_quick_scan_conf == | ||
1267 | ATH_ANT_DIV_COMB_LNA2)) | ||
1268 | /* Set alt LNA1 or LNA2 */ | ||
1269 | if (div_ant_conf->main_lna_conf == | ||
1270 | ATH_ANT_DIV_COMB_LNA2) | ||
1271 | div_ant_conf->alt_lna_conf = | ||
1272 | ATH_ANT_DIV_COMB_LNA1; | ||
1273 | else | ||
1274 | div_ant_conf->alt_lna_conf = | ||
1275 | ATH_ANT_DIV_COMB_LNA2; | ||
1276 | else | ||
1277 | /* Set alt to A+B or A-B */ | ||
1278 | div_ant_conf->alt_lna_conf = | ||
1279 | antcomb->first_quick_scan_conf; | ||
1280 | } else if (antcomb->second_ratio) { | ||
1281 | /* second alt */ | ||
1282 | if ((antcomb->second_quick_scan_conf == | ||
1283 | ATH_ANT_DIV_COMB_LNA1) || | ||
1284 | (antcomb->second_quick_scan_conf == | ||
1285 | ATH_ANT_DIV_COMB_LNA2)) | ||
1286 | /* Set alt LNA1 or LNA2 */ | ||
1287 | if (div_ant_conf->main_lna_conf == | ||
1288 | ATH_ANT_DIV_COMB_LNA2) | ||
1289 | div_ant_conf->alt_lna_conf = | ||
1290 | ATH_ANT_DIV_COMB_LNA1; | ||
1291 | else | ||
1292 | div_ant_conf->alt_lna_conf = | ||
1293 | ATH_ANT_DIV_COMB_LNA2; | ||
1294 | else | ||
1295 | /* Set alt to A+B or A-B */ | ||
1296 | div_ant_conf->alt_lna_conf = | ||
1297 | antcomb->second_quick_scan_conf; | ||
1298 | } else { | ||
1299 | /* main is largest */ | ||
1300 | if ((antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) || | ||
1301 | (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2)) | ||
1302 | /* Set alt LNA1 or LNA2 */ | ||
1303 | if (div_ant_conf->main_lna_conf == | ||
1304 | ATH_ANT_DIV_COMB_LNA2) | ||
1305 | div_ant_conf->alt_lna_conf = | ||
1306 | ATH_ANT_DIV_COMB_LNA1; | ||
1307 | else | ||
1308 | div_ant_conf->alt_lna_conf = | ||
1309 | ATH_ANT_DIV_COMB_LNA2; | ||
1310 | else | ||
1311 | /* Set alt to A+B or A-B */ | ||
1312 | div_ant_conf->alt_lna_conf = antcomb->main_conf; | ||
1313 | } | ||
1314 | break; | ||
1315 | default: | ||
1316 | break; | ||
1317 | } | ||
1318 | } | ||
1319 | |||
1320 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, | ||
1321 | struct ath_ant_comb *antcomb, int alt_ratio) | ||
1322 | { | ||
1323 | if (ant_conf->div_group == 0) { | ||
1324 | /* Adjust the fast_div_bias based on main and alt lna conf */ | ||
1325 | switch ((ant_conf->main_lna_conf << 4) | | ||
1326 | ant_conf->alt_lna_conf) { | ||
1327 | case (0x01): /* A-B LNA2 */ | ||
1328 | ant_conf->fast_div_bias = 0x3b; | ||
1329 | break; | ||
1330 | case (0x02): /* A-B LNA1 */ | ||
1331 | ant_conf->fast_div_bias = 0x3d; | ||
1332 | break; | ||
1333 | case (0x03): /* A-B A+B */ | ||
1334 | ant_conf->fast_div_bias = 0x1; | ||
1335 | break; | ||
1336 | case (0x10): /* LNA2 A-B */ | ||
1337 | ant_conf->fast_div_bias = 0x7; | ||
1338 | break; | ||
1339 | case (0x12): /* LNA2 LNA1 */ | ||
1340 | ant_conf->fast_div_bias = 0x2; | ||
1341 | break; | ||
1342 | case (0x13): /* LNA2 A+B */ | ||
1343 | ant_conf->fast_div_bias = 0x7; | ||
1344 | break; | ||
1345 | case (0x20): /* LNA1 A-B */ | ||
1346 | ant_conf->fast_div_bias = 0x6; | ||
1347 | break; | ||
1348 | case (0x21): /* LNA1 LNA2 */ | ||
1349 | ant_conf->fast_div_bias = 0x0; | ||
1350 | break; | ||
1351 | case (0x23): /* LNA1 A+B */ | ||
1352 | ant_conf->fast_div_bias = 0x6; | ||
1353 | break; | ||
1354 | case (0x30): /* A+B A-B */ | ||
1355 | ant_conf->fast_div_bias = 0x1; | ||
1356 | break; | ||
1357 | case (0x31): /* A+B LNA2 */ | ||
1358 | ant_conf->fast_div_bias = 0x3b; | ||
1359 | break; | ||
1360 | case (0x32): /* A+B LNA1 */ | ||
1361 | ant_conf->fast_div_bias = 0x3d; | ||
1362 | break; | ||
1363 | default: | ||
1364 | break; | ||
1365 | } | ||
1366 | } else if (ant_conf->div_group == 2) { | ||
1367 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
1368 | switch ((ant_conf->main_lna_conf << 4) | | ||
1369 | ant_conf->alt_lna_conf) { | ||
1370 | case (0x01): /* A-B LNA2 */ | ||
1371 | ant_conf->fast_div_bias = 0x1; | ||
1372 | ant_conf->main_gaintb = 0; | ||
1373 | ant_conf->alt_gaintb = 0; | ||
1374 | break; | ||
1375 | case (0x02): /* A-B LNA1 */ | ||
1376 | ant_conf->fast_div_bias = 0x1; | ||
1377 | ant_conf->main_gaintb = 0; | ||
1378 | ant_conf->alt_gaintb = 0; | ||
1379 | break; | ||
1380 | case (0x03): /* A-B A+B */ | ||
1381 | ant_conf->fast_div_bias = 0x1; | ||
1382 | ant_conf->main_gaintb = 0; | ||
1383 | ant_conf->alt_gaintb = 0; | ||
1384 | break; | ||
1385 | case (0x10): /* LNA2 A-B */ | ||
1386 | if (!(antcomb->scan) && | ||
1387 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1388 | ant_conf->fast_div_bias = 0x1; | ||
1389 | else | ||
1390 | ant_conf->fast_div_bias = 0x2; | ||
1391 | ant_conf->main_gaintb = 0; | ||
1392 | ant_conf->alt_gaintb = 0; | ||
1393 | break; | ||
1394 | case (0x12): /* LNA2 LNA1 */ | ||
1395 | ant_conf->fast_div_bias = 0x1; | ||
1396 | ant_conf->main_gaintb = 0; | ||
1397 | ant_conf->alt_gaintb = 0; | ||
1398 | break; | ||
1399 | case (0x13): /* LNA2 A+B */ | ||
1400 | if (!(antcomb->scan) && | ||
1401 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1402 | ant_conf->fast_div_bias = 0x1; | ||
1403 | else | ||
1404 | ant_conf->fast_div_bias = 0x2; | ||
1405 | ant_conf->main_gaintb = 0; | ||
1406 | ant_conf->alt_gaintb = 0; | ||
1407 | break; | ||
1408 | case (0x20): /* LNA1 A-B */ | ||
1409 | if (!(antcomb->scan) && | ||
1410 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1411 | ant_conf->fast_div_bias = 0x1; | ||
1412 | else | ||
1413 | ant_conf->fast_div_bias = 0x2; | ||
1414 | ant_conf->main_gaintb = 0; | ||
1415 | ant_conf->alt_gaintb = 0; | ||
1416 | break; | ||
1417 | case (0x21): /* LNA1 LNA2 */ | ||
1418 | ant_conf->fast_div_bias = 0x1; | ||
1419 | ant_conf->main_gaintb = 0; | ||
1420 | ant_conf->alt_gaintb = 0; | ||
1421 | break; | ||
1422 | case (0x23): /* LNA1 A+B */ | ||
1423 | if (!(antcomb->scan) && | ||
1424 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1425 | ant_conf->fast_div_bias = 0x1; | ||
1426 | else | ||
1427 | ant_conf->fast_div_bias = 0x2; | ||
1428 | ant_conf->main_gaintb = 0; | ||
1429 | ant_conf->alt_gaintb = 0; | ||
1430 | break; | ||
1431 | case (0x30): /* A+B A-B */ | ||
1432 | ant_conf->fast_div_bias = 0x1; | ||
1433 | ant_conf->main_gaintb = 0; | ||
1434 | ant_conf->alt_gaintb = 0; | ||
1435 | break; | ||
1436 | case (0x31): /* A+B LNA2 */ | ||
1437 | ant_conf->fast_div_bias = 0x1; | ||
1438 | ant_conf->main_gaintb = 0; | ||
1439 | ant_conf->alt_gaintb = 0; | ||
1440 | break; | ||
1441 | case (0x32): /* A+B LNA1 */ | ||
1442 | ant_conf->fast_div_bias = 0x1; | ||
1443 | ant_conf->main_gaintb = 0; | ||
1444 | ant_conf->alt_gaintb = 0; | ||
1445 | break; | ||
1446 | default: | ||
1447 | break; | ||
1448 | } | ||
1449 | |||
1450 | } | ||
1451 | |||
1452 | } | ||
1453 | |||
1454 | /* Antenna diversity and combining */ | ||
1455 | static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | ||
1456 | { | ||
1457 | struct ath_hw_antcomb_conf div_ant_conf; | ||
1458 | struct ath_ant_comb *antcomb = &sc->ant_comb; | ||
1459 | int alt_ratio = 0, alt_rssi_avg = 0, main_rssi_avg = 0, curr_alt_set; | ||
1460 | int curr_main_set; | ||
1461 | int main_rssi = rs->rs_rssi_ctl0; | ||
1462 | int alt_rssi = rs->rs_rssi_ctl1; | ||
1463 | int rx_ant_conf, main_ant_conf; | ||
1464 | bool short_scan = false; | ||
1465 | |||
1466 | rx_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_CURRENT_SHIFT) & | ||
1467 | ATH_ANT_RX_MASK; | ||
1468 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | ||
1469 | ATH_ANT_RX_MASK; | ||
1470 | |||
1471 | /* Record packet only when both main_rssi and alt_rssi is positive */ | ||
1472 | if (main_rssi > 0 && alt_rssi > 0) { | ||
1473 | antcomb->total_pkt_count++; | ||
1474 | antcomb->main_total_rssi += main_rssi; | ||
1475 | antcomb->alt_total_rssi += alt_rssi; | ||
1476 | if (main_ant_conf == rx_ant_conf) | ||
1477 | antcomb->main_recv_cnt++; | ||
1478 | else | ||
1479 | antcomb->alt_recv_cnt++; | ||
1480 | } | ||
1481 | |||
1482 | /* Short scan check */ | ||
1483 | if (antcomb->scan && antcomb->alt_good) { | ||
1484 | if (time_after(jiffies, antcomb->scan_start_time + | ||
1485 | msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR))) | ||
1486 | short_scan = true; | ||
1487 | else | ||
1488 | if (antcomb->total_pkt_count == | ||
1489 | ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) { | ||
1490 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1491 | antcomb->total_pkt_count); | ||
1492 | if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
1493 | short_scan = true; | ||
1494 | } | ||
1495 | } | ||
1496 | |||
1497 | if (((antcomb->total_pkt_count < ATH_ANT_DIV_COMB_MAX_PKTCOUNT) || | ||
1498 | rs->rs_moreaggr) && !short_scan) | ||
1499 | return; | ||
1500 | |||
1501 | if (antcomb->total_pkt_count) { | ||
1502 | alt_ratio = ((antcomb->alt_recv_cnt * 100) / | ||
1503 | antcomb->total_pkt_count); | ||
1504 | main_rssi_avg = (antcomb->main_total_rssi / | ||
1505 | antcomb->total_pkt_count); | ||
1506 | alt_rssi_avg = (antcomb->alt_total_rssi / | ||
1507 | antcomb->total_pkt_count); | ||
1508 | } | ||
1509 | |||
1510 | |||
1511 | ath9k_hw_antdiv_comb_conf_get(sc->sc_ah, &div_ant_conf); | ||
1512 | curr_alt_set = div_ant_conf.alt_lna_conf; | ||
1513 | curr_main_set = div_ant_conf.main_lna_conf; | ||
1514 | |||
1515 | antcomb->count++; | ||
1516 | |||
1517 | if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) { | ||
1518 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | ||
1519 | ath_lnaconf_alt_good_scan(antcomb, div_ant_conf, | ||
1520 | main_rssi_avg); | ||
1521 | antcomb->alt_good = true; | ||
1522 | } else { | ||
1523 | antcomb->alt_good = false; | ||
1524 | } | ||
1525 | |||
1526 | antcomb->count = 0; | ||
1527 | antcomb->scan = true; | ||
1528 | antcomb->scan_not_start = true; | ||
1529 | } | ||
1530 | |||
1531 | if (!antcomb->scan) { | ||
1532 | if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, | ||
1533 | alt_ratio, curr_main_set, curr_alt_set, | ||
1534 | alt_rssi_avg, main_rssi_avg)) { | ||
1535 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1536 | /* Switch main and alt LNA */ | ||
1537 | div_ant_conf.main_lna_conf = | ||
1538 | ATH_ANT_DIV_COMB_LNA2; | ||
1539 | div_ant_conf.alt_lna_conf = | ||
1540 | ATH_ANT_DIV_COMB_LNA1; | ||
1541 | } else if (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1542 | div_ant_conf.main_lna_conf = | ||
1543 | ATH_ANT_DIV_COMB_LNA1; | ||
1544 | div_ant_conf.alt_lna_conf = | ||
1545 | ATH_ANT_DIV_COMB_LNA2; | ||
1546 | } | ||
1547 | |||
1548 | goto div_comb_done; | ||
1549 | } else if ((curr_alt_set != ATH_ANT_DIV_COMB_LNA1) && | ||
1550 | (curr_alt_set != ATH_ANT_DIV_COMB_LNA2)) { | ||
1551 | /* Set alt to another LNA */ | ||
1552 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) | ||
1553 | div_ant_conf.alt_lna_conf = | ||
1554 | ATH_ANT_DIV_COMB_LNA1; | ||
1555 | else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) | ||
1556 | div_ant_conf.alt_lna_conf = | ||
1557 | ATH_ANT_DIV_COMB_LNA2; | ||
1558 | |||
1559 | goto div_comb_done; | ||
1560 | } | ||
1561 | |||
1562 | if ((alt_rssi_avg < (main_rssi_avg + | ||
1563 | div_ant_conf.lna1_lna2_delta))) | ||
1564 | goto div_comb_done; | ||
1565 | } | ||
1566 | |||
1567 | if (!antcomb->scan_not_start) { | ||
1568 | switch (curr_alt_set) { | ||
1569 | case ATH_ANT_DIV_COMB_LNA2: | ||
1570 | antcomb->rssi_lna2 = alt_rssi_avg; | ||
1571 | antcomb->rssi_lna1 = main_rssi_avg; | ||
1572 | antcomb->scan = true; | ||
1573 | /* set to A+B */ | ||
1574 | div_ant_conf.main_lna_conf = | ||
1575 | ATH_ANT_DIV_COMB_LNA1; | ||
1576 | div_ant_conf.alt_lna_conf = | ||
1577 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1578 | break; | ||
1579 | case ATH_ANT_DIV_COMB_LNA1: | ||
1580 | antcomb->rssi_lna1 = alt_rssi_avg; | ||
1581 | antcomb->rssi_lna2 = main_rssi_avg; | ||
1582 | antcomb->scan = true; | ||
1583 | /* set to A+B */ | ||
1584 | div_ant_conf.main_lna_conf = ATH_ANT_DIV_COMB_LNA2; | ||
1585 | div_ant_conf.alt_lna_conf = | ||
1586 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1587 | break; | ||
1588 | case ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2: | ||
1589 | antcomb->rssi_add = alt_rssi_avg; | ||
1590 | antcomb->scan = true; | ||
1591 | /* set to A-B */ | ||
1592 | div_ant_conf.alt_lna_conf = | ||
1593 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1594 | break; | ||
1595 | case ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2: | ||
1596 | antcomb->rssi_sub = alt_rssi_avg; | ||
1597 | antcomb->scan = false; | ||
1598 | if (antcomb->rssi_lna2 > | ||
1599 | (antcomb->rssi_lna1 + | ||
1600 | ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA)) { | ||
1601 | /* use LNA2 as main LNA */ | ||
1602 | if ((antcomb->rssi_add > antcomb->rssi_lna1) && | ||
1603 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1604 | /* set to A+B */ | ||
1605 | div_ant_conf.main_lna_conf = | ||
1606 | ATH_ANT_DIV_COMB_LNA2; | ||
1607 | div_ant_conf.alt_lna_conf = | ||
1608 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1609 | } else if (antcomb->rssi_sub > | ||
1610 | antcomb->rssi_lna1) { | ||
1611 | /* set to A-B */ | ||
1612 | div_ant_conf.main_lna_conf = | ||
1613 | ATH_ANT_DIV_COMB_LNA2; | ||
1614 | div_ant_conf.alt_lna_conf = | ||
1615 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1616 | } else { | ||
1617 | /* set to LNA1 */ | ||
1618 | div_ant_conf.main_lna_conf = | ||
1619 | ATH_ANT_DIV_COMB_LNA2; | ||
1620 | div_ant_conf.alt_lna_conf = | ||
1621 | ATH_ANT_DIV_COMB_LNA1; | ||
1622 | } | ||
1623 | } else { | ||
1624 | /* use LNA1 as main LNA */ | ||
1625 | if ((antcomb->rssi_add > antcomb->rssi_lna2) && | ||
1626 | (antcomb->rssi_add > antcomb->rssi_sub)) { | ||
1627 | /* set to A+B */ | ||
1628 | div_ant_conf.main_lna_conf = | ||
1629 | ATH_ANT_DIV_COMB_LNA1; | ||
1630 | div_ant_conf.alt_lna_conf = | ||
1631 | ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2; | ||
1632 | } else if (antcomb->rssi_sub > | ||
1633 | antcomb->rssi_lna1) { | ||
1634 | /* set to A-B */ | ||
1635 | div_ant_conf.main_lna_conf = | ||
1636 | ATH_ANT_DIV_COMB_LNA1; | ||
1637 | div_ant_conf.alt_lna_conf = | ||
1638 | ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2; | ||
1639 | } else { | ||
1640 | /* set to LNA2 */ | ||
1641 | div_ant_conf.main_lna_conf = | ||
1642 | ATH_ANT_DIV_COMB_LNA1; | ||
1643 | div_ant_conf.alt_lna_conf = | ||
1644 | ATH_ANT_DIV_COMB_LNA2; | ||
1645 | } | ||
1646 | } | ||
1647 | break; | ||
1648 | default: | ||
1649 | break; | ||
1650 | } | ||
1651 | } else { | ||
1652 | if (!antcomb->alt_good) { | ||
1653 | antcomb->scan_not_start = false; | ||
1654 | /* Set alt to another LNA */ | ||
1655 | if (curr_main_set == ATH_ANT_DIV_COMB_LNA2) { | ||
1656 | div_ant_conf.main_lna_conf = | ||
1657 | ATH_ANT_DIV_COMB_LNA2; | ||
1658 | div_ant_conf.alt_lna_conf = | ||
1659 | ATH_ANT_DIV_COMB_LNA1; | ||
1660 | } else if (curr_main_set == ATH_ANT_DIV_COMB_LNA1) { | ||
1661 | div_ant_conf.main_lna_conf = | ||
1662 | ATH_ANT_DIV_COMB_LNA1; | ||
1663 | div_ant_conf.alt_lna_conf = | ||
1664 | ATH_ANT_DIV_COMB_LNA2; | ||
1665 | } | ||
1666 | goto div_comb_done; | ||
1667 | } | ||
1668 | } | ||
1669 | |||
1670 | ath_select_ant_div_from_quick_scan(antcomb, &div_ant_conf, | ||
1671 | main_rssi_avg, alt_rssi_avg, | ||
1672 | alt_ratio); | ||
1673 | |||
1674 | antcomb->quick_scan_cnt++; | ||
1675 | |||
1676 | div_comb_done: | ||
1677 | ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); | ||
1678 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | ||
1679 | |||
1680 | antcomb->scan_start_time = jiffies; | ||
1681 | antcomb->total_pkt_count = 0; | ||
1682 | antcomb->main_total_rssi = 0; | ||
1683 | antcomb->alt_total_rssi = 0; | ||
1684 | antcomb->main_recv_cnt = 0; | ||
1685 | antcomb->alt_recv_cnt = 0; | ||
1686 | } | ||
1687 | |||
1076 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | 1688 | int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) |
1077 | { | 1689 | { |
1078 | struct ath_buf *bf; | 1690 | struct ath_buf *bf; |
1079 | struct sk_buff *skb = NULL, *requeue_skb; | 1691 | struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb; |
1080 | struct ieee80211_rx_status *rxs; | 1692 | struct ieee80211_rx_status *rxs; |
1081 | struct ath_hw *ah = sc->sc_ah; | 1693 | struct ath_hw *ah = sc->sc_ah; |
1082 | struct ath_common *common = ath9k_hw_common(ah); | 1694 | struct ath_common *common = ath9k_hw_common(ah); |
1083 | /* | 1695 | /* |
1084 | * The hw can techncically differ from common->hw when using ath9k | 1696 | * The hw can technically differ from common->hw when using ath9k |
1085 | * virtual wiphy so to account for that we iterate over the active | 1697 | * virtual wiphy so to account for that we iterate over the active |
1086 | * wiphys and find the appropriate wiphy and therefore hw. | 1698 | * wiphys and find the appropriate wiphy and therefore hw. |
1087 | */ | 1699 | */ |
1088 | struct ieee80211_hw *hw = NULL; | 1700 | struct ieee80211_hw *hw = sc->hw; |
1089 | struct ieee80211_hdr *hdr; | 1701 | struct ieee80211_hdr *hdr; |
1090 | int retval; | 1702 | int retval; |
1091 | bool decrypt_error = false; | 1703 | bool decrypt_error = false; |
@@ -1096,6 +1708,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1096 | u8 rx_status_len = ah->caps.rx_status_len; | 1708 | u8 rx_status_len = ah->caps.rx_status_len; |
1097 | u64 tsf = 0; | 1709 | u64 tsf = 0; |
1098 | u32 tsf_lower = 0; | 1710 | u32 tsf_lower = 0; |
1711 | unsigned long flags; | ||
1099 | 1712 | ||
1100 | if (edma) | 1713 | if (edma) |
1101 | dma_type = DMA_BIDIRECTIONAL; | 1714 | dma_type = DMA_BIDIRECTIONAL; |
@@ -1126,10 +1739,17 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1126 | if (!skb) | 1739 | if (!skb) |
1127 | continue; | 1740 | continue; |
1128 | 1741 | ||
1129 | hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len); | 1742 | /* |
1130 | rxs = IEEE80211_SKB_RXCB(skb); | 1743 | * Take frame header from the first fragment and RX status from |
1744 | * the last one. | ||
1745 | */ | ||
1746 | if (sc->rx.frag) | ||
1747 | hdr_skb = sc->rx.frag; | ||
1748 | else | ||
1749 | hdr_skb = skb; | ||
1131 | 1750 | ||
1132 | hw = ath_get_virt_hw(sc, hdr); | 1751 | hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len); |
1752 | rxs = IEEE80211_SKB_RXCB(hdr_skb); | ||
1133 | 1753 | ||
1134 | ath_debug_stat_rx(sc, &rs); | 1754 | ath_debug_stat_rx(sc, &rs); |
1135 | 1755 | ||
@@ -1138,12 +1758,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1138 | * chain it back at the queue without processing it. | 1758 | * chain it back at the queue without processing it. |
1139 | */ | 1759 | */ |
1140 | if (flush) | 1760 | if (flush) |
1141 | goto requeue; | 1761 | goto requeue_drop_frag; |
1142 | 1762 | ||
1143 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, | 1763 | retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs, |
1144 | rxs, &decrypt_error); | 1764 | rxs, &decrypt_error); |
1145 | if (retval) | 1765 | if (retval) |
1146 | goto requeue; | 1766 | goto requeue_drop_frag; |
1147 | 1767 | ||
1148 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | 1768 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |
1149 | if (rs.rs_tstamp > tsf_lower && | 1769 | if (rs.rs_tstamp > tsf_lower && |
@@ -1163,7 +1783,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1163 | * skb and put it at the tail of the sc->rx.rxbuf list for | 1783 | * skb and put it at the tail of the sc->rx.rxbuf list for |
1164 | * processing. */ | 1784 | * processing. */ |
1165 | if (!requeue_skb) | 1785 | if (!requeue_skb) |
1166 | goto requeue; | 1786 | goto requeue_drop_frag; |
1167 | 1787 | ||
1168 | /* Unmap the frame */ | 1788 | /* Unmap the frame */ |
1169 | dma_unmap_single(sc->dev, bf->bf_buf_addr, | 1789 | dma_unmap_single(sc->dev, bf->bf_buf_addr, |
@@ -1174,8 +1794,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1174 | if (ah->caps.rx_status_len) | 1794 | if (ah->caps.rx_status_len) |
1175 | skb_pull(skb, ah->caps.rx_status_len); | 1795 | skb_pull(skb, ah->caps.rx_status_len); |
1176 | 1796 | ||
1177 | ath9k_rx_skb_postprocess(common, skb, &rs, | 1797 | if (!rs.rs_more) |
1178 | rxs, decrypt_error); | 1798 | ath9k_rx_skb_postprocess(common, hdr_skb, &rs, |
1799 | rxs, decrypt_error); | ||
1179 | 1800 | ||
1180 | /* We will now give hardware our shiny new allocated skb */ | 1801 | /* We will now give hardware our shiny new allocated skb */ |
1181 | bf->bf_mpdu = requeue_skb; | 1802 | bf->bf_mpdu = requeue_skb; |
@@ -1186,12 +1807,43 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1186 | bf->bf_buf_addr))) { | 1807 | bf->bf_buf_addr))) { |
1187 | dev_kfree_skb_any(requeue_skb); | 1808 | dev_kfree_skb_any(requeue_skb); |
1188 | bf->bf_mpdu = NULL; | 1809 | bf->bf_mpdu = NULL; |
1189 | ath_print(common, ATH_DBG_FATAL, | 1810 | bf->bf_buf_addr = 0; |
1190 | "dma_mapping_error() on RX\n"); | 1811 | ath_err(common, "dma_mapping_error() on RX\n"); |
1191 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); | 1812 | ieee80211_rx(hw, skb); |
1192 | break; | 1813 | break; |
1193 | } | 1814 | } |
1194 | bf->bf_dmacontext = bf->bf_buf_addr; | 1815 | |
1816 | if (rs.rs_more) { | ||
1817 | /* | ||
1818 | * rs_more indicates chained descriptors which can be | ||
1819 | * used to link buffers together for a sort of | ||
1820 | * scatter-gather operation. | ||
1821 | */ | ||
1822 | if (sc->rx.frag) { | ||
1823 | /* too many fragments - cannot handle frame */ | ||
1824 | dev_kfree_skb_any(sc->rx.frag); | ||
1825 | dev_kfree_skb_any(skb); | ||
1826 | skb = NULL; | ||
1827 | } | ||
1828 | sc->rx.frag = skb; | ||
1829 | goto requeue; | ||
1830 | } | ||
1831 | |||
1832 | if (sc->rx.frag) { | ||
1833 | int space = skb->len - skb_tailroom(hdr_skb); | ||
1834 | |||
1835 | sc->rx.frag = NULL; | ||
1836 | |||
1837 | if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) { | ||
1838 | dev_kfree_skb(skb); | ||
1839 | goto requeue_drop_frag; | ||
1840 | } | ||
1841 | |||
1842 | skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len), | ||
1843 | skb->len); | ||
1844 | dev_kfree_skb_any(skb); | ||
1845 | skb = hdr_skb; | ||
1846 | } | ||
1195 | 1847 | ||
1196 | /* | 1848 | /* |
1197 | * change the default rx antenna if rx diversity chooses the | 1849 | * change the default rx antenna if rx diversity chooses the |
@@ -1204,14 +1856,25 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1204 | sc->rx.rxotherant = 0; | 1856 | sc->rx.rxotherant = 0; |
1205 | } | 1857 | } |
1206 | 1858 | ||
1207 | if (unlikely(ath9k_check_auto_sleep(sc) || | 1859 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
1208 | (sc->ps_flags & (PS_WAIT_FOR_BEACON | | 1860 | |
1861 | if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | | ||
1209 | PS_WAIT_FOR_CAB | | 1862 | PS_WAIT_FOR_CAB | |
1210 | PS_WAIT_FOR_PSPOLL_DATA)))) | 1863 | PS_WAIT_FOR_PSPOLL_DATA)) || |
1864 | ath9k_check_auto_sleep(sc)) | ||
1211 | ath_rx_ps(sc, skb); | 1865 | ath_rx_ps(sc, skb); |
1866 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
1212 | 1867 | ||
1213 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); | 1868 | if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) |
1869 | ath_ant_comb_scan(sc, &rs); | ||
1214 | 1870 | ||
1871 | ieee80211_rx(hw, skb); | ||
1872 | |||
1873 | requeue_drop_frag: | ||
1874 | if (sc->rx.frag) { | ||
1875 | dev_kfree_skb_any(sc->rx.frag); | ||
1876 | sc->rx.frag = NULL; | ||
1877 | } | ||
1215 | requeue: | 1878 | requeue: |
1216 | if (edma) { | 1879 | if (edma) { |
1217 | list_add_tail(&bf->list, &sc->rx.rxbuf); | 1880 | list_add_tail(&bf->list, &sc->rx.rxbuf); |
@@ -1219,6 +1882,7 @@ requeue: | |||
1219 | } else { | 1882 | } else { |
1220 | list_move_tail(&bf->list, &sc->rx.rxbuf); | 1883 | list_move_tail(&bf->list, &sc->rx.rxbuf); |
1221 | ath_rx_buf_link(sc, bf); | 1884 | ath_rx_buf_link(sc, bf); |
1885 | ath9k_hw_rxena(ah); | ||
1222 | } | 1886 | } |
1223 | } while (1); | 1887 | } while (1); |
1224 | 1888 | ||
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d01c4adab8d6..c18ee9921fb1 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -107,12 +107,6 @@ | |||
107 | #define AR_RXCFG_DMASZ_256B 6 | 107 | #define AR_RXCFG_DMASZ_256B 6 |
108 | #define AR_RXCFG_DMASZ_512B 7 | 108 | #define AR_RXCFG_DMASZ_512B 7 |
109 | 109 | ||
110 | #define AR_MIBC 0x0040 | ||
111 | #define AR_MIBC_COW 0x00000001 | ||
112 | #define AR_MIBC_FMC 0x00000002 | ||
113 | #define AR_MIBC_CMC 0x00000004 | ||
114 | #define AR_MIBC_MCS 0x00000008 | ||
115 | |||
116 | #define AR_TOPS 0x0044 | 110 | #define AR_TOPS 0x0044 |
117 | #define AR_TOPS_MASK 0x0000FFFF | 111 | #define AR_TOPS_MASK 0x0000FFFF |
118 | 112 | ||
@@ -699,7 +693,7 @@ | |||
699 | #define AR_RC_APB 0x00000002 | 693 | #define AR_RC_APB 0x00000002 |
700 | #define AR_RC_HOSTIF 0x00000100 | 694 | #define AR_RC_HOSTIF 0x00000100 |
701 | 695 | ||
702 | #define AR_WA 0x4004 | 696 | #define AR_WA (AR_SREV_9340(ah) ? 0x40c4 : 0x4004) |
703 | #define AR_WA_BIT6 (1 << 6) | 697 | #define AR_WA_BIT6 (1 << 6) |
704 | #define AR_WA_BIT7 (1 << 7) | 698 | #define AR_WA_BIT7 (1 << 7) |
705 | #define AR_WA_BIT23 (1 << 23) | 699 | #define AR_WA_BIT23 (1 << 23) |
@@ -709,6 +703,7 @@ | |||
709 | #define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */ | 703 | #define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */ |
710 | #define AR_WA_ANALOG_SHIFT (1 << 20) | 704 | #define AR_WA_ANALOG_SHIFT (1 << 20) |
711 | #define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */ | 705 | #define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */ |
706 | #define AR_WA_BIT22 (1 << 22) | ||
712 | #define AR9285_WA_DEFAULT 0x004a050b | 707 | #define AR9285_WA_DEFAULT 0x004a050b |
713 | #define AR9280_WA_DEFAULT 0x0040073b | 708 | #define AR9280_WA_DEFAULT 0x0040073b |
714 | #define AR_WA_DEFAULT 0x0000073f | 709 | #define AR_WA_DEFAULT 0x0000073f |
@@ -717,7 +712,7 @@ | |||
717 | #define AR_PM_STATE 0x4008 | 712 | #define AR_PM_STATE 0x4008 |
718 | #define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 | 713 | #define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 |
719 | 714 | ||
720 | #define AR_HOST_TIMEOUT 0x4018 | 715 | #define AR_HOST_TIMEOUT (AR_SREV_9340(ah) ? 0x4008 : 0x4018) |
721 | #define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF | 716 | #define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF |
722 | #define AR_HOST_TIMEOUT_APB_CNTR_S 0 | 717 | #define AR_HOST_TIMEOUT_APB_CNTR_S 0 |
723 | #define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 | 718 | #define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 |
@@ -747,7 +742,8 @@ | |||
747 | #define EEPROM_PROTECT_WP_1024_2047 0x8000 | 742 | #define EEPROM_PROTECT_WP_1024_2047 0x8000 |
748 | 743 | ||
749 | #define AR_SREV \ | 744 | #define AR_SREV \ |
750 | ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020) | 745 | ((AR_SREV_9100(ah)) ? 0x0600 : (AR_SREV_9340(ah) \ |
746 | ? 0x400c : 0x4020)) | ||
751 | 747 | ||
752 | #define AR_SREV_ID \ | 748 | #define AR_SREV_ID \ |
753 | ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF) | 749 | ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF) |
@@ -792,6 +788,10 @@ | |||
792 | #define AR_SREV_REVISION_9271_11 1 | 788 | #define AR_SREV_REVISION_9271_11 1 |
793 | #define AR_SREV_VERSION_9300 0x1c0 | 789 | #define AR_SREV_VERSION_9300 0x1c0 |
794 | #define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ | 790 | #define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */ |
791 | #define AR_SREV_VERSION_9485 0x240 | ||
792 | #define AR_SREV_REVISION_9485_10 0 | ||
793 | #define AR_SREV_REVISION_9485_11 1 | ||
794 | #define AR_SREV_VERSION_9340 0x300 | ||
795 | 795 | ||
796 | #define AR_SREV_5416(_ah) \ | 796 | #define AR_SREV_5416(_ah) \ |
797 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ | 797 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ |
@@ -819,49 +819,23 @@ | |||
819 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11)) | 819 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11)) |
820 | #define AR_SREV_9280(_ah) \ | 820 | #define AR_SREV_9280(_ah) \ |
821 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280)) | 821 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280)) |
822 | #define AR_SREV_9280_10_OR_LATER(_ah) \ | 822 | #define AR_SREV_9280_20_OR_LATER(_ah) \ |
823 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280)) | 823 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280)) |
824 | #define AR_SREV_9280_20(_ah) \ | 824 | #define AR_SREV_9280_20(_ah) \ |
825 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ | 825 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280)) |
826 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)) | ||
827 | #define AR_SREV_9280_20_OR_LATER(_ah) \ | ||
828 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \ | ||
829 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ | ||
830 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))) | ||
831 | 826 | ||
832 | #define AR_SREV_9285(_ah) \ | 827 | #define AR_SREV_9285(_ah) \ |
833 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285)) | 828 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285)) |
834 | #define AR_SREV_9285_10_OR_LATER(_ah) \ | ||
835 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) | ||
836 | #define AR_SREV_9285_11(_ah) \ | ||
837 | (AR_SREV_9285(ah) && \ | ||
838 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11)) | ||
839 | #define AR_SREV_9285_11_OR_LATER(_ah) \ | ||
840 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ | ||
841 | (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ | ||
842 | AR_SREV_REVISION_9285_11))) | ||
843 | #define AR_SREV_9285_12(_ah) \ | ||
844 | (AR_SREV_9285(ah) && \ | ||
845 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12)) | ||
846 | #define AR_SREV_9285_12_OR_LATER(_ah) \ | 829 | #define AR_SREV_9285_12_OR_LATER(_ah) \ |
847 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ | 830 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) |
848 | (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ | ||
849 | AR_SREV_REVISION_9285_12))) | ||
850 | 831 | ||
851 | #define AR_SREV_9287(_ah) \ | 832 | #define AR_SREV_9287(_ah) \ |
852 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287)) | 833 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287)) |
853 | #define AR_SREV_9287_10_OR_LATER(_ah) \ | 834 | #define AR_SREV_9287_11_OR_LATER(_ah) \ |
854 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287)) | 835 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287)) |
855 | #define AR_SREV_9287_10(_ah) \ | ||
856 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | ||
857 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_10)) | ||
858 | #define AR_SREV_9287_11(_ah) \ | 836 | #define AR_SREV_9287_11(_ah) \ |
859 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | 837 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ |
860 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11)) | 838 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11)) |
861 | #define AR_SREV_9287_11_OR_LATER(_ah) \ | ||
862 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ | ||
863 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | ||
864 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) | ||
865 | #define AR_SREV_9287_12(_ah) \ | 839 | #define AR_SREV_9287_12(_ah) \ |
866 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | 840 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ |
867 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12)) | 841 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12)) |
@@ -885,22 +859,36 @@ | |||
885 | 859 | ||
886 | #define AR_SREV_9300(_ah) \ | 860 | #define AR_SREV_9300(_ah) \ |
887 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) | 861 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) |
888 | #define AR_SREV_9300_20(_ah) \ | ||
889 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ | ||
890 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_20)) | ||
891 | #define AR_SREV_9300_20_OR_LATER(_ah) \ | 862 | #define AR_SREV_9300_20_OR_LATER(_ah) \ |
892 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \ | 863 | ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300) |
893 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ | 864 | |
894 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20))) | 865 | #define AR_SREV_9485(_ah) \ |
866 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) | ||
867 | #define AR_SREV_9485_10(_ah) \ | ||
868 | (AR_SREV_9485(_ah) && \ | ||
869 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_10)) | ||
870 | #define AR_SREV_9485_11(_ah) \ | ||
871 | (AR_SREV_9485(_ah) && \ | ||
872 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) | ||
873 | #define AR_SREV_9485_OR_LATER(_ah) \ | ||
874 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) | ||
875 | |||
876 | #define AR_SREV_9340(_ah) \ | ||
877 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340)) | ||
895 | 878 | ||
896 | #define AR_SREV_9285E_20(_ah) \ | 879 | #define AR_SREV_9285E_20(_ah) \ |
897 | (AR_SREV_9285_12_OR_LATER(_ah) && \ | 880 | (AR_SREV_9285_12_OR_LATER(_ah) && \ |
898 | ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) | 881 | ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) |
899 | 882 | ||
883 | enum ath_usb_dev { | ||
884 | AR9280_USB = 1, /* AR7010 + AR9280, UB94 */ | ||
885 | AR9287_USB = 2, /* AR7010 + AR9287, UB95 */ | ||
886 | STORAGE_DEVICE = 3, | ||
887 | }; | ||
888 | |||
900 | #define AR_DEVID_7010(_ah) \ | 889 | #define AR_DEVID_7010(_ah) \ |
901 | (((_ah)->hw_version.devid == 0x7010) || \ | 890 | (((_ah)->hw_version.usbdev == AR9280_USB) || \ |
902 | ((_ah)->hw_version.devid == 0x7015) || \ | 891 | ((_ah)->hw_version.usbdev == AR9287_USB)) |
903 | ((_ah)->hw_version.devid == 0x9018)) | ||
904 | 892 | ||
905 | #define AR_RADIO_SREV_MAJOR 0xf0 | 893 | #define AR_RADIO_SREV_MAJOR 0xf0 |
906 | #define AR_RAD5133_SREV_MAJOR 0xc0 | 894 | #define AR_RAD5133_SREV_MAJOR 0xc0 |
@@ -929,11 +917,11 @@ | |||
929 | #define AR_INTR_SPURIOUS 0xFFFFFFFF | 917 | #define AR_INTR_SPURIOUS 0xFFFFFFFF |
930 | 918 | ||
931 | 919 | ||
932 | #define AR_INTR_SYNC_CAUSE_CLR 0x4028 | 920 | #define AR_INTR_SYNC_CAUSE (AR_SREV_9340(ah) ? 0x4010 : 0x4028) |
921 | #define AR_INTR_SYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4010 : 0x4028) | ||
933 | 922 | ||
934 | #define AR_INTR_SYNC_CAUSE 0x4028 | ||
935 | 923 | ||
936 | #define AR_INTR_SYNC_ENABLE 0x402c | 924 | #define AR_INTR_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4014 : 0x402c) |
937 | #define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 | 925 | #define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 |
938 | #define AR_INTR_SYNC_ENABLE_GPIO_S 18 | 926 | #define AR_INTR_SYNC_ENABLE_GPIO_S 18 |
939 | 927 | ||
@@ -973,24 +961,24 @@ enum { | |||
973 | 961 | ||
974 | }; | 962 | }; |
975 | 963 | ||
976 | #define AR_INTR_ASYNC_MASK 0x4030 | 964 | #define AR_INTR_ASYNC_MASK (AR_SREV_9340(ah) ? 0x4018 : 0x4030) |
977 | #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 | 965 | #define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 |
978 | #define AR_INTR_ASYNC_MASK_GPIO_S 18 | 966 | #define AR_INTR_ASYNC_MASK_GPIO_S 18 |
979 | 967 | ||
980 | #define AR_INTR_SYNC_MASK 0x4034 | 968 | #define AR_INTR_SYNC_MASK (AR_SREV_9340(ah) ? 0x401c : 0x4034) |
981 | #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 | 969 | #define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 |
982 | #define AR_INTR_SYNC_MASK_GPIO_S 18 | 970 | #define AR_INTR_SYNC_MASK_GPIO_S 18 |
983 | 971 | ||
984 | #define AR_INTR_ASYNC_CAUSE_CLR 0x4038 | 972 | #define AR_INTR_ASYNC_CAUSE_CLR (AR_SREV_9340(ah) ? 0x4020 : 0x4038) |
985 | #define AR_INTR_ASYNC_CAUSE 0x4038 | 973 | #define AR_INTR_ASYNC_CAUSE (AR_SREV_9340(ah) ? 0x4020 : 0x4038) |
986 | 974 | ||
987 | #define AR_INTR_ASYNC_ENABLE 0x403c | 975 | #define AR_INTR_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4024 : 0x403c) |
988 | #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 | 976 | #define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 |
989 | #define AR_INTR_ASYNC_ENABLE_GPIO_S 18 | 977 | #define AR_INTR_ASYNC_ENABLE_GPIO_S 18 |
990 | 978 | ||
991 | #define AR_PCIE_SERDES 0x4040 | 979 | #define AR_PCIE_SERDES 0x4040 |
992 | #define AR_PCIE_SERDES2 0x4044 | 980 | #define AR_PCIE_SERDES2 0x4044 |
993 | #define AR_PCIE_PM_CTRL 0x4014 | 981 | #define AR_PCIE_PM_CTRL (AR_SREV_9340(ah) ? 0x4004 : 0x4014) |
994 | #define AR_PCIE_PM_CTRL_ENA 0x00080000 | 982 | #define AR_PCIE_PM_CTRL_ENA 0x00080000 |
995 | 983 | ||
996 | #define AR_NUM_GPIO 14 | 984 | #define AR_NUM_GPIO 14 |
@@ -1001,7 +989,7 @@ enum { | |||
1001 | #define AR9300_NUM_GPIO 17 | 989 | #define AR9300_NUM_GPIO 17 |
1002 | #define AR7010_NUM_GPIO 16 | 990 | #define AR7010_NUM_GPIO 16 |
1003 | 991 | ||
1004 | #define AR_GPIO_IN_OUT 0x4048 | 992 | #define AR_GPIO_IN_OUT (AR_SREV_9340(ah) ? 0x4028 : 0x4048) |
1005 | #define AR_GPIO_IN_VAL 0x0FFFC000 | 993 | #define AR_GPIO_IN_VAL 0x0FFFC000 |
1006 | #define AR_GPIO_IN_VAL_S 14 | 994 | #define AR_GPIO_IN_VAL_S 14 |
1007 | #define AR928X_GPIO_IN_VAL 0x000FFC00 | 995 | #define AR928X_GPIO_IN_VAL 0x000FFC00 |
@@ -1012,12 +1000,15 @@ enum { | |||
1012 | #define AR9287_GPIO_IN_VAL_S 11 | 1000 | #define AR9287_GPIO_IN_VAL_S 11 |
1013 | #define AR9271_GPIO_IN_VAL 0xFFFF0000 | 1001 | #define AR9271_GPIO_IN_VAL 0xFFFF0000 |
1014 | #define AR9271_GPIO_IN_VAL_S 16 | 1002 | #define AR9271_GPIO_IN_VAL_S 16 |
1015 | #define AR9300_GPIO_IN_VAL 0x0001FFFF | ||
1016 | #define AR9300_GPIO_IN_VAL_S 0 | ||
1017 | #define AR7010_GPIO_IN_VAL 0x0000FFFF | 1003 | #define AR7010_GPIO_IN_VAL 0x0000FFFF |
1018 | #define AR7010_GPIO_IN_VAL_S 0 | 1004 | #define AR7010_GPIO_IN_VAL_S 0 |
1019 | 1005 | ||
1020 | #define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c) | 1006 | #define AR_GPIO_IN (AR_SREV_9340(ah) ? 0x402c : 0x404c) |
1007 | #define AR9300_GPIO_IN_VAL 0x0001FFFF | ||
1008 | #define AR9300_GPIO_IN_VAL_S 0 | ||
1009 | |||
1010 | #define AR_GPIO_OE_OUT (AR_SREV_9340(ah) ? 0x4030 : \ | ||
1011 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)) | ||
1021 | #define AR_GPIO_OE_OUT_DRV 0x3 | 1012 | #define AR_GPIO_OE_OUT_DRV 0x3 |
1022 | #define AR_GPIO_OE_OUT_DRV_NO 0x0 | 1013 | #define AR_GPIO_OE_OUT_DRV_NO 0x0 |
1023 | #define AR_GPIO_OE_OUT_DRV_LOW 0x1 | 1014 | #define AR_GPIO_OE_OUT_DRV_LOW 0x1 |
@@ -1039,11 +1030,13 @@ enum { | |||
1039 | #define AR7010_GPIO_INT_MASK 0x52024 | 1030 | #define AR7010_GPIO_INT_MASK 0x52024 |
1040 | #define AR7010_GPIO_FUNCTION 0x52028 | 1031 | #define AR7010_GPIO_FUNCTION 0x52028 |
1041 | 1032 | ||
1042 | #define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050) | 1033 | #define AR_GPIO_INTR_POL (AR_SREV_9340(ah) ? 0x4038 : \ |
1034 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050)) | ||
1043 | #define AR_GPIO_INTR_POL_VAL 0x0001FFFF | 1035 | #define AR_GPIO_INTR_POL_VAL 0x0001FFFF |
1044 | #define AR_GPIO_INTR_POL_VAL_S 0 | 1036 | #define AR_GPIO_INTR_POL_VAL_S 0 |
1045 | 1037 | ||
1046 | #define AR_GPIO_INPUT_EN_VAL (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054) | 1038 | #define AR_GPIO_INPUT_EN_VAL (AR_SREV_9340(ah) ? 0x403c : \ |
1039 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054)) | ||
1047 | #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 | 1040 | #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 |
1048 | #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 | 1041 | #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 |
1049 | #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 | 1042 | #define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 |
@@ -1061,13 +1054,15 @@ enum { | |||
1061 | #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 | 1054 | #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 |
1062 | #define AR_GPIO_JTAG_DISABLE 0x00020000 | 1055 | #define AR_GPIO_JTAG_DISABLE 0x00020000 |
1063 | 1056 | ||
1064 | #define AR_GPIO_INPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058) | 1057 | #define AR_GPIO_INPUT_MUX1 (AR_SREV_9340(ah) ? 0x4040 : \ |
1058 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058)) | ||
1065 | #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 | 1059 | #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 |
1066 | #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 | 1060 | #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 |
1067 | #define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 | 1061 | #define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 |
1068 | #define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 | 1062 | #define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 |
1069 | 1063 | ||
1070 | #define AR_GPIO_INPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c) | 1064 | #define AR_GPIO_INPUT_MUX2 (AR_SREV_9340(ah) ? 0x4044 : \ |
1065 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c)) | ||
1071 | #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f | 1066 | #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f |
1072 | #define AR_GPIO_INPUT_MUX2_CLK25_S 0 | 1067 | #define AR_GPIO_INPUT_MUX2_CLK25_S 0 |
1073 | #define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 | 1068 | #define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 |
@@ -1075,13 +1070,18 @@ enum { | |||
1075 | #define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 | 1070 | #define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 |
1076 | #define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 | 1071 | #define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 |
1077 | 1072 | ||
1078 | #define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060) | 1073 | #define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9340(ah) ? 0x4048 : \ |
1079 | #define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064) | 1074 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060)) |
1080 | #define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068) | 1075 | #define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9340(ah) ? 0x404c : \ |
1076 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064)) | ||
1077 | #define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9340(ah) ? 0x4050 : \ | ||
1078 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068)) | ||
1081 | 1079 | ||
1082 | #define AR_INPUT_STATE (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c) | 1080 | #define AR_INPUT_STATE (AR_SREV_9340(ah) ? 0x4054 : \ |
1081 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c)) | ||
1083 | 1082 | ||
1084 | #define AR_EEPROM_STATUS_DATA (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c) | 1083 | #define AR_EEPROM_STATUS_DATA (AR_SREV_9340(ah) ? 0x40c8 : \ |
1084 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c)) | ||
1085 | #define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff | 1085 | #define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff |
1086 | #define AR_EEPROM_STATUS_DATA_VAL_S 0 | 1086 | #define AR_EEPROM_STATUS_DATA_VAL_S 0 |
1087 | #define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 | 1087 | #define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 |
@@ -1089,17 +1089,54 @@ enum { | |||
1089 | #define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 | 1089 | #define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 |
1090 | #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 | 1090 | #define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 |
1091 | 1091 | ||
1092 | #define AR_OBS (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080) | 1092 | #define AR_OBS (AR_SREV_9340(ah) ? 0x405c : \ |
1093 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080)) | ||
1093 | 1094 | ||
1094 | #define AR_GPIO_PDPU (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088) | 1095 | #define AR_GPIO_PDPU (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088) |
1095 | 1096 | ||
1096 | #define AR_PCIE_MSI (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094) | 1097 | #define AR_PCIE_MSI (AR_SREV_9340(ah) ? 0x40d8 : \ |
1098 | (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094)) | ||
1097 | #define AR_PCIE_MSI_ENABLE 0x00000001 | 1099 | #define AR_PCIE_MSI_ENABLE 0x00000001 |
1098 | 1100 | ||
1099 | #define AR_INTR_PRIO_SYNC_ENABLE 0x40c4 | 1101 | #define AR_INTR_PRIO_SYNC_ENABLE (AR_SREV_9340(ah) ? 0x4088 : 0x40c4) |
1100 | #define AR_INTR_PRIO_ASYNC_MASK 0x40c8 | 1102 | #define AR_INTR_PRIO_ASYNC_MASK (AR_SREV_9340(ah) ? 0x408c : 0x40c8) |
1101 | #define AR_INTR_PRIO_SYNC_MASK 0x40cc | 1103 | #define AR_INTR_PRIO_SYNC_MASK (AR_SREV_9340(ah) ? 0x4090 : 0x40cc) |
1102 | #define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4 | 1104 | #define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4) |
1105 | #define AR_ENT_OTP 0x40d8 | ||
1106 | #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 | ||
1107 | #define AR_ENT_OTP_MPSD 0x00800000 | ||
1108 | |||
1109 | #define AR_CH0_BB_DPLL1 0x16180 | ||
1110 | #define AR_CH0_BB_DPLL1_REFDIV 0xF8000000 | ||
1111 | #define AR_CH0_BB_DPLL1_REFDIV_S 27 | ||
1112 | #define AR_CH0_BB_DPLL1_NINI 0x07FC0000 | ||
1113 | #define AR_CH0_BB_DPLL1_NINI_S 18 | ||
1114 | #define AR_CH0_BB_DPLL1_NFRAC 0x0003FFFF | ||
1115 | #define AR_CH0_BB_DPLL1_NFRAC_S 0 | ||
1116 | |||
1117 | #define AR_CH0_BB_DPLL2 0x16184 | ||
1118 | #define AR_CH0_BB_DPLL2_LOCAL_PLL 0x40000000 | ||
1119 | #define AR_CH0_BB_DPLL2_LOCAL_PLL_S 30 | ||
1120 | #define AR_CH0_DPLL2_KI 0x3C000000 | ||
1121 | #define AR_CH0_DPLL2_KI_S 26 | ||
1122 | #define AR_CH0_DPLL2_KD 0x03F80000 | ||
1123 | #define AR_CH0_DPLL2_KD_S 19 | ||
1124 | #define AR_CH0_BB_DPLL2_EN_NEGTRIG 0x00040000 | ||
1125 | #define AR_CH0_BB_DPLL2_EN_NEGTRIG_S 18 | ||
1126 | #define AR_CH0_BB_DPLL2_PLL_PWD 0x00010000 | ||
1127 | #define AR_CH0_BB_DPLL2_PLL_PWD_S 16 | ||
1128 | #define AR_CH0_BB_DPLL2_OUTDIV 0x0000E000 | ||
1129 | #define AR_CH0_BB_DPLL2_OUTDIV_S 13 | ||
1130 | |||
1131 | #define AR_CH0_BB_DPLL3 0x16188 | ||
1132 | #define AR_CH0_BB_DPLL3_PHASE_SHIFT 0x3F800000 | ||
1133 | #define AR_CH0_BB_DPLL3_PHASE_SHIFT_S 23 | ||
1134 | |||
1135 | #define AR_CH0_DDR_DPLL2 0x16244 | ||
1136 | #define AR_CH0_DDR_DPLL3 0x16248 | ||
1137 | #define AR_CH0_DPLL3_PHASE_SHIFT 0x3F800000 | ||
1138 | #define AR_CH0_DPLL3_PHASE_SHIFT_S 23 | ||
1139 | #define AR_PHY_CCA_NOM_VAL_2GHZ -118 | ||
1103 | 1140 | ||
1104 | #define AR_RTC_9300_PLL_DIV 0x000003ff | 1141 | #define AR_RTC_9300_PLL_DIV 0x000003ff |
1105 | #define AR_RTC_9300_PLL_DIV_S 0 | 1142 | #define AR_RTC_9300_PLL_DIV_S 0 |
@@ -1137,12 +1174,21 @@ enum { | |||
1137 | #define AR_RTC_PLL_CONTROL \ | 1174 | #define AR_RTC_PLL_CONTROL \ |
1138 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014) | 1175 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014) |
1139 | 1176 | ||
1177 | #define AR_RTC_PLL_CONTROL2 0x703c | ||
1178 | |||
1140 | #define AR_RTC_PLL_DIV 0x0000001f | 1179 | #define AR_RTC_PLL_DIV 0x0000001f |
1141 | #define AR_RTC_PLL_DIV_S 0 | 1180 | #define AR_RTC_PLL_DIV_S 0 |
1142 | #define AR_RTC_PLL_DIV2 0x00000020 | 1181 | #define AR_RTC_PLL_DIV2 0x00000020 |
1143 | #define AR_RTC_PLL_REFDIV_5 0x000000c0 | 1182 | #define AR_RTC_PLL_REFDIV_5 0x000000c0 |
1144 | #define AR_RTC_PLL_CLKSEL 0x00000300 | 1183 | #define AR_RTC_PLL_CLKSEL 0x00000300 |
1145 | #define AR_RTC_PLL_CLKSEL_S 8 | 1184 | #define AR_RTC_PLL_CLKSEL_S 8 |
1185 | #define AR_RTC_PLL_BYPASS 0x00010000 | ||
1186 | |||
1187 | #define PLL3 0x16188 | ||
1188 | #define PLL3_DO_MEAS_MASK 0x40000000 | ||
1189 | #define PLL4 0x1618c | ||
1190 | #define PLL4_MEAS_DONE 0x8 | ||
1191 | #define SQSUM_DVC_MASK 0x007ffff8 | ||
1146 | 1192 | ||
1147 | #define AR_RTC_RESET \ | 1193 | #define AR_RTC_RESET \ |
1148 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040) | 1194 | ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040) |
@@ -1183,7 +1229,8 @@ enum { | |||
1183 | 1229 | ||
1184 | /* RTC_DERIVED_* - only for AR9100 */ | 1230 | /* RTC_DERIVED_* - only for AR9100 */ |
1185 | 1231 | ||
1186 | #define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038) | 1232 | #define AR_RTC_DERIVED_CLK \ |
1233 | (AR_SREV_9100(ah) ? (AR_RTC_BASE + 0x0038) : 0x7038) | ||
1187 | #define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe | 1234 | #define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe |
1188 | #define AR_RTC_DERIVED_CLK_PERIOD_S 1 | 1235 | #define AR_RTC_DERIVED_CLK_PERIOD_S 1 |
1189 | 1236 | ||
@@ -1389,6 +1436,7 @@ enum { | |||
1389 | #define AR_STA_ID1_PCF 0x00100000 | 1436 | #define AR_STA_ID1_PCF 0x00100000 |
1390 | #define AR_STA_ID1_USE_DEFANT 0x00200000 | 1437 | #define AR_STA_ID1_USE_DEFANT 0x00200000 |
1391 | #define AR_STA_ID1_DEFANT_UPDATE 0x00400000 | 1438 | #define AR_STA_ID1_DEFANT_UPDATE 0x00400000 |
1439 | #define AR_STA_ID1_AR9100_BA_FIX 0x00400000 | ||
1392 | #define AR_STA_ID1_RTS_USE_DEF 0x00800000 | 1440 | #define AR_STA_ID1_RTS_USE_DEF 0x00800000 |
1393 | #define AR_STA_ID1_ACKCTS_6MB 0x01000000 | 1441 | #define AR_STA_ID1_ACKCTS_6MB 0x01000000 |
1394 | #define AR_STA_ID1_BASE_RATE_11B 0x02000000 | 1442 | #define AR_STA_ID1_BASE_RATE_11B 0x02000000 |
@@ -1550,11 +1598,6 @@ enum { | |||
1550 | #define AR_TPC_CHIRP 0x003f0000 | 1598 | #define AR_TPC_CHIRP 0x003f0000 |
1551 | #define AR_TPC_CHIRP_S 0x16 | 1599 | #define AR_TPC_CHIRP_S 0x16 |
1552 | 1600 | ||
1553 | #define AR_TFCNT 0x80ec | ||
1554 | #define AR_RFCNT 0x80f0 | ||
1555 | #define AR_RCCNT 0x80f4 | ||
1556 | #define AR_CCCNT 0x80f8 | ||
1557 | |||
1558 | #define AR_QUIET1 0x80fc | 1601 | #define AR_QUIET1 0x80fc |
1559 | #define AR_QUIET1_NEXT_QUIET_S 0 | 1602 | #define AR_QUIET1_NEXT_QUIET_S 0 |
1560 | #define AR_QUIET1_NEXT_QUIET_M 0x0000ffff | 1603 | #define AR_QUIET1_NEXT_QUIET_M 0x0000ffff |
@@ -1605,6 +1648,7 @@ enum { | |||
1605 | #define AR_PCU_TBTT_PROTECT 0x00200000 | 1648 | #define AR_PCU_TBTT_PROTECT 0x00200000 |
1606 | #define AR_PCU_CLEAR_VMF 0x01000000 | 1649 | #define AR_PCU_CLEAR_VMF 0x01000000 |
1607 | #define AR_PCU_CLEAR_BA_VALID 0x04000000 | 1650 | #define AR_PCU_CLEAR_BA_VALID 0x04000000 |
1651 | #define AR_PCU_ALWAYS_PERFORM_KEYSEARCH 0x10000000 | ||
1608 | 1652 | ||
1609 | #define AR_PCU_BT_ANT_PREVENT_RX 0x00100000 | 1653 | #define AR_PCU_BT_ANT_PREVENT_RX 0x00100000 |
1610 | #define AR_PCU_BT_ANT_PREVENT_RX_S 20 | 1654 | #define AR_PCU_BT_ANT_PREVENT_RX_S 20 |
@@ -1665,6 +1709,22 @@ enum { | |||
1665 | #define AR_BTCOEX_WL_WGHT 0xffff0000 | 1709 | #define AR_BTCOEX_WL_WGHT 0xffff0000 |
1666 | #define AR_BTCOEX_WL_WGHT_S 16 | 1710 | #define AR_BTCOEX_WL_WGHT_S 16 |
1667 | 1711 | ||
1712 | #define AR_BT_COEX_WL_WEIGHTS0 0x8174 | ||
1713 | #define AR_BT_COEX_WL_WEIGHTS1 0x81c4 | ||
1714 | |||
1715 | #define AR_BT_COEX_BT_WEIGHTS0 0x83ac | ||
1716 | #define AR_BT_COEX_BT_WEIGHTS1 0x83b0 | ||
1717 | #define AR_BT_COEX_BT_WEIGHTS2 0x83b4 | ||
1718 | #define AR_BT_COEX_BT_WEIGHTS3 0x83b8 | ||
1719 | |||
1720 | #define AR9300_BT_WGHT 0xcccc4444 | ||
1721 | #define AR9300_STOMP_ALL_WLAN_WGHT0 0xfffffff0 | ||
1722 | #define AR9300_STOMP_ALL_WLAN_WGHT1 0xfffffff0 | ||
1723 | #define AR9300_STOMP_LOW_WLAN_WGHT0 0x88888880 | ||
1724 | #define AR9300_STOMP_LOW_WLAN_WGHT1 0x88888880 | ||
1725 | #define AR9300_STOMP_NONE_WLAN_WGHT0 0x00000000 | ||
1726 | #define AR9300_STOMP_NONE_WLAN_WGHT1 0x00000000 | ||
1727 | |||
1668 | #define AR_BT_COEX_MODE2 0x817c | 1728 | #define AR_BT_COEX_MODE2 0x817c |
1669 | #define AR_BT_BCN_MISS_THRESH 0x000000ff | 1729 | #define AR_BT_BCN_MISS_THRESH 0x000000ff |
1670 | #define AR_BT_BCN_MISS_THRESH_S 0 | 1730 | #define AR_BT_BCN_MISS_THRESH_S 0 |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c deleted file mode 100644 index fd20241f57d8..000000000000 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ /dev/null | |||
@@ -1,752 +0,0 @@ | |||
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/slab.h> | ||
18 | |||
19 | #include "ath9k.h" | ||
20 | |||
21 | struct ath9k_vif_iter_data { | ||
22 | int count; | ||
23 | u8 *addr; | ||
24 | }; | ||
25 | |||
26 | static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
27 | { | ||
28 | struct ath9k_vif_iter_data *iter_data = data; | ||
29 | u8 *nbuf; | ||
30 | |||
31 | nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN, | ||
32 | GFP_ATOMIC); | ||
33 | if (nbuf == NULL) | ||
34 | return; | ||
35 | |||
36 | memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN); | ||
37 | iter_data->addr = nbuf; | ||
38 | iter_data->count++; | ||
39 | } | ||
40 | |||
41 | void ath9k_set_bssid_mask(struct ieee80211_hw *hw) | ||
42 | { | ||
43 | struct ath_wiphy *aphy = hw->priv; | ||
44 | struct ath_softc *sc = aphy->sc; | ||
45 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
46 | struct ath9k_vif_iter_data iter_data; | ||
47 | int i, j; | ||
48 | u8 mask[ETH_ALEN]; | ||
49 | |||
50 | /* | ||
51 | * Add primary MAC address even if it is not in active use since it | ||
52 | * will be configured to the hardware as the starting point and the | ||
53 | * BSSID mask will need to be changed if another address is active. | ||
54 | */ | ||
55 | iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); | ||
56 | if (iter_data.addr) { | ||
57 | memcpy(iter_data.addr, common->macaddr, ETH_ALEN); | ||
58 | iter_data.count = 1; | ||
59 | } else | ||
60 | iter_data.count = 0; | ||
61 | |||
62 | /* Get list of all active MAC addresses */ | ||
63 | spin_lock_bh(&sc->wiphy_lock); | ||
64 | ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, | ||
65 | &iter_data); | ||
66 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
67 | if (sc->sec_wiphy[i] == NULL) | ||
68 | continue; | ||
69 | ieee80211_iterate_active_interfaces_atomic( | ||
70 | sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data); | ||
71 | } | ||
72 | spin_unlock_bh(&sc->wiphy_lock); | ||
73 | |||
74 | /* Generate an address mask to cover all active addresses */ | ||
75 | memset(mask, 0, ETH_ALEN); | ||
76 | for (i = 0; i < iter_data.count; i++) { | ||
77 | u8 *a1 = iter_data.addr + i * ETH_ALEN; | ||
78 | for (j = i + 1; j < iter_data.count; j++) { | ||
79 | u8 *a2 = iter_data.addr + j * ETH_ALEN; | ||
80 | mask[0] |= a1[0] ^ a2[0]; | ||
81 | mask[1] |= a1[1] ^ a2[1]; | ||
82 | mask[2] |= a1[2] ^ a2[2]; | ||
83 | mask[3] |= a1[3] ^ a2[3]; | ||
84 | mask[4] |= a1[4] ^ a2[4]; | ||
85 | mask[5] |= a1[5] ^ a2[5]; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | kfree(iter_data.addr); | ||
90 | |||
91 | /* Invert the mask and configure hardware */ | ||
92 | common->bssidmask[0] = ~mask[0]; | ||
93 | common->bssidmask[1] = ~mask[1]; | ||
94 | common->bssidmask[2] = ~mask[2]; | ||
95 | common->bssidmask[3] = ~mask[3]; | ||
96 | common->bssidmask[4] = ~mask[4]; | ||
97 | common->bssidmask[5] = ~mask[5]; | ||
98 | |||
99 | ath_hw_setbssidmask(common); | ||
100 | } | ||
101 | |||
102 | int ath9k_wiphy_add(struct ath_softc *sc) | ||
103 | { | ||
104 | int i, error; | ||
105 | struct ath_wiphy *aphy; | ||
106 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
107 | struct ieee80211_hw *hw; | ||
108 | u8 addr[ETH_ALEN]; | ||
109 | |||
110 | hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops); | ||
111 | if (hw == NULL) | ||
112 | return -ENOMEM; | ||
113 | |||
114 | spin_lock_bh(&sc->wiphy_lock); | ||
115 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
116 | if (sc->sec_wiphy[i] == NULL) | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | if (i == sc->num_sec_wiphy) { | ||
121 | /* No empty slot available; increase array length */ | ||
122 | struct ath_wiphy **n; | ||
123 | n = krealloc(sc->sec_wiphy, | ||
124 | (sc->num_sec_wiphy + 1) * | ||
125 | sizeof(struct ath_wiphy *), | ||
126 | GFP_ATOMIC); | ||
127 | if (n == NULL) { | ||
128 | spin_unlock_bh(&sc->wiphy_lock); | ||
129 | ieee80211_free_hw(hw); | ||
130 | return -ENOMEM; | ||
131 | } | ||
132 | n[i] = NULL; | ||
133 | sc->sec_wiphy = n; | ||
134 | sc->num_sec_wiphy++; | ||
135 | } | ||
136 | |||
137 | SET_IEEE80211_DEV(hw, sc->dev); | ||
138 | |||
139 | aphy = hw->priv; | ||
140 | aphy->sc = sc; | ||
141 | aphy->hw = hw; | ||
142 | sc->sec_wiphy[i] = aphy; | ||
143 | spin_unlock_bh(&sc->wiphy_lock); | ||
144 | |||
145 | memcpy(addr, common->macaddr, ETH_ALEN); | ||
146 | addr[0] |= 0x02; /* Locally managed address */ | ||
147 | /* | ||
148 | * XOR virtual wiphy index into the least significant bits to generate | ||
149 | * a different MAC address for each virtual wiphy. | ||
150 | */ | ||
151 | addr[5] ^= i & 0xff; | ||
152 | addr[4] ^= (i & 0xff00) >> 8; | ||
153 | addr[3] ^= (i & 0xff0000) >> 16; | ||
154 | |||
155 | SET_IEEE80211_PERM_ADDR(hw, addr); | ||
156 | |||
157 | ath9k_set_hw_capab(sc, hw); | ||
158 | |||
159 | error = ieee80211_register_hw(hw); | ||
160 | |||
161 | if (error == 0) { | ||
162 | /* Make sure wiphy scheduler is started (if enabled) */ | ||
163 | ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int); | ||
164 | } | ||
165 | |||
166 | return error; | ||
167 | } | ||
168 | |||
169 | int ath9k_wiphy_del(struct ath_wiphy *aphy) | ||
170 | { | ||
171 | struct ath_softc *sc = aphy->sc; | ||
172 | int i; | ||
173 | |||
174 | spin_lock_bh(&sc->wiphy_lock); | ||
175 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
176 | if (aphy == sc->sec_wiphy[i]) { | ||
177 | sc->sec_wiphy[i] = NULL; | ||
178 | spin_unlock_bh(&sc->wiphy_lock); | ||
179 | ieee80211_unregister_hw(aphy->hw); | ||
180 | ieee80211_free_hw(aphy->hw); | ||
181 | return 0; | ||
182 | } | ||
183 | } | ||
184 | spin_unlock_bh(&sc->wiphy_lock); | ||
185 | return -ENOENT; | ||
186 | } | ||
187 | |||
188 | static int ath9k_send_nullfunc(struct ath_wiphy *aphy, | ||
189 | struct ieee80211_vif *vif, const u8 *bssid, | ||
190 | int ps) | ||
191 | { | ||
192 | struct ath_softc *sc = aphy->sc; | ||
193 | struct ath_tx_control txctl; | ||
194 | struct sk_buff *skb; | ||
195 | struct ieee80211_hdr *hdr; | ||
196 | __le16 fc; | ||
197 | struct ieee80211_tx_info *info; | ||
198 | |||
199 | skb = dev_alloc_skb(24); | ||
200 | if (skb == NULL) | ||
201 | return -ENOMEM; | ||
202 | hdr = (struct ieee80211_hdr *) skb_put(skb, 24); | ||
203 | memset(hdr, 0, 24); | ||
204 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | ||
205 | IEEE80211_FCTL_TODS); | ||
206 | if (ps) | ||
207 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | ||
208 | hdr->frame_control = fc; | ||
209 | memcpy(hdr->addr1, bssid, ETH_ALEN); | ||
210 | memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN); | ||
211 | memcpy(hdr->addr3, bssid, ETH_ALEN); | ||
212 | |||
213 | info = IEEE80211_SKB_CB(skb); | ||
214 | memset(info, 0, sizeof(*info)); | ||
215 | info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
216 | info->control.vif = vif; | ||
217 | info->control.rates[0].idx = 0; | ||
218 | info->control.rates[0].count = 4; | ||
219 | info->control.rates[1].idx = -1; | ||
220 | |||
221 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | ||
222 | txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]]; | ||
223 | txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE; | ||
224 | |||
225 | if (ath_tx_start(aphy->hw, skb, &txctl) != 0) | ||
226 | goto exit; | ||
227 | |||
228 | return 0; | ||
229 | exit: | ||
230 | dev_kfree_skb_any(skb); | ||
231 | return -1; | ||
232 | } | ||
233 | |||
234 | static bool __ath9k_wiphy_pausing(struct ath_softc *sc) | ||
235 | { | ||
236 | int i; | ||
237 | if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING) | ||
238 | return true; | ||
239 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
240 | if (sc->sec_wiphy[i] && | ||
241 | sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING) | ||
242 | return true; | ||
243 | } | ||
244 | return false; | ||
245 | } | ||
246 | |||
247 | static bool ath9k_wiphy_pausing(struct ath_softc *sc) | ||
248 | { | ||
249 | bool ret; | ||
250 | spin_lock_bh(&sc->wiphy_lock); | ||
251 | ret = __ath9k_wiphy_pausing(sc); | ||
252 | spin_unlock_bh(&sc->wiphy_lock); | ||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | static bool __ath9k_wiphy_scanning(struct ath_softc *sc) | ||
257 | { | ||
258 | int i; | ||
259 | if (sc->pri_wiphy->state == ATH_WIPHY_SCAN) | ||
260 | return true; | ||
261 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
262 | if (sc->sec_wiphy[i] && | ||
263 | sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN) | ||
264 | return true; | ||
265 | } | ||
266 | return false; | ||
267 | } | ||
268 | |||
269 | bool ath9k_wiphy_scanning(struct ath_softc *sc) | ||
270 | { | ||
271 | bool ret; | ||
272 | spin_lock_bh(&sc->wiphy_lock); | ||
273 | ret = __ath9k_wiphy_scanning(sc); | ||
274 | spin_unlock_bh(&sc->wiphy_lock); | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy); | ||
279 | |||
280 | /* caller must hold wiphy_lock */ | ||
281 | static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy) | ||
282 | { | ||
283 | if (aphy == NULL) | ||
284 | return; | ||
285 | if (aphy->chan_idx != aphy->sc->chan_idx) | ||
286 | return; /* wiphy not on the selected channel */ | ||
287 | __ath9k_wiphy_unpause(aphy); | ||
288 | } | ||
289 | |||
290 | static void ath9k_wiphy_unpause_channel(struct ath_softc *sc) | ||
291 | { | ||
292 | int i; | ||
293 | spin_lock_bh(&sc->wiphy_lock); | ||
294 | __ath9k_wiphy_unpause_ch(sc->pri_wiphy); | ||
295 | for (i = 0; i < sc->num_sec_wiphy; i++) | ||
296 | __ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]); | ||
297 | spin_unlock_bh(&sc->wiphy_lock); | ||
298 | } | ||
299 | |||
300 | void ath9k_wiphy_chan_work(struct work_struct *work) | ||
301 | { | ||
302 | struct ath_softc *sc = container_of(work, struct ath_softc, chan_work); | ||
303 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
304 | struct ath_wiphy *aphy = sc->next_wiphy; | ||
305 | |||
306 | if (aphy == NULL) | ||
307 | return; | ||
308 | |||
309 | /* | ||
310 | * All pending interfaces paused; ready to change | ||
311 | * channels. | ||
312 | */ | ||
313 | |||
314 | /* Change channels */ | ||
315 | mutex_lock(&sc->mutex); | ||
316 | /* XXX: remove me eventually */ | ||
317 | ath9k_update_ichannel(sc, aphy->hw, | ||
318 | &sc->sc_ah->channels[sc->chan_idx]); | ||
319 | |||
320 | /* sync hw configuration for hw code */ | ||
321 | common->hw = aphy->hw; | ||
322 | |||
323 | ath_update_chainmask(sc, sc->chan_is_ht); | ||
324 | if (ath_set_channel(sc, aphy->hw, | ||
325 | &sc->sc_ah->channels[sc->chan_idx]) < 0) { | ||
326 | printk(KERN_DEBUG "ath9k: Failed to set channel for new " | ||
327 | "virtual wiphy\n"); | ||
328 | mutex_unlock(&sc->mutex); | ||
329 | return; | ||
330 | } | ||
331 | mutex_unlock(&sc->mutex); | ||
332 | |||
333 | ath9k_wiphy_unpause_channel(sc); | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | * ath9k version of ieee80211_tx_status() for TX frames that are generated | ||
338 | * internally in the driver. | ||
339 | */ | ||
340 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
341 | { | ||
342 | struct ath_wiphy *aphy = hw->priv; | ||
343 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
344 | |||
345 | if ((tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_PAUSE) && | ||
346 | aphy->state == ATH_WIPHY_PAUSING) { | ||
347 | if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) { | ||
348 | printk(KERN_DEBUG "ath9k: %s: no ACK for pause " | ||
349 | "frame\n", wiphy_name(hw->wiphy)); | ||
350 | /* | ||
351 | * The AP did not reply; ignore this to allow us to | ||
352 | * continue. | ||
353 | */ | ||
354 | } | ||
355 | aphy->state = ATH_WIPHY_PAUSED; | ||
356 | if (!ath9k_wiphy_pausing(aphy->sc)) { | ||
357 | /* | ||
358 | * Drop from tasklet to work to allow mutex for channel | ||
359 | * change. | ||
360 | */ | ||
361 | ieee80211_queue_work(aphy->sc->hw, | ||
362 | &aphy->sc->chan_work); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | dev_kfree_skb(skb); | ||
367 | } | ||
368 | |||
369 | static void ath9k_mark_paused(struct ath_wiphy *aphy) | ||
370 | { | ||
371 | struct ath_softc *sc = aphy->sc; | ||
372 | aphy->state = ATH_WIPHY_PAUSED; | ||
373 | if (!__ath9k_wiphy_pausing(sc)) | ||
374 | ieee80211_queue_work(sc->hw, &sc->chan_work); | ||
375 | } | ||
376 | |||
377 | static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
378 | { | ||
379 | struct ath_wiphy *aphy = data; | ||
380 | struct ath_vif *avp = (void *) vif->drv_priv; | ||
381 | |||
382 | switch (vif->type) { | ||
383 | case NL80211_IFTYPE_STATION: | ||
384 | if (!vif->bss_conf.assoc) { | ||
385 | ath9k_mark_paused(aphy); | ||
386 | break; | ||
387 | } | ||
388 | /* TODO: could avoid this if already in PS mode */ | ||
389 | if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) { | ||
390 | printk(KERN_DEBUG "%s: failed to send PS nullfunc\n", | ||
391 | __func__); | ||
392 | ath9k_mark_paused(aphy); | ||
393 | } | ||
394 | break; | ||
395 | case NL80211_IFTYPE_AP: | ||
396 | /* Beacon transmission is paused by aphy->state change */ | ||
397 | ath9k_mark_paused(aphy); | ||
398 | break; | ||
399 | default: | ||
400 | break; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | /* caller must hold wiphy_lock */ | ||
405 | static int __ath9k_wiphy_pause(struct ath_wiphy *aphy) | ||
406 | { | ||
407 | ieee80211_stop_queues(aphy->hw); | ||
408 | aphy->state = ATH_WIPHY_PAUSING; | ||
409 | /* | ||
410 | * TODO: handle PAUSING->PAUSED for the case where there are multiple | ||
411 | * active vifs (now we do it on the first vif getting ready; should be | ||
412 | * on the last) | ||
413 | */ | ||
414 | ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter, | ||
415 | aphy); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | int ath9k_wiphy_pause(struct ath_wiphy *aphy) | ||
420 | { | ||
421 | int ret; | ||
422 | spin_lock_bh(&aphy->sc->wiphy_lock); | ||
423 | ret = __ath9k_wiphy_pause(aphy); | ||
424 | spin_unlock_bh(&aphy->sc->wiphy_lock); | ||
425 | return ret; | ||
426 | } | ||
427 | |||
428 | static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
429 | { | ||
430 | struct ath_wiphy *aphy = data; | ||
431 | struct ath_vif *avp = (void *) vif->drv_priv; | ||
432 | |||
433 | switch (vif->type) { | ||
434 | case NL80211_IFTYPE_STATION: | ||
435 | if (!vif->bss_conf.assoc) | ||
436 | break; | ||
437 | ath9k_send_nullfunc(aphy, vif, avp->bssid, 0); | ||
438 | break; | ||
439 | case NL80211_IFTYPE_AP: | ||
440 | /* Beacon transmission is re-enabled by aphy->state change */ | ||
441 | break; | ||
442 | default: | ||
443 | break; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /* caller must hold wiphy_lock */ | ||
448 | static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy) | ||
449 | { | ||
450 | ieee80211_iterate_active_interfaces_atomic(aphy->hw, | ||
451 | ath9k_unpause_iter, aphy); | ||
452 | aphy->state = ATH_WIPHY_ACTIVE; | ||
453 | ieee80211_wake_queues(aphy->hw); | ||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | int ath9k_wiphy_unpause(struct ath_wiphy *aphy) | ||
458 | { | ||
459 | int ret; | ||
460 | spin_lock_bh(&aphy->sc->wiphy_lock); | ||
461 | ret = __ath9k_wiphy_unpause(aphy); | ||
462 | spin_unlock_bh(&aphy->sc->wiphy_lock); | ||
463 | return ret; | ||
464 | } | ||
465 | |||
466 | static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc) | ||
467 | { | ||
468 | int i; | ||
469 | if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) | ||
470 | sc->pri_wiphy->state = ATH_WIPHY_PAUSED; | ||
471 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
472 | if (sc->sec_wiphy[i] && | ||
473 | sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) | ||
474 | sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | /* caller must hold wiphy_lock */ | ||
479 | static void __ath9k_wiphy_pause_all(struct ath_softc *sc) | ||
480 | { | ||
481 | int i; | ||
482 | if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) | ||
483 | __ath9k_wiphy_pause(sc->pri_wiphy); | ||
484 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
485 | if (sc->sec_wiphy[i] && | ||
486 | sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) | ||
487 | __ath9k_wiphy_pause(sc->sec_wiphy[i]); | ||
488 | } | ||
489 | } | ||
490 | |||
491 | int ath9k_wiphy_select(struct ath_wiphy *aphy) | ||
492 | { | ||
493 | struct ath_softc *sc = aphy->sc; | ||
494 | bool now; | ||
495 | |||
496 | spin_lock_bh(&sc->wiphy_lock); | ||
497 | if (__ath9k_wiphy_scanning(sc)) { | ||
498 | /* | ||
499 | * For now, we are using mac80211 sw scan and it expects to | ||
500 | * have full control over channel changes, so avoid wiphy | ||
501 | * scheduling during a scan. This could be optimized if the | ||
502 | * scanning control were moved into the driver. | ||
503 | */ | ||
504 | spin_unlock_bh(&sc->wiphy_lock); | ||
505 | return -EBUSY; | ||
506 | } | ||
507 | if (__ath9k_wiphy_pausing(sc)) { | ||
508 | if (sc->wiphy_select_failures == 0) | ||
509 | sc->wiphy_select_first_fail = jiffies; | ||
510 | sc->wiphy_select_failures++; | ||
511 | if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2)) | ||
512 | { | ||
513 | printk(KERN_DEBUG "ath9k: Previous wiphy select timed " | ||
514 | "out; disable/enable hw to recover\n"); | ||
515 | __ath9k_wiphy_mark_all_paused(sc); | ||
516 | /* | ||
517 | * TODO: this workaround to fix hardware is unlikely to | ||
518 | * be specific to virtual wiphy changes. It can happen | ||
519 | * on normal channel change, too, and as such, this | ||
520 | * should really be made more generic. For example, | ||
521 | * tricker radio disable/enable on GTT interrupt burst | ||
522 | * (say, 10 GTT interrupts received without any TX | ||
523 | * frame being completed) | ||
524 | */ | ||
525 | spin_unlock_bh(&sc->wiphy_lock); | ||
526 | ath_radio_disable(sc, aphy->hw); | ||
527 | ath_radio_enable(sc, aphy->hw); | ||
528 | /* Only the primary wiphy hw is used for queuing work */ | ||
529 | ieee80211_queue_work(aphy->sc->hw, | ||
530 | &aphy->sc->chan_work); | ||
531 | return -EBUSY; /* previous select still in progress */ | ||
532 | } | ||
533 | spin_unlock_bh(&sc->wiphy_lock); | ||
534 | return -EBUSY; /* previous select still in progress */ | ||
535 | } | ||
536 | sc->wiphy_select_failures = 0; | ||
537 | |||
538 | /* Store the new channel */ | ||
539 | sc->chan_idx = aphy->chan_idx; | ||
540 | sc->chan_is_ht = aphy->chan_is_ht; | ||
541 | sc->next_wiphy = aphy; | ||
542 | |||
543 | __ath9k_wiphy_pause_all(sc); | ||
544 | now = !__ath9k_wiphy_pausing(aphy->sc); | ||
545 | spin_unlock_bh(&sc->wiphy_lock); | ||
546 | |||
547 | if (now) { | ||
548 | /* Ready to request channel change immediately */ | ||
549 | ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work); | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | * wiphys will be unpaused in ath9k_tx_status() once channel has been | ||
554 | * changed if any wiphy needs time to become paused. | ||
555 | */ | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | bool ath9k_wiphy_started(struct ath_softc *sc) | ||
561 | { | ||
562 | int i; | ||
563 | spin_lock_bh(&sc->wiphy_lock); | ||
564 | if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { | ||
565 | spin_unlock_bh(&sc->wiphy_lock); | ||
566 | return true; | ||
567 | } | ||
568 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
569 | if (sc->sec_wiphy[i] && | ||
570 | sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) { | ||
571 | spin_unlock_bh(&sc->wiphy_lock); | ||
572 | return true; | ||
573 | } | ||
574 | } | ||
575 | spin_unlock_bh(&sc->wiphy_lock); | ||
576 | return false; | ||
577 | } | ||
578 | |||
579 | static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy, | ||
580 | struct ath_wiphy *selected) | ||
581 | { | ||
582 | if (selected->state == ATH_WIPHY_SCAN) { | ||
583 | if (aphy == selected) | ||
584 | return; | ||
585 | /* | ||
586 | * Pause all other wiphys for the duration of the scan even if | ||
587 | * they are on the current channel now. | ||
588 | */ | ||
589 | } else if (aphy->chan_idx == selected->chan_idx) | ||
590 | return; | ||
591 | aphy->state = ATH_WIPHY_PAUSED; | ||
592 | ieee80211_stop_queues(aphy->hw); | ||
593 | } | ||
594 | |||
595 | void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, | ||
596 | struct ath_wiphy *selected) | ||
597 | { | ||
598 | int i; | ||
599 | spin_lock_bh(&sc->wiphy_lock); | ||
600 | if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) | ||
601 | ath9k_wiphy_pause_chan(sc->pri_wiphy, selected); | ||
602 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
603 | if (sc->sec_wiphy[i] && | ||
604 | sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) | ||
605 | ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected); | ||
606 | } | ||
607 | spin_unlock_bh(&sc->wiphy_lock); | ||
608 | } | ||
609 | |||
610 | void ath9k_wiphy_work(struct work_struct *work) | ||
611 | { | ||
612 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
613 | wiphy_work.work); | ||
614 | struct ath_wiphy *aphy = NULL; | ||
615 | bool first = true; | ||
616 | |||
617 | spin_lock_bh(&sc->wiphy_lock); | ||
618 | |||
619 | if (sc->wiphy_scheduler_int == 0) { | ||
620 | /* wiphy scheduler is disabled */ | ||
621 | spin_unlock_bh(&sc->wiphy_lock); | ||
622 | return; | ||
623 | } | ||
624 | |||
625 | try_again: | ||
626 | sc->wiphy_scheduler_index++; | ||
627 | while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) { | ||
628 | aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1]; | ||
629 | if (aphy && aphy->state != ATH_WIPHY_INACTIVE) | ||
630 | break; | ||
631 | |||
632 | sc->wiphy_scheduler_index++; | ||
633 | aphy = NULL; | ||
634 | } | ||
635 | if (aphy == NULL) { | ||
636 | sc->wiphy_scheduler_index = 0; | ||
637 | if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) { | ||
638 | if (first) { | ||
639 | first = false; | ||
640 | goto try_again; | ||
641 | } | ||
642 | /* No wiphy is ready to be scheduled */ | ||
643 | } else | ||
644 | aphy = sc->pri_wiphy; | ||
645 | } | ||
646 | |||
647 | spin_unlock_bh(&sc->wiphy_lock); | ||
648 | |||
649 | if (aphy && | ||
650 | aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN && | ||
651 | ath9k_wiphy_select(aphy)) { | ||
652 | printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy " | ||
653 | "change\n"); | ||
654 | } | ||
655 | |||
656 | ieee80211_queue_delayed_work(sc->hw, | ||
657 | &sc->wiphy_work, | ||
658 | sc->wiphy_scheduler_int); | ||
659 | } | ||
660 | |||
661 | void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) | ||
662 | { | ||
663 | cancel_delayed_work_sync(&sc->wiphy_work); | ||
664 | sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); | ||
665 | if (sc->wiphy_scheduler_int) | ||
666 | ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work, | ||
667 | sc->wiphy_scheduler_int); | ||
668 | } | ||
669 | |||
670 | /* caller must hold wiphy_lock */ | ||
671 | bool ath9k_all_wiphys_idle(struct ath_softc *sc) | ||
672 | { | ||
673 | unsigned int i; | ||
674 | if (!sc->pri_wiphy->idle) | ||
675 | return false; | ||
676 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
677 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
678 | if (!aphy) | ||
679 | continue; | ||
680 | if (!aphy->idle) | ||
681 | return false; | ||
682 | } | ||
683 | return true; | ||
684 | } | ||
685 | |||
686 | /* caller must hold wiphy_lock */ | ||
687 | void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle) | ||
688 | { | ||
689 | struct ath_softc *sc = aphy->sc; | ||
690 | |||
691 | aphy->idle = idle; | ||
692 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, | ||
693 | "Marking %s as %s\n", | ||
694 | wiphy_name(aphy->hw->wiphy), | ||
695 | idle ? "idle" : "not-idle"); | ||
696 | } | ||
697 | /* Only bother starting a queue on an active virtual wiphy */ | ||
698 | bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue) | ||
699 | { | ||
700 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | ||
701 | unsigned int i; | ||
702 | bool txq_started = false; | ||
703 | |||
704 | spin_lock_bh(&sc->wiphy_lock); | ||
705 | |||
706 | /* Start the primary wiphy */ | ||
707 | if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) { | ||
708 | ieee80211_wake_queue(hw, skb_queue); | ||
709 | txq_started = true; | ||
710 | goto unlock; | ||
711 | } | ||
712 | |||
713 | /* Now start the secondary wiphy queues */ | ||
714 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
715 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
716 | if (!aphy) | ||
717 | continue; | ||
718 | if (aphy->state != ATH_WIPHY_ACTIVE) | ||
719 | continue; | ||
720 | |||
721 | hw = aphy->hw; | ||
722 | ieee80211_wake_queue(hw, skb_queue); | ||
723 | txq_started = true; | ||
724 | break; | ||
725 | } | ||
726 | |||
727 | unlock: | ||
728 | spin_unlock_bh(&sc->wiphy_lock); | ||
729 | return txq_started; | ||
730 | } | ||
731 | |||
732 | /* Go ahead and propagate information to all virtual wiphys, it won't hurt */ | ||
733 | void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue) | ||
734 | { | ||
735 | struct ieee80211_hw *hw = sc->pri_wiphy->hw; | ||
736 | unsigned int i; | ||
737 | |||
738 | spin_lock_bh(&sc->wiphy_lock); | ||
739 | |||
740 | /* Stop the primary wiphy */ | ||
741 | ieee80211_stop_queue(hw, skb_queue); | ||
742 | |||
743 | /* Now stop the secondary wiphy queues */ | ||
744 | for (i = 0; i < sc->num_sec_wiphy; i++) { | ||
745 | struct ath_wiphy *aphy = sc->sec_wiphy[i]; | ||
746 | if (!aphy) | ||
747 | continue; | ||
748 | hw = aphy->hw; | ||
749 | ieee80211_stop_queue(hw, skb_queue); | ||
750 | } | ||
751 | spin_unlock_bh(&sc->wiphy_lock); | ||
752 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 6260faa658a2..35422fc1f2ce 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -23,20 +23,18 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
23 | return "WMI_ECHO_CMDID"; | 23 | return "WMI_ECHO_CMDID"; |
24 | case WMI_ACCESS_MEMORY_CMDID: | 24 | case WMI_ACCESS_MEMORY_CMDID: |
25 | return "WMI_ACCESS_MEMORY_CMDID"; | 25 | return "WMI_ACCESS_MEMORY_CMDID"; |
26 | case WMI_GET_FW_VERSION: | ||
27 | return "WMI_GET_FW_VERSION"; | ||
26 | case WMI_DISABLE_INTR_CMDID: | 28 | case WMI_DISABLE_INTR_CMDID: |
27 | return "WMI_DISABLE_INTR_CMDID"; | 29 | return "WMI_DISABLE_INTR_CMDID"; |
28 | case WMI_ENABLE_INTR_CMDID: | 30 | case WMI_ENABLE_INTR_CMDID: |
29 | return "WMI_ENABLE_INTR_CMDID"; | 31 | return "WMI_ENABLE_INTR_CMDID"; |
30 | case WMI_RX_LINK_CMDID: | ||
31 | return "WMI_RX_LINK_CMDID"; | ||
32 | case WMI_ATH_INIT_CMDID: | 32 | case WMI_ATH_INIT_CMDID: |
33 | return "WMI_ATH_INIT_CMDID"; | 33 | return "WMI_ATH_INIT_CMDID"; |
34 | case WMI_ABORT_TXQ_CMDID: | 34 | case WMI_ABORT_TXQ_CMDID: |
35 | return "WMI_ABORT_TXQ_CMDID"; | 35 | return "WMI_ABORT_TXQ_CMDID"; |
36 | case WMI_STOP_TX_DMA_CMDID: | 36 | case WMI_STOP_TX_DMA_CMDID: |
37 | return "WMI_STOP_TX_DMA_CMDID"; | 37 | return "WMI_STOP_TX_DMA_CMDID"; |
38 | case WMI_STOP_DMA_RECV_CMDID: | ||
39 | return "WMI_STOP_DMA_RECV_CMDID"; | ||
40 | case WMI_ABORT_TX_DMA_CMDID: | 38 | case WMI_ABORT_TX_DMA_CMDID: |
41 | return "WMI_ABORT_TX_DMA_CMDID"; | 39 | return "WMI_ABORT_TX_DMA_CMDID"; |
42 | case WMI_DRAIN_TXQ_CMDID: | 40 | case WMI_DRAIN_TXQ_CMDID: |
@@ -51,8 +49,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
51 | return "WMI_FLUSH_RECV_CMDID"; | 49 | return "WMI_FLUSH_RECV_CMDID"; |
52 | case WMI_SET_MODE_CMDID: | 50 | case WMI_SET_MODE_CMDID: |
53 | return "WMI_SET_MODE_CMDID"; | 51 | return "WMI_SET_MODE_CMDID"; |
54 | case WMI_RESET_CMDID: | ||
55 | return "WMI_RESET_CMDID"; | ||
56 | case WMI_NODE_CREATE_CMDID: | 52 | case WMI_NODE_CREATE_CMDID: |
57 | return "WMI_NODE_CREATE_CMDID"; | 53 | return "WMI_NODE_CREATE_CMDID"; |
58 | case WMI_NODE_REMOVE_CMDID: | 54 | case WMI_NODE_REMOVE_CMDID: |
@@ -61,8 +57,6 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
61 | return "WMI_VAP_REMOVE_CMDID"; | 57 | return "WMI_VAP_REMOVE_CMDID"; |
62 | case WMI_VAP_CREATE_CMDID: | 58 | case WMI_VAP_CREATE_CMDID: |
63 | return "WMI_VAP_CREATE_CMDID"; | 59 | return "WMI_VAP_CREATE_CMDID"; |
64 | case WMI_BEACON_UPDATE_CMDID: | ||
65 | return "WMI_BEACON_UPDATE_CMDID"; | ||
66 | case WMI_REG_READ_CMDID: | 60 | case WMI_REG_READ_CMDID: |
67 | return "WMI_REG_READ_CMDID"; | 61 | return "WMI_REG_READ_CMDID"; |
68 | case WMI_REG_WRITE_CMDID: | 62 | case WMI_REG_WRITE_CMDID: |
@@ -71,20 +65,22 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
71 | return "WMI_RC_STATE_CHANGE_CMDID"; | 65 | return "WMI_RC_STATE_CHANGE_CMDID"; |
72 | case WMI_RC_RATE_UPDATE_CMDID: | 66 | case WMI_RC_RATE_UPDATE_CMDID: |
73 | return "WMI_RC_RATE_UPDATE_CMDID"; | 67 | return "WMI_RC_RATE_UPDATE_CMDID"; |
74 | case WMI_DEBUG_INFO_CMDID: | ||
75 | return "WMI_DEBUG_INFO_CMDID"; | ||
76 | case WMI_HOST_ATTACH: | ||
77 | return "WMI_HOST_ATTACH"; | ||
78 | case WMI_TARGET_IC_UPDATE_CMDID: | 68 | case WMI_TARGET_IC_UPDATE_CMDID: |
79 | return "WMI_TARGET_IC_UPDATE_CMDID"; | 69 | return "WMI_TARGET_IC_UPDATE_CMDID"; |
80 | case WMI_TGT_STATS_CMDID: | ||
81 | return "WMI_TGT_STATS_CMDID"; | ||
82 | case WMI_TX_AGGR_ENABLE_CMDID: | 70 | case WMI_TX_AGGR_ENABLE_CMDID: |
83 | return "WMI_TX_AGGR_ENABLE_CMDID"; | 71 | return "WMI_TX_AGGR_ENABLE_CMDID"; |
84 | case WMI_TGT_DETACH_CMDID: | 72 | case WMI_TGT_DETACH_CMDID: |
85 | return "WMI_TGT_DETACH_CMDID"; | 73 | return "WMI_TGT_DETACH_CMDID"; |
86 | case WMI_TGT_TXQ_ENABLE_CMDID: | 74 | case WMI_NODE_UPDATE_CMDID: |
87 | return "WMI_TGT_TXQ_ENABLE_CMDID"; | 75 | return "WMI_NODE_UPDATE_CMDID"; |
76 | case WMI_INT_STATS_CMDID: | ||
77 | return "WMI_INT_STATS_CMDID"; | ||
78 | case WMI_TX_STATS_CMDID: | ||
79 | return "WMI_TX_STATS_CMDID"; | ||
80 | case WMI_RX_STATS_CMDID: | ||
81 | return "WMI_RX_STATS_CMDID"; | ||
82 | case WMI_BITRATE_MASK_CMDID: | ||
83 | return "WMI_BITRATE_MASK_CMDID"; | ||
88 | } | 84 | } |
89 | 85 | ||
90 | return "Bogus"; | 86 | return "Bogus"; |
@@ -100,9 +96,15 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv) | |||
100 | 96 | ||
101 | wmi->drv_priv = priv; | 97 | wmi->drv_priv = priv; |
102 | wmi->stopped = false; | 98 | wmi->stopped = false; |
99 | skb_queue_head_init(&wmi->wmi_event_queue); | ||
100 | spin_lock_init(&wmi->wmi_lock); | ||
101 | spin_lock_init(&wmi->event_lock); | ||
103 | mutex_init(&wmi->op_mutex); | 102 | mutex_init(&wmi->op_mutex); |
104 | mutex_init(&wmi->multi_write_mutex); | 103 | mutex_init(&wmi->multi_write_mutex); |
105 | init_completion(&wmi->cmd_wait); | 104 | init_completion(&wmi->cmd_wait); |
105 | INIT_LIST_HEAD(&wmi->pending_tx_events); | ||
106 | tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet, | ||
107 | (unsigned long)wmi); | ||
106 | 108 | ||
107 | return wmi; | 109 | return wmi; |
108 | } | 110 | } |
@@ -118,59 +120,75 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv) | |||
118 | kfree(priv->wmi); | 120 | kfree(priv->wmi); |
119 | } | 121 | } |
120 | 122 | ||
121 | void ath9k_wmi_tasklet(unsigned long data) | 123 | void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv) |
122 | { | 124 | { |
123 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | ||
124 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
125 | struct wmi_cmd_hdr *hdr; | ||
126 | struct wmi_swba *swba_hdr; | ||
127 | enum wmi_event_id event; | ||
128 | struct sk_buff *skb; | ||
129 | void *wmi_event; | ||
130 | unsigned long flags; | 125 | unsigned long flags; |
131 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
132 | __be32 txrate; | ||
133 | #endif | ||
134 | 126 | ||
127 | tasklet_kill(&priv->wmi->wmi_event_tasklet); | ||
135 | spin_lock_irqsave(&priv->wmi->wmi_lock, flags); | 128 | spin_lock_irqsave(&priv->wmi->wmi_lock, flags); |
136 | skb = priv->wmi->wmi_skb; | 129 | __skb_queue_purge(&priv->wmi->wmi_event_queue); |
137 | spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); | 130 | spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags); |
131 | } | ||
138 | 132 | ||
139 | hdr = (struct wmi_cmd_hdr *) skb->data; | 133 | void ath9k_wmi_event_tasklet(unsigned long data) |
140 | event = be16_to_cpu(hdr->command_id); | 134 | { |
141 | wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); | 135 | struct wmi *wmi = (struct wmi *)data; |
142 | 136 | struct ath9k_htc_priv *priv = wmi->drv_priv; | |
143 | ath_print(common, ATH_DBG_WMI, | 137 | struct wmi_cmd_hdr *hdr; |
144 | "WMI Event: 0x%x\n", event); | 138 | void *wmi_event; |
145 | 139 | struct wmi_event_swba *swba; | |
146 | switch (event) { | 140 | struct sk_buff *skb = NULL; |
147 | case WMI_TGT_RDY_EVENTID: | 141 | unsigned long flags; |
148 | break; | 142 | u16 cmd_id; |
149 | case WMI_SWBA_EVENTID: | ||
150 | swba_hdr = (struct wmi_swba *) wmi_event; | ||
151 | ath9k_htc_swba(priv, swba_hdr->beacon_pending); | ||
152 | break; | ||
153 | case WMI_FATAL_EVENTID: | ||
154 | break; | ||
155 | case WMI_TXTO_EVENTID: | ||
156 | break; | ||
157 | case WMI_BMISS_EVENTID: | ||
158 | break; | ||
159 | case WMI_WLAN_TXCOMP_EVENTID: | ||
160 | break; | ||
161 | case WMI_DELBA_EVENTID: | ||
162 | break; | ||
163 | case WMI_TXRATE_EVENTID: | ||
164 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
165 | txrate = ((struct wmi_event_txrate *)wmi_event)->txrate; | ||
166 | priv->debug.txrate = be32_to_cpu(txrate); | ||
167 | #endif | ||
168 | break; | ||
169 | default: | ||
170 | break; | ||
171 | } | ||
172 | 143 | ||
173 | kfree_skb(skb); | 144 | do { |
145 | spin_lock_irqsave(&wmi->wmi_lock, flags); | ||
146 | skb = __skb_dequeue(&wmi->wmi_event_queue); | ||
147 | if (!skb) { | ||
148 | spin_unlock_irqrestore(&wmi->wmi_lock, flags); | ||
149 | return; | ||
150 | } | ||
151 | spin_unlock_irqrestore(&wmi->wmi_lock, flags); | ||
152 | |||
153 | hdr = (struct wmi_cmd_hdr *) skb->data; | ||
154 | cmd_id = be16_to_cpu(hdr->command_id); | ||
155 | wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr)); | ||
156 | |||
157 | switch (cmd_id) { | ||
158 | case WMI_SWBA_EVENTID: | ||
159 | swba = (struct wmi_event_swba *) wmi_event; | ||
160 | ath9k_htc_swba(priv, swba); | ||
161 | break; | ||
162 | case WMI_FATAL_EVENTID: | ||
163 | ieee80211_queue_work(wmi->drv_priv->hw, | ||
164 | &wmi->drv_priv->fatal_work); | ||
165 | break; | ||
166 | case WMI_TXSTATUS_EVENTID: | ||
167 | spin_lock_bh(&priv->tx.tx_lock); | ||
168 | if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) { | ||
169 | spin_unlock_bh(&priv->tx.tx_lock); | ||
170 | break; | ||
171 | } | ||
172 | spin_unlock_bh(&priv->tx.tx_lock); | ||
173 | |||
174 | ath9k_htc_txstatus(priv, wmi_event); | ||
175 | break; | ||
176 | default: | ||
177 | break; | ||
178 | } | ||
179 | |||
180 | kfree_skb(skb); | ||
181 | } while (1); | ||
182 | } | ||
183 | |||
184 | void ath9k_fatal_work(struct work_struct *work) | ||
185 | { | ||
186 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | ||
187 | fatal_work); | ||
188 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
189 | |||
190 | ath_dbg(common, ATH_DBG_FATAL, "FATAL Event received, resetting device\n"); | ||
191 | ath9k_htc_reset(priv); | ||
174 | } | 192 | } |
175 | 193 | ||
176 | static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) | 194 | static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) |
@@ -198,9 +216,9 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, | |||
198 | 216 | ||
199 | if (cmd_id & 0x1000) { | 217 | if (cmd_id & 0x1000) { |
200 | spin_lock(&wmi->wmi_lock); | 218 | spin_lock(&wmi->wmi_lock); |
201 | wmi->wmi_skb = skb; | 219 | __skb_queue_tail(&wmi->wmi_event_queue, skb); |
202 | spin_unlock(&wmi->wmi_lock); | 220 | spin_unlock(&wmi->wmi_lock); |
203 | tasklet_schedule(&wmi->drv_priv->wmi_tasklet); | 221 | tasklet_schedule(&wmi->wmi_event_tasklet); |
204 | return; | 222 | return; |
205 | } | 223 | } |
206 | 224 | ||
@@ -259,7 +277,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi, | |||
259 | hdr->command_id = cpu_to_be16(cmd); | 277 | hdr->command_id = cpu_to_be16(cmd); |
260 | hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); | 278 | hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id); |
261 | 279 | ||
262 | return htc_send(wmi->htc, skb, wmi->ctrl_epid, NULL); | 280 | return htc_send_epid(wmi->htc, skb, wmi->ctrl_epid); |
263 | } | 281 | } |
264 | 282 | ||
265 | int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | 283 | int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, |
@@ -276,7 +294,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | |||
276 | int time_left, ret = 0; | 294 | int time_left, ret = 0; |
277 | unsigned long flags; | 295 | unsigned long flags; |
278 | 296 | ||
279 | if (wmi->drv_priv->op_flags & OP_UNPLUGGED) | 297 | if (ah->ah_flags & AH_UNPLUGGED) |
280 | return 0; | 298 | return 0; |
281 | 299 | ||
282 | skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC); | 300 | skb = alloc_skb(headroom + cmd_len, GFP_ATOMIC); |
@@ -312,9 +330,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | |||
312 | 330 | ||
313 | time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout); | 331 | time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout); |
314 | if (!time_left) { | 332 | if (!time_left) { |
315 | ath_print(common, ATH_DBG_WMI, | 333 | ath_dbg(common, ATH_DBG_WMI, |
316 | "Timeout waiting for WMI command: %s\n", | 334 | "Timeout waiting for WMI command: %s\n", |
317 | wmi_cmd_to_name(cmd_id)); | 335 | wmi_cmd_to_name(cmd_id)); |
318 | mutex_unlock(&wmi->op_mutex); | 336 | mutex_unlock(&wmi->op_mutex); |
319 | return -ETIMEDOUT; | 337 | return -ETIMEDOUT; |
320 | } | 338 | } |
@@ -324,8 +342,8 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | |||
324 | return 0; | 342 | return 0; |
325 | 343 | ||
326 | out: | 344 | out: |
327 | ath_print(common, ATH_DBG_WMI, | 345 | ath_dbg(common, ATH_DBG_WMI, |
328 | "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); | 346 | "WMI failure for: %s\n", wmi_cmd_to_name(cmd_id)); |
329 | mutex_unlock(&wmi->op_mutex); | 347 | mutex_unlock(&wmi->op_mutex); |
330 | kfree_skb(skb); | 348 | kfree_skb(skb); |
331 | 349 | ||
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 765db5faa2d3..fde6da619f30 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2010 Atheros Communications Inc. | 2 | * Copyright (c) 2010-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -17,7 +17,6 @@ | |||
17 | #ifndef WMI_H | 17 | #ifndef WMI_H |
18 | #define WMI_H | 18 | #define WMI_H |
19 | 19 | ||
20 | |||
21 | struct wmi_event_txrate { | 20 | struct wmi_event_txrate { |
22 | __be32 txrate; | 21 | __be32 txrate; |
23 | struct { | 22 | struct { |
@@ -31,8 +30,52 @@ struct wmi_cmd_hdr { | |||
31 | __be16 seq_no; | 30 | __be16 seq_no; |
32 | } __packed; | 31 | } __packed; |
33 | 32 | ||
34 | struct wmi_swba { | 33 | struct wmi_fw_version { |
34 | __be16 major; | ||
35 | __be16 minor; | ||
36 | |||
37 | } __packed; | ||
38 | |||
39 | struct wmi_event_swba { | ||
40 | __be64 tsf; | ||
35 | u8 beacon_pending; | 41 | u8 beacon_pending; |
42 | }; | ||
43 | |||
44 | /* | ||
45 | * 64 - HTC header - WMI header - 1 / txstatus | ||
46 | * And some other hdr. space is also accounted for. | ||
47 | * 12 seems to be the magic number. | ||
48 | */ | ||
49 | #define HTC_MAX_TX_STATUS 12 | ||
50 | |||
51 | #define ATH9K_HTC_TXSTAT_ACK BIT(0) | ||
52 | #define ATH9K_HTC_TXSTAT_FILT BIT(1) | ||
53 | #define ATH9K_HTC_TXSTAT_RTC_CTS BIT(2) | ||
54 | #define ATH9K_HTC_TXSTAT_MCS BIT(3) | ||
55 | #define ATH9K_HTC_TXSTAT_CW40 BIT(4) | ||
56 | #define ATH9K_HTC_TXSTAT_SGI BIT(5) | ||
57 | |||
58 | /* | ||
59 | * Legacy rates are indicated as indices. | ||
60 | * HT rates are indicated as dot11 numbers. | ||
61 | * This allows us to resrict the rate field | ||
62 | * to 4 bits. | ||
63 | */ | ||
64 | #define ATH9K_HTC_TXSTAT_RATE 0x0f | ||
65 | #define ATH9K_HTC_TXSTAT_RATE_S 0 | ||
66 | |||
67 | #define ATH9K_HTC_TXSTAT_EPID 0xf0 | ||
68 | #define ATH9K_HTC_TXSTAT_EPID_S 4 | ||
69 | |||
70 | struct __wmi_event_txstatus { | ||
71 | u8 cookie; | ||
72 | u8 ts_rate; /* Also holds EP ID */ | ||
73 | u8 ts_flags; | ||
74 | }; | ||
75 | |||
76 | struct wmi_event_txstatus { | ||
77 | u8 cnt; | ||
78 | struct __wmi_event_txstatus txstatus[HTC_MAX_TX_STATUS]; | ||
36 | } __packed; | 79 | } __packed; |
37 | 80 | ||
38 | enum wmi_cmd_id { | 81 | enum wmi_cmd_id { |
@@ -40,13 +83,12 @@ enum wmi_cmd_id { | |||
40 | WMI_ACCESS_MEMORY_CMDID, | 83 | WMI_ACCESS_MEMORY_CMDID, |
41 | 84 | ||
42 | /* Commands to Target */ | 85 | /* Commands to Target */ |
86 | WMI_GET_FW_VERSION, | ||
43 | WMI_DISABLE_INTR_CMDID, | 87 | WMI_DISABLE_INTR_CMDID, |
44 | WMI_ENABLE_INTR_CMDID, | 88 | WMI_ENABLE_INTR_CMDID, |
45 | WMI_RX_LINK_CMDID, | ||
46 | WMI_ATH_INIT_CMDID, | 89 | WMI_ATH_INIT_CMDID, |
47 | WMI_ABORT_TXQ_CMDID, | 90 | WMI_ABORT_TXQ_CMDID, |
48 | WMI_STOP_TX_DMA_CMDID, | 91 | WMI_STOP_TX_DMA_CMDID, |
49 | WMI_STOP_DMA_RECV_CMDID, | ||
50 | WMI_ABORT_TX_DMA_CMDID, | 92 | WMI_ABORT_TX_DMA_CMDID, |
51 | WMI_DRAIN_TXQ_CMDID, | 93 | WMI_DRAIN_TXQ_CMDID, |
52 | WMI_DRAIN_TXQ_ALL_CMDID, | 94 | WMI_DRAIN_TXQ_ALL_CMDID, |
@@ -54,23 +96,22 @@ enum wmi_cmd_id { | |||
54 | WMI_STOP_RECV_CMDID, | 96 | WMI_STOP_RECV_CMDID, |
55 | WMI_FLUSH_RECV_CMDID, | 97 | WMI_FLUSH_RECV_CMDID, |
56 | WMI_SET_MODE_CMDID, | 98 | WMI_SET_MODE_CMDID, |
57 | WMI_RESET_CMDID, | ||
58 | WMI_NODE_CREATE_CMDID, | 99 | WMI_NODE_CREATE_CMDID, |
59 | WMI_NODE_REMOVE_CMDID, | 100 | WMI_NODE_REMOVE_CMDID, |
60 | WMI_VAP_REMOVE_CMDID, | 101 | WMI_VAP_REMOVE_CMDID, |
61 | WMI_VAP_CREATE_CMDID, | 102 | WMI_VAP_CREATE_CMDID, |
62 | WMI_BEACON_UPDATE_CMDID, | ||
63 | WMI_REG_READ_CMDID, | 103 | WMI_REG_READ_CMDID, |
64 | WMI_REG_WRITE_CMDID, | 104 | WMI_REG_WRITE_CMDID, |
65 | WMI_RC_STATE_CHANGE_CMDID, | 105 | WMI_RC_STATE_CHANGE_CMDID, |
66 | WMI_RC_RATE_UPDATE_CMDID, | 106 | WMI_RC_RATE_UPDATE_CMDID, |
67 | WMI_DEBUG_INFO_CMDID, | ||
68 | WMI_HOST_ATTACH, | ||
69 | WMI_TARGET_IC_UPDATE_CMDID, | 107 | WMI_TARGET_IC_UPDATE_CMDID, |
70 | WMI_TGT_STATS_CMDID, | ||
71 | WMI_TX_AGGR_ENABLE_CMDID, | 108 | WMI_TX_AGGR_ENABLE_CMDID, |
72 | WMI_TGT_DETACH_CMDID, | 109 | WMI_TGT_DETACH_CMDID, |
73 | WMI_TGT_TXQ_ENABLE_CMDID, | 110 | WMI_NODE_UPDATE_CMDID, |
111 | WMI_INT_STATS_CMDID, | ||
112 | WMI_TX_STATS_CMDID, | ||
113 | WMI_RX_STATS_CMDID, | ||
114 | WMI_BITRATE_MASK_CMDID, | ||
74 | }; | 115 | }; |
75 | 116 | ||
76 | enum wmi_event_id { | 117 | enum wmi_event_id { |
@@ -79,9 +120,8 @@ enum wmi_event_id { | |||
79 | WMI_FATAL_EVENTID, | 120 | WMI_FATAL_EVENTID, |
80 | WMI_TXTO_EVENTID, | 121 | WMI_TXTO_EVENTID, |
81 | WMI_BMISS_EVENTID, | 122 | WMI_BMISS_EVENTID, |
82 | WMI_WLAN_TXCOMP_EVENTID, | ||
83 | WMI_DELBA_EVENTID, | 123 | WMI_DELBA_EVENTID, |
84 | WMI_TXRATE_EVENTID, | 124 | WMI_TXSTATUS_EVENTID, |
85 | }; | 125 | }; |
86 | 126 | ||
87 | #define MAX_CMD_NUMBER 62 | 127 | #define MAX_CMD_NUMBER 62 |
@@ -91,6 +131,12 @@ struct register_write { | |||
91 | __be32 val; | 131 | __be32 val; |
92 | }; | 132 | }; |
93 | 133 | ||
134 | struct ath9k_htc_tx_event { | ||
135 | int count; | ||
136 | struct __wmi_event_txstatus txs; | ||
137 | struct list_head list; | ||
138 | }; | ||
139 | |||
94 | struct wmi { | 140 | struct wmi { |
95 | struct ath9k_htc_priv *drv_priv; | 141 | struct ath9k_htc_priv *drv_priv; |
96 | struct htc_target *htc; | 142 | struct htc_target *htc; |
@@ -98,12 +144,16 @@ struct wmi { | |||
98 | struct mutex op_mutex; | 144 | struct mutex op_mutex; |
99 | struct completion cmd_wait; | 145 | struct completion cmd_wait; |
100 | enum wmi_cmd_id last_cmd_id; | 146 | enum wmi_cmd_id last_cmd_id; |
147 | struct sk_buff_head wmi_event_queue; | ||
148 | struct tasklet_struct wmi_event_tasklet; | ||
101 | u16 tx_seq_id; | 149 | u16 tx_seq_id; |
102 | u8 *cmd_rsp_buf; | 150 | u8 *cmd_rsp_buf; |
103 | u32 cmd_rsp_len; | 151 | u32 cmd_rsp_len; |
104 | bool stopped; | 152 | bool stopped; |
105 | 153 | ||
106 | struct sk_buff *wmi_skb; | 154 | struct list_head pending_tx_events; |
155 | spinlock_t event_lock; | ||
156 | |||
107 | spinlock_t wmi_lock; | 157 | spinlock_t wmi_lock; |
108 | 158 | ||
109 | atomic_t mwrite_cnt; | 159 | atomic_t mwrite_cnt; |
@@ -120,7 +170,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id, | |||
120 | u8 *cmd_buf, u32 cmd_len, | 170 | u8 *cmd_buf, u32 cmd_len, |
121 | u8 *rsp_buf, u32 rsp_len, | 171 | u8 *rsp_buf, u32 rsp_len, |
122 | u32 timeout); | 172 | u32 timeout); |
123 | void ath9k_wmi_tasklet(unsigned long data); | 173 | void ath9k_wmi_event_tasklet(unsigned long data); |
174 | void ath9k_fatal_work(struct work_struct *work); | ||
175 | void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv); | ||
124 | 176 | ||
125 | #define WMI_CMD(_wmi_cmd) \ | 177 | #define WMI_CMD(_wmi_cmd) \ |
126 | do { \ | 178 | do { \ |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4dda14e36227..33443bcaa8d9 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2011 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 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 | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #define BITS_PER_BYTE 8 | 20 | #define BITS_PER_BYTE 8 |
21 | #define OFDM_PLCP_BITS 22 | 21 | #define OFDM_PLCP_BITS 22 |
22 | #define HT_RC_2_MCS(_rc) ((_rc) & 0x1f) | ||
23 | #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) | 22 | #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) |
24 | #define L_STF 8 | 23 | #define L_STF 8 |
25 | #define L_LTF 8 | 24 | #define L_LTF 8 |
@@ -32,7 +31,6 @@ | |||
32 | #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) | 31 | #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) |
33 | #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) | 32 | #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) |
34 | 33 | ||
35 | #define OFDM_SIFS_TIME 16 | ||
36 | 34 | ||
37 | static u16 bits_per_symbol[][2] = { | 35 | static u16 bits_per_symbol[][2] = { |
38 | /* 20MHz 40MHz */ | 36 | /* 20MHz 40MHz */ |
@@ -48,19 +46,20 @@ static u16 bits_per_symbol[][2] = { | |||
48 | 46 | ||
49 | #define IS_HT_RATE(_rate) ((_rate) & 0x80) | 47 | #define IS_HT_RATE(_rate) ((_rate) & 0x80) |
50 | 48 | ||
51 | static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, | 49 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, |
52 | struct ath_atx_tid *tid, | 50 | struct ath_atx_tid *tid, |
53 | struct list_head *bf_head); | 51 | struct list_head *bf_head); |
54 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 52 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
55 | struct ath_txq *txq, struct list_head *bf_q, | 53 | struct ath_txq *txq, struct list_head *bf_q, |
56 | struct ath_tx_status *ts, int txok, int sendbar); | 54 | struct ath_tx_status *ts, int txok, int sendbar); |
57 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | 55 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, |
58 | struct list_head *head); | 56 | struct list_head *head); |
59 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); | 57 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len); |
60 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | 58 | static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, |
61 | struct ath_tx_status *ts, int txok); | 59 | struct ath_tx_status *ts, int nframes, int nbad, |
62 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | 60 | int txok, bool update_rc); |
63 | int nbad, int txok, bool update_rc); | 61 | static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, |
62 | int seqno); | ||
64 | 63 | ||
65 | enum { | 64 | enum { |
66 | MCS_HT20, | 65 | MCS_HT20, |
@@ -122,7 +121,7 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) | |||
122 | 121 | ||
123 | static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 122 | static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
124 | { | 123 | { |
125 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; | 124 | struct ath_txq *txq = tid->ac->txq; |
126 | 125 | ||
127 | WARN_ON(!tid->paused); | 126 | WARN_ON(!tid->paused); |
128 | 127 | ||
@@ -138,23 +137,40 @@ unlock: | |||
138 | spin_unlock_bh(&txq->axq_lock); | 137 | spin_unlock_bh(&txq->axq_lock); |
139 | } | 138 | } |
140 | 139 | ||
140 | static struct ath_frame_info *get_frame_info(struct sk_buff *skb) | ||
141 | { | ||
142 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
143 | BUILD_BUG_ON(sizeof(struct ath_frame_info) > | ||
144 | sizeof(tx_info->rate_driver_data)); | ||
145 | return (struct ath_frame_info *) &tx_info->rate_driver_data[0]; | ||
146 | } | ||
147 | |||
141 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) | 148 | static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) |
142 | { | 149 | { |
143 | struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; | 150 | struct ath_txq *txq = tid->ac->txq; |
144 | struct ath_buf *bf; | 151 | struct ath_buf *bf; |
145 | struct list_head bf_head; | 152 | struct list_head bf_head; |
146 | INIT_LIST_HEAD(&bf_head); | 153 | struct ath_tx_status ts; |
154 | struct ath_frame_info *fi; | ||
147 | 155 | ||
148 | WARN_ON(!tid->paused); | 156 | INIT_LIST_HEAD(&bf_head); |
149 | 157 | ||
158 | memset(&ts, 0, sizeof(ts)); | ||
150 | spin_lock_bh(&txq->axq_lock); | 159 | spin_lock_bh(&txq->axq_lock); |
151 | tid->paused = false; | ||
152 | 160 | ||
153 | while (!list_empty(&tid->buf_q)) { | 161 | while (!list_empty(&tid->buf_q)) { |
154 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 162 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
155 | BUG_ON(bf_isretried(bf)); | ||
156 | list_move_tail(&bf->list, &bf_head); | 163 | list_move_tail(&bf->list, &bf_head); |
157 | ath_tx_send_ht_normal(sc, txq, tid, &bf_head); | 164 | |
165 | spin_unlock_bh(&txq->axq_lock); | ||
166 | fi = get_frame_info(bf->bf_mpdu); | ||
167 | if (fi->retries) { | ||
168 | ath_tx_update_baw(sc, tid, fi->seqno); | ||
169 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1); | ||
170 | } else { | ||
171 | ath_tx_send_normal(sc, txq, NULL, &bf_head); | ||
172 | } | ||
173 | spin_lock_bh(&txq->axq_lock); | ||
158 | } | 174 | } |
159 | 175 | ||
160 | spin_unlock_bh(&txq->axq_lock); | 176 | spin_unlock_bh(&txq->axq_lock); |
@@ -168,27 +184,22 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
168 | index = ATH_BA_INDEX(tid->seq_start, seqno); | 184 | index = ATH_BA_INDEX(tid->seq_start, seqno); |
169 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 185 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
170 | 186 | ||
171 | tid->tx_buf[cindex] = NULL; | 187 | __clear_bit(cindex, tid->tx_buf); |
172 | 188 | ||
173 | while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) { | 189 | while (tid->baw_head != tid->baw_tail && !test_bit(tid->baw_head, tid->tx_buf)) { |
174 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | 190 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); |
175 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); | 191 | INCR(tid->baw_head, ATH_TID_MAX_BUFS); |
176 | } | 192 | } |
177 | } | 193 | } |
178 | 194 | ||
179 | static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, | 195 | static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, |
180 | struct ath_buf *bf) | 196 | u16 seqno) |
181 | { | 197 | { |
182 | int index, cindex; | 198 | int index, cindex; |
183 | 199 | ||
184 | if (bf_isretried(bf)) | 200 | index = ATH_BA_INDEX(tid->seq_start, seqno); |
185 | return; | ||
186 | |||
187 | index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); | ||
188 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); | 201 | cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); |
189 | 202 | __set_bit(cindex, tid->tx_buf); | |
190 | BUG_ON(tid->tx_buf[cindex] != NULL); | ||
191 | tid->tx_buf[cindex] = bf; | ||
192 | 203 | ||
193 | if (index >= ((tid->baw_tail - tid->baw_head) & | 204 | if (index >= ((tid->baw_tail - tid->baw_head) & |
194 | (ATH_TID_MAX_BUFS - 1))) { | 205 | (ATH_TID_MAX_BUFS - 1))) { |
@@ -210,6 +221,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
210 | struct ath_buf *bf; | 221 | struct ath_buf *bf; |
211 | struct list_head bf_head; | 222 | struct list_head bf_head; |
212 | struct ath_tx_status ts; | 223 | struct ath_tx_status ts; |
224 | struct ath_frame_info *fi; | ||
213 | 225 | ||
214 | memset(&ts, 0, sizeof(ts)); | 226 | memset(&ts, 0, sizeof(ts)); |
215 | INIT_LIST_HEAD(&bf_head); | 227 | INIT_LIST_HEAD(&bf_head); |
@@ -221,8 +233,9 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
221 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 233 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
222 | list_move_tail(&bf->list, &bf_head); | 234 | list_move_tail(&bf->list, &bf_head); |
223 | 235 | ||
224 | if (bf_isretried(bf)) | 236 | fi = get_frame_info(bf->bf_mpdu); |
225 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | 237 | if (fi->retries) |
238 | ath_tx_update_baw(sc, tid, fi->seqno); | ||
226 | 239 | ||
227 | spin_unlock(&txq->axq_lock); | 240 | spin_unlock(&txq->axq_lock); |
228 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | 241 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); |
@@ -234,16 +247,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, | |||
234 | } | 247 | } |
235 | 248 | ||
236 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, | 249 | static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, |
237 | struct ath_buf *bf) | 250 | struct sk_buff *skb) |
238 | { | 251 | { |
239 | struct sk_buff *skb; | 252 | struct ath_frame_info *fi = get_frame_info(skb); |
240 | struct ieee80211_hdr *hdr; | 253 | struct ieee80211_hdr *hdr; |
241 | 254 | ||
242 | bf->bf_state.bf_type |= BUF_RETRY; | ||
243 | bf->bf_retries++; | ||
244 | TX_STAT_INC(txq->axq_qnum, a_retries); | 255 | TX_STAT_INC(txq->axq_qnum, a_retries); |
256 | if (fi->retries++ > 0) | ||
257 | return; | ||
245 | 258 | ||
246 | skb = bf->bf_mpdu; | ||
247 | hdr = (struct ieee80211_hdr *)skb->data; | 259 | hdr = (struct ieee80211_hdr *)skb->data; |
248 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); | 260 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); |
249 | } | 261 | } |
@@ -284,24 +296,54 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) | |||
284 | 296 | ||
285 | ATH_TXBUF_RESET(tbf); | 297 | ATH_TXBUF_RESET(tbf); |
286 | 298 | ||
287 | tbf->aphy = bf->aphy; | ||
288 | tbf->bf_mpdu = bf->bf_mpdu; | 299 | tbf->bf_mpdu = bf->bf_mpdu; |
289 | tbf->bf_buf_addr = bf->bf_buf_addr; | 300 | tbf->bf_buf_addr = bf->bf_buf_addr; |
290 | memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len); | 301 | memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len); |
291 | tbf->bf_state = bf->bf_state; | 302 | tbf->bf_state = bf->bf_state; |
292 | tbf->bf_dmacontext = bf->bf_dmacontext; | ||
293 | 303 | ||
294 | return tbf; | 304 | return tbf; |
295 | } | 305 | } |
296 | 306 | ||
307 | static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf, | ||
308 | struct ath_tx_status *ts, int txok, | ||
309 | int *nframes, int *nbad) | ||
310 | { | ||
311 | struct ath_frame_info *fi; | ||
312 | u16 seq_st = 0; | ||
313 | u32 ba[WME_BA_BMP_SIZE >> 5]; | ||
314 | int ba_index; | ||
315 | int isaggr = 0; | ||
316 | |||
317 | *nbad = 0; | ||
318 | *nframes = 0; | ||
319 | |||
320 | isaggr = bf_isaggr(bf); | ||
321 | if (isaggr) { | ||
322 | seq_st = ts->ts_seqnum; | ||
323 | memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); | ||
324 | } | ||
325 | |||
326 | while (bf) { | ||
327 | fi = get_frame_info(bf->bf_mpdu); | ||
328 | ba_index = ATH_BA_INDEX(seq_st, fi->seqno); | ||
329 | |||
330 | (*nframes)++; | ||
331 | if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) | ||
332 | (*nbad)++; | ||
333 | |||
334 | bf = bf->bf_next; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | |||
297 | static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | 339 | static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, |
298 | struct ath_buf *bf, struct list_head *bf_q, | 340 | struct ath_buf *bf, struct list_head *bf_q, |
299 | struct ath_tx_status *ts, int txok) | 341 | struct ath_tx_status *ts, int txok, bool retry) |
300 | { | 342 | { |
301 | struct ath_node *an = NULL; | 343 | struct ath_node *an = NULL; |
302 | struct sk_buff *skb; | 344 | struct sk_buff *skb; |
303 | struct ieee80211_sta *sta; | 345 | struct ieee80211_sta *sta; |
304 | struct ieee80211_hw *hw; | 346 | struct ieee80211_hw *hw = sc->hw; |
305 | struct ieee80211_hdr *hdr; | 347 | struct ieee80211_hdr *hdr; |
306 | struct ieee80211_tx_info *tx_info; | 348 | struct ieee80211_tx_info *tx_info; |
307 | struct ath_atx_tid *tid = NULL; | 349 | struct ath_atx_tid *tid = NULL; |
@@ -312,19 +354,21 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
312 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; | 354 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; |
313 | bool rc_update = true; | 355 | bool rc_update = true; |
314 | struct ieee80211_tx_rate rates[4]; | 356 | struct ieee80211_tx_rate rates[4]; |
357 | struct ath_frame_info *fi; | ||
358 | int nframes; | ||
359 | u8 tidno; | ||
360 | bool clear_filter; | ||
315 | 361 | ||
316 | skb = bf->bf_mpdu; | 362 | skb = bf->bf_mpdu; |
317 | hdr = (struct ieee80211_hdr *)skb->data; | 363 | hdr = (struct ieee80211_hdr *)skb->data; |
318 | 364 | ||
319 | tx_info = IEEE80211_SKB_CB(skb); | 365 | tx_info = IEEE80211_SKB_CB(skb); |
320 | hw = bf->aphy->hw; | ||
321 | 366 | ||
322 | memcpy(rates, tx_info->control.rates, sizeof(rates)); | 367 | memcpy(rates, tx_info->control.rates, sizeof(rates)); |
323 | 368 | ||
324 | rcu_read_lock(); | 369 | rcu_read_lock(); |
325 | 370 | ||
326 | /* XXX: use ieee80211_find_sta! */ | 371 | sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); |
327 | sta = ieee80211_find_sta_by_hw(hw, hdr->addr1); | ||
328 | if (!sta) { | 372 | if (!sta) { |
329 | rcu_read_unlock(); | 373 | rcu_read_unlock(); |
330 | 374 | ||
@@ -337,7 +381,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
337 | !bf->bf_stale || bf_next != NULL) | 381 | !bf->bf_stale || bf_next != NULL) |
338 | list_move_tail(&bf->list, &bf_head); | 382 | list_move_tail(&bf->list, &bf_head); |
339 | 383 | ||
340 | ath_tx_rc_status(bf, ts, 0, 0, false); | 384 | ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false); |
341 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, | 385 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, |
342 | 0, 0); | 386 | 0, 0); |
343 | 387 | ||
@@ -347,14 +391,15 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
347 | } | 391 | } |
348 | 392 | ||
349 | an = (struct ath_node *)sta->drv_priv; | 393 | an = (struct ath_node *)sta->drv_priv; |
350 | tid = ATH_AN_2_TID(an, bf->bf_tidno); | 394 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; |
395 | tid = ATH_AN_2_TID(an, tidno); | ||
351 | 396 | ||
352 | /* | 397 | /* |
353 | * The hardware occasionally sends a tx status for the wrong TID. | 398 | * The hardware occasionally sends a tx status for the wrong TID. |
354 | * In this case, the BA status cannot be considered valid and all | 399 | * In this case, the BA status cannot be considered valid and all |
355 | * subframes need to be retransmitted | 400 | * subframes need to be retransmitted |
356 | */ | 401 | */ |
357 | if (bf->bf_tidno != ts->tid) | 402 | if (tidno != ts->tid) |
358 | txok = false; | 403 | txok = false; |
359 | 404 | ||
360 | isaggr = bf_isaggr(bf); | 405 | isaggr = bf_isaggr(bf); |
@@ -380,15 +425,16 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
380 | INIT_LIST_HEAD(&bf_pending); | 425 | INIT_LIST_HEAD(&bf_pending); |
381 | INIT_LIST_HEAD(&bf_head); | 426 | INIT_LIST_HEAD(&bf_head); |
382 | 427 | ||
383 | nbad = ath_tx_num_badfrms(sc, bf, ts, txok); | 428 | ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad); |
384 | while (bf) { | 429 | while (bf) { |
385 | txfail = txpending = 0; | 430 | txfail = txpending = sendbar = 0; |
386 | bf_next = bf->bf_next; | 431 | bf_next = bf->bf_next; |
387 | 432 | ||
388 | skb = bf->bf_mpdu; | 433 | skb = bf->bf_mpdu; |
389 | tx_info = IEEE80211_SKB_CB(skb); | 434 | tx_info = IEEE80211_SKB_CB(skb); |
435 | fi = get_frame_info(skb); | ||
390 | 436 | ||
391 | if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { | 437 | if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, fi->seqno))) { |
392 | /* transmit completion, subframe is | 438 | /* transmit completion, subframe is |
393 | * acked by block ack */ | 439 | * acked by block ack */ |
394 | acked_cnt++; | 440 | acked_cnt++; |
@@ -396,23 +442,24 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
396 | /* transmit completion */ | 442 | /* transmit completion */ |
397 | acked_cnt++; | 443 | acked_cnt++; |
398 | } else { | 444 | } else { |
399 | if (!(tid->state & AGGR_CLEANUP) && | 445 | if ((tid->state & AGGR_CLEANUP) || !retry) { |
400 | !bf_last->bf_tx_aborted) { | ||
401 | if (bf->bf_retries < ATH_MAX_SW_RETRIES) { | ||
402 | ath_tx_set_retry(sc, txq, bf); | ||
403 | txpending = 1; | ||
404 | } else { | ||
405 | bf->bf_state.bf_type |= BUF_XRETRY; | ||
406 | txfail = 1; | ||
407 | sendbar = 1; | ||
408 | txfail_cnt++; | ||
409 | } | ||
410 | } else { | ||
411 | /* | 446 | /* |
412 | * cleanup in progress, just fail | 447 | * cleanup in progress, just fail |
413 | * the un-acked sub-frames | 448 | * the un-acked sub-frames |
414 | */ | 449 | */ |
415 | txfail = 1; | 450 | txfail = 1; |
451 | } else if (fi->retries < ATH_MAX_SW_RETRIES) { | ||
452 | if (!(ts->ts_status & ATH9K_TXERR_FILT) || | ||
453 | !an->sleeping) | ||
454 | ath_tx_set_retry(sc, txq, bf->bf_mpdu); | ||
455 | |||
456 | clear_filter = true; | ||
457 | txpending = 1; | ||
458 | } else { | ||
459 | bf->bf_state.bf_type |= BUF_XRETRY; | ||
460 | txfail = 1; | ||
461 | sendbar = 1; | ||
462 | txfail_cnt++; | ||
416 | } | 463 | } |
417 | } | 464 | } |
418 | 465 | ||
@@ -431,27 +478,28 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
431 | list_move_tail(&bf->list, &bf_head); | 478 | list_move_tail(&bf->list, &bf_head); |
432 | } | 479 | } |
433 | 480 | ||
434 | if (!txpending) { | 481 | if (!txpending || (tid->state & AGGR_CLEANUP)) { |
435 | /* | 482 | /* |
436 | * complete the acked-ones/xretried ones; update | 483 | * complete the acked-ones/xretried ones; update |
437 | * block-ack window | 484 | * block-ack window |
438 | */ | 485 | */ |
439 | spin_lock_bh(&txq->axq_lock); | 486 | spin_lock_bh(&txq->axq_lock); |
440 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | 487 | ath_tx_update_baw(sc, tid, fi->seqno); |
441 | spin_unlock_bh(&txq->axq_lock); | 488 | spin_unlock_bh(&txq->axq_lock); |
442 | 489 | ||
443 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { | 490 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { |
444 | memcpy(tx_info->control.rates, rates, sizeof(rates)); | 491 | memcpy(tx_info->control.rates, rates, sizeof(rates)); |
445 | ath_tx_rc_status(bf, ts, nbad, txok, true); | 492 | ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true); |
446 | rc_update = false; | 493 | rc_update = false; |
447 | } else { | 494 | } else { |
448 | ath_tx_rc_status(bf, ts, nbad, txok, false); | 495 | ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false); |
449 | } | 496 | } |
450 | 497 | ||
451 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, | 498 | ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, |
452 | !txfail, sendbar); | 499 | !txfail, sendbar); |
453 | } else { | 500 | } else { |
454 | /* retry the un-acked ones */ | 501 | /* retry the un-acked ones */ |
502 | ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false); | ||
455 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { | 503 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { |
456 | if (bf->bf_next == NULL && bf_last->bf_stale) { | 504 | if (bf->bf_next == NULL && bf_last->bf_stale) { |
457 | struct ath_buf *tbf; | 505 | struct ath_buf *tbf; |
@@ -464,14 +512,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
464 | */ | 512 | */ |
465 | if (!tbf) { | 513 | if (!tbf) { |
466 | spin_lock_bh(&txq->axq_lock); | 514 | spin_lock_bh(&txq->axq_lock); |
467 | ath_tx_update_baw(sc, tid, | 515 | ath_tx_update_baw(sc, tid, fi->seqno); |
468 | bf->bf_seqno); | ||
469 | spin_unlock_bh(&txq->axq_lock); | 516 | spin_unlock_bh(&txq->axq_lock); |
470 | 517 | ||
471 | bf->bf_state.bf_type |= | 518 | bf->bf_state.bf_type |= |
472 | BUF_XRETRY; | 519 | BUF_XRETRY; |
473 | ath_tx_rc_status(bf, ts, nbad, | 520 | ath_tx_rc_status(sc, bf, ts, nframes, |
474 | 0, false); | 521 | nbad, 0, false); |
475 | ath_tx_complete_buf(sc, bf, txq, | 522 | ath_tx_complete_buf(sc, bf, txq, |
476 | &bf_head, | 523 | &bf_head, |
477 | ts, 0, 0); | 524 | ts, 0, 0); |
@@ -503,28 +550,33 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
503 | 550 | ||
504 | /* prepend un-acked frames to the beginning of the pending frame queue */ | 551 | /* prepend un-acked frames to the beginning of the pending frame queue */ |
505 | if (!list_empty(&bf_pending)) { | 552 | if (!list_empty(&bf_pending)) { |
553 | if (an->sleeping) | ||
554 | ieee80211_sta_set_tim(sta); | ||
555 | |||
506 | spin_lock_bh(&txq->axq_lock); | 556 | spin_lock_bh(&txq->axq_lock); |
557 | if (clear_filter) | ||
558 | tid->ac->clear_ps_filter = true; | ||
507 | list_splice(&bf_pending, &tid->buf_q); | 559 | list_splice(&bf_pending, &tid->buf_q); |
508 | ath_tx_queue_tid(txq, tid); | 560 | ath_tx_queue_tid(txq, tid); |
509 | spin_unlock_bh(&txq->axq_lock); | 561 | spin_unlock_bh(&txq->axq_lock); |
510 | } | 562 | } |
511 | 563 | ||
512 | if (tid->state & AGGR_CLEANUP) { | 564 | if (tid->state & AGGR_CLEANUP) { |
565 | ath_tx_flush_tid(sc, tid); | ||
566 | |||
513 | if (tid->baw_head == tid->baw_tail) { | 567 | if (tid->baw_head == tid->baw_tail) { |
514 | tid->state &= ~AGGR_ADDBA_COMPLETE; | 568 | tid->state &= ~AGGR_ADDBA_COMPLETE; |
515 | tid->state &= ~AGGR_CLEANUP; | 569 | tid->state &= ~AGGR_CLEANUP; |
516 | |||
517 | /* send buffered frames as singles */ | ||
518 | ath_tx_flush_tid(sc, tid); | ||
519 | } | 570 | } |
520 | rcu_read_unlock(); | ||
521 | return; | ||
522 | } | 571 | } |
523 | 572 | ||
524 | rcu_read_unlock(); | 573 | rcu_read_unlock(); |
525 | 574 | ||
526 | if (needreset) | 575 | if (needreset) { |
576 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
527 | ath_reset(sc, false); | 577 | ath_reset(sc, false); |
578 | spin_lock_bh(&sc->sc_pcu_lock); | ||
579 | } | ||
528 | } | 580 | } |
529 | 581 | ||
530 | static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | 582 | static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, |
@@ -585,8 +637,8 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
585 | (u32)ATH_AMPDU_LIMIT_MAX); | 637 | (u32)ATH_AMPDU_LIMIT_MAX); |
586 | 638 | ||
587 | /* | 639 | /* |
588 | * h/w can accept aggregates upto 16 bit lengths (65535). | 640 | * h/w can accept aggregates up to 16 bit lengths (65535). |
589 | * The IE, however can hold upto 65536, which shows up here | 641 | * The IE, however can hold up to 65536, which shows up here |
590 | * as zero. Ignore 65536 since we are constrained by hw. | 642 | * as zero. Ignore 65536 since we are constrained by hw. |
591 | */ | 643 | */ |
592 | if (tid->an->maxampdu) | 644 | if (tid->an->maxampdu) |
@@ -608,6 +660,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
608 | u16 minlen; | 660 | u16 minlen; |
609 | u8 flags, rix; | 661 | u8 flags, rix; |
610 | int width, streams, half_gi, ndelim, mindelim; | 662 | int width, streams, half_gi, ndelim, mindelim; |
663 | struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); | ||
611 | 664 | ||
612 | /* Select standard number of delimiters based on frame length alone */ | 665 | /* Select standard number of delimiters based on frame length alone */ |
613 | ndelim = ATH_AGGR_GET_NDELIM(frmlen); | 666 | ndelim = ATH_AGGR_GET_NDELIM(frmlen); |
@@ -618,7 +671,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
618 | * TODO - this could be improved to be dependent on the rate. | 671 | * TODO - this could be improved to be dependent on the rate. |
619 | * The hardware can keep up at lower rates, but not higher rates | 672 | * The hardware can keep up at lower rates, but not higher rates |
620 | */ | 673 | */ |
621 | if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) | 674 | if ((fi->keyix != ATH9K_TXKEYIX_INVALID) && |
675 | !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) | ||
622 | ndelim += ATH_AGGR_ENCRYPTDELIM; | 676 | ndelim += ATH_AGGR_ENCRYPTDELIM; |
623 | 677 | ||
624 | /* | 678 | /* |
@@ -662,7 +716,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
662 | static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | 716 | static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, |
663 | struct ath_txq *txq, | 717 | struct ath_txq *txq, |
664 | struct ath_atx_tid *tid, | 718 | struct ath_atx_tid *tid, |
665 | struct list_head *bf_q) | 719 | struct list_head *bf_q, |
720 | int *aggr_len) | ||
666 | { | 721 | { |
667 | #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) | 722 | #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) |
668 | struct ath_buf *bf, *bf_first, *bf_prev = NULL; | 723 | struct ath_buf *bf, *bf_first, *bf_prev = NULL; |
@@ -670,14 +725,17 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
670 | u16 aggr_limit = 0, al = 0, bpad = 0, | 725 | u16 aggr_limit = 0, al = 0, bpad = 0, |
671 | al_delta, h_baw = tid->baw_size / 2; | 726 | al_delta, h_baw = tid->baw_size / 2; |
672 | enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; | 727 | enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; |
728 | struct ieee80211_tx_info *tx_info; | ||
729 | struct ath_frame_info *fi; | ||
673 | 730 | ||
674 | bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); | 731 | bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); |
675 | 732 | ||
676 | do { | 733 | do { |
677 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); | 734 | bf = list_first_entry(&tid->buf_q, struct ath_buf, list); |
735 | fi = get_frame_info(bf->bf_mpdu); | ||
678 | 736 | ||
679 | /* do not step over block-ack window */ | 737 | /* do not step over block-ack window */ |
680 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { | 738 | if (!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno)) { |
681 | status = ATH_AGGR_BAW_CLOSED; | 739 | status = ATH_AGGR_BAW_CLOSED; |
682 | break; | 740 | break; |
683 | } | 741 | } |
@@ -688,7 +746,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
688 | } | 746 | } |
689 | 747 | ||
690 | /* do not exceed aggregation limit */ | 748 | /* do not exceed aggregation limit */ |
691 | al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; | 749 | al_delta = ATH_AGGR_DELIM_SZ + fi->framelen; |
692 | 750 | ||
693 | if (nframes && | 751 | if (nframes && |
694 | (aggr_limit < (al + bpad + al_delta + prev_al))) { | 752 | (aggr_limit < (al + bpad + al_delta + prev_al))) { |
@@ -696,6 +754,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
696 | break; | 754 | break; |
697 | } | 755 | } |
698 | 756 | ||
757 | tx_info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
758 | if (nframes && ((tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) || | ||
759 | !(tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS))) | ||
760 | break; | ||
761 | |||
699 | /* do not exceed subframe limit */ | 762 | /* do not exceed subframe limit */ |
700 | if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { | 763 | if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { |
701 | status = ATH_AGGR_LIMITED; | 764 | status = ATH_AGGR_LIMITED; |
@@ -710,14 +773,15 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
710 | * Get the delimiters needed to meet the MPDU | 773 | * Get the delimiters needed to meet the MPDU |
711 | * density for this node. | 774 | * density for this node. |
712 | */ | 775 | */ |
713 | ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); | 776 | ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen); |
714 | bpad = PADBYTES(al_delta) + (ndelim << 2); | 777 | bpad = PADBYTES(al_delta) + (ndelim << 2); |
715 | 778 | ||
716 | bf->bf_next = NULL; | 779 | bf->bf_next = NULL; |
717 | ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); | 780 | ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); |
718 | 781 | ||
719 | /* link buffers of this frame to the aggregate */ | 782 | /* link buffers of this frame to the aggregate */ |
720 | ath_tx_addto_baw(sc, tid, bf); | 783 | if (!fi->retries) |
784 | ath_tx_addto_baw(sc, tid, fi->seqno); | ||
721 | ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); | 785 | ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); |
722 | list_move_tail(&bf->list, bf_q); | 786 | list_move_tail(&bf->list, bf_q); |
723 | if (bf_prev) { | 787 | if (bf_prev) { |
@@ -729,8 +793,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, | |||
729 | 793 | ||
730 | } while (!list_empty(&tid->buf_q)); | 794 | } while (!list_empty(&tid->buf_q)); |
731 | 795 | ||
732 | bf_first->bf_al = al; | 796 | *aggr_len = al; |
733 | bf_first->bf_nframes = nframes; | ||
734 | 797 | ||
735 | return status; | 798 | return status; |
736 | #undef PADBYTES | 799 | #undef PADBYTES |
@@ -741,7 +804,9 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
741 | { | 804 | { |
742 | struct ath_buf *bf; | 805 | struct ath_buf *bf; |
743 | enum ATH_AGGR_STATUS status; | 806 | enum ATH_AGGR_STATUS status; |
807 | struct ath_frame_info *fi; | ||
744 | struct list_head bf_q; | 808 | struct list_head bf_q; |
809 | int aggr_len; | ||
745 | 810 | ||
746 | do { | 811 | do { |
747 | if (list_empty(&tid->buf_q)) | 812 | if (list_empty(&tid->buf_q)) |
@@ -749,7 +814,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
749 | 814 | ||
750 | INIT_LIST_HEAD(&bf_q); | 815 | INIT_LIST_HEAD(&bf_q); |
751 | 816 | ||
752 | status = ath_tx_form_aggr(sc, txq, tid, &bf_q); | 817 | status = ath_tx_form_aggr(sc, txq, tid, &bf_q, &aggr_len); |
753 | 818 | ||
754 | /* | 819 | /* |
755 | * no frames picked up to be aggregated; | 820 | * no frames picked up to be aggregated; |
@@ -761,19 +826,26 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
761 | bf = list_first_entry(&bf_q, struct ath_buf, list); | 826 | bf = list_first_entry(&bf_q, struct ath_buf, list); |
762 | bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); | 827 | bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); |
763 | 828 | ||
829 | if (tid->ac->clear_ps_filter) { | ||
830 | tid->ac->clear_ps_filter = false; | ||
831 | ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); | ||
832 | } | ||
833 | |||
764 | /* if only one frame, send as non-aggregate */ | 834 | /* if only one frame, send as non-aggregate */ |
765 | if (bf->bf_nframes == 1) { | 835 | if (bf == bf->bf_lastbf) { |
836 | fi = get_frame_info(bf->bf_mpdu); | ||
837 | |||
766 | bf->bf_state.bf_type &= ~BUF_AGGR; | 838 | bf->bf_state.bf_type &= ~BUF_AGGR; |
767 | ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); | 839 | ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); |
768 | ath_buf_set_rate(sc, bf); | 840 | ath_buf_set_rate(sc, bf, fi->framelen); |
769 | ath_tx_txqaddbuf(sc, txq, &bf_q); | 841 | ath_tx_txqaddbuf(sc, txq, &bf_q); |
770 | continue; | 842 | continue; |
771 | } | 843 | } |
772 | 844 | ||
773 | /* setup first desc of aggregate */ | 845 | /* setup first desc of aggregate */ |
774 | bf->bf_state.bf_type |= BUF_AGGR; | 846 | bf->bf_state.bf_type |= BUF_AGGR; |
775 | ath_buf_set_rate(sc, bf); | 847 | ath_buf_set_rate(sc, bf, aggr_len); |
776 | ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); | 848 | ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, aggr_len); |
777 | 849 | ||
778 | /* anchor last desc of aggregate */ | 850 | /* anchor last desc of aggregate */ |
779 | ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); | 851 | ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); |
@@ -781,34 +853,37 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
781 | ath_tx_txqaddbuf(sc, txq, &bf_q); | 853 | ath_tx_txqaddbuf(sc, txq, &bf_q); |
782 | TX_STAT_INC(txq->axq_qnum, a_aggr); | 854 | TX_STAT_INC(txq->axq_qnum, a_aggr); |
783 | 855 | ||
784 | } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && | 856 | } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH && |
785 | status != ATH_AGGR_BAW_CLOSED); | 857 | status != ATH_AGGR_BAW_CLOSED); |
786 | } | 858 | } |
787 | 859 | ||
788 | void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 860 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
789 | u16 tid, u16 *ssn) | 861 | u16 tid, u16 *ssn) |
790 | { | 862 | { |
791 | struct ath_atx_tid *txtid; | 863 | struct ath_atx_tid *txtid; |
792 | struct ath_node *an; | 864 | struct ath_node *an; |
793 | 865 | ||
794 | an = (struct ath_node *)sta->drv_priv; | 866 | an = (struct ath_node *)sta->drv_priv; |
795 | txtid = ATH_AN_2_TID(an, tid); | 867 | txtid = ATH_AN_2_TID(an, tid); |
868 | |||
869 | if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE)) | ||
870 | return -EAGAIN; | ||
871 | |||
796 | txtid->state |= AGGR_ADDBA_PROGRESS; | 872 | txtid->state |= AGGR_ADDBA_PROGRESS; |
797 | txtid->paused = true; | 873 | txtid->paused = true; |
798 | *ssn = txtid->seq_start; | 874 | *ssn = txtid->seq_start = txtid->seq_next; |
875 | |||
876 | memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf)); | ||
877 | txtid->baw_head = txtid->baw_tail = 0; | ||
878 | |||
879 | return 0; | ||
799 | } | 880 | } |
800 | 881 | ||
801 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | 882 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) |
802 | { | 883 | { |
803 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 884 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
804 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); | 885 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); |
805 | struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; | 886 | struct ath_txq *txq = txtid->ac->txq; |
806 | struct ath_tx_status ts; | ||
807 | struct ath_buf *bf; | ||
808 | struct list_head bf_head; | ||
809 | |||
810 | memset(&ts, 0, sizeof(ts)); | ||
811 | INIT_LIST_HEAD(&bf_head); | ||
812 | 887 | ||
813 | if (txtid->state & AGGR_CLEANUP) | 888 | if (txtid->state & AGGR_CLEANUP) |
814 | return; | 889 | return; |
@@ -818,30 +893,82 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
818 | return; | 893 | return; |
819 | } | 894 | } |
820 | 895 | ||
821 | /* drop all software retried frames and mark this TID */ | ||
822 | spin_lock_bh(&txq->axq_lock); | 896 | spin_lock_bh(&txq->axq_lock); |
823 | txtid->paused = true; | 897 | txtid->paused = true; |
824 | while (!list_empty(&txtid->buf_q)) { | ||
825 | bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); | ||
826 | if (!bf_isretried(bf)) { | ||
827 | /* | ||
828 | * NB: it's based on the assumption that | ||
829 | * software retried frame will always stay | ||
830 | * at the head of software queue. | ||
831 | */ | ||
832 | break; | ||
833 | } | ||
834 | list_move_tail(&bf->list, &bf_head); | ||
835 | ath_tx_update_baw(sc, txtid, bf->bf_seqno); | ||
836 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | ||
837 | } | ||
838 | spin_unlock_bh(&txq->axq_lock); | ||
839 | 898 | ||
840 | if (txtid->baw_head != txtid->baw_tail) { | 899 | /* |
900 | * If frames are still being transmitted for this TID, they will be | ||
901 | * cleaned up during tx completion. To prevent race conditions, this | ||
902 | * TID can only be reused after all in-progress subframes have been | ||
903 | * completed. | ||
904 | */ | ||
905 | if (txtid->baw_head != txtid->baw_tail) | ||
841 | txtid->state |= AGGR_CLEANUP; | 906 | txtid->state |= AGGR_CLEANUP; |
842 | } else { | 907 | else |
843 | txtid->state &= ~AGGR_ADDBA_COMPLETE; | 908 | txtid->state &= ~AGGR_ADDBA_COMPLETE; |
844 | ath_tx_flush_tid(sc, txtid); | 909 | spin_unlock_bh(&txq->axq_lock); |
910 | |||
911 | ath_tx_flush_tid(sc, txtid); | ||
912 | } | ||
913 | |||
914 | bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) | ||
915 | { | ||
916 | struct ath_atx_tid *tid; | ||
917 | struct ath_atx_ac *ac; | ||
918 | struct ath_txq *txq; | ||
919 | bool buffered = false; | ||
920 | int tidno; | ||
921 | |||
922 | for (tidno = 0, tid = &an->tid[tidno]; | ||
923 | tidno < WME_NUM_TID; tidno++, tid++) { | ||
924 | |||
925 | if (!tid->sched) | ||
926 | continue; | ||
927 | |||
928 | ac = tid->ac; | ||
929 | txq = ac->txq; | ||
930 | |||
931 | spin_lock_bh(&txq->axq_lock); | ||
932 | |||
933 | if (!list_empty(&tid->buf_q)) | ||
934 | buffered = true; | ||
935 | |||
936 | tid->sched = false; | ||
937 | list_del(&tid->list); | ||
938 | |||
939 | if (ac->sched) { | ||
940 | ac->sched = false; | ||
941 | list_del(&ac->list); | ||
942 | } | ||
943 | |||
944 | spin_unlock_bh(&txq->axq_lock); | ||
945 | } | ||
946 | |||
947 | return buffered; | ||
948 | } | ||
949 | |||
950 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | ||
951 | { | ||
952 | struct ath_atx_tid *tid; | ||
953 | struct ath_atx_ac *ac; | ||
954 | struct ath_txq *txq; | ||
955 | int tidno; | ||
956 | |||
957 | for (tidno = 0, tid = &an->tid[tidno]; | ||
958 | tidno < WME_NUM_TID; tidno++, tid++) { | ||
959 | |||
960 | ac = tid->ac; | ||
961 | txq = ac->txq; | ||
962 | |||
963 | spin_lock_bh(&txq->axq_lock); | ||
964 | ac->clear_ps_filter = true; | ||
965 | |||
966 | if (!list_empty(&tid->buf_q) && !tid->paused) { | ||
967 | ath_tx_queue_tid(txq, tid); | ||
968 | ath_txq_schedule(sc, txq); | ||
969 | } | ||
970 | |||
971 | spin_unlock_bh(&txq->axq_lock); | ||
845 | } | 972 | } |
846 | } | 973 | } |
847 | 974 | ||
@@ -862,20 +989,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid | |||
862 | } | 989 | } |
863 | } | 990 | } |
864 | 991 | ||
865 | bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno) | ||
866 | { | ||
867 | struct ath_atx_tid *txtid; | ||
868 | |||
869 | if (!(sc->sc_flags & SC_OP_TXAGGR)) | ||
870 | return false; | ||
871 | |||
872 | txtid = ATH_AN_2_TID(an, tidno); | ||
873 | |||
874 | if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS))) | ||
875 | return true; | ||
876 | return false; | ||
877 | } | ||
878 | |||
879 | /********************/ | 992 | /********************/ |
880 | /* Queue Management */ | 993 | /* Queue Management */ |
881 | /********************/ | 994 | /********************/ |
@@ -902,10 +1015,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
902 | struct ath_hw *ah = sc->sc_ah; | 1015 | struct ath_hw *ah = sc->sc_ah; |
903 | struct ath_common *common = ath9k_hw_common(ah); | 1016 | struct ath_common *common = ath9k_hw_common(ah); |
904 | struct ath9k_tx_queue_info qi; | 1017 | struct ath9k_tx_queue_info qi; |
905 | int qnum, i; | 1018 | static const int subtype_txq_to_hwq[] = { |
1019 | [WME_AC_BE] = ATH_TXQ_AC_BE, | ||
1020 | [WME_AC_BK] = ATH_TXQ_AC_BK, | ||
1021 | [WME_AC_VI] = ATH_TXQ_AC_VI, | ||
1022 | [WME_AC_VO] = ATH_TXQ_AC_VO, | ||
1023 | }; | ||
1024 | int axq_qnum, i; | ||
906 | 1025 | ||
907 | memset(&qi, 0, sizeof(qi)); | 1026 | memset(&qi, 0, sizeof(qi)); |
908 | qi.tqi_subtype = subtype; | 1027 | qi.tqi_subtype = subtype_txq_to_hwq[subtype]; |
909 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; | 1028 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; |
910 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; | 1029 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; |
911 | qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; | 1030 | qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; |
@@ -936,40 +1055,40 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
936 | qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | | 1055 | qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | |
937 | TXQ_FLAG_TXDESCINT_ENABLE; | 1056 | TXQ_FLAG_TXDESCINT_ENABLE; |
938 | } | 1057 | } |
939 | qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); | 1058 | axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); |
940 | if (qnum == -1) { | 1059 | if (axq_qnum == -1) { |
941 | /* | 1060 | /* |
942 | * NB: don't print a message, this happens | 1061 | * NB: don't print a message, this happens |
943 | * normally on parts with too few tx queues | 1062 | * normally on parts with too few tx queues |
944 | */ | 1063 | */ |
945 | return NULL; | 1064 | return NULL; |
946 | } | 1065 | } |
947 | if (qnum >= ARRAY_SIZE(sc->tx.txq)) { | 1066 | if (axq_qnum >= ARRAY_SIZE(sc->tx.txq)) { |
948 | ath_print(common, ATH_DBG_FATAL, | 1067 | ath_err(common, "qnum %u out of range, max %zu!\n", |
949 | "qnum %u out of range, max %u!\n", | 1068 | axq_qnum, ARRAY_SIZE(sc->tx.txq)); |
950 | qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); | 1069 | ath9k_hw_releasetxqueue(ah, axq_qnum); |
951 | ath9k_hw_releasetxqueue(ah, qnum); | ||
952 | return NULL; | 1070 | return NULL; |
953 | } | 1071 | } |
954 | if (!ATH_TXQ_SETUP(sc, qnum)) { | 1072 | if (!ATH_TXQ_SETUP(sc, axq_qnum)) { |
955 | struct ath_txq *txq = &sc->tx.txq[qnum]; | 1073 | struct ath_txq *txq = &sc->tx.txq[axq_qnum]; |
956 | 1074 | ||
957 | txq->axq_class = subtype; | 1075 | txq->axq_qnum = axq_qnum; |
958 | txq->axq_qnum = qnum; | 1076 | txq->mac80211_qnum = -1; |
959 | txq->axq_link = NULL; | 1077 | txq->axq_link = NULL; |
960 | INIT_LIST_HEAD(&txq->axq_q); | 1078 | INIT_LIST_HEAD(&txq->axq_q); |
961 | INIT_LIST_HEAD(&txq->axq_acq); | 1079 | INIT_LIST_HEAD(&txq->axq_acq); |
962 | spin_lock_init(&txq->axq_lock); | 1080 | spin_lock_init(&txq->axq_lock); |
963 | txq->axq_depth = 0; | 1081 | txq->axq_depth = 0; |
1082 | txq->axq_ampdu_depth = 0; | ||
964 | txq->axq_tx_inprogress = false; | 1083 | txq->axq_tx_inprogress = false; |
965 | sc->tx.txqsetup |= 1<<qnum; | 1084 | sc->tx.txqsetup |= 1<<axq_qnum; |
966 | 1085 | ||
967 | txq->txq_headidx = txq->txq_tailidx = 0; | 1086 | txq->txq_headidx = txq->txq_tailidx = 0; |
968 | for (i = 0; i < ATH_TXFIFO_DEPTH; i++) | 1087 | for (i = 0; i < ATH_TXFIFO_DEPTH; i++) |
969 | INIT_LIST_HEAD(&txq->txq_fifo[i]); | 1088 | INIT_LIST_HEAD(&txq->txq_fifo[i]); |
970 | INIT_LIST_HEAD(&txq->txq_fifo_pending); | 1089 | INIT_LIST_HEAD(&txq->txq_fifo_pending); |
971 | } | 1090 | } |
972 | return &sc->tx.txq[qnum]; | 1091 | return &sc->tx.txq[axq_qnum]; |
973 | } | 1092 | } |
974 | 1093 | ||
975 | int ath_txq_update(struct ath_softc *sc, int qnum, | 1094 | int ath_txq_update(struct ath_softc *sc, int qnum, |
@@ -999,8 +1118,8 @@ int ath_txq_update(struct ath_softc *sc, int qnum, | |||
999 | qi.tqi_readyTime = qinfo->tqi_readyTime; | 1118 | qi.tqi_readyTime = qinfo->tqi_readyTime; |
1000 | 1119 | ||
1001 | if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { | 1120 | if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { |
1002 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 1121 | ath_err(ath9k_hw_common(sc->sc_ah), |
1003 | "Unable to update hardware queue %u!\n", qnum); | 1122 | "Unable to update hardware queue %u!\n", qnum); |
1004 | error = -EIO; | 1123 | error = -EIO; |
1005 | } else { | 1124 | } else { |
1006 | ath9k_hw_resettxqueue(ah, qnum); | 1125 | ath9k_hw_resettxqueue(ah, qnum); |
@@ -1012,6 +1131,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum, | |||
1012 | int ath_cabq_update(struct ath_softc *sc) | 1131 | int ath_cabq_update(struct ath_softc *sc) |
1013 | { | 1132 | { |
1014 | struct ath9k_tx_queue_info qi; | 1133 | struct ath9k_tx_queue_info qi; |
1134 | struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; | ||
1015 | int qnum = sc->beacon.cabq->axq_qnum; | 1135 | int qnum = sc->beacon.cabq->axq_qnum; |
1016 | 1136 | ||
1017 | ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); | 1137 | ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); |
@@ -1023,13 +1143,19 @@ int ath_cabq_update(struct ath_softc *sc) | |||
1023 | else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) | 1143 | else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) |
1024 | sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; | 1144 | sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; |
1025 | 1145 | ||
1026 | qi.tqi_readyTime = (sc->beacon_interval * | 1146 | qi.tqi_readyTime = (cur_conf->beacon_interval * |
1027 | sc->config.cabqReadytime) / 100; | 1147 | sc->config.cabqReadytime) / 100; |
1028 | ath_txq_update(sc, qnum, &qi); | 1148 | ath_txq_update(sc, qnum, &qi); |
1029 | 1149 | ||
1030 | return 0; | 1150 | return 0; |
1031 | } | 1151 | } |
1032 | 1152 | ||
1153 | static bool bf_is_ampdu_not_probing(struct ath_buf *bf) | ||
1154 | { | ||
1155 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu); | ||
1156 | return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); | ||
1157 | } | ||
1158 | |||
1033 | /* | 1159 | /* |
1034 | * Drain a given TX queue (could be Beacon or Data) | 1160 | * Drain a given TX queue (could be Beacon or Data) |
1035 | * | 1161 | * |
@@ -1076,8 +1202,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1076 | } | 1202 | } |
1077 | 1203 | ||
1078 | lastbf = bf->bf_lastbf; | 1204 | lastbf = bf->bf_lastbf; |
1079 | if (!retry_tx) | ||
1080 | lastbf->bf_tx_aborted = true; | ||
1081 | 1205 | ||
1082 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 1206 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
1083 | list_cut_position(&bf_head, | 1207 | list_cut_position(&bf_head, |
@@ -1090,11 +1214,13 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1090 | } | 1214 | } |
1091 | 1215 | ||
1092 | txq->axq_depth--; | 1216 | txq->axq_depth--; |
1093 | 1217 | if (bf_is_ampdu_not_probing(bf)) | |
1218 | txq->axq_ampdu_depth--; | ||
1094 | spin_unlock_bh(&txq->axq_lock); | 1219 | spin_unlock_bh(&txq->axq_lock); |
1095 | 1220 | ||
1096 | if (bf_isampdu(bf)) | 1221 | if (bf_isampdu(bf)) |
1097 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0); | 1222 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0, |
1223 | retry_tx); | ||
1098 | else | 1224 | else |
1099 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); | 1225 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); |
1100 | } | 1226 | } |
@@ -1103,15 +1229,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1103 | txq->axq_tx_inprogress = false; | 1229 | txq->axq_tx_inprogress = false; |
1104 | spin_unlock_bh(&txq->axq_lock); | 1230 | spin_unlock_bh(&txq->axq_lock); |
1105 | 1231 | ||
1106 | /* flush any pending frames if aggregation is enabled */ | ||
1107 | if (sc->sc_flags & SC_OP_TXAGGR) { | ||
1108 | if (!retry_tx) { | ||
1109 | spin_lock_bh(&txq->axq_lock); | ||
1110 | ath_txq_drain_pending_buffers(sc, txq); | ||
1111 | spin_unlock_bh(&txq->axq_lock); | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 1232 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
1116 | spin_lock_bh(&txq->axq_lock); | 1233 | spin_lock_bh(&txq->axq_lock); |
1117 | while (!list_empty(&txq->txq_fifo_pending)) { | 1234 | while (!list_empty(&txq->txq_fifo_pending)) { |
@@ -1124,7 +1241,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1124 | 1241 | ||
1125 | if (bf_isampdu(bf)) | 1242 | if (bf_isampdu(bf)) |
1126 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, | 1243 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, |
1127 | &ts, 0); | 1244 | &ts, 0, retry_tx); |
1128 | else | 1245 | else |
1129 | ath_tx_complete_buf(sc, bf, txq, &bf_head, | 1246 | ath_tx_complete_buf(sc, bf, txq, &bf_head, |
1130 | &ts, 0, 0); | 1247 | &ts, 0, 0); |
@@ -1132,9 +1249,18 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1132 | } | 1249 | } |
1133 | spin_unlock_bh(&txq->axq_lock); | 1250 | spin_unlock_bh(&txq->axq_lock); |
1134 | } | 1251 | } |
1252 | |||
1253 | /* flush any pending frames if aggregation is enabled */ | ||
1254 | if (sc->sc_flags & SC_OP_TXAGGR) { | ||
1255 | if (!retry_tx) { | ||
1256 | spin_lock_bh(&txq->axq_lock); | ||
1257 | ath_txq_drain_pending_buffers(sc, txq); | ||
1258 | spin_unlock_bh(&txq->axq_lock); | ||
1259 | } | ||
1260 | } | ||
1135 | } | 1261 | } |
1136 | 1262 | ||
1137 | void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | 1263 | bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) |
1138 | { | 1264 | { |
1139 | struct ath_hw *ah = sc->sc_ah; | 1265 | struct ath_hw *ah = sc->sc_ah; |
1140 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1266 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -1142,39 +1268,36 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) | |||
1142 | int i, npend = 0; | 1268 | int i, npend = 0; |
1143 | 1269 | ||
1144 | if (sc->sc_flags & SC_OP_INVALID) | 1270 | if (sc->sc_flags & SC_OP_INVALID) |
1145 | return; | 1271 | return true; |
1146 | 1272 | ||
1147 | /* Stop beacon queue */ | 1273 | ath9k_hw_abort_tx_dma(ah); |
1148 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | ||
1149 | 1274 | ||
1150 | /* Stop data queues */ | 1275 | /* Check if any queue remains active */ |
1151 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | 1276 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { |
1152 | if (ATH_TXQ_SETUP(sc, i)) { | 1277 | if (!ATH_TXQ_SETUP(sc, i)) |
1153 | txq = &sc->tx.txq[i]; | 1278 | continue; |
1154 | ath9k_hw_stoptxdma(ah, txq->axq_qnum); | 1279 | |
1155 | npend += ath9k_hw_numtxpending(ah, txq->axq_qnum); | 1280 | npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum); |
1156 | } | ||
1157 | } | 1281 | } |
1158 | 1282 | ||
1159 | if (npend) { | 1283 | if (npend) |
1160 | int r; | 1284 | ath_err(common, "Failed to stop TX DMA!\n"); |
1161 | 1285 | ||
1162 | ath_print(common, ATH_DBG_FATAL, | 1286 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { |
1163 | "Failed to stop TX DMA. Resetting hardware!\n"); | 1287 | if (!ATH_TXQ_SETUP(sc, i)) |
1288 | continue; | ||
1164 | 1289 | ||
1165 | spin_lock_bh(&sc->sc_resetlock); | 1290 | /* |
1166 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); | 1291 | * The caller will resume queues with ieee80211_wake_queues. |
1167 | if (r) | 1292 | * Mark the queue as not stopped to prevent ath_tx_complete |
1168 | ath_print(common, ATH_DBG_FATAL, | 1293 | * from waking the queue too early. |
1169 | "Unable to reset hardware; reset status %d\n", | 1294 | */ |
1170 | r); | 1295 | txq = &sc->tx.txq[i]; |
1171 | spin_unlock_bh(&sc->sc_resetlock); | 1296 | txq->stopped = false; |
1297 | ath_draintxq(sc, txq, retry_tx); | ||
1172 | } | 1298 | } |
1173 | 1299 | ||
1174 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | 1300 | return !npend; |
1175 | if (ATH_TXQ_SETUP(sc, i)) | ||
1176 | ath_draintxq(sc, &sc->tx.txq[i], retry_tx); | ||
1177 | } | ||
1178 | } | 1301 | } |
1179 | 1302 | ||
1180 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) | 1303 | void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) |
@@ -1183,65 +1306,60 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) | |||
1183 | sc->tx.txqsetup &= ~(1<<txq->axq_qnum); | 1306 | sc->tx.txqsetup &= ~(1<<txq->axq_qnum); |
1184 | } | 1307 | } |
1185 | 1308 | ||
1309 | /* For each axq_acq entry, for each tid, try to schedule packets | ||
1310 | * for transmit until ampdu_depth has reached min Q depth. | ||
1311 | */ | ||
1186 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | 1312 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) |
1187 | { | 1313 | { |
1188 | struct ath_atx_ac *ac; | 1314 | struct ath_atx_ac *ac, *ac_tmp, *last_ac; |
1189 | struct ath_atx_tid *tid; | 1315 | struct ath_atx_tid *tid, *last_tid; |
1190 | 1316 | ||
1191 | if (list_empty(&txq->axq_acq)) | 1317 | if (list_empty(&txq->axq_acq) || |
1318 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) | ||
1192 | return; | 1319 | return; |
1193 | 1320 | ||
1194 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); | 1321 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); |
1195 | list_del(&ac->list); | 1322 | last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list); |
1196 | ac->sched = false; | ||
1197 | |||
1198 | do { | ||
1199 | if (list_empty(&ac->tid_q)) | ||
1200 | return; | ||
1201 | 1323 | ||
1202 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list); | 1324 | list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { |
1203 | list_del(&tid->list); | 1325 | last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); |
1204 | tid->sched = false; | 1326 | list_del(&ac->list); |
1327 | ac->sched = false; | ||
1205 | 1328 | ||
1206 | if (tid->paused) | 1329 | while (!list_empty(&ac->tid_q)) { |
1207 | continue; | 1330 | tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, |
1331 | list); | ||
1332 | list_del(&tid->list); | ||
1333 | tid->sched = false; | ||
1208 | 1334 | ||
1209 | ath_tx_sched_aggr(sc, txq, tid); | 1335 | if (tid->paused) |
1336 | continue; | ||
1210 | 1337 | ||
1211 | /* | 1338 | ath_tx_sched_aggr(sc, txq, tid); |
1212 | * add tid to round-robin queue if more frames | ||
1213 | * are pending for the tid | ||
1214 | */ | ||
1215 | if (!list_empty(&tid->buf_q)) | ||
1216 | ath_tx_queue_tid(txq, tid); | ||
1217 | 1339 | ||
1218 | break; | 1340 | /* |
1219 | } while (!list_empty(&ac->tid_q)); | 1341 | * add tid to round-robin queue if more frames |
1342 | * are pending for the tid | ||
1343 | */ | ||
1344 | if (!list_empty(&tid->buf_q)) | ||
1345 | ath_tx_queue_tid(txq, tid); | ||
1220 | 1346 | ||
1221 | if (!list_empty(&ac->tid_q)) { | 1347 | if (tid == last_tid || |
1222 | if (!ac->sched) { | 1348 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) |
1223 | ac->sched = true; | 1349 | break; |
1224 | list_add_tail(&ac->list, &txq->axq_acq); | ||
1225 | } | 1350 | } |
1226 | } | ||
1227 | } | ||
1228 | 1351 | ||
1229 | int ath_tx_setup(struct ath_softc *sc, int haltype) | 1352 | if (!list_empty(&ac->tid_q)) { |
1230 | { | 1353 | if (!ac->sched) { |
1231 | struct ath_txq *txq; | 1354 | ac->sched = true; |
1355 | list_add_tail(&ac->list, &txq->axq_acq); | ||
1356 | } | ||
1357 | } | ||
1232 | 1358 | ||
1233 | if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { | 1359 | if (ac == last_ac || |
1234 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 1360 | txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) |
1235 | "HAL AC %u out of range, max %zu!\n", | 1361 | return; |
1236 | haltype, ARRAY_SIZE(sc->tx.hwq_map)); | ||
1237 | return 0; | ||
1238 | } | 1362 | } |
1239 | txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); | ||
1240 | if (txq != NULL) { | ||
1241 | sc->tx.hwq_map[haltype] = txq->axq_qnum; | ||
1242 | return 1; | ||
1243 | } else | ||
1244 | return 0; | ||
1245 | } | 1363 | } |
1246 | 1364 | ||
1247 | /***********/ | 1365 | /***********/ |
@@ -1269,8 +1387,8 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1269 | 1387 | ||
1270 | bf = list_first_entry(head, struct ath_buf, list); | 1388 | bf = list_first_entry(head, struct ath_buf, list); |
1271 | 1389 | ||
1272 | ath_print(common, ATH_DBG_QUEUE, | 1390 | ath_dbg(common, ATH_DBG_QUEUE, |
1273 | "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); | 1391 | "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); |
1274 | 1392 | ||
1275 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { | 1393 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
1276 | if (txq->axq_depth >= ATH_TXFIFO_DEPTH) { | 1394 | if (txq->axq_depth >= ATH_TXFIFO_DEPTH) { |
@@ -1278,49 +1396,49 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1278 | return; | 1396 | return; |
1279 | } | 1397 | } |
1280 | if (!list_empty(&txq->txq_fifo[txq->txq_headidx])) | 1398 | if (!list_empty(&txq->txq_fifo[txq->txq_headidx])) |
1281 | ath_print(common, ATH_DBG_XMIT, | 1399 | ath_dbg(common, ATH_DBG_XMIT, |
1282 | "Initializing tx fifo %d which " | 1400 | "Initializing tx fifo %d which is non-empty\n", |
1283 | "is non-empty\n", | 1401 | txq->txq_headidx); |
1284 | txq->txq_headidx); | ||
1285 | INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]); | 1402 | INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]); |
1286 | list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]); | 1403 | list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]); |
1287 | INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH); | 1404 | INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH); |
1405 | TX_STAT_INC(txq->axq_qnum, puttxbuf); | ||
1288 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); | 1406 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); |
1289 | ath_print(common, ATH_DBG_XMIT, | 1407 | ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", |
1290 | "TXDP[%u] = %llx (%p)\n", | 1408 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); |
1291 | txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); | ||
1292 | } else { | 1409 | } else { |
1293 | list_splice_tail_init(head, &txq->axq_q); | 1410 | list_splice_tail_init(head, &txq->axq_q); |
1294 | 1411 | ||
1295 | if (txq->axq_link == NULL) { | 1412 | if (txq->axq_link == NULL) { |
1413 | TX_STAT_INC(txq->axq_qnum, puttxbuf); | ||
1296 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); | 1414 | ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); |
1297 | ath_print(common, ATH_DBG_XMIT, | 1415 | ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n", |
1298 | "TXDP[%u] = %llx (%p)\n", | 1416 | txq->axq_qnum, ito64(bf->bf_daddr), |
1299 | txq->axq_qnum, ito64(bf->bf_daddr), | 1417 | bf->bf_desc); |
1300 | bf->bf_desc); | ||
1301 | } else { | 1418 | } else { |
1302 | *txq->axq_link = bf->bf_daddr; | 1419 | *txq->axq_link = bf->bf_daddr; |
1303 | ath_print(common, ATH_DBG_XMIT, | 1420 | ath_dbg(common, ATH_DBG_XMIT, |
1304 | "link[%u] (%p)=%llx (%p)\n", | 1421 | "link[%u] (%p)=%llx (%p)\n", |
1305 | txq->axq_qnum, txq->axq_link, | 1422 | txq->axq_qnum, txq->axq_link, |
1306 | ito64(bf->bf_daddr), bf->bf_desc); | 1423 | ito64(bf->bf_daddr), bf->bf_desc); |
1307 | } | 1424 | } |
1308 | ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, | 1425 | ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc, |
1309 | &txq->axq_link); | 1426 | &txq->axq_link); |
1427 | TX_STAT_INC(txq->axq_qnum, txstart); | ||
1310 | ath9k_hw_txstart(ah, txq->axq_qnum); | 1428 | ath9k_hw_txstart(ah, txq->axq_qnum); |
1311 | } | 1429 | } |
1312 | txq->axq_depth++; | 1430 | txq->axq_depth++; |
1431 | if (bf_is_ampdu_not_probing(bf)) | ||
1432 | txq->axq_ampdu_depth++; | ||
1313 | } | 1433 | } |
1314 | 1434 | ||
1315 | static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | 1435 | static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, |
1316 | struct list_head *bf_head, | 1436 | struct ath_buf *bf, struct ath_tx_control *txctl) |
1317 | struct ath_tx_control *txctl) | ||
1318 | { | 1437 | { |
1319 | struct ath_buf *bf; | 1438 | struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); |
1439 | struct list_head bf_head; | ||
1320 | 1440 | ||
1321 | bf = list_first_entry(bf_head, struct ath_buf, list); | ||
1322 | bf->bf_state.bf_type |= BUF_AMPDU; | 1441 | bf->bf_state.bf_type |= BUF_AMPDU; |
1323 | TX_STAT_INC(txctl->txq->axq_qnum, a_queued); | ||
1324 | 1442 | ||
1325 | /* | 1443 | /* |
1326 | * Do not queue to h/w when any of the following conditions is true: | 1444 | * Do not queue to h/w when any of the following conditions is true: |
@@ -1330,56 +1448,49 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, | |||
1330 | * - h/w queue depth exceeds low water mark | 1448 | * - h/w queue depth exceeds low water mark |
1331 | */ | 1449 | */ |
1332 | if (!list_empty(&tid->buf_q) || tid->paused || | 1450 | if (!list_empty(&tid->buf_q) || tid->paused || |
1333 | !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || | 1451 | !BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) || |
1334 | txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { | 1452 | txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) { |
1335 | /* | 1453 | /* |
1336 | * Add this frame to software queue for scheduling later | 1454 | * Add this frame to software queue for scheduling later |
1337 | * for aggregation. | 1455 | * for aggregation. |
1338 | */ | 1456 | */ |
1339 | list_move_tail(&bf->list, &tid->buf_q); | 1457 | TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); |
1458 | list_add_tail(&bf->list, &tid->buf_q); | ||
1340 | ath_tx_queue_tid(txctl->txq, tid); | 1459 | ath_tx_queue_tid(txctl->txq, tid); |
1341 | return; | 1460 | return; |
1342 | } | 1461 | } |
1343 | 1462 | ||
1463 | INIT_LIST_HEAD(&bf_head); | ||
1464 | list_add(&bf->list, &bf_head); | ||
1465 | |||
1344 | /* Add sub-frame to BAW */ | 1466 | /* Add sub-frame to BAW */ |
1345 | ath_tx_addto_baw(sc, tid, bf); | 1467 | if (!fi->retries) |
1468 | ath_tx_addto_baw(sc, tid, fi->seqno); | ||
1346 | 1469 | ||
1347 | /* Queue to h/w without aggregation */ | 1470 | /* Queue to h/w without aggregation */ |
1348 | bf->bf_nframes = 1; | 1471 | TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw); |
1349 | bf->bf_lastbf = bf; | 1472 | bf->bf_lastbf = bf; |
1350 | ath_buf_set_rate(sc, bf); | 1473 | ath_buf_set_rate(sc, bf, fi->framelen); |
1351 | ath_tx_txqaddbuf(sc, txctl->txq, bf_head); | 1474 | ath_tx_txqaddbuf(sc, txctl->txq, &bf_head); |
1352 | } | 1475 | } |
1353 | 1476 | ||
1354 | static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, | 1477 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, |
1355 | struct ath_atx_tid *tid, | 1478 | struct ath_atx_tid *tid, |
1356 | struct list_head *bf_head) | 1479 | struct list_head *bf_head) |
1357 | { | 1480 | { |
1481 | struct ath_frame_info *fi; | ||
1358 | struct ath_buf *bf; | 1482 | struct ath_buf *bf; |
1359 | 1483 | ||
1360 | bf = list_first_entry(bf_head, struct ath_buf, list); | 1484 | bf = list_first_entry(bf_head, struct ath_buf, list); |
1361 | bf->bf_state.bf_type &= ~BUF_AMPDU; | 1485 | bf->bf_state.bf_type &= ~BUF_AMPDU; |
1362 | 1486 | ||
1363 | /* update starting sequence number for subsequent ADDBA request */ | 1487 | /* update starting sequence number for subsequent ADDBA request */ |
1364 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | 1488 | if (tid) |
1365 | 1489 | INCR(tid->seq_start, IEEE80211_SEQ_MAX); | |
1366 | bf->bf_nframes = 1; | ||
1367 | bf->bf_lastbf = bf; | ||
1368 | ath_buf_set_rate(sc, bf); | ||
1369 | ath_tx_txqaddbuf(sc, txq, bf_head); | ||
1370 | TX_STAT_INC(txq->axq_qnum, queued); | ||
1371 | } | ||
1372 | |||
1373 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | ||
1374 | struct list_head *bf_head) | ||
1375 | { | ||
1376 | struct ath_buf *bf; | ||
1377 | |||
1378 | bf = list_first_entry(bf_head, struct ath_buf, list); | ||
1379 | 1490 | ||
1380 | bf->bf_lastbf = bf; | 1491 | bf->bf_lastbf = bf; |
1381 | bf->bf_nframes = 1; | 1492 | fi = get_frame_info(bf->bf_mpdu); |
1382 | ath_buf_set_rate(sc, bf); | 1493 | ath_buf_set_rate(sc, bf, fi->framelen); |
1383 | ath_tx_txqaddbuf(sc, txq, bf_head); | 1494 | ath_tx_txqaddbuf(sc, txq, bf_head); |
1384 | TX_STAT_INC(txq->axq_qnum, queued); | 1495 | TX_STAT_INC(txq->axq_qnum, queued); |
1385 | } | 1496 | } |
@@ -1407,67 +1518,65 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) | |||
1407 | return htype; | 1518 | return htype; |
1408 | } | 1519 | } |
1409 | 1520 | ||
1410 | static int get_hw_crypto_keytype(struct sk_buff *skb) | 1521 | static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, |
1411 | { | 1522 | int framelen) |
1412 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1413 | |||
1414 | if (tx_info->control.hw_key) { | ||
1415 | if (tx_info->control.hw_key->alg == ALG_WEP) | ||
1416 | return ATH9K_KEY_TYPE_WEP; | ||
1417 | else if (tx_info->control.hw_key->alg == ALG_TKIP) | ||
1418 | return ATH9K_KEY_TYPE_TKIP; | ||
1419 | else if (tx_info->control.hw_key->alg == ALG_CCMP) | ||
1420 | return ATH9K_KEY_TYPE_AES; | ||
1421 | } | ||
1422 | |||
1423 | return ATH9K_KEY_TYPE_CLEAR; | ||
1424 | } | ||
1425 | |||
1426 | static void assign_aggr_tid_seqno(struct sk_buff *skb, | ||
1427 | struct ath_buf *bf) | ||
1428 | { | 1523 | { |
1524 | struct ath_softc *sc = hw->priv; | ||
1429 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1525 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1526 | struct ieee80211_sta *sta = tx_info->control.sta; | ||
1527 | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; | ||
1430 | struct ieee80211_hdr *hdr; | 1528 | struct ieee80211_hdr *hdr; |
1431 | struct ath_node *an; | 1529 | struct ath_frame_info *fi = get_frame_info(skb); |
1530 | struct ath_node *an = NULL; | ||
1432 | struct ath_atx_tid *tid; | 1531 | struct ath_atx_tid *tid; |
1433 | __le16 fc; | 1532 | enum ath9k_key_type keytype; |
1434 | u8 *qc; | 1533 | u16 seqno = 0; |
1534 | u8 tidno; | ||
1435 | 1535 | ||
1436 | if (!tx_info->control.sta) | 1536 | keytype = ath9k_cmn_get_hw_crypto_keytype(skb); |
1437 | return; | 1537 | |
1538 | if (sta) | ||
1539 | an = (struct ath_node *) sta->drv_priv; | ||
1438 | 1540 | ||
1439 | an = (struct ath_node *)tx_info->control.sta->drv_priv; | ||
1440 | hdr = (struct ieee80211_hdr *)skb->data; | 1541 | hdr = (struct ieee80211_hdr *)skb->data; |
1441 | fc = hdr->frame_control; | 1542 | if (an && ieee80211_is_data_qos(hdr->frame_control) && |
1543 | conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { | ||
1442 | 1544 | ||
1443 | if (ieee80211_is_data_qos(fc)) { | 1545 | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; |
1444 | qc = ieee80211_get_qos_ctl(hdr); | 1546 | |
1445 | bf->bf_tidno = qc[0] & 0xf; | 1547 | /* |
1548 | * Override seqno set by upper layer with the one | ||
1549 | * in tx aggregation state. | ||
1550 | */ | ||
1551 | tid = ATH_AN_2_TID(an, tidno); | ||
1552 | seqno = tid->seq_next; | ||
1553 | hdr->seq_ctrl = cpu_to_le16(seqno << IEEE80211_SEQ_SEQ_SHIFT); | ||
1554 | INCR(tid->seq_next, IEEE80211_SEQ_MAX); | ||
1446 | } | 1555 | } |
1447 | 1556 | ||
1448 | /* | 1557 | memset(fi, 0, sizeof(*fi)); |
1449 | * For HT capable stations, we save tidno for later use. | 1558 | if (hw_key) |
1450 | * We also override seqno set by upper layer with the one | 1559 | fi->keyix = hw_key->hw_key_idx; |
1451 | * in tx aggregation state. | 1560 | else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) |
1452 | */ | 1561 | fi->keyix = an->ps_key; |
1453 | tid = ATH_AN_2_TID(an, bf->bf_tidno); | 1562 | else |
1454 | hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); | 1563 | fi->keyix = ATH9K_TXKEYIX_INVALID; |
1455 | bf->bf_seqno = tid->seq_next; | 1564 | fi->keytype = keytype; |
1456 | INCR(tid->seq_next, IEEE80211_SEQ_MAX); | 1565 | fi->framelen = framelen; |
1566 | fi->seqno = seqno; | ||
1457 | } | 1567 | } |
1458 | 1568 | ||
1459 | static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) | 1569 | static int setup_tx_flags(struct sk_buff *skb) |
1460 | { | 1570 | { |
1461 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1571 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1462 | int flags = 0; | 1572 | int flags = 0; |
1463 | 1573 | ||
1464 | flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ | ||
1465 | flags |= ATH9K_TXDESC_INTREQ; | 1574 | flags |= ATH9K_TXDESC_INTREQ; |
1466 | 1575 | ||
1467 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) | 1576 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) |
1468 | flags |= ATH9K_TXDESC_NOACK; | 1577 | flags |= ATH9K_TXDESC_NOACK; |
1469 | 1578 | ||
1470 | if (use_ldpc) | 1579 | if (tx_info->flags & IEEE80211_TX_CTL_LDPC) |
1471 | flags |= ATH9K_TXDESC_LDPC; | 1580 | flags |= ATH9K_TXDESC_LDPC; |
1472 | 1581 | ||
1473 | return flags; | 1582 | return flags; |
@@ -1479,13 +1588,11 @@ static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc) | |||
1479 | * width - 0 for 20 MHz, 1 for 40 MHz | 1588 | * width - 0 for 20 MHz, 1 for 40 MHz |
1480 | * half_gi - to use 4us v/s 3.6 us for symbol time | 1589 | * half_gi - to use 4us v/s 3.6 us for symbol time |
1481 | */ | 1590 | */ |
1482 | static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, | 1591 | static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen, |
1483 | int width, int half_gi, bool shortPreamble) | 1592 | int width, int half_gi, bool shortPreamble) |
1484 | { | 1593 | { |
1485 | u32 nbits, nsymbits, duration, nsymbols; | 1594 | u32 nbits, nsymbits, duration, nsymbols; |
1486 | int streams, pktlen; | 1595 | int streams; |
1487 | |||
1488 | pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; | ||
1489 | 1596 | ||
1490 | /* find number of symbols: PLCP + data */ | 1597 | /* find number of symbols: PLCP + data */ |
1491 | streams = HT_RC_2_STREAMS(rix); | 1598 | streams = HT_RC_2_STREAMS(rix); |
@@ -1504,7 +1611,19 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, | |||
1504 | return duration; | 1611 | return duration; |
1505 | } | 1612 | } |
1506 | 1613 | ||
1507 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | 1614 | u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) |
1615 | { | ||
1616 | struct ath_hw *ah = sc->sc_ah; | ||
1617 | struct ath9k_channel *curchan = ah->curchan; | ||
1618 | if ((sc->sc_flags & SC_OP_ENABLE_APM) && | ||
1619 | (curchan->channelFlags & CHANNEL_5GHZ) && | ||
1620 | (chainmask == 0x7) && (rate < 0x90)) | ||
1621 | return 0x3; | ||
1622 | else | ||
1623 | return chainmask; | ||
1624 | } | ||
1625 | |||
1626 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | ||
1508 | { | 1627 | { |
1509 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1628 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1510 | struct ath9k_11n_rate_series series[4]; | 1629 | struct ath9k_11n_rate_series series[4]; |
@@ -1544,10 +1663,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
1544 | 1663 | ||
1545 | rix = rates[i].idx; | 1664 | rix = rates[i].idx; |
1546 | series[i].Tries = rates[i].count; | 1665 | series[i].Tries = rates[i].count; |
1547 | series[i].ChSel = common->tx_chainmask; | ||
1548 | 1666 | ||
1549 | if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || | 1667 | if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) { |
1550 | (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { | ||
1551 | series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; | 1668 | series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; |
1552 | flags |= ATH9K_TXDESC_RTSENA; | 1669 | flags |= ATH9K_TXDESC_RTSENA; |
1553 | } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 1670 | } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
@@ -1567,14 +1684,16 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
1567 | if (rates[i].flags & IEEE80211_TX_RC_MCS) { | 1684 | if (rates[i].flags & IEEE80211_TX_RC_MCS) { |
1568 | /* MCS rates */ | 1685 | /* MCS rates */ |
1569 | series[i].Rate = rix | 0x80; | 1686 | series[i].Rate = rix | 0x80; |
1570 | series[i].PktDuration = ath_pkt_duration(sc, rix, bf, | 1687 | series[i].ChSel = ath_txchainmask_reduction(sc, |
1688 | common->tx_chainmask, series[i].Rate); | ||
1689 | series[i].PktDuration = ath_pkt_duration(sc, rix, len, | ||
1571 | is_40, is_sgi, is_sp); | 1690 | is_40, is_sgi, is_sp); |
1572 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) | 1691 | if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) |
1573 | series[i].RateFlags |= ATH9K_RATESERIES_STBC; | 1692 | series[i].RateFlags |= ATH9K_RATESERIES_STBC; |
1574 | continue; | 1693 | continue; |
1575 | } | 1694 | } |
1576 | 1695 | ||
1577 | /* legcay rates */ | 1696 | /* legacy rates */ |
1578 | if ((tx_info->band == IEEE80211_BAND_2GHZ) && | 1697 | if ((tx_info->band == IEEE80211_BAND_2GHZ) && |
1579 | !(rate->flags & IEEE80211_RATE_ERP_G)) | 1698 | !(rate->flags & IEEE80211_RATE_ERP_G)) |
1580 | phy = WLAN_RC_PHY_CCK; | 1699 | phy = WLAN_RC_PHY_CCK; |
@@ -1590,12 +1709,18 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
1590 | is_sp = false; | 1709 | is_sp = false; |
1591 | } | 1710 | } |
1592 | 1711 | ||
1712 | if (bf->bf_state.bfs_paprd) | ||
1713 | series[i].ChSel = common->tx_chainmask; | ||
1714 | else | ||
1715 | series[i].ChSel = ath_txchainmask_reduction(sc, | ||
1716 | common->tx_chainmask, series[i].Rate); | ||
1717 | |||
1593 | series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, | 1718 | series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah, |
1594 | phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp); | 1719 | phy, rate->bitrate * 100, len, rix, is_sp); |
1595 | } | 1720 | } |
1596 | 1721 | ||
1597 | /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ | 1722 | /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ |
1598 | if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit)) | 1723 | if (bf_isaggr(bf) && (len > sc->sc_ah->caps.rts_aggr_limit)) |
1599 | flags &= ~ATH9K_TXDESC_RTSENA; | 1724 | flags &= ~ATH9K_TXDESC_RTSENA; |
1600 | 1725 | ||
1601 | /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */ | 1726 | /* ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. */ |
@@ -1608,122 +1733,49 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
1608 | !is_pspoll, ctsrate, | 1733 | !is_pspoll, ctsrate, |
1609 | 0, series, 4, flags); | 1734 | 0, series, 4, flags); |
1610 | 1735 | ||
1611 | if (sc->config.ath_aggr_prot && flags) | ||
1612 | ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); | ||
1613 | } | 1736 | } |
1614 | 1737 | ||
1615 | static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | 1738 | static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, |
1616 | struct sk_buff *skb, | 1739 | struct ath_txq *txq, |
1617 | struct ath_tx_control *txctl) | 1740 | struct sk_buff *skb) |
1618 | { | 1741 | { |
1619 | struct ath_wiphy *aphy = hw->priv; | 1742 | struct ath_softc *sc = hw->priv; |
1620 | struct ath_softc *sc = aphy->sc; | 1743 | struct ath_hw *ah = sc->sc_ah; |
1621 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1744 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1622 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1745 | struct ath_frame_info *fi = get_frame_info(skb); |
1623 | int hdrlen; | 1746 | struct ath_buf *bf; |
1624 | __le16 fc; | 1747 | struct ath_desc *ds; |
1625 | int padpos, padsize; | 1748 | int frm_type; |
1626 | bool use_ldpc = false; | ||
1627 | |||
1628 | tx_info->pad[0] = 0; | ||
1629 | switch (txctl->frame_type) { | ||
1630 | case ATH9K_IFT_NOT_INTERNAL: | ||
1631 | break; | ||
1632 | case ATH9K_IFT_PAUSE: | ||
1633 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; | ||
1634 | /* fall through */ | ||
1635 | case ATH9K_IFT_UNPAUSE: | ||
1636 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; | ||
1637 | break; | ||
1638 | } | ||
1639 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
1640 | fc = hdr->frame_control; | ||
1641 | |||
1642 | ATH_TXBUF_RESET(bf); | ||
1643 | |||
1644 | bf->aphy = aphy; | ||
1645 | bf->bf_frmlen = skb->len + FCS_LEN; | ||
1646 | /* Remove the padding size from bf_frmlen, if any */ | ||
1647 | padpos = ath9k_cmn_padpos(hdr->frame_control); | ||
1648 | padsize = padpos & 3; | ||
1649 | if (padsize && skb->len>padpos+padsize) { | ||
1650 | bf->bf_frmlen -= padsize; | ||
1651 | } | ||
1652 | |||
1653 | if (!txctl->paprd && conf_is_ht(&hw->conf)) { | ||
1654 | bf->bf_state.bf_type |= BUF_HT; | ||
1655 | if (tx_info->flags & IEEE80211_TX_CTL_LDPC) | ||
1656 | use_ldpc = true; | ||
1657 | } | ||
1658 | |||
1659 | bf->bf_state.bfs_paprd = txctl->paprd; | ||
1660 | if (txctl->paprd) | ||
1661 | bf->bf_state.bfs_paprd_timestamp = jiffies; | ||
1662 | bf->bf_flags = setup_tx_flags(skb, use_ldpc); | ||
1663 | 1749 | ||
1664 | bf->bf_keytype = get_hw_crypto_keytype(skb); | 1750 | bf = ath_tx_get_buffer(sc); |
1665 | if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { | 1751 | if (!bf) { |
1666 | bf->bf_frmlen += tx_info->control.hw_key->icv_len; | 1752 | ath_dbg(common, ATH_DBG_XMIT, "TX buffers are full\n"); |
1667 | bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; | 1753 | return NULL; |
1668 | } else { | ||
1669 | bf->bf_keyix = ATH9K_TXKEYIX_INVALID; | ||
1670 | } | 1754 | } |
1671 | 1755 | ||
1672 | if (ieee80211_is_data_qos(fc) && bf_isht(bf) && | 1756 | ATH_TXBUF_RESET(bf); |
1673 | (sc->sc_flags & SC_OP_TXAGGR)) | ||
1674 | assign_aggr_tid_seqno(skb, bf); | ||
1675 | 1757 | ||
1758 | bf->bf_flags = setup_tx_flags(skb); | ||
1676 | bf->bf_mpdu = skb; | 1759 | bf->bf_mpdu = skb; |
1677 | 1760 | ||
1678 | bf->bf_dmacontext = dma_map_single(sc->dev, skb->data, | 1761 | bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, |
1679 | skb->len, DMA_TO_DEVICE); | 1762 | skb->len, DMA_TO_DEVICE); |
1680 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { | 1763 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { |
1681 | bf->bf_mpdu = NULL; | 1764 | bf->bf_mpdu = NULL; |
1682 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 1765 | bf->bf_buf_addr = 0; |
1683 | "dma_mapping_error() on TX\n"); | 1766 | ath_err(ath9k_hw_common(sc->sc_ah), |
1684 | return -ENOMEM; | 1767 | "dma_mapping_error() on TX\n"); |
1768 | ath_tx_return_buffer(sc, bf); | ||
1769 | return NULL; | ||
1685 | } | 1770 | } |
1686 | 1771 | ||
1687 | bf->bf_buf_addr = bf->bf_dmacontext; | ||
1688 | |||
1689 | /* tag if this is a nullfunc frame to enable PS when AP acks it */ | ||
1690 | if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) { | ||
1691 | bf->bf_isnullfunc = true; | ||
1692 | sc->ps_flags &= ~PS_NULLFUNC_COMPLETED; | ||
1693 | } else | ||
1694 | bf->bf_isnullfunc = false; | ||
1695 | |||
1696 | bf->bf_tx_aborted = false; | ||
1697 | |||
1698 | return 0; | ||
1699 | } | ||
1700 | |||
1701 | /* FIXME: tx power */ | ||
1702 | static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | ||
1703 | struct ath_tx_control *txctl) | ||
1704 | { | ||
1705 | struct sk_buff *skb = bf->bf_mpdu; | ||
1706 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1707 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1708 | struct ath_node *an = NULL; | ||
1709 | struct list_head bf_head; | ||
1710 | struct ath_desc *ds; | ||
1711 | struct ath_atx_tid *tid; | ||
1712 | struct ath_hw *ah = sc->sc_ah; | ||
1713 | int frm_type; | ||
1714 | __le16 fc; | ||
1715 | |||
1716 | frm_type = get_hw_packet_type(skb); | 1772 | frm_type = get_hw_packet_type(skb); |
1717 | fc = hdr->frame_control; | ||
1718 | |||
1719 | INIT_LIST_HEAD(&bf_head); | ||
1720 | list_add_tail(&bf->list, &bf_head); | ||
1721 | 1773 | ||
1722 | ds = bf->bf_desc; | 1774 | ds = bf->bf_desc; |
1723 | ath9k_hw_set_desc_link(ah, ds, 0); | 1775 | ath9k_hw_set_desc_link(ah, ds, 0); |
1724 | 1776 | ||
1725 | ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, | 1777 | ath9k_hw_set11n_txdesc(ah, ds, fi->framelen, frm_type, MAX_RATE_POWER, |
1726 | bf->bf_keyix, bf->bf_keytype, bf->bf_flags); | 1778 | fi->keyix, fi->keytype, bf->bf_flags); |
1727 | 1779 | ||
1728 | ath9k_hw_filltxdesc(ah, ds, | 1780 | ath9k_hw_filltxdesc(ah, ds, |
1729 | skb->len, /* segment length */ | 1781 | skb->len, /* segment length */ |
@@ -1731,109 +1783,83 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, | |||
1731 | true, /* last segment */ | 1783 | true, /* last segment */ |
1732 | ds, /* first descriptor */ | 1784 | ds, /* first descriptor */ |
1733 | bf->bf_buf_addr, | 1785 | bf->bf_buf_addr, |
1734 | txctl->txq->axq_qnum); | 1786 | txq->axq_qnum); |
1735 | |||
1736 | if (bf->bf_state.bfs_paprd) | ||
1737 | ar9003_hw_set_paprd_txdesc(ah, ds, bf->bf_state.bfs_paprd); | ||
1738 | |||
1739 | spin_lock_bh(&txctl->txq->axq_lock); | ||
1740 | |||
1741 | if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && | ||
1742 | tx_info->control.sta) { | ||
1743 | an = (struct ath_node *)tx_info->control.sta->drv_priv; | ||
1744 | tid = ATH_AN_2_TID(an, bf->bf_tidno); | ||
1745 | |||
1746 | if (!ieee80211_is_data_qos(fc)) { | ||
1747 | ath_tx_send_normal(sc, txctl->txq, &bf_head); | ||
1748 | goto tx_done; | ||
1749 | } | ||
1750 | 1787 | ||
1751 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { | ||
1752 | /* | ||
1753 | * Try aggregation if it's a unicast data frame | ||
1754 | * and the destination is HT capable. | ||
1755 | */ | ||
1756 | ath_tx_send_ampdu(sc, tid, &bf_head, txctl); | ||
1757 | } else { | ||
1758 | /* | ||
1759 | * Send this frame as regular when ADDBA | ||
1760 | * exchange is neither complete nor pending. | ||
1761 | */ | ||
1762 | ath_tx_send_ht_normal(sc, txctl->txq, | ||
1763 | tid, &bf_head); | ||
1764 | } | ||
1765 | } else { | ||
1766 | ath_tx_send_normal(sc, txctl->txq, &bf_head); | ||
1767 | } | ||
1768 | 1788 | ||
1769 | tx_done: | 1789 | return bf; |
1770 | spin_unlock_bh(&txctl->txq->axq_lock); | ||
1771 | } | 1790 | } |
1772 | 1791 | ||
1773 | /* Upon failure caller should free skb */ | 1792 | /* FIXME: tx power */ |
1774 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | 1793 | static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, |
1775 | struct ath_tx_control *txctl) | 1794 | struct ath_tx_control *txctl) |
1776 | { | 1795 | { |
1777 | struct ath_wiphy *aphy = hw->priv; | 1796 | struct sk_buff *skb = bf->bf_mpdu; |
1778 | struct ath_softc *sc = aphy->sc; | 1797 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1779 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1798 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1780 | struct ath_txq *txq = txctl->txq; | 1799 | struct list_head bf_head; |
1781 | struct ath_buf *bf; | 1800 | struct ath_atx_tid *tid = NULL; |
1782 | int q, r; | 1801 | u8 tidno; |
1783 | 1802 | ||
1784 | bf = ath_tx_get_buffer(sc); | 1803 | spin_lock_bh(&txctl->txq->axq_lock); |
1785 | if (!bf) { | 1804 | if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an && |
1786 | ath_print(common, ATH_DBG_XMIT, "TX buffers are full\n"); | 1805 | ieee80211_is_data_qos(hdr->frame_control)) { |
1787 | return -1; | 1806 | tidno = ieee80211_get_qos_ctl(hdr)[0] & |
1807 | IEEE80211_QOS_CTL_TID_MASK; | ||
1808 | tid = ATH_AN_2_TID(txctl->an, tidno); | ||
1809 | |||
1810 | WARN_ON(tid->ac->txq != txctl->txq); | ||
1788 | } | 1811 | } |
1789 | 1812 | ||
1790 | r = ath_tx_setup_buffer(hw, bf, skb, txctl); | 1813 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) { |
1791 | if (unlikely(r)) { | 1814 | /* |
1792 | ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n"); | 1815 | * Try aggregation if it's a unicast data frame |
1816 | * and the destination is HT capable. | ||
1817 | */ | ||
1818 | ath_tx_send_ampdu(sc, tid, bf, txctl); | ||
1819 | } else { | ||
1820 | INIT_LIST_HEAD(&bf_head); | ||
1821 | list_add_tail(&bf->list, &bf_head); | ||
1793 | 1822 | ||
1794 | /* upon ath_tx_processq() this TX queue will be resumed, we | 1823 | bf->bf_state.bfs_ftype = txctl->frame_type; |
1795 | * guarantee this will happen by knowing beforehand that | 1824 | bf->bf_state.bfs_paprd = txctl->paprd; |
1796 | * we will at least have to run TX completionon one buffer | ||
1797 | * on the queue */ | ||
1798 | spin_lock_bh(&txq->axq_lock); | ||
1799 | if (!txq->stopped && txq->axq_depth > 1) { | ||
1800 | ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); | ||
1801 | txq->stopped = 1; | ||
1802 | } | ||
1803 | spin_unlock_bh(&txq->axq_lock); | ||
1804 | 1825 | ||
1805 | ath_tx_return_buffer(sc, bf); | 1826 | if (bf->bf_state.bfs_paprd) |
1827 | ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc, | ||
1828 | bf->bf_state.bfs_paprd); | ||
1806 | 1829 | ||
1807 | return r; | 1830 | if (txctl->paprd) |
1808 | } | 1831 | bf->bf_state.bfs_paprd_timestamp = jiffies; |
1809 | 1832 | ||
1810 | q = skb_get_queue_mapping(skb); | 1833 | if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) |
1811 | if (q >= 4) | 1834 | ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); |
1812 | q = 0; | ||
1813 | 1835 | ||
1814 | spin_lock_bh(&txq->axq_lock); | 1836 | ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); |
1815 | if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) { | ||
1816 | ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb)); | ||
1817 | txq->stopped = 1; | ||
1818 | } | 1837 | } |
1819 | spin_unlock_bh(&txq->axq_lock); | ||
1820 | 1838 | ||
1821 | ath_tx_start_dma(sc, bf, txctl); | 1839 | spin_unlock_bh(&txctl->txq->axq_lock); |
1822 | |||
1823 | return 0; | ||
1824 | } | 1840 | } |
1825 | 1841 | ||
1826 | void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | 1842 | /* Upon failure caller should free skb */ |
1843 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | ||
1844 | struct ath_tx_control *txctl) | ||
1827 | { | 1845 | { |
1828 | struct ath_wiphy *aphy = hw->priv; | ||
1829 | struct ath_softc *sc = aphy->sc; | ||
1830 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1831 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1846 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1832 | int padpos, padsize; | ||
1833 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1847 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1834 | struct ath_tx_control txctl; | 1848 | struct ieee80211_sta *sta = info->control.sta; |
1849 | struct ieee80211_vif *vif = info->control.vif; | ||
1850 | struct ath_softc *sc = hw->priv; | ||
1851 | struct ath_txq *txq = txctl->txq; | ||
1852 | struct ath_buf *bf; | ||
1853 | int padpos, padsize; | ||
1854 | int frmlen = skb->len + FCS_LEN; | ||
1855 | int q; | ||
1835 | 1856 | ||
1836 | memset(&txctl, 0, sizeof(struct ath_tx_control)); | 1857 | /* NOTE: sta can be NULL according to net/mac80211.h */ |
1858 | if (sta) | ||
1859 | txctl->an = (struct ath_node *)sta->drv_priv; | ||
1860 | |||
1861 | if (info->control.hw_key) | ||
1862 | frmlen += info->control.hw_key->icv_len; | ||
1837 | 1863 | ||
1838 | /* | 1864 | /* |
1839 | * As a temporary workaround, assign seq# here; this will likely need | 1865 | * As a temporary workaround, assign seq# here; this will likely need |
@@ -1850,30 +1876,42 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1850 | /* Add the padding after the header if this is not already done */ | 1876 | /* Add the padding after the header if this is not already done */ |
1851 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 1877 | padpos = ath9k_cmn_padpos(hdr->frame_control); |
1852 | padsize = padpos & 3; | 1878 | padsize = padpos & 3; |
1853 | if (padsize && skb->len>padpos) { | 1879 | if (padsize && skb->len > padpos) { |
1854 | if (skb_headroom(skb) < padsize) { | 1880 | if (skb_headroom(skb) < padsize) |
1855 | ath_print(common, ATH_DBG_XMIT, | 1881 | return -ENOMEM; |
1856 | "TX CABQ padding failed\n"); | 1882 | |
1857 | dev_kfree_skb_any(skb); | ||
1858 | return; | ||
1859 | } | ||
1860 | skb_push(skb, padsize); | 1883 | skb_push(skb, padsize); |
1861 | memmove(skb->data, skb->data + padsize, padpos); | 1884 | memmove(skb->data, skb->data + padsize, padpos); |
1862 | } | 1885 | } |
1863 | 1886 | ||
1864 | txctl.txq = sc->beacon.cabq; | 1887 | if ((vif && vif->type != NL80211_IFTYPE_AP && |
1888 | vif->type != NL80211_IFTYPE_AP_VLAN) || | ||
1889 | !ieee80211_is_data(hdr->frame_control)) | ||
1890 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
1865 | 1891 | ||
1866 | ath_print(common, ATH_DBG_XMIT, | 1892 | setup_frame_info(hw, skb, frmlen); |
1867 | "transmitting CABQ packet, skb: %p\n", skb); | ||
1868 | 1893 | ||
1869 | if (ath_tx_start(hw, skb, &txctl) != 0) { | 1894 | /* |
1870 | ath_print(common, ATH_DBG_XMIT, "CABQ TX failed\n"); | 1895 | * At this point, the vif, hw_key and sta pointers in the tx control |
1871 | goto exit; | 1896 | * info are no longer valid (overwritten by the ath_frame_info data. |
1897 | */ | ||
1898 | |||
1899 | bf = ath_tx_setup_buffer(hw, txctl->txq, skb); | ||
1900 | if (unlikely(!bf)) | ||
1901 | return -ENOMEM; | ||
1902 | |||
1903 | q = skb_get_queue_mapping(skb); | ||
1904 | spin_lock_bh(&txq->axq_lock); | ||
1905 | if (txq == sc->tx.txq_map[q] && | ||
1906 | ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) { | ||
1907 | ieee80211_stop_queue(sc->hw, q); | ||
1908 | txq->stopped = 1; | ||
1872 | } | 1909 | } |
1910 | spin_unlock_bh(&txq->axq_lock); | ||
1911 | |||
1912 | ath_tx_start_dma(sc, bf, txctl); | ||
1873 | 1913 | ||
1874 | return; | 1914 | return 0; |
1875 | exit: | ||
1876 | dev_kfree_skb_any(skb); | ||
1877 | } | 1915 | } |
1878 | 1916 | ||
1879 | /*****************/ | 1917 | /*****************/ |
@@ -1881,7 +1919,7 @@ exit: | |||
1881 | /*****************/ | 1919 | /*****************/ |
1882 | 1920 | ||
1883 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | 1921 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |
1884 | struct ath_wiphy *aphy, int tx_flags) | 1922 | int tx_flags, int ftype, struct ath_txq *txq) |
1885 | { | 1923 | { |
1886 | struct ieee80211_hw *hw = sc->hw; | 1924 | struct ieee80211_hw *hw = sc->hw; |
1887 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1925 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
@@ -1889,10 +1927,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1889 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; | 1927 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; |
1890 | int q, padpos, padsize; | 1928 | int q, padpos, padsize; |
1891 | 1929 | ||
1892 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 1930 | ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
1893 | |||
1894 | if (aphy) | ||
1895 | hw = aphy->hw; | ||
1896 | 1931 | ||
1897 | if (tx_flags & ATH_TX_BAR) | 1932 | if (tx_flags & ATH_TX_BAR) |
1898 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 1933 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
@@ -1915,27 +1950,28 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1915 | 1950 | ||
1916 | if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { | 1951 | if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) { |
1917 | sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; | 1952 | sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; |
1918 | ath_print(common, ATH_DBG_PS, | 1953 | ath_dbg(common, ATH_DBG_PS, |
1919 | "Going back to sleep after having " | 1954 | "Going back to sleep after having received TX status (0x%lx)\n", |
1920 | "received TX status (0x%lx)\n", | ||
1921 | sc->ps_flags & (PS_WAIT_FOR_BEACON | | 1955 | sc->ps_flags & (PS_WAIT_FOR_BEACON | |
1922 | PS_WAIT_FOR_CAB | | 1956 | PS_WAIT_FOR_CAB | |
1923 | PS_WAIT_FOR_PSPOLL_DATA | | 1957 | PS_WAIT_FOR_PSPOLL_DATA | |
1924 | PS_WAIT_FOR_TX_ACK)); | 1958 | PS_WAIT_FOR_TX_ACK)); |
1925 | } | 1959 | } |
1926 | 1960 | ||
1927 | if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) | 1961 | q = skb_get_queue_mapping(skb); |
1928 | ath9k_tx_status(hw, skb); | 1962 | if (txq == sc->tx.txq_map[q]) { |
1929 | else { | 1963 | spin_lock_bh(&txq->axq_lock); |
1930 | q = skb_get_queue_mapping(skb); | 1964 | if (WARN_ON(--txq->pending_frames < 0)) |
1931 | if (q >= 4) | 1965 | txq->pending_frames = 0; |
1932 | q = 0; | ||
1933 | |||
1934 | if (--sc->tx.pending_frames[q] < 0) | ||
1935 | sc->tx.pending_frames[q] = 0; | ||
1936 | 1966 | ||
1937 | ieee80211_tx_status(hw, skb); | 1967 | if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) { |
1968 | ieee80211_wake_queue(sc->hw, q); | ||
1969 | txq->stopped = 0; | ||
1970 | } | ||
1971 | spin_unlock_bh(&txq->axq_lock); | ||
1938 | } | 1972 | } |
1973 | |||
1974 | ieee80211_tx_status(hw, skb); | ||
1939 | } | 1975 | } |
1940 | 1976 | ||
1941 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1977 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
@@ -1956,19 +1992,25 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1956 | tx_flags |= ATH_TX_XRETRY; | 1992 | tx_flags |= ATH_TX_XRETRY; |
1957 | } | 1993 | } |
1958 | 1994 | ||
1959 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); | 1995 | dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); |
1996 | bf->bf_buf_addr = 0; | ||
1960 | 1997 | ||
1961 | if (bf->bf_state.bfs_paprd) { | 1998 | if (bf->bf_state.bfs_paprd) { |
1962 | if (time_after(jiffies, | 1999 | if (time_after(jiffies, |
1963 | bf->bf_state.bfs_paprd_timestamp + | 2000 | bf->bf_state.bfs_paprd_timestamp + |
1964 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT))) | 2001 | msecs_to_jiffies(ATH_PAPRD_TIMEOUT))) |
1965 | dev_kfree_skb_any(skb); | 2002 | dev_kfree_skb_any(skb); |
1966 | else | 2003 | else |
1967 | complete(&sc->paprd_complete); | 2004 | complete(&sc->paprd_complete); |
1968 | } else { | 2005 | } else { |
1969 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); | 2006 | ath_debug_stat_tx(sc, bf, ts, txq); |
1970 | ath_debug_stat_tx(sc, txq, bf, ts); | 2007 | ath_tx_complete(sc, skb, tx_flags, |
2008 | bf->bf_state.bfs_ftype, txq); | ||
1971 | } | 2009 | } |
2010 | /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't | ||
2011 | * accidentally reference it later. | ||
2012 | */ | ||
2013 | bf->bf_mpdu = NULL; | ||
1972 | 2014 | ||
1973 | /* | 2015 | /* |
1974 | * Return the list of ath_buf of this mpdu to free queue | 2016 | * Return the list of ath_buf of this mpdu to free queue |
@@ -1978,42 +2020,15 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1978 | spin_unlock_irqrestore(&sc->tx.txbuflock, flags); | 2020 | spin_unlock_irqrestore(&sc->tx.txbuflock, flags); |
1979 | } | 2021 | } |
1980 | 2022 | ||
1981 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | 2023 | static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf, |
1982 | struct ath_tx_status *ts, int txok) | 2024 | struct ath_tx_status *ts, int nframes, int nbad, |
1983 | { | 2025 | int txok, bool update_rc) |
1984 | u16 seq_st = 0; | ||
1985 | u32 ba[WME_BA_BMP_SIZE >> 5]; | ||
1986 | int ba_index; | ||
1987 | int nbad = 0; | ||
1988 | int isaggr = 0; | ||
1989 | |||
1990 | if (bf->bf_lastbf->bf_tx_aborted) | ||
1991 | return 0; | ||
1992 | |||
1993 | isaggr = bf_isaggr(bf); | ||
1994 | if (isaggr) { | ||
1995 | seq_st = ts->ts_seqnum; | ||
1996 | memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3); | ||
1997 | } | ||
1998 | |||
1999 | while (bf) { | ||
2000 | ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); | ||
2001 | if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) | ||
2002 | nbad++; | ||
2003 | |||
2004 | bf = bf->bf_next; | ||
2005 | } | ||
2006 | |||
2007 | return nbad; | ||
2008 | } | ||
2009 | |||
2010 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | ||
2011 | int nbad, int txok, bool update_rc) | ||
2012 | { | 2026 | { |
2013 | struct sk_buff *skb = bf->bf_mpdu; | 2027 | struct sk_buff *skb = bf->bf_mpdu; |
2014 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 2028 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
2015 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 2029 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
2016 | struct ieee80211_hw *hw = bf->aphy->hw; | 2030 | struct ieee80211_hw *hw = sc->hw; |
2031 | struct ath_hw *ah = sc->sc_ah; | ||
2017 | u8 i, tx_rateindex; | 2032 | u8 i, tx_rateindex; |
2018 | 2033 | ||
2019 | if (txok) | 2034 | if (txok) |
@@ -2024,21 +2039,35 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | |||
2024 | 2039 | ||
2025 | if (ts->ts_status & ATH9K_TXERR_FILT) | 2040 | if (ts->ts_status & ATH9K_TXERR_FILT) |
2026 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 2041 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
2027 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) | 2042 | if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) { |
2028 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU; | 2043 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU; |
2029 | 2044 | ||
2045 | BUG_ON(nbad > nframes); | ||
2046 | |||
2047 | tx_info->status.ampdu_len = nframes; | ||
2048 | tx_info->status.ampdu_ack_len = nframes - nbad; | ||
2049 | } | ||
2050 | |||
2030 | if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && | 2051 | if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && |
2031 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { | 2052 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { |
2032 | if (ieee80211_is_data(hdr->frame_control)) { | 2053 | /* |
2033 | if (ts->ts_flags & | 2054 | * If an underrun error is seen assume it as an excessive |
2034 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) | 2055 | * retry only if max frame trigger level has been reached |
2035 | tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; | 2056 | * (2 KB for single stream, and 4 KB for dual stream). |
2036 | if ((ts->ts_status & ATH9K_TXERR_XRETRY) || | 2057 | * Adjust the long retry as if the frame was tried |
2037 | (ts->ts_status & ATH9K_TXERR_FIFO)) | 2058 | * hw->max_rate_tries times to affect how rate control updates |
2038 | tx_info->pad[0] |= ATH_TX_INFO_XRETRY; | 2059 | * PER for the failed rate. |
2039 | tx_info->status.ampdu_len = bf->bf_nframes; | 2060 | * In case of congestion on the bus penalizing this type of |
2040 | tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; | 2061 | * underruns should help hardware actually transmit new frames |
2041 | } | 2062 | * successfully by eventually preferring slower rates. |
2063 | * This itself should also alleviate congestion on the bus. | ||
2064 | */ | ||
2065 | if (ieee80211_is_data(hdr->frame_control) && | ||
2066 | (ts->ts_flags & (ATH9K_TX_DATA_UNDERRUN | | ||
2067 | ATH9K_TX_DELIM_UNDERRUN)) && | ||
2068 | ah->tx_trig_level >= sc->sc_ah->config.max_txtrig_level) | ||
2069 | tx_info->status.rates[tx_rateindex].count = | ||
2070 | hw->max_rate_tries; | ||
2042 | } | 2071 | } |
2043 | 2072 | ||
2044 | for (i = tx_rateindex + 1; i < hw->max_rates; i++) { | 2073 | for (i = tx_rateindex + 1; i < hw->max_rates; i++) { |
@@ -2049,22 +2078,6 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, | |||
2049 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; | 2078 | tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; |
2050 | } | 2079 | } |
2051 | 2080 | ||
2052 | static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) | ||
2053 | { | ||
2054 | int qnum; | ||
2055 | |||
2056 | qnum = ath_get_mac80211_qnum(txq->axq_class, sc); | ||
2057 | if (qnum == -1) | ||
2058 | return; | ||
2059 | |||
2060 | spin_lock_bh(&txq->axq_lock); | ||
2061 | if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) { | ||
2062 | if (ath_mac80211_start_queue(sc, qnum)) | ||
2063 | txq->stopped = 0; | ||
2064 | } | ||
2065 | spin_unlock_bh(&txq->axq_lock); | ||
2066 | } | ||
2067 | |||
2068 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | 2081 | static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) |
2069 | { | 2082 | { |
2070 | struct ath_hw *ah = sc->sc_ah; | 2083 | struct ath_hw *ah = sc->sc_ah; |
@@ -2076,14 +2089,16 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2076 | int txok; | 2089 | int txok; |
2077 | int status; | 2090 | int status; |
2078 | 2091 | ||
2079 | ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", | 2092 | ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", |
2080 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), | 2093 | txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), |
2081 | txq->axq_link); | 2094 | txq->axq_link); |
2082 | 2095 | ||
2083 | for (;;) { | 2096 | for (;;) { |
2084 | spin_lock_bh(&txq->axq_lock); | 2097 | spin_lock_bh(&txq->axq_lock); |
2085 | if (list_empty(&txq->axq_q)) { | 2098 | if (list_empty(&txq->axq_q)) { |
2086 | txq->axq_link = NULL; | 2099 | txq->axq_link = NULL; |
2100 | if (sc->sc_flags & SC_OP_TXAGGR) | ||
2101 | ath_txq_schedule(sc, txq); | ||
2087 | spin_unlock_bh(&txq->axq_lock); | 2102 | spin_unlock_bh(&txq->axq_lock); |
2088 | break; | 2103 | break; |
2089 | } | 2104 | } |
@@ -2118,18 +2133,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2118 | spin_unlock_bh(&txq->axq_lock); | 2133 | spin_unlock_bh(&txq->axq_lock); |
2119 | break; | 2134 | break; |
2120 | } | 2135 | } |
2121 | 2136 | TX_STAT_INC(txq->axq_qnum, txprocdesc); | |
2122 | /* | ||
2123 | * We now know the nullfunc frame has been ACKed so we | ||
2124 | * can disable RX. | ||
2125 | */ | ||
2126 | if (bf->bf_isnullfunc && | ||
2127 | (ts.ts_status & ATH9K_TX_ACKED)) { | ||
2128 | if ((sc->ps_flags & PS_ENABLED)) | ||
2129 | ath9k_enable_ps(sc); | ||
2130 | else | ||
2131 | sc->ps_flags |= PS_NULLFUNC_COMPLETED; | ||
2132 | } | ||
2133 | 2137 | ||
2134 | /* | 2138 | /* |
2135 | * Remove ath_buf's of the same transmit unit from txq, | 2139 | * Remove ath_buf's of the same transmit unit from txq, |
@@ -2147,6 +2151,10 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2147 | txq->axq_tx_inprogress = false; | 2151 | txq->axq_tx_inprogress = false; |
2148 | if (bf_held) | 2152 | if (bf_held) |
2149 | list_del(&bf_held->list); | 2153 | list_del(&bf_held->list); |
2154 | |||
2155 | if (bf_is_ampdu_not_probing(bf)) | ||
2156 | txq->axq_ampdu_depth--; | ||
2157 | |||
2150 | spin_unlock_bh(&txq->axq_lock); | 2158 | spin_unlock_bh(&txq->axq_lock); |
2151 | 2159 | ||
2152 | if (bf_held) | 2160 | if (bf_held) |
@@ -2159,17 +2167,17 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2159 | */ | 2167 | */ |
2160 | if (ts.ts_status & ATH9K_TXERR_XRETRY) | 2168 | if (ts.ts_status & ATH9K_TXERR_XRETRY) |
2161 | bf->bf_state.bf_type |= BUF_XRETRY; | 2169 | bf->bf_state.bf_type |= BUF_XRETRY; |
2162 | ath_tx_rc_status(bf, &ts, 0, txok, true); | 2170 | ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true); |
2163 | } | 2171 | } |
2164 | 2172 | ||
2165 | if (bf_isampdu(bf)) | 2173 | if (bf_isampdu(bf)) |
2166 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok); | 2174 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok, |
2175 | true); | ||
2167 | else | 2176 | else |
2168 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); | 2177 | ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); |
2169 | 2178 | ||
2170 | ath_wake_mac80211_queue(sc, txq); | ||
2171 | |||
2172 | spin_lock_bh(&txq->axq_lock); | 2179 | spin_lock_bh(&txq->axq_lock); |
2180 | |||
2173 | if (sc->sc_flags & SC_OP_TXAGGR) | 2181 | if (sc->sc_flags & SC_OP_TXAGGR) |
2174 | ath_txq_schedule(sc, txq); | 2182 | ath_txq_schedule(sc, txq); |
2175 | spin_unlock_bh(&txq->axq_lock); | 2183 | spin_unlock_bh(&txq->axq_lock); |
@@ -2183,6 +2191,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work) | |||
2183 | struct ath_txq *txq; | 2191 | struct ath_txq *txq; |
2184 | int i; | 2192 | int i; |
2185 | bool needreset = false; | 2193 | bool needreset = false; |
2194 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
2195 | sc->tx_complete_poll_work_seen++; | ||
2196 | #endif | ||
2186 | 2197 | ||
2187 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 2198 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) |
2188 | if (ATH_TXQ_SETUP(sc, i)) { | 2199 | if (ATH_TXQ_SETUP(sc, i)) { |
@@ -2201,11 +2212,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work) | |||
2201 | } | 2212 | } |
2202 | 2213 | ||
2203 | if (needreset) { | 2214 | if (needreset) { |
2204 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, | 2215 | ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, |
2205 | "tx hung, resetting the chip\n"); | 2216 | "tx hung, resetting the chip\n"); |
2206 | ath9k_ps_wakeup(sc); | 2217 | ath_reset(sc, true); |
2207 | ath_reset(sc, false); | ||
2208 | ath9k_ps_restore(sc); | ||
2209 | } | 2218 | } |
2210 | 2219 | ||
2211 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, | 2220 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, |
@@ -2243,8 +2252,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2243 | if (status == -EINPROGRESS) | 2252 | if (status == -EINPROGRESS) |
2244 | break; | 2253 | break; |
2245 | if (status == -EIO) { | 2254 | if (status == -EIO) { |
2246 | ath_print(common, ATH_DBG_XMIT, | 2255 | ath_dbg(common, ATH_DBG_XMIT, |
2247 | "Error processing tx status\n"); | 2256 | "Error processing tx status\n"); |
2248 | break; | 2257 | break; |
2249 | } | 2258 | } |
2250 | 2259 | ||
@@ -2270,45 +2279,38 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) | |||
2270 | INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); | 2279 | INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH); |
2271 | txq->axq_depth--; | 2280 | txq->axq_depth--; |
2272 | txq->axq_tx_inprogress = false; | 2281 | txq->axq_tx_inprogress = false; |
2282 | if (bf_is_ampdu_not_probing(bf)) | ||
2283 | txq->axq_ampdu_depth--; | ||
2273 | spin_unlock_bh(&txq->axq_lock); | 2284 | spin_unlock_bh(&txq->axq_lock); |
2274 | 2285 | ||
2275 | txok = !(txs.ts_status & ATH9K_TXERR_MASK); | 2286 | txok = !(txs.ts_status & ATH9K_TXERR_MASK); |
2276 | 2287 | ||
2277 | /* | ||
2278 | * Make sure null func frame is acked before configuring | ||
2279 | * hw into ps mode. | ||
2280 | */ | ||
2281 | if (bf->bf_isnullfunc && txok) { | ||
2282 | if ((sc->ps_flags & PS_ENABLED)) | ||
2283 | ath9k_enable_ps(sc); | ||
2284 | else | ||
2285 | sc->ps_flags |= PS_NULLFUNC_COMPLETED; | ||
2286 | } | ||
2287 | |||
2288 | if (!bf_isampdu(bf)) { | 2288 | if (!bf_isampdu(bf)) { |
2289 | if (txs.ts_status & ATH9K_TXERR_XRETRY) | 2289 | if (txs.ts_status & ATH9K_TXERR_XRETRY) |
2290 | bf->bf_state.bf_type |= BUF_XRETRY; | 2290 | bf->bf_state.bf_type |= BUF_XRETRY; |
2291 | ath_tx_rc_status(bf, &txs, 0, txok, true); | 2291 | ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true); |
2292 | } | 2292 | } |
2293 | 2293 | ||
2294 | if (bf_isampdu(bf)) | 2294 | if (bf_isampdu(bf)) |
2295 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok); | 2295 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, |
2296 | txok, true); | ||
2296 | else | 2297 | else |
2297 | ath_tx_complete_buf(sc, bf, txq, &bf_head, | 2298 | ath_tx_complete_buf(sc, bf, txq, &bf_head, |
2298 | &txs, txok, 0); | 2299 | &txs, txok, 0); |
2299 | 2300 | ||
2300 | ath_wake_mac80211_queue(sc, txq); | ||
2301 | |||
2302 | spin_lock_bh(&txq->axq_lock); | 2301 | spin_lock_bh(&txq->axq_lock); |
2302 | |||
2303 | if (!list_empty(&txq->txq_fifo_pending)) { | 2303 | if (!list_empty(&txq->txq_fifo_pending)) { |
2304 | INIT_LIST_HEAD(&bf_head); | 2304 | INIT_LIST_HEAD(&bf_head); |
2305 | bf = list_first_entry(&txq->txq_fifo_pending, | 2305 | bf = list_first_entry(&txq->txq_fifo_pending, |
2306 | struct ath_buf, list); | 2306 | struct ath_buf, list); |
2307 | list_cut_position(&bf_head, &txq->txq_fifo_pending, | 2307 | list_cut_position(&bf_head, |
2308 | &bf->bf_lastbf->list); | 2308 | &txq->txq_fifo_pending, |
2309 | &bf->bf_lastbf->list); | ||
2309 | ath_tx_txqaddbuf(sc, txq, &bf_head); | 2310 | ath_tx_txqaddbuf(sc, txq, &bf_head); |
2310 | } else if (sc->sc_flags & SC_OP_TXAGGR) | 2311 | } else if (sc->sc_flags & SC_OP_TXAGGR) |
2311 | ath_txq_schedule(sc, txq); | 2312 | ath_txq_schedule(sc, txq); |
2313 | |||
2312 | spin_unlock_bh(&txq->axq_lock); | 2314 | spin_unlock_bh(&txq->axq_lock); |
2313 | } | 2315 | } |
2314 | } | 2316 | } |
@@ -2362,16 +2364,16 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) | |||
2362 | error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, | 2364 | error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, |
2363 | "tx", nbufs, 1, 1); | 2365 | "tx", nbufs, 1, 1); |
2364 | if (error != 0) { | 2366 | if (error != 0) { |
2365 | ath_print(common, ATH_DBG_FATAL, | 2367 | ath_err(common, |
2366 | "Failed to allocate tx descriptors: %d\n", error); | 2368 | "Failed to allocate tx descriptors: %d\n", error); |
2367 | goto err; | 2369 | goto err; |
2368 | } | 2370 | } |
2369 | 2371 | ||
2370 | error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, | 2372 | error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, |
2371 | "beacon", ATH_BCBUF, 1, 1); | 2373 | "beacon", ATH_BCBUF, 1, 1); |
2372 | if (error != 0) { | 2374 | if (error != 0) { |
2373 | ath_print(common, ATH_DBG_FATAL, | 2375 | ath_err(common, |
2374 | "Failed to allocate beacon descriptors: %d\n", error); | 2376 | "Failed to allocate beacon descriptors: %d\n", error); |
2375 | goto err; | 2377 | goto err; |
2376 | } | 2378 | } |
2377 | 2379 | ||
@@ -2429,7 +2431,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) | |||
2429 | for (acno = 0, ac = &an->ac[acno]; | 2431 | for (acno = 0, ac = &an->ac[acno]; |
2430 | acno < WME_NUM_AC; acno++, ac++) { | 2432 | acno < WME_NUM_AC; acno++, ac++) { |
2431 | ac->sched = false; | 2433 | ac->sched = false; |
2432 | ac->qnum = sc->tx.hwq_map[acno]; | 2434 | ac->txq = sc->tx.txq_map[acno]; |
2433 | INIT_LIST_HEAD(&ac->tid_q); | 2435 | INIT_LIST_HEAD(&ac->tid_q); |
2434 | } | 2436 | } |
2435 | } | 2437 | } |
@@ -2439,17 +2441,13 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) | |||
2439 | struct ath_atx_ac *ac; | 2441 | struct ath_atx_ac *ac; |
2440 | struct ath_atx_tid *tid; | 2442 | struct ath_atx_tid *tid; |
2441 | struct ath_txq *txq; | 2443 | struct ath_txq *txq; |
2442 | int i, tidno; | 2444 | int tidno; |
2443 | 2445 | ||
2444 | for (tidno = 0, tid = &an->tid[tidno]; | 2446 | for (tidno = 0, tid = &an->tid[tidno]; |
2445 | tidno < WME_NUM_TID; tidno++, tid++) { | 2447 | tidno < WME_NUM_TID; tidno++, tid++) { |
2446 | i = tid->ac->qnum; | ||
2447 | 2448 | ||
2448 | if (!ATH_TXQ_SETUP(sc, i)) | ||
2449 | continue; | ||
2450 | |||
2451 | txq = &sc->tx.txq[i]; | ||
2452 | ac = tid->ac; | 2449 | ac = tid->ac; |
2450 | txq = ac->txq; | ||
2453 | 2451 | ||
2454 | spin_lock_bh(&txq->axq_lock); | 2452 | spin_lock_bh(&txq->axq_lock); |
2455 | 2453 | ||