Commit 58da1318 authored by Vasanthakumar Thiagarajan's avatar Vasanthakumar Thiagarajan Committed by John W. Linville

ath9k: Fix wifi disconnection when collocated bt scan is active

As all bt packets are priority traffic during bt scan, wifi
will get disconnected when bt scan lasts for few seconds. Fix
this by allocating 10% of bt period time (4.5ms) to wifi fully.
Signed-off-by: default avatarVasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a951ae21
...@@ -364,6 +364,7 @@ struct ath_btcoex { ...@@ -364,6 +364,7 @@ struct ath_btcoex {
int bt_stomp_type; /* Types of BT stomping */ int bt_stomp_type; /* Types of BT stomping */
u32 btcoex_no_stomp; /* in usec */ u32 btcoex_no_stomp; /* in usec */
u32 btcoex_period; /* in usec */ u32 btcoex_period; /* in usec */
u32 btscan_no_stomp; /* in usec */
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
}; };
...@@ -429,6 +430,7 @@ void ath_deinit_leds(struct ath_softc *sc); ...@@ -429,6 +430,7 @@ void ath_deinit_leds(struct ath_softc *sc);
#define SC_OP_SCANNING BIT(10) #define SC_OP_SCANNING BIT(10)
#define SC_OP_TSF_RESET BIT(11) #define SC_OP_TSF_RESET BIT(11)
#define SC_OP_BT_PRIORITY_DETECTED BIT(12) #define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
/* Powersave flags */ /* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0) #define PS_WAIT_FOR_BEACON BIT(0)
......
...@@ -25,10 +25,12 @@ ...@@ -25,10 +25,12 @@
#define ATH_BTCOEX_DEF_BT_PERIOD 45 #define ATH_BTCOEX_DEF_BT_PERIOD 45
#define ATH_BTCOEX_DEF_DUTY_CYCLE 55 #define ATH_BTCOEX_DEF_DUTY_CYCLE 55
#define ATH_BTCOEX_BTSCAN_DUTY_CYCLE 90
#define ATH_BTCOEX_BMISS_THRESH 50 #define ATH_BTCOEX_BMISS_THRESH 50
#define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */ #define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */
#define ATH_BT_CNT_THRESHOLD 3 #define ATH_BT_CNT_THRESHOLD 3
#define ATH_BT_CNT_SCAN_THRESHOLD 15
enum ath_btcoex_scheme { enum ath_btcoex_scheme {
ATH_BTCOEX_CFG_NONE, ATH_BTCOEX_CFG_NONE,
......
...@@ -230,12 +230,17 @@ static void ath_detect_bt_priority(struct ath_softc *sc) ...@@ -230,12 +230,17 @@ static void ath_detect_bt_priority(struct ath_softc *sc)
if (time_after(jiffies, btcoex->bt_priority_time + if (time_after(jiffies, btcoex->bt_priority_time +
msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN);
/* Detect if colocated bt started scanning */
if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
"BT scan detected");
sc->sc_flags |= (SC_OP_BT_SCAN |
SC_OP_BT_PRIORITY_DETECTED);
} else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX, ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
"BT priority traffic detected"); "BT priority traffic detected");
sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
} else {
sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
} }
btcoex->bt_priority_cnt = 0; btcoex->bt_priority_cnt = 0;
...@@ -316,12 +321,17 @@ static void ath_btcoex_period_timer(unsigned long data) ...@@ -316,12 +321,17 @@ static void ath_btcoex_period_timer(unsigned long data)
struct ath_softc *sc = (struct ath_softc *) data; struct ath_softc *sc = (struct ath_softc *) data;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_btcoex *btcoex = &sc->btcoex; struct ath_btcoex *btcoex = &sc->btcoex;
u32 timer_period;
bool is_btscan;
ath_detect_bt_priority(sc); ath_detect_bt_priority(sc);
is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
spin_lock_bh(&btcoex->btcoex_lock); spin_lock_bh(&btcoex->btcoex_lock);
ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type); ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL :
btcoex->bt_stomp_type);
spin_unlock_bh(&btcoex->btcoex_lock); spin_unlock_bh(&btcoex->btcoex_lock);
...@@ -329,11 +339,12 @@ static void ath_btcoex_period_timer(unsigned long data) ...@@ -329,11 +339,12 @@ static void ath_btcoex_period_timer(unsigned long data)
if (btcoex->hw_timer_enabled) if (btcoex->hw_timer_enabled)
ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
timer_period = is_btscan ? btcoex->btscan_no_stomp :
btcoex->btcoex_no_stomp;
ath9k_gen_timer_start(ah, ath9k_gen_timer_start(ah,
btcoex->no_stomp_timer, btcoex->no_stomp_timer,
(ath9k_hw_gettsf32(ah) + (ath9k_hw_gettsf32(ah) +
btcoex->btcoex_no_stomp), timer_period), timer_period * 10);
btcoex->btcoex_no_stomp * 10);
btcoex->hw_timer_enabled = true; btcoex->hw_timer_enabled = true;
} }
...@@ -350,13 +361,14 @@ static void ath_btcoex_no_stomp_timer(void *arg) ...@@ -350,13 +361,14 @@ static void ath_btcoex_no_stomp_timer(void *arg)
struct ath_softc *sc = (struct ath_softc *)arg; struct ath_softc *sc = (struct ath_softc *)arg;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_btcoex *btcoex = &sc->btcoex; struct ath_btcoex *btcoex = &sc->btcoex;
bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
"no stomp timer running \n"); "no stomp timer running \n");
spin_lock_bh(&btcoex->btcoex_lock); spin_lock_bh(&btcoex->btcoex_lock);
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan)
ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE);
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW);
...@@ -371,6 +383,8 @@ int ath_init_btcoex_timer(struct ath_softc *sc) ...@@ -371,6 +383,8 @@ int ath_init_btcoex_timer(struct ath_softc *sc)
btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
btcoex->btcoex_period / 100; btcoex->btcoex_period / 100;
btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
btcoex->btcoex_period / 100;
setup_timer(&btcoex->period_timer, ath_btcoex_period_timer, setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
(unsigned long) sc); (unsigned long) sc);
...@@ -405,7 +419,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc) ...@@ -405,7 +419,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)
btcoex->bt_priority_cnt = 0; btcoex->bt_priority_cnt = 0;
btcoex->bt_priority_time = jiffies; btcoex->bt_priority_time = jiffies;
sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; sc->sc_flags &= ~(SC_OP_BT_PRIORITY_DETECTED | SC_OP_BT_SCAN);
mod_timer(&btcoex->period_timer, jiffies); mod_timer(&btcoex->period_timer, jiffies);
} }
......
...@@ -1547,9 +1547,9 @@ enum { ...@@ -1547,9 +1547,9 @@ enum {
#define AR_BT_COEX_WEIGHT 0x8174 #define AR_BT_COEX_WEIGHT 0x8174
#define AR_BT_COEX_WGHT 0xff55 #define AR_BT_COEX_WGHT 0xff55
#define AR_STOMP_ALL_WLAN_WGHT 0xffcc #define AR_STOMP_ALL_WLAN_WGHT 0xfcfc
#define AR_STOMP_LOW_WLAN_WGHT 0xaaa8 #define AR_STOMP_LOW_WLAN_WGHT 0xa8a8
#define AR_STOMP_NONE_WLAN_WGHT 0xaa00 #define AR_STOMP_NONE_WLAN_WGHT 0x0000
#define AR_BTCOEX_BT_WGHT 0x0000ffff #define AR_BTCOEX_BT_WGHT 0x0000ffff
#define AR_BTCOEX_BT_WGHT_S 0 #define AR_BTCOEX_BT_WGHT_S 0
#define AR_BTCOEX_WL_WGHT 0xffff0000 #define AR_BTCOEX_WL_WGHT 0xffff0000
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment