aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.c214
-rw-r--r--drivers/net/wireless/ath/ath9k/btcoex.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c215
5 files changed, 218 insertions, 222 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index e8a630ccfd96..f001cc262660 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -458,6 +458,7 @@ struct ath_btcoex {
458 unsigned long bt_priority_time; 458 unsigned long bt_priority_time;
459 u32 btcoex_no_stomp; /* in usec */ 459 u32 btcoex_no_stomp; /* in usec */
460 u32 btcoex_period; /* in usec */ 460 u32 btcoex_period; /* in usec */
461 struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
461}; 462};
462 463
463/********************/ 464/********************/
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c
index be699241ca75..6209a56f7a9a 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.c
+++ b/drivers/net/wireless/ath/ath9k/btcoex.c
@@ -43,144 +43,10 @@ bool ath_btcoex_supported(u16 subsysid)
43 return false; 43 return false;
44} 44}
45 45
46static void ath_btcoex_set_weight(struct ath_btcoex_info *btcoex_info, 46void ath9k_hw_init_btcoex_hw_info(struct ath_hw *ah, int qnum)
47 u32 bt_weight,
48 u32 wlan_weight)
49{ 47{
50 btcoex_info->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) | 48 struct ath_btcoex_info *btcoex_info = &ah->btcoex_info;
51 SM(wlan_weight, AR_BTCOEX_WL_WGHT);
52}
53
54void ath9k_hw_btcoex_init_weight(struct ath_hw *ah)
55{
56 ath_btcoex_set_weight(&ah->btcoex_info, AR_BT_COEX_WGHT,
57 AR_STOMP_LOW_WLAN_WGHT);
58}
59
60/*
61 * Detects if there is any priority bt traffic
62 */
63static void ath_detect_bt_priority(struct ath_softc *sc)
64{
65 struct ath_btcoex *btcoex = &sc->btcoex;
66 struct ath_hw *ah = sc->sc_ah;
67
68 if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_info.btpriority_gpio))
69 btcoex->bt_priority_cnt++;
70
71 if (time_after(jiffies, btcoex->bt_priority_time +
72 msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
73 if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
74 DPRINTF(sc->sc_ah, ATH_DBG_BTCOEX,
75 "BT priority traffic detected");
76 sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
77 } else {
78 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
79 }
80
81 btcoex->bt_priority_cnt = 0;
82 btcoex->bt_priority_time = jiffies;
83 }
84}
85
86/*
87 * Configures appropriate weight based on stomp type.
88 */
89static void ath_btcoex_bt_stomp(struct ath_softc *sc,
90 struct ath_btcoex_info *btinfo,
91 int stomp_type)
92{
93
94 switch (stomp_type) {
95 case ATH_BTCOEX_STOMP_ALL:
96 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
97 AR_STOMP_ALL_WLAN_WGHT);
98 break;
99 case ATH_BTCOEX_STOMP_LOW:
100 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
101 AR_STOMP_LOW_WLAN_WGHT);
102 break;
103 case ATH_BTCOEX_STOMP_NONE:
104 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
105 AR_STOMP_NONE_WLAN_WGHT);
106 break;
107 default:
108 DPRINTF(sc->sc_ah, ATH_DBG_BTCOEX, "Invalid Stomptype\n");
109 break;
110 }
111
112 ath9k_hw_btcoex_enable(sc->sc_ah);
113}
114
115/*
116 * This is the master bt coex timer which runs for every
117 * 45ms, bt traffic will be given priority during 55% of this
118 * period while wlan gets remaining 45%
119 */
120
121static void ath_btcoex_period_timer(unsigned long data)
122{
123 struct ath_softc *sc = (struct ath_softc *) data;
124 struct ath_hw *ah = sc->sc_ah;
125 struct ath_btcoex *btcoex = &sc->btcoex;
126 struct ath_btcoex_info *btinfo = &ah->btcoex_info;
127
128 ath_detect_bt_priority(sc);
129
130 spin_lock_bh(&btcoex->btcoex_lock);
131
132 ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type);
133
134 spin_unlock_bh(&btcoex->btcoex_lock);
135
136 if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
137 if (btcoex->hw_timer_enabled)
138 ath_gen_timer_stop(ah, btinfo->no_stomp_timer);
139
140 ath_gen_timer_start(ah,
141 btinfo->no_stomp_timer,
142 (ath9k_hw_gettsf32(sc->sc_ah) +
143 btcoex->btcoex_no_stomp),
144 btcoex->btcoex_no_stomp * 10);
145 btcoex->hw_timer_enabled = true;
146 }
147
148 mod_timer(&btcoex->period_timer, jiffies +
149 msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
150}
151
152/*
153 * Generic tsf based hw timer which configures weight
154 * registers to time slice between wlan and bt traffic
155 */
156
157static void ath_btcoex_no_stomp_timer(void *arg)
158{
159 struct ath_softc *sc = (struct ath_softc *)arg;
160 struct ath_hw *ah = sc->sc_ah;
161 struct ath_btcoex *btcoex = &sc->btcoex;
162 struct ath_btcoex_info *btinfo = &ah->btcoex_info;
163
164 DPRINTF(ah, ATH_DBG_BTCOEX, "no stomp timer running \n");
165
166 spin_lock_bh(&btcoex->btcoex_lock);
167
168 if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW)
169 ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE);
170 else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
171 ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW);
172
173 spin_unlock_bh(&btcoex->btcoex_lock);
174}
175
176static int ath_init_btcoex_info(struct ath_hw *ah,
177 struct ath_btcoex_info *btcoex_info)
178{
179 struct ath_btcoex *btcoex = &ah->ah_sc->btcoex;
180 u32 i; 49 u32 i;
181 int qnum;
182
183 qnum = ath_tx_get_qnum(ah->ah_sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
184 50
185 btcoex_info->bt_coex_mode = 51 btcoex_info->bt_coex_mode =
186 (btcoex_info->bt_coex_mode & AR_BT_QCU_THRESH) | 52 (btcoex_info->bt_coex_mode & AR_BT_QCU_THRESH) |
@@ -201,31 +67,11 @@ static int ath_init_btcoex_info(struct ath_hw *ah,
201 67
202 btcoex_info->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; 68 btcoex_info->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
203 69
204 btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
205
206 btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
207 btcoex->btcoex_period / 100;
208
209 for (i = 0; i < 32; i++) 70 for (i = 0; i < 32; i++)
210 ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; 71 ah->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i;
211
212 setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
213 (unsigned long) ah->ah_sc);
214
215 btcoex_info->no_stomp_timer = ath_gen_timer_alloc(ah,
216 ath_btcoex_no_stomp_timer,
217 ath_btcoex_no_stomp_timer,
218 (void *)ah->ah_sc, AR_FIRST_NDP_TIMER);
219
220 if (btcoex_info->no_stomp_timer == NULL)
221 return -ENOMEM;
222
223 spin_lock_init(&btcoex->btcoex_lock);
224
225 return 0;
226} 72}
227 73
228static void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah) 74void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
229{ 75{
230 struct ath_btcoex_info *btcoex_info = &ah->btcoex_info; 76 struct ath_btcoex_info *btcoex_info = &ah->btcoex_info;
231 77
@@ -246,7 +92,7 @@ static void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
246 ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); 92 ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio);
247} 93}
248 94
249static void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah) 95void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
250{ 96{
251 struct ath_btcoex_info *btcoex_info = &ah->btcoex_info; 97 struct ath_btcoex_info *btcoex_info = &ah->btcoex_info;
252 98
@@ -271,21 +117,6 @@ static void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
271 ath9k_hw_cfg_gpio_input(ah, btcoex_info->btpriority_gpio); 117 ath9k_hw_cfg_gpio_input(ah, btcoex_info->btpriority_gpio);
272} 118}
273 119
274int ath9k_hw_btcoex_init(struct ath_hw *ah)
275{
276 struct ath_btcoex_info *btcoex_info = &ah->btcoex_info;
277 int ret = 0;
278
279 if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE)
280 ath9k_hw_btcoex_init_2wire(ah);
281 else {
282 ath9k_hw_btcoex_init_3wire(ah);
283 ret = ath_init_btcoex_info(ah, btcoex_info);
284 }
285
286 return ret;
287}
288
289void ath9k_hw_btcoex_enable(struct ath_hw *ah) 120void ath9k_hw_btcoex_enable(struct ath_hw *ah)
290{ 121{
291 struct ath_btcoex_info *btcoex_info = &ah->btcoex_info; 122 struct ath_btcoex_info *btcoex_info = &ah->btcoex_info;
@@ -336,40 +167,3 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah)
336 167
337 ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED; 168 ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED;
338} 169}
339
340/*
341 * Pause btcoex timer and bt duty cycle timer
342 */
343void ath_btcoex_timer_pause(struct ath_softc *sc)
344{
345 struct ath_btcoex *btcoex = &sc->btcoex;
346 struct ath_hw *ah = sc->sc_ah;
347
348 del_timer_sync(&btcoex->period_timer);
349
350 if (btcoex->hw_timer_enabled)
351 ath_gen_timer_stop(ah, ah->btcoex_info.no_stomp_timer);
352
353 btcoex->hw_timer_enabled = false;
354}
355
356/*
357 * (Re)start btcoex timers
358 */
359void ath_btcoex_timer_resume(struct ath_softc *sc)
360{
361 struct ath_btcoex *btcoex = &sc->btcoex;
362 struct ath_hw *ah = sc->sc_ah;
363
364 DPRINTF(ah, ATH_DBG_BTCOEX, "Starting btcoex timers");
365
366 /* make sure duty cycle timer is also stopped when resuming */
367 if (btcoex->hw_timer_enabled)
368 ath_gen_timer_stop(sc->sc_ah, ah->btcoex_info.no_stomp_timer);
369
370 btcoex->bt_priority_cnt = 0;
371 btcoex->bt_priority_time = jiffies;
372 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
373
374 mod_timer(&btcoex->period_timer, jiffies);
375}
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h
index 12e86b70d950..ed8d01d2f762 100644
--- a/drivers/net/wireless/ath/ath9k/btcoex.h
+++ b/drivers/net/wireless/ath/ath9k/btcoex.h
@@ -72,13 +72,14 @@ struct ath_btcoex_info {
72 u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */ 72 u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */
73 u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */ 73 u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */
74 u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ 74 u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
75 struct ath_gen_timer *no_stomp_timer; /*Timer for no BT stomping*/
76}; 75};
77 76
78bool ath_btcoex_supported(u16 subsysid); 77bool ath_btcoex_supported(u16 subsysid);
79void ath9k_hw_btcoex_init_weight(struct ath_hw *ah); 78void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah);
80int ath9k_hw_btcoex_init(struct ath_hw *ah); 79void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah);
80void ath9k_hw_init_btcoex_hw_info(struct ath_hw *ah, int qnum);
81void ath9k_hw_btcoex_enable(struct ath_hw *ah); 81void ath9k_hw_btcoex_enable(struct ath_hw *ah);
82void ath9k_hw_btcoex_disable(struct ath_hw *ah); 82void ath9k_hw_btcoex_disable(struct ath_hw *ah);
83 83
84
84#endif 85#endif
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index f2b3a601d6a9..b244225ca050 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -679,7 +679,4 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah);
679#define ATH_PCIE_CAP_LINK_L1 2 679#define ATH_PCIE_CAP_LINK_L1 2
680 680
681void ath_pcie_aspm_disable(struct ath_softc *sc); 681void ath_pcie_aspm_disable(struct ath_softc *sc);
682
683void ath_btcoex_timer_resume(struct ath_softc *sc);
684void ath_btcoex_timer_pause(struct ath_softc *sc);
685#endif 682#endif
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 63e1f183b470..9ac1ee0638f0 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1286,9 +1286,9 @@ void ath_detach(struct ath_softc *sc)
1286 if (ATH_TXQ_SETUP(sc, i)) 1286 if (ATH_TXQ_SETUP(sc, i))
1287 ath_tx_cleanupq(sc, &sc->tx.txq[i]); 1287 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
1288 1288
1289 if ((ah->btcoex_info.no_stomp_timer) && 1289 if ((sc->btcoex.no_stomp_timer) &&
1290 ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) 1290 ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
1291 ath_gen_timer_free(ah, ah->btcoex_info.no_stomp_timer); 1291 ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer);
1292 1292
1293 ath9k_hw_detach(ah); 1293 ath9k_hw_detach(ah);
1294 ath9k_exit_debug(ah); 1294 ath9k_exit_debug(ah);
@@ -1307,6 +1307,158 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
1307} 1307}
1308 1308
1309/* 1309/*
1310 * Detects if there is any priority bt traffic
1311 */
1312static void ath_detect_bt_priority(struct ath_softc *sc)
1313{
1314 struct ath_btcoex *btcoex = &sc->btcoex;
1315 struct ath_hw *ah = sc->sc_ah;
1316
1317 if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_info.btpriority_gpio))
1318 btcoex->bt_priority_cnt++;
1319
1320 if (time_after(jiffies, btcoex->bt_priority_time +
1321 msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
1322 if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
1323 DPRINTF(sc->sc_ah, ATH_DBG_BTCOEX,
1324 "BT priority traffic detected");
1325 sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
1326 } else {
1327 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
1328 }
1329
1330 btcoex->bt_priority_cnt = 0;
1331 btcoex->bt_priority_time = jiffies;
1332 }
1333}
1334
1335static void ath_btcoex_set_weight(struct ath_btcoex_info *btcoex_info,
1336 u32 bt_weight,
1337 u32 wlan_weight)
1338{
1339 btcoex_info->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
1340 SM(wlan_weight, AR_BTCOEX_WL_WGHT);
1341}
1342
1343static void ath9k_hw_btcoex_init_weight(struct ath_hw *ah)
1344{
1345 ath_btcoex_set_weight(&ah->btcoex_info, AR_BT_COEX_WGHT,
1346 AR_STOMP_LOW_WLAN_WGHT);
1347}
1348
1349/*
1350 * Configures appropriate weight based on stomp type.
1351 */
1352static void ath_btcoex_bt_stomp(struct ath_softc *sc,
1353 struct ath_btcoex_info *btinfo,
1354 int stomp_type)
1355{
1356
1357 switch (stomp_type) {
1358 case ATH_BTCOEX_STOMP_ALL:
1359 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
1360 AR_STOMP_ALL_WLAN_WGHT);
1361 break;
1362 case ATH_BTCOEX_STOMP_LOW:
1363 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
1364 AR_STOMP_LOW_WLAN_WGHT);
1365 break;
1366 case ATH_BTCOEX_STOMP_NONE:
1367 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
1368 AR_STOMP_NONE_WLAN_WGHT);
1369 break;
1370 default:
1371 DPRINTF(sc->sc_ah, ATH_DBG_BTCOEX, "Invalid Stomptype\n");
1372 break;
1373 }
1374
1375 ath9k_hw_btcoex_enable(sc->sc_ah);
1376}
1377
1378/*
1379 * This is the master bt coex timer which runs for every
1380 * 45ms, bt traffic will be given priority during 55% of this
1381 * period while wlan gets remaining 45%
1382 */
1383static void ath_btcoex_period_timer(unsigned long data)
1384{
1385 struct ath_softc *sc = (struct ath_softc *) data;
1386 struct ath_hw *ah = sc->sc_ah;
1387 struct ath_btcoex *btcoex = &sc->btcoex;
1388 struct ath_btcoex_info *btinfo = &ah->btcoex_info;
1389
1390 ath_detect_bt_priority(sc);
1391
1392 spin_lock_bh(&btcoex->btcoex_lock);
1393
1394 ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type);
1395
1396 spin_unlock_bh(&btcoex->btcoex_lock);
1397
1398 if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
1399 if (btcoex->hw_timer_enabled)
1400 ath_gen_timer_stop(ah, btcoex->no_stomp_timer);
1401
1402 ath_gen_timer_start(ah,
1403 btcoex->no_stomp_timer,
1404 (ath9k_hw_gettsf32(ah) +
1405 btcoex->btcoex_no_stomp),
1406 btcoex->btcoex_no_stomp * 10);
1407 btcoex->hw_timer_enabled = true;
1408 }
1409
1410 mod_timer(&btcoex->period_timer, jiffies +
1411 msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
1412}
1413
1414/*
1415 * Generic tsf based hw timer which configures weight
1416 * registers to time slice between wlan and bt traffic
1417 */
1418static void ath_btcoex_no_stomp_timer(void *arg)
1419{
1420 struct ath_softc *sc = (struct ath_softc *)arg;
1421 struct ath_hw *ah = sc->sc_ah;
1422 struct ath_btcoex *btcoex = &sc->btcoex;
1423 struct ath_btcoex_info *btinfo = &ah->btcoex_info;
1424
1425 DPRINTF(ah, ATH_DBG_BTCOEX, "no stomp timer running \n");
1426
1427 spin_lock_bh(&btcoex->btcoex_lock);
1428
1429 if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW)
1430 ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE);
1431 else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
1432 ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW);
1433
1434 spin_unlock_bh(&btcoex->btcoex_lock);
1435}
1436
1437static int ath_init_btcoex_timer(struct ath_softc *sc)
1438{
1439 struct ath_btcoex *btcoex = &sc->btcoex;
1440
1441 btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
1442 btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
1443 btcoex->btcoex_period / 100;
1444
1445 setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
1446 (unsigned long) sc);
1447
1448 spin_lock_init(&btcoex->btcoex_lock);
1449
1450 btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah,
1451 ath_btcoex_no_stomp_timer,
1452 ath_btcoex_no_stomp_timer,
1453 (void *) sc, AR_FIRST_NDP_TIMER);
1454
1455 if (!btcoex->no_stomp_timer)
1456 return -ENOMEM;
1457
1458 return 0;
1459}
1460
1461/*
1310 * Initialize and fill ath_softc, ath_sofct is the 1462 * Initialize and fill ath_softc, ath_sofct is the
1311 * "Software Carrier" struct. Historically it has existed 1463 * "Software Carrier" struct. Historically it has existed
1312 * to allow the separation between hardware specific 1464 * to allow the separation between hardware specific
@@ -1317,6 +1469,7 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid)
1317 struct ath_hw *ah = NULL; 1469 struct ath_hw *ah = NULL;
1318 int r = 0, i; 1470 int r = 0, i;
1319 int csz = 0; 1471 int csz = 0;
1472 int qnum;
1320 1473
1321 /* XXX: hardware will not be ready until ath_open() being called */ 1474 /* XXX: hardware will not be ready until ath_open() being called */
1322 sc->sc_flags |= SC_OP_INVALID; 1475 sc->sc_flags |= SC_OP_INVALID;
@@ -1521,10 +1674,23 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid)
1521 ARRAY_SIZE(ath9k_5ghz_chantable); 1674 ARRAY_SIZE(ath9k_5ghz_chantable);
1522 } 1675 }
1523 1676
1524 if (ah->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) { 1677 switch (ah->btcoex_info.btcoex_scheme) {
1525 r = ath9k_hw_btcoex_init(ah); 1678 case ATH_BTCOEX_CFG_NONE:
1679 break;
1680 case ATH_BTCOEX_CFG_2WIRE:
1681 ath9k_hw_btcoex_init_2wire(ah);
1682 break;
1683 case ATH_BTCOEX_CFG_3WIRE:
1684 ath9k_hw_btcoex_init_3wire(ah);
1685 r = ath_init_btcoex_timer(sc);
1526 if (r) 1686 if (r)
1527 goto bad2; 1687 goto bad2;
1688 qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
1689 ath9k_hw_init_btcoex_hw_info(ah, qnum);
1690 break;
1691 default:
1692 WARN_ON(1);
1693 break;
1528 } 1694 }
1529 1695
1530 return 0; 1696 return 0;
@@ -1906,6 +2072,27 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
1906/* mac80211 callbacks */ 2072/* mac80211 callbacks */
1907/**********************/ 2073/**********************/
1908 2074
2075/*
2076 * (Re)start btcoex timers
2077 */
2078static void ath9k_btcoex_timer_resume(struct ath_softc *sc)
2079{
2080 struct ath_btcoex *btcoex = &sc->btcoex;
2081 struct ath_hw *ah = sc->sc_ah;
2082
2083 DPRINTF(ah, ATH_DBG_BTCOEX, "Starting btcoex timers");
2084
2085 /* make sure duty cycle timer is also stopped when resuming */
2086 if (btcoex->hw_timer_enabled)
2087 ath_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
2088
2089 btcoex->bt_priority_cnt = 0;
2090 btcoex->bt_priority_time = jiffies;
2091 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
2092
2093 mod_timer(&btcoex->period_timer, jiffies);
2094}
2095
1909static int ath9k_start(struct ieee80211_hw *hw) 2096static int ath9k_start(struct ieee80211_hw *hw)
1910{ 2097{
1911 struct ath_wiphy *aphy = hw->priv; 2098 struct ath_wiphy *aphy = hw->priv;
@@ -2018,7 +2205,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
2018 2205
2019 ath_pcie_aspm_disable(sc); 2206 ath_pcie_aspm_disable(sc);
2020 if (ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) 2207 if (ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
2021 ath_btcoex_timer_resume(sc); 2208 ath9k_btcoex_timer_resume(sc);
2022 } 2209 }
2023 2210
2024mutex_unlock: 2211mutex_unlock:
@@ -2126,6 +2313,22 @@ exit:
2126 return 0; 2313 return 0;
2127} 2314}
2128 2315
2316/*
2317 * Pause btcoex timer and bt duty cycle timer
2318 */
2319static void ath9k_btcoex_timer_pause(struct ath_softc *sc)
2320{
2321 struct ath_btcoex *btcoex = &sc->btcoex;
2322 struct ath_hw *ah = sc->sc_ah;
2323
2324 del_timer_sync(&btcoex->period_timer);
2325
2326 if (btcoex->hw_timer_enabled)
2327 ath_gen_timer_stop(ah, btcoex->no_stomp_timer);
2328
2329 btcoex->hw_timer_enabled = false;
2330}
2331
2129static void ath9k_stop(struct ieee80211_hw *hw) 2332static void ath9k_stop(struct ieee80211_hw *hw)
2130{ 2333{
2131 struct ath_wiphy *aphy = hw->priv; 2334 struct ath_wiphy *aphy = hw->priv;
@@ -2158,7 +2361,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
2158 if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) { 2361 if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) {
2159 ath9k_hw_btcoex_disable(ah); 2362 ath9k_hw_btcoex_disable(ah);
2160 if (ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) 2363 if (ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
2161 ath_btcoex_timer_pause(sc); 2364 ath9k_btcoex_timer_pause(sc);
2162 } 2365 }
2163 2366
2164 /* make sure h/w will not generate any interrupt 2367 /* make sure h/w will not generate any interrupt