aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vasanth@atheros.com>2009-08-26 11:38:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-28 14:40:51 -0400
commit1773912bd25196c2a3ca6c174574561363f43b2b (patch)
tree9e48b824bb5800f90c59bfa2a9a4d6437f230e2f
parentff155a45cea56ad7a90c3f5192db59a4c7812fde (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.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c290
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.h61
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c34
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h49
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c9
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
527struct ath_bus_ops { 528struct 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);
708void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); 709void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val);
709unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); 710unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset);
710 711
712int 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
19void ath9k_hw_btcoex_init(struct ath_hw *ah) 19static 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 */
26static 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 */
51static 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
83static 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
118static 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
136static 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
187int 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
40void ath9k_hw_btcoex_enable(struct ath_hw *ah) 235void 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 */
289void 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 */
304void 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
23enum ath_btcoex_scheme { 30enum 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
36enum 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
43enum 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
50struct 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
29struct ath_btcoex_info { 62struct 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
35void ath9k_hw_btcoex_init(struct ath_hw *ah); 82int ath9k_hw_btcoex_init(struct ath_hw *ah);
36void ath9k_hw_btcoex_enable(struct ath_hw *ah); 83void ath9k_hw_btcoex_enable(struct ath_hw *ah);
37void ath9k_hw_btcoex_disable(struct ath_hw *ah); 84void ath9k_hw_btcoex_disable(struct ath_hw *ah);
85void ath_btcoex_timer_resume(struct ath_softc *sc,
86 struct ath_btcoex_info *btinfo);
87void ath_btcoex_timer_pause(struct ath_softc *sc,
88 struct ath_btcoex_info *btinfo);
89
90static 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
4144static u32 ath9k_hw_gettsf32(struct ath_hw *ah) 4144u32 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,
662void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); 663void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
663void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); 664void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
664void ath_gen_timer_isr(struct ath_hw *hw); 665void ath_gen_timer_isr(struct ath_hw *hw);
666u32 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
605chip_reset: 609chip_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;
1516bad2: 1527bad2:
@@ -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
1999mutex_unlock: 2016mutex_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
875static int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) 880int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
876{ 881{
877 int qnum; 882 int qnum;
878 883