diff options
author | Vasanthakumar Thiagarajan <vasanth@atheros.com> | 2009-08-26 11:38:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-28 14:40:51 -0400 |
commit | 1773912bd25196c2a3ca6c174574561363f43b2b (patch) | |
tree | 9e48b824bb5800f90c59bfa2a9a4d6437f230e2f | |
parent | ff155a45cea56ad7a90c3f5192db59a4c7812fde (diff) |
ath9k: Add Bluetooth Coexistence 3-wire support
This patch adds 3-wire bluetooth coex support for AR9285.
This support can be enabled through btcoex_enable modparam.
Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/btcoex.c | 290 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/btcoex.h | 61 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 34 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/reg.h | 49 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 9 |
9 files changed, 423 insertions, 27 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 83f2c8fa8879..1c68a9da22d4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -523,6 +523,7 @@ struct ath_led { | |||
523 | #define SC_OP_WAIT_FOR_TX_ACK BIT(18) | 523 | #define SC_OP_WAIT_FOR_TX_ACK BIT(18) |
524 | #define SC_OP_BEACON_SYNC BIT(19) | 524 | #define SC_OP_BEACON_SYNC BIT(19) |
525 | #define SC_OP_BTCOEX_ENABLED BIT(20) | 525 | #define SC_OP_BTCOEX_ENABLED BIT(20) |
526 | #define SC_OP_BT_PRIORITY_DETECTED BIT(21) | ||
526 | 527 | ||
527 | struct ath_bus_ops { | 528 | struct ath_bus_ops { |
528 | void (*read_cachesize)(struct ath_softc *sc, int *csz); | 529 | void (*read_cachesize)(struct ath_softc *sc, int *csz); |
@@ -708,4 +709,5 @@ bool ath9k_all_wiphys_idle(struct ath_softc *sc); | |||
708 | void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); | 709 | void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); |
709 | unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); | 710 | unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); |
710 | 711 | ||
712 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); | ||
711 | #endif /* ATH9K_H */ | 713 | #endif /* ATH9K_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 9f19cd1c1bef..8fb356748823 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -16,34 +16,251 @@ | |||
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "ath9k.h" |
18 | 18 | ||
19 | void ath9k_hw_btcoex_init(struct ath_hw *ah) | 19 | static const struct ath_btcoex_config ath_bt_config = { 0, true, true, |
20 | ATH_BT_COEX_MODE_SLOTTED, true, true, 2, 5, true }; | ||
21 | |||
22 | |||
23 | /* | ||
24 | * Detects if there is any priority bt traffic | ||
25 | */ | ||
26 | static void ath_detect_bt_priority(struct ath_softc *sc) | ||
27 | { | ||
28 | struct ath_btcoex_info *btinfo = &sc->btcoex_info; | ||
29 | |||
30 | if (ath9k_hw_gpio_get(sc->sc_ah, btinfo->btpriority_gpio)) | ||
31 | btinfo->bt_priority_cnt++; | ||
32 | |||
33 | if (time_after(jiffies, btinfo->bt_priority_time + | ||
34 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { | ||
35 | if (btinfo->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | ||
36 | DPRINTF(sc, ATH_DBG_BTCOEX, | ||
37 | "BT priority traffic detected"); | ||
38 | sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; | ||
39 | } else { | ||
40 | sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; | ||
41 | } | ||
42 | |||
43 | btinfo->bt_priority_cnt = 0; | ||
44 | btinfo->bt_priority_time = jiffies; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * Configures appropriate weight based on stomp type. | ||
50 | */ | ||
51 | static void ath_btcoex_bt_stomp(struct ath_softc *sc, | ||
52 | struct ath_btcoex_info *btinfo, | ||
53 | int stomp_type) | ||
54 | { | ||
55 | |||
56 | switch (stomp_type) { | ||
57 | case ATH_BTCOEX_STOMP_ALL: | ||
58 | ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, | ||
59 | AR_STOMP_ALL_WLAN_WGHT); | ||
60 | break; | ||
61 | case ATH_BTCOEX_STOMP_LOW: | ||
62 | ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, | ||
63 | AR_STOMP_LOW_WLAN_WGHT); | ||
64 | break; | ||
65 | case ATH_BTCOEX_STOMP_NONE: | ||
66 | ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, | ||
67 | AR_STOMP_NONE_WLAN_WGHT); | ||
68 | break; | ||
69 | default: | ||
70 | DPRINTF(sc, ATH_DBG_BTCOEX, "Invalid Stomptype\n"); | ||
71 | break; | ||
72 | } | ||
73 | |||
74 | ath9k_hw_btcoex_enable(sc->sc_ah); | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * This is the master bt coex timer which runs for every | ||
79 | * 45ms, bt traffic will be given priority during 55% of this | ||
80 | * period while wlan gets remaining 45% | ||
81 | */ | ||
82 | |||
83 | static void ath_btcoex_period_timer(unsigned long data) | ||
84 | { | ||
85 | struct ath_softc *sc = (struct ath_softc *) data; | ||
86 | struct ath_btcoex_info *btinfo = &sc->btcoex_info; | ||
87 | unsigned long flags; | ||
88 | |||
89 | ath_detect_bt_priority(sc); | ||
90 | |||
91 | spin_lock_irqsave(&btinfo->btcoex_lock, flags); | ||
92 | |||
93 | ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type); | ||
94 | |||
95 | spin_unlock_irqrestore(&btinfo->btcoex_lock, flags); | ||
96 | |||
97 | if (btinfo->btcoex_period != btinfo->btcoex_no_stomp) { | ||
98 | if (btinfo->hw_timer_enabled) | ||
99 | ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); | ||
100 | |||
101 | ath_gen_timer_start(sc->sc_ah, | ||
102 | btinfo->no_stomp_timer, | ||
103 | (ath9k_hw_gettsf32(sc->sc_ah) + | ||
104 | btinfo->btcoex_no_stomp), | ||
105 | btinfo->btcoex_no_stomp * 10); | ||
106 | btinfo->hw_timer_enabled = true; | ||
107 | } | ||
108 | |||
109 | mod_timer(&btinfo->period_timer, jiffies + | ||
110 | msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Generic tsf based hw timer which configures weight | ||
115 | * registers to time slice between wlan and bt traffic | ||
116 | */ | ||
117 | |||
118 | static void ath_btcoex_no_stomp_timer(void *arg) | ||
119 | { | ||
120 | struct ath_softc *sc = (struct ath_softc *)arg; | ||
121 | struct ath_btcoex_info *btinfo = &sc->btcoex_info; | ||
122 | unsigned long flags; | ||
123 | |||
124 | DPRINTF(sc, ATH_DBG_BTCOEX, "no stomp timer running \n"); | ||
125 | |||
126 | spin_lock_irqsave(&btinfo->btcoex_lock, flags); | ||
127 | |||
128 | if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) | ||
129 | ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE); | ||
130 | else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | ||
131 | ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW); | ||
132 | |||
133 | spin_unlock_irqrestore(&btinfo->btcoex_lock, flags); | ||
134 | } | ||
135 | |||
136 | static int ath_init_btcoex_info(struct ath_hw *hw, | ||
137 | struct ath_btcoex_info *btcoex_info) | ||
138 | { | ||
139 | u32 i; | ||
140 | int qnum; | ||
141 | |||
142 | qnum = ath_tx_get_qnum(hw->ah_sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); | ||
143 | |||
144 | btcoex_info->bt_coex_mode = | ||
145 | (btcoex_info->bt_coex_mode & AR_BT_QCU_THRESH) | | ||
146 | SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) | | ||
147 | SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | | ||
148 | SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | | ||
149 | SM(ath_bt_config.bt_mode, AR_BT_MODE) | | ||
150 | SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | | ||
151 | SM(ath_bt_config.bt_rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | | ||
152 | SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | | ||
153 | SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | | ||
154 | SM(qnum, AR_BT_QCU_THRESH); | ||
155 | |||
156 | btcoex_info->bt_coex_mode2 = | ||
157 | SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | | ||
158 | SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | | ||
159 | AR_BT_DISABLE_BT_ANT; | ||
160 | |||
161 | btcoex_info->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
162 | |||
163 | btcoex_info->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; | ||
164 | |||
165 | btcoex_info->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * | ||
166 | btcoex_info->btcoex_period / 100; | ||
167 | |||
168 | for (i = 0; i < 32; i++) | ||
169 | hw->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; | ||
170 | |||
171 | setup_timer(&btcoex_info->period_timer, ath_btcoex_period_timer, | ||
172 | (unsigned long) hw->ah_sc); | ||
173 | |||
174 | btcoex_info->no_stomp_timer = ath_gen_timer_alloc(hw, | ||
175 | ath_btcoex_no_stomp_timer, | ||
176 | ath_btcoex_no_stomp_timer, | ||
177 | (void *)hw->ah_sc, AR_FIRST_NDP_TIMER); | ||
178 | |||
179 | if (btcoex_info->no_stomp_timer == NULL) | ||
180 | return -ENOMEM; | ||
181 | |||
182 | spin_lock_init(&btcoex_info->btcoex_lock); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | int ath9k_hw_btcoex_init(struct ath_hw *ah) | ||
20 | { | 188 | { |
21 | struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; | 189 | struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; |
190 | int ret = 0; | ||
191 | |||
192 | if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) { | ||
193 | /* connect bt_active to baseband */ | ||
194 | REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
195 | (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | | ||
196 | AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); | ||
197 | |||
198 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
199 | AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); | ||
200 | |||
201 | /* Set input mux for bt_active to gpio pin */ | ||
202 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, | ||
203 | AR_GPIO_INPUT_MUX1_BT_ACTIVE, | ||
204 | btcoex_info->btactive_gpio); | ||
22 | 205 | ||
23 | /* connect bt_active to baseband */ | 206 | /* Configure the desired gpio port for input */ |
24 | REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, | 207 | ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); |
25 | (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | | 208 | } else { |
26 | AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); | 209 | /* btcoex 3-wire */ |
210 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
211 | (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB | | ||
212 | AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB)); | ||
27 | 213 | ||
28 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | 214 | /* Set input mux for bt_prority_async and |
29 | AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); | 215 | * bt_active_async to GPIO pins */ |
216 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, | ||
217 | AR_GPIO_INPUT_MUX1_BT_ACTIVE, | ||
218 | btcoex_info->btactive_gpio); | ||
30 | 219 | ||
31 | /* Set input mux for bt_active to gpio pin */ | 220 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, |
32 | REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, | 221 | AR_GPIO_INPUT_MUX1_BT_PRIORITY, |
33 | AR_GPIO_INPUT_MUX1_BT_ACTIVE, | 222 | btcoex_info->btpriority_gpio); |
34 | btcoex_info->btactive_gpio); | ||
35 | 223 | ||
36 | /* Configure the desired gpio port for input */ | 224 | /* Configure the desired GPIO ports for input */ |
37 | ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); | 225 | |
226 | ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); | ||
227 | ath9k_hw_cfg_gpio_input(ah, btcoex_info->btpriority_gpio); | ||
228 | |||
229 | ret = ath_init_btcoex_info(ah, btcoex_info); | ||
230 | } | ||
231 | |||
232 | return ret; | ||
38 | } | 233 | } |
39 | 234 | ||
40 | void ath9k_hw_btcoex_enable(struct ath_hw *ah) | 235 | void ath9k_hw_btcoex_enable(struct ath_hw *ah) |
41 | { | 236 | { |
42 | struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; | 237 | struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; |
43 | 238 | ||
44 | /* Configure the desired GPIO port for TX_FRAME output */ | 239 | if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) { |
45 | ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, | 240 | /* Configure the desired GPIO port for TX_FRAME output */ |
46 | AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); | 241 | ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, |
242 | AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); | ||
243 | } else { | ||
244 | /* | ||
245 | * Program coex mode and weight registers to | ||
246 | * enable coex 3-wire | ||
247 | */ | ||
248 | REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_info->bt_coex_mode); | ||
249 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_info->bt_coex_weights); | ||
250 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_info->bt_coex_mode2); | ||
251 | |||
252 | REG_RMW_FIELD(ah, AR_QUIET1, | ||
253 | AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); | ||
254 | REG_RMW_FIELD(ah, AR_PCU_MISC, | ||
255 | AR_PCU_BT_ANT_PREVENT_RX, 0); | ||
256 | |||
257 | ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, | ||
258 | AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL); | ||
259 | } | ||
260 | |||
261 | REG_RMW(ah, AR_GPIO_PDPU, | ||
262 | (0x2 << (btcoex_info->btactive_gpio * 2)), | ||
263 | (0x3 << (btcoex_info->btactive_gpio * 2))); | ||
47 | 264 | ||
48 | ah->ah_sc->sc_flags |= SC_OP_BTCOEX_ENABLED; | 265 | ah->ah_sc->sc_flags |= SC_OP_BTCOEX_ENABLED; |
49 | } | 266 | } |
@@ -57,5 +274,46 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) | |||
57 | ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, | 274 | ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, |
58 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 275 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
59 | 276 | ||
277 | if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) { | ||
278 | REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); | ||
279 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); | ||
280 | REG_WRITE(ah, AR_BT_COEX_MODE2, 0); | ||
281 | } | ||
282 | |||
60 | ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED; | 283 | ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED; |
61 | } | 284 | } |
285 | |||
286 | /* | ||
287 | * Pause btcoex timer and bt duty cycle timer | ||
288 | */ | ||
289 | void ath_btcoex_timer_pause(struct ath_softc *sc, | ||
290 | struct ath_btcoex_info *btinfo) | ||
291 | { | ||
292 | |||
293 | del_timer_sync(&btinfo->period_timer); | ||
294 | |||
295 | if (btinfo->hw_timer_enabled) | ||
296 | ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); | ||
297 | |||
298 | btinfo->hw_timer_enabled = false; | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * (Re)start btcoex timers | ||
303 | */ | ||
304 | void ath_btcoex_timer_resume(struct ath_softc *sc, | ||
305 | struct ath_btcoex_info *btinfo) | ||
306 | { | ||
307 | |||
308 | DPRINTF(sc, ATH_DBG_BTCOEX, "Starting btcoex timers"); | ||
309 | |||
310 | /* make sure duty cycle timer is also stopped when resuming */ | ||
311 | if (btinfo->hw_timer_enabled) | ||
312 | ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); | ||
313 | |||
314 | btinfo->bt_priority_cnt = 0; | ||
315 | btinfo->bt_priority_time = jiffies; | ||
316 | sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; | ||
317 | |||
318 | mod_timer(&btinfo->period_timer, jiffies); | ||
319 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index cdfa80d0eb4d..45568196c59a 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h | |||
@@ -20,20 +20,79 @@ | |||
20 | #define ATH_WLANACTIVE_GPIO 5 | 20 | #define ATH_WLANACTIVE_GPIO 5 |
21 | #define ATH_BTACTIVE_GPIO 6 | 21 | #define ATH_BTACTIVE_GPIO 6 |
22 | 22 | ||
23 | #define ATH_BTCOEX_DEF_BT_PERIOD 45 | ||
24 | #define ATH_BTCOEX_DEF_DUTY_CYCLE 55 | ||
25 | #define ATH_BTCOEX_BMISS_THRESH 50 | ||
26 | |||
27 | #define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */ | ||
28 | #define ATH_BT_CNT_THRESHOLD 3 | ||
29 | |||
23 | enum ath_btcoex_scheme { | 30 | enum ath_btcoex_scheme { |
24 | ATH_BTCOEX_CFG_NONE, | 31 | ATH_BTCOEX_CFG_NONE, |
25 | ATH_BTCOEX_CFG_2WIRE, | 32 | ATH_BTCOEX_CFG_2WIRE, |
26 | ATH_BTCOEX_CFG_3WIRE, | 33 | ATH_BTCOEX_CFG_3WIRE, |
27 | }; | 34 | }; |
28 | 35 | ||
36 | enum ath_stomp_type { | ||
37 | ATH_BTCOEX_NO_STOMP, | ||
38 | ATH_BTCOEX_STOMP_ALL, | ||
39 | ATH_BTCOEX_STOMP_LOW, | ||
40 | ATH_BTCOEX_STOMP_NONE | ||
41 | }; | ||
42 | |||
43 | enum ath_bt_mode { | ||
44 | ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */ | ||
45 | ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */ | ||
46 | ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */ | ||
47 | ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */ | ||
48 | }; | ||
49 | |||
50 | struct ath_btcoex_config { | ||
51 | u8 bt_time_extend; | ||
52 | bool bt_txstate_extend; | ||
53 | bool bt_txframe_extend; | ||
54 | enum ath_bt_mode bt_mode; /* coexistence mode */ | ||
55 | bool bt_quiet_collision; | ||
56 | bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/ | ||
57 | u8 bt_priority_time; | ||
58 | u8 bt_first_slot_time; | ||
59 | bool bt_hold_rx_clear; | ||
60 | }; | ||
61 | |||
29 | struct ath_btcoex_info { | 62 | struct ath_btcoex_info { |
30 | enum ath_btcoex_scheme btcoex_scheme; | 63 | enum ath_btcoex_scheme btcoex_scheme; |
31 | u8 wlanactive_gpio; | 64 | u8 wlanactive_gpio; |
32 | u8 btactive_gpio; | 65 | u8 btactive_gpio; |
66 | u8 btpriority_gpio; | ||
67 | u8 bt_duty_cycle; /* BT duty cycle in percentage */ | ||
68 | int bt_stomp_type; /* Types of BT stomping */ | ||
69 | u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */ | ||
70 | u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */ | ||
71 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ | ||
72 | u32 btcoex_no_stomp; /* in usec */ | ||
73 | u32 btcoex_period; /* in usec */ | ||
74 | u32 bt_priority_cnt; | ||
75 | unsigned long bt_priority_time; | ||
76 | bool hw_timer_enabled; | ||
77 | spinlock_t btcoex_lock; | ||
78 | struct timer_list period_timer; /* Timer for BT period */ | ||
79 | struct ath_gen_timer *no_stomp_timer; /*Timer for no BT stomping*/ | ||
33 | }; | 80 | }; |
34 | 81 | ||
35 | void ath9k_hw_btcoex_init(struct ath_hw *ah); | 82 | int ath9k_hw_btcoex_init(struct ath_hw *ah); |
36 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); | 83 | void ath9k_hw_btcoex_enable(struct ath_hw *ah); |
37 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); | 84 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); |
85 | void ath_btcoex_timer_resume(struct ath_softc *sc, | ||
86 | struct ath_btcoex_info *btinfo); | ||
87 | void ath_btcoex_timer_pause(struct ath_softc *sc, | ||
88 | struct ath_btcoex_info *btinfo); | ||
89 | |||
90 | static inline void ath_btcoex_set_weight(struct ath_btcoex_info *btcoex_info, | ||
91 | u32 bt_weight, | ||
92 | u32 wlan_weight) | ||
93 | { | ||
94 | btcoex_info->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) | | ||
95 | SM(wlan_weight, AR_BTCOEX_WL_WGHT); | ||
96 | } | ||
38 | 97 | ||
39 | #endif | 98 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index ea0dd1ec15c3..7241f4748338 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -31,6 +31,7 @@ enum ATH_DEBUG { | |||
31 | ATH_DBG_FATAL = 0x00000400, | 31 | ATH_DBG_FATAL = 0x00000400, |
32 | ATH_DBG_PS = 0x00000800, | 32 | ATH_DBG_PS = 0x00000800, |
33 | ATH_DBG_HWTIMER = 0x00001000, | 33 | ATH_DBG_HWTIMER = 0x00001000, |
34 | ATH_DBG_BTCOEX = 0x00002000, | ||
34 | ATH_DBG_ANY = 0xffffffff | 35 | ATH_DBG_ANY = 0xffffffff |
35 | }; | 36 | }; |
36 | 37 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 3afd7a9fc8a3..e340dacc6ebe 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -4141,7 +4141,7 @@ static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask) | |||
4141 | return timer_table->gen_timer_index[b]; | 4141 | return timer_table->gen_timer_index[b]; |
4142 | } | 4142 | } |
4143 | 4143 | ||
4144 | static u32 ath9k_hw_gettsf32(struct ath_hw *ah) | 4144 | u32 ath9k_hw_gettsf32(struct ath_hw *ah) |
4145 | { | 4145 | { |
4146 | return REG_READ(ah, AR_TSF_L32); | 4146 | return REG_READ(ah, AR_TSF_L32); |
4147 | } | 4147 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 052a9c4ebb92..5ca6ffa70912 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -79,6 +79,7 @@ | |||
79 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 | 79 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 |
80 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 | 80 | #define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 |
81 | #define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3 | 81 | #define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3 |
82 | #define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4 | ||
82 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 | 83 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 |
83 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 | 84 | #define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 |
84 | 85 | ||
@@ -662,5 +663,6 @@ void ath_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, | |||
662 | void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); | 663 | void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); |
663 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); | 664 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); |
664 | void ath_gen_timer_isr(struct ath_hw *hw); | 665 | void ath_gen_timer_isr(struct ath_hw *hw); |
666 | u32 ath9k_hw_gettsf32(struct ath_hw *ah); | ||
665 | 667 | ||
666 | #endif | 668 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 215c67251f79..4fae699a53c2 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -602,6 +602,10 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
602 | sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; | 602 | sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; |
603 | } | 603 | } |
604 | 604 | ||
605 | if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) | ||
606 | if (status & ATH9K_INT_GENTIMER) | ||
607 | ath_gen_timer_isr(ah); | ||
608 | |||
605 | chip_reset: | 609 | chip_reset: |
606 | 610 | ||
607 | ath_debug_stat_interrupt(sc, status); | 611 | ath_debug_stat_interrupt(sc, status); |
@@ -1279,6 +1283,10 @@ void ath_detach(struct ath_softc *sc) | |||
1279 | if (ATH_TXQ_SETUP(sc, i)) | 1283 | if (ATH_TXQ_SETUP(sc, i)) |
1280 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); | 1284 | ath_tx_cleanupq(sc, &sc->tx.txq[i]); |
1281 | 1285 | ||
1286 | if ((sc->btcoex_info.no_stomp_timer) && | ||
1287 | sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) | ||
1288 | ath_gen_timer_free(sc->sc_ah, sc->btcoex_info.no_stomp_timer); | ||
1289 | |||
1282 | ath9k_hw_detach(sc->sc_ah); | 1290 | ath9k_hw_detach(sc->sc_ah); |
1283 | sc->sc_ah = NULL; | 1291 | sc->sc_ah = NULL; |
1284 | ath9k_exit_debug(sc); | 1292 | ath9k_exit_debug(sc); |
@@ -1509,8 +1517,11 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc) | |||
1509 | ARRAY_SIZE(ath9k_5ghz_chantable); | 1517 | ARRAY_SIZE(ath9k_5ghz_chantable); |
1510 | } | 1518 | } |
1511 | 1519 | ||
1512 | if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) | 1520 | if (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) { |
1513 | ath9k_hw_btcoex_init(ah); | 1521 | r = ath9k_hw_btcoex_init(ah); |
1522 | if (r) | ||
1523 | goto bad2; | ||
1524 | } | ||
1514 | 1525 | ||
1515 | return 0; | 1526 | return 0; |
1516 | bad2: | 1527 | bad2: |
@@ -1992,10 +2003,16 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1992 | 2003 | ||
1993 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 2004 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
1994 | 2005 | ||
1995 | if ((sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) && | 2006 | if ((sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) && |
1996 | !(sc->sc_flags & SC_OP_BTCOEX_ENABLED)) | 2007 | !(sc->sc_flags & SC_OP_BTCOEX_ENABLED)) { |
2008 | ath_btcoex_set_weight(&sc->btcoex_info, AR_BT_COEX_WGHT, | ||
2009 | AR_STOMP_LOW_WLAN_WGHT); | ||
1997 | ath9k_hw_btcoex_enable(sc->sc_ah); | 2010 | ath9k_hw_btcoex_enable(sc->sc_ah); |
1998 | 2011 | ||
2012 | if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) | ||
2013 | ath_btcoex_timer_resume(sc, &sc->btcoex_info); | ||
2014 | } | ||
2015 | |||
1999 | mutex_unlock: | 2016 | mutex_unlock: |
2000 | mutex_unlock(&sc->mutex); | 2017 | mutex_unlock(&sc->mutex); |
2001 | 2018 | ||
@@ -2129,6 +2146,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2129 | return; /* another wiphy still in use */ | 2146 | return; /* another wiphy still in use */ |
2130 | } | 2147 | } |
2131 | 2148 | ||
2149 | if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) { | ||
2150 | ath9k_hw_btcoex_disable(sc->sc_ah); | ||
2151 | if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) | ||
2152 | ath_btcoex_timer_pause(sc, &sc->btcoex_info); | ||
2153 | } | ||
2154 | |||
2132 | /* make sure h/w will not generate any interrupt | 2155 | /* make sure h/w will not generate any interrupt |
2133 | * before setting the invalid flag. */ | 2156 | * before setting the invalid flag. */ |
2134 | ath9k_hw_set_interrupts(sc->sc_ah, 0); | 2157 | ath9k_hw_set_interrupts(sc->sc_ah, 0); |
@@ -2142,9 +2165,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2142 | 2165 | ||
2143 | wiphy_rfkill_stop_polling(sc->hw->wiphy); | 2166 | wiphy_rfkill_stop_polling(sc->hw->wiphy); |
2144 | 2167 | ||
2145 | if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) | ||
2146 | ath9k_hw_btcoex_disable(sc->sc_ah); | ||
2147 | |||
2148 | /* disable HAL and put h/w to sleep */ | 2168 | /* disable HAL and put h/w to sleep */ |
2149 | ath9k_hw_disable(sc->sc_ah); | 2169 | ath9k_hw_disable(sc->sc_ah); |
2150 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); | 2170 | ath9k_hw_configpcipowersave(sc->sc_ah, 1); |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 1d8e0a8b587c..3ddb243f0000 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -970,6 +970,8 @@ enum { | |||
970 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 | 970 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 |
971 | #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 | 971 | #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 |
972 | #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 | 972 | #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 |
973 | #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00001000 | ||
974 | #define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 1 | ||
973 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 | 975 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 |
974 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 | 976 | #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 |
975 | #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 | 977 | #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 |
@@ -978,6 +980,8 @@ enum { | |||
978 | #define AR_GPIO_INPUT_MUX1 0x4058 | 980 | #define AR_GPIO_INPUT_MUX1 0x4058 |
979 | #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 | 981 | #define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 |
980 | #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 | 982 | #define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 |
983 | #define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 | ||
984 | #define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 | ||
981 | 985 | ||
982 | #define AR_GPIO_INPUT_MUX2 0x405c | 986 | #define AR_GPIO_INPUT_MUX2 0x405c |
983 | #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f | 987 | #define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f |
@@ -1003,6 +1007,8 @@ enum { | |||
1003 | 1007 | ||
1004 | #define AR_OBS 0x4080 | 1008 | #define AR_OBS 0x4080 |
1005 | 1009 | ||
1010 | #define AR_GPIO_PDPU 0x4088 | ||
1011 | |||
1006 | #define AR_PCIE_MSI 0x4094 | 1012 | #define AR_PCIE_MSI 0x4094 |
1007 | #define AR_PCIE_MSI_ENABLE 0x00000001 | 1013 | #define AR_PCIE_MSI_ENABLE 0x00000001 |
1008 | 1014 | ||
@@ -1436,6 +1442,7 @@ enum { | |||
1436 | #define AR_QUIET1_NEXT_QUIET_M 0x0000ffff | 1442 | #define AR_QUIET1_NEXT_QUIET_M 0x0000ffff |
1437 | #define AR_QUIET1_QUIET_ENABLE 0x00010000 | 1443 | #define AR_QUIET1_QUIET_ENABLE 0x00010000 |
1438 | #define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000 | 1444 | #define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000 |
1445 | #define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17 | ||
1439 | #define AR_QUIET2 0x8100 | 1446 | #define AR_QUIET2 0x8100 |
1440 | #define AR_QUIET2_QUIET_PERIOD_S 0 | 1447 | #define AR_QUIET2_QUIET_PERIOD_S 0 |
1441 | #define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff | 1448 | #define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff |
@@ -1481,6 +1488,8 @@ enum { | |||
1481 | #define AR_PCU_CLEAR_VMF 0x01000000 | 1488 | #define AR_PCU_CLEAR_VMF 0x01000000 |
1482 | #define AR_PCU_CLEAR_BA_VALID 0x04000000 | 1489 | #define AR_PCU_CLEAR_BA_VALID 0x04000000 |
1483 | 1490 | ||
1491 | #define AR_PCU_BT_ANT_PREVENT_RX 0x00100000 | ||
1492 | #define AR_PCU_BT_ANT_PREVENT_RX_S 20 | ||
1484 | 1493 | ||
1485 | #define AR_FILT_OFDM 0x8124 | 1494 | #define AR_FILT_OFDM 0x8124 |
1486 | #define AR_FILT_OFDM_COUNT 0x00FFFFFF | 1495 | #define AR_FILT_OFDM_COUNT 0x00FFFFFF |
@@ -1508,6 +1517,46 @@ enum { | |||
1508 | #define AR_PHY_ERR_3_COUNT 0x00FFFFFF | 1517 | #define AR_PHY_ERR_3_COUNT 0x00FFFFFF |
1509 | #define AR_PHY_ERR_MASK_3 0x816c | 1518 | #define AR_PHY_ERR_MASK_3 0x816c |
1510 | 1519 | ||
1520 | #define AR_BT_COEX_MODE 0x8170 | ||
1521 | #define AR_BT_TIME_EXTEND 0x000000ff | ||
1522 | #define AR_BT_TIME_EXTEND_S 0 | ||
1523 | #define AR_BT_TXSTATE_EXTEND 0x00000100 | ||
1524 | #define AR_BT_TXSTATE_EXTEND_S 8 | ||
1525 | #define AR_BT_TX_FRAME_EXTEND 0x00000200 | ||
1526 | #define AR_BT_TX_FRAME_EXTEND_S 9 | ||
1527 | #define AR_BT_MODE 0x00000c00 | ||
1528 | #define AR_BT_MODE_S 10 | ||
1529 | #define AR_BT_QUIET 0x00001000 | ||
1530 | #define AR_BT_QUIET_S 12 | ||
1531 | #define AR_BT_QCU_THRESH 0x0001e000 | ||
1532 | #define AR_BT_QCU_THRESH_S 13 | ||
1533 | #define AR_BT_RX_CLEAR_POLARITY 0x00020000 | ||
1534 | #define AR_BT_RX_CLEAR_POLARITY_S 17 | ||
1535 | #define AR_BT_PRIORITY_TIME 0x00fc0000 | ||
1536 | #define AR_BT_PRIORITY_TIME_S 18 | ||
1537 | #define AR_BT_FIRST_SLOT_TIME 0xff000000 | ||
1538 | #define AR_BT_FIRST_SLOT_TIME_S 24 | ||
1539 | |||
1540 | #define AR_BT_COEX_WEIGHT 0x8174 | ||
1541 | #define AR_BT_COEX_WGHT 0xff55 | ||
1542 | #define AR_STOMP_ALL_WLAN_WGHT 0xffcc | ||
1543 | #define AR_STOMP_LOW_WLAN_WGHT 0xaaa8 | ||
1544 | #define AR_STOMP_NONE_WLAN_WGHT 0xaa00 | ||
1545 | #define AR_BTCOEX_BT_WGHT 0x0000ffff | ||
1546 | #define AR_BTCOEX_BT_WGHT_S 0 | ||
1547 | #define AR_BTCOEX_WL_WGHT 0xffff0000 | ||
1548 | #define AR_BTCOEX_WL_WGHT_S 16 | ||
1549 | |||
1550 | #define AR_BT_COEX_MODE2 0x817c | ||
1551 | #define AR_BT_BCN_MISS_THRESH 0x000000ff | ||
1552 | #define AR_BT_BCN_MISS_THRESH_S 0 | ||
1553 | #define AR_BT_BCN_MISS_CNT 0x0000ff00 | ||
1554 | #define AR_BT_BCN_MISS_CNT_S 8 | ||
1555 | #define AR_BT_HOLD_RX_CLEAR 0x00010000 | ||
1556 | #define AR_BT_HOLD_RX_CLEAR_S 16 | ||
1557 | #define AR_BT_DISABLE_BT_ANT 0x00100000 | ||
1558 | #define AR_BT_DISABLE_BT_ANT_S 20 | ||
1559 | |||
1511 | #define AR_TXSIFS 0x81d0 | 1560 | #define AR_TXSIFS 0x81d0 |
1512 | #define AR_TXSIFS_TIME 0x000000FF | 1561 | #define AR_TXSIFS_TIME 0x000000FF |
1513 | #define AR_TXSIFS_TX_LATENCY 0x00000F00 | 1562 | #define AR_TXSIFS_TX_LATENCY 0x00000F00 |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 87762da0383b..42551a48c8ac 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -493,7 +493,12 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
493 | if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) | 493 | if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) |
494 | return 0; | 494 | return 0; |
495 | 495 | ||
496 | aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_MAX); | 496 | if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED) |
497 | aggr_limit = min((max_4ms_framelen * 3) / 8, | ||
498 | (u32)ATH_AMPDU_LIMIT_MAX); | ||
499 | else | ||
500 | aggr_limit = min(max_4ms_framelen, | ||
501 | (u32)ATH_AMPDU_LIMIT_MAX); | ||
497 | 502 | ||
498 | /* | 503 | /* |
499 | * h/w can accept aggregates upto 16 bit lengths (65535). | 504 | * h/w can accept aggregates upto 16 bit lengths (65535). |
@@ -872,7 +877,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
872 | return &sc->tx.txq[qnum]; | 877 | return &sc->tx.txq[qnum]; |
873 | } | 878 | } |
874 | 879 | ||
875 | static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) | 880 | int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) |
876 | { | 881 | { |
877 | int qnum; | 882 | int qnum; |
878 | 883 | ||