ath9k: improve BT FTP/PAN performance
authorRajkumar Manoharan <rmanohar@qca.qualcomm.com>
Mon, 4 Jun 2012 10:58:52 +0000 (16:28 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 6 Jun 2012 19:20:30 +0000 (15:20 -0400)
When BT FTP/PAN transmits while WLAN is idle, the one of 9462 chain
often picks up BT's tx signal and starts receiving. If the current
weight is set to be higher than BT tx, BT tx will be aborted and this
also degrades BT performance. Hence lower WLAN rx priority in this
case only when there are no WLAN traffic.

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/btcoex.c
drivers/net/wireless/ath/ath9k/btcoex.h
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/recv.c

index ee946b8fe00c1982fe9e58687220ca2c09c8cae3..ce10d1a9e493ed347deaeb163e850c88e250be73 100644 (file)
@@ -307,6 +307,7 @@ struct ath_rx {
        u8 defant;
        u8 rxotherant;
        u32 *rxlink;
+       u32 num_pkts;
        unsigned int rxfilter;
        spinlock_t rxbuflock;
        struct list_head rxbuf;
@@ -458,6 +459,7 @@ struct ath_btcoex {
        u32 btcoex_period; /* in usec */
        u32 btscan_no_stomp; /* in usec */
        u32 duty_cycle;
+       u32 bt_wait_time;
        struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
        struct ath_mci_profile mci;
 };
index 1ca6da80d4ad3f16c1ac152b31d1b8724e598052..acd437384fe47840852aeb3f967524ac52265975 100644 (file)
@@ -336,10 +336,16 @@ static void ar9003_btcoex_bt_stomp(struct ath_hw *ah,
                         enum ath_stomp_type stomp_type)
 {
        struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
-       const u32 *weight = AR_SREV_9462(ah) ? ar9003_wlan_weights[stomp_type] :
-                                              ar9462_wlan_weights[stomp_type];
+       const u32 *weight = ar9003_wlan_weights[stomp_type];
        int i;
 
+       if (AR_SREV_9462(ah)) {
+               if ((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
+                   btcoex->mci.stomp_ftp)
+                       stomp_type = ATH_BTCOEX_STOMP_LOW_FTP;
+               weight = ar9462_wlan_weights[stomp_type];
+       }
+
        for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
                btcoex->bt_weight[i] = AR9300_BT_WGHT;
                btcoex->wlan_weight[i] = weight[i];
index 3a1e1cfabd5e28f15345f89b1f428c1a35c63841..20092f98658f84b3f0ad2429543f168de2d2866b 100644 (file)
@@ -36,6 +36,9 @@
 #define ATH_BT_CNT_THRESHOLD          3
 #define ATH_BT_CNT_SCAN_THRESHOLD      15
 
+#define ATH_BTCOEX_RX_WAIT_TIME       100
+#define ATH_BTCOEX_STOMP_FTP_THRESH   5
+
 #define AR9300_NUM_BT_WEIGHTS   4
 #define AR9300_NUM_WLAN_WEIGHTS 4
 /* Defines the BT AR_BT_COEX_WGHT used */
@@ -80,6 +83,7 @@ struct ath9k_hw_mci {
        u8 bt_ver_major;
        u8 bt_ver_minor;
        u8 bt_state;
+       u8 stomp_ftp;
 };
 
 struct ath_btcoex_hw {
index 9397a6d2ed5d9a20a96fdec98ebbf6eed0691dcc..af6d27350291a7ed1c770c001acbf8823107f408 100644 (file)
@@ -191,6 +191,7 @@ 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;
+       struct ath_mci_profile *mci = &btcoex->mci;
        u32 timer_period;
        bool is_btscan;
 
@@ -199,6 +200,18 @@ static void ath_btcoex_period_timer(unsigned long data)
                ath_detect_bt_priority(sc);
        is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags);
 
+       btcoex->bt_wait_time += btcoex->btcoex_period;
+       if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
+               if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP, NULL) &&
+                   (mci->num_pan || mci->num_other_acl))
+                       ah->btcoex_hw.mci.stomp_ftp =
+                               (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
+               else
+                       ah->btcoex_hw.mci.stomp_ftp = false;
+               btcoex->bt_wait_time = 0;
+               sc->rx.num_pkts = 0;
+       }
+
        spin_lock_bh(&btcoex->btcoex_lock);
 
        ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
index 18acdbcbb03f995d403dd802be1ba1840a8bc2ea..611be4f934e722b1e48bbcb1b9cabd55a7fae3f9 100644 (file)
@@ -1841,6 +1841,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                else
                        rs.is_mybeacon = false;
 
+               sc->rx.num_pkts++;
                ath_debug_stat_rx(sc, &rs);
 
                /*