Skip to content

Commit

Permalink
ath9k: Fix wifi disconnection when collocated bt scan is active
Browse files Browse the repository at this point in the history
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: Vasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Vasanthakumar Thiagarajan authored and John W. Linville committed Jan 22, 2010
1 parent a951ae2 commit 58da131
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 11 deletions.
2 changes: 2 additions & 0 deletions drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ struct ath_btcoex {
int bt_stomp_type; /* Types of BT stomping */
u32 btcoex_no_stomp; /* 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 */
};

Expand Down Expand Up @@ -429,6 +430,7 @@ void ath_deinit_leds(struct ath_softc *sc);
#define SC_OP_SCANNING BIT(10)
#define SC_OP_TSF_RESET BIT(11)
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)

/* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0)
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/ath/ath9k/btcoex.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@

#define ATH_BTCOEX_DEF_BT_PERIOD 45
#define ATH_BTCOEX_DEF_DUTY_CYCLE 55
#define ATH_BTCOEX_BTSCAN_DUTY_CYCLE 90
#define ATH_BTCOEX_BMISS_THRESH 50

#define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */
#define ATH_BT_CNT_THRESHOLD 3
#define ATH_BT_CNT_SCAN_THRESHOLD 15

enum ath_btcoex_scheme {
ATH_BTCOEX_CFG_NONE,
Expand Down
30 changes: 22 additions & 8 deletions drivers/net/wireless/ath/ath9k/gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,17 @@ static void ath_detect_bt_priority(struct ath_softc *sc)

if (time_after(jiffies, btcoex->bt_priority_time +
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,
"BT priority traffic detected");
sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
} else {
sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
}

btcoex->bt_priority_cnt = 0;
Expand Down Expand Up @@ -316,24 +321,30 @@ static void ath_btcoex_period_timer(unsigned long data)
struct ath_softc *sc = (struct ath_softc *) data;
struct ath_hw *ah = sc->sc_ah;
struct ath_btcoex *btcoex = &sc->btcoex;
u32 timer_period;
bool is_btscan;

ath_detect_bt_priority(sc);

is_btscan = sc->sc_flags & SC_OP_BT_SCAN;

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);

if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
if (btcoex->hw_timer_enabled)
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,
btcoex->no_stomp_timer,
(ath9k_hw_gettsf32(ah) +
btcoex->btcoex_no_stomp),
btcoex->btcoex_no_stomp * 10);
timer_period), timer_period * 10);
btcoex->hw_timer_enabled = true;
}

Expand All @@ -350,13 +361,14 @@ static void ath_btcoex_no_stomp_timer(void *arg)
struct ath_softc *sc = (struct ath_softc *)arg;
struct ath_hw *ah = sc->sc_ah;
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,
"no stomp timer running \n");

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);
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW);
Expand All @@ -371,6 +383,8 @@ int ath_init_btcoex_timer(struct ath_softc *sc)
btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
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,
(unsigned long) sc);
Expand Down Expand Up @@ -405,7 +419,7 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)

btcoex->bt_priority_cnt = 0;
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);
}
Expand Down
6 changes: 3 additions & 3 deletions drivers/net/wireless/ath/ath9k/reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -1547,9 +1547,9 @@ enum {

#define AR_BT_COEX_WEIGHT 0x8174
#define AR_BT_COEX_WGHT 0xff55
#define AR_STOMP_ALL_WLAN_WGHT 0xffcc
#define AR_STOMP_LOW_WLAN_WGHT 0xaaa8
#define AR_STOMP_NONE_WLAN_WGHT 0xaa00
#define AR_STOMP_ALL_WLAN_WGHT 0xfcfc
#define AR_STOMP_LOW_WLAN_WGHT 0xa8a8
#define AR_STOMP_NONE_WLAN_WGHT 0x0000
#define AR_BTCOEX_BT_WGHT 0x0000ffff
#define AR_BTCOEX_BT_WGHT_S 0
#define AR_BTCOEX_WL_WGHT 0xffff0000
Expand Down

0 comments on commit 58da131

Please sign in to comment.