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 ee946b8..ce10d1a 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 1ca6da8..acd4373 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 3a1e1cf..20092f9 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 9397a6d..af6d273 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 18acdbc..611be4f 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);
 
                /*