2012-11-28 12:52:02

by Bala Shanmugam

[permalink] [raw]
Subject: [PATCH v2 3/3] compat-drivers: Add a crap patch for AR9565

This patch is required to improve BT throughput to
meet customer requirement. This patch is a workaround
to put WLAN to sleep during BT cycle and cannot be
upstreamed.

Signed-off-by: Bala Shanmugam <[email protected]>
---
...9k-Improve-BT-PAN-FTP-profile-performance.patch | 291 ++++++++++++++++++++
1 files changed, 291 insertions(+), 0 deletions(-)
create mode 100644 crap/0005-ath9k-Improve-BT-PAN-FTP-profile-performance.patch

diff --git a/crap/0005-ath9k-Improve-BT-PAN-FTP-profile-performance.patch b/crap/0005-ath9k-Improve-BT-PAN-FTP-profile-performance.patch
new file mode 100644
index 0000000..ea3a88f
--- /dev/null
+++ b/crap/0005-ath9k-Improve-BT-PAN-FTP-profile-performance.patch
@@ -0,0 +1,291 @@
+From 16366309f4752330ee93d6c6cbebe935371d235a Mon Sep 17 00:00:00 2001
+From: Rajkumar Manoharan <[email protected]>
+Date: Fri, 23 Nov 2012 14:17:59 +0530
+Subject: [PATCH] ath9k: Improve BT PAN/FTP profile performance
+
+As AR9565 shares LNA and antenna for both BT & WLAN, there
+are some degrade in BT performance. In order to improve BT PAN/FTP
+profile performance, this change puts WLAN into sleep state
+and inform the same to AP via nullfuc whenever BT gets its slot
+during BTCOEX period. It improves BT performance at the cost of
+WLAN throughout. Hence this change is applied only for AR9565
+and BT FTP/PAN profiles.
+
+Signed-off-by: Rajkumar Manoharan <[email protected]>
+---
+ drivers/net/wireless/ath/ath9k/ath9k.h | 3 ++
+ drivers/net/wireless/ath/ath9k/btcoex.c | 13 ++++++++
+ drivers/net/wireless/ath/ath9k/btcoex.h | 1 +
+ drivers/net/wireless/ath/ath9k/gpio.c | 5 ++-
+ drivers/net/wireless/ath/ath9k/mci.c | 59 +++++++++++++++++++++++++++++++++
+ drivers/net/wireless/ath/ath9k/mci.h | 2 ++
+ drivers/net/wireless/ath/ath9k/reg.h | 5 ++-
+ drivers/net/wireless/ath/ath9k/xmit.c | 18 ++++++----
+ 8 files changed, 97 insertions(+), 9 deletions(-)
+
+Index: compat-drivers/drivers/net/wireless/ath/ath9k/ath9k.h
+===================================================================
+--- compat-drivers.orig/drivers/net/wireless/ath/ath9k/ath9k.h 2012-11-28 16:59:36.776615151 +0530
++++ compat-drivers/drivers/net/wireless/ath/ath9k/ath9k.h 2012-11-28 17:00:37.880918151 +0530
+@@ -93,6 +93,7 @@
+ enum buffer_type {
+ BUF_AMPDU = BIT(0),
+ BUF_AGGR = BIT(1),
++ BUF_INJECT = BIT(2),
+ };
+
+ #define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU)
+@@ -282,6 +283,7 @@
+ struct ath_txq *txq;
+ struct ath_node *an;
+ u8 paprd;
++ u8 inject;
+ };
+
+ #define ATH_TX_ERROR 0x01
+@@ -483,6 +485,7 @@
+ struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
+ struct ath_mci_profile mci;
+ u8 stomp_audio;
++ u8 stomp_pan;
+ };
+
+ #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+Index: compat-drivers/drivers/net/wireless/ath/ath9k/btcoex.c
+===================================================================
+--- compat-drivers.orig/drivers/net/wireless/ath/ath9k/btcoex.c 2012-11-28 16:59:36.776615151 +0530
++++ compat-drivers/drivers/net/wireless/ath/ath9k/btcoex.c 2012-11-28 16:59:37.612619297 +0530
+@@ -414,3 +414,16 @@
+ btcoex->tx_prio[i] = stomp_txprio[i];
+ }
+ EXPORT_SYMBOL(ath9k_hw_btcoex_set_concur_txprio);
++
++void ath9k_hw_btcoex_set_sleep(struct ath_hw *ah, u8 state)
++{
++ REG_RMW_FIELD(ah, AR_PCU_MISC_MODE2,
++ AR_PCU_MISC_MODE2_PM_FIELD_FOR_DAT, state);
++ REG_RMW_FIELD(ah, AR_PCU_MISC_MODE3,
++ AR_PCU_MISC_MODE3_PM_FIELD_FOR_MGT, state);
++ if (state)
++ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
++ else
++ REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
++}
++EXPORT_SYMBOL(ath9k_hw_btcoex_set_sleep);
+Index: compat-drivers/drivers/net/wireless/ath/ath9k/btcoex.h
+===================================================================
+--- compat-drivers.orig/drivers/net/wireless/ath/ath9k/btcoex.h 2012-11-28 16:59:36.780615171 +0530
++++ compat-drivers/drivers/net/wireless/ath/ath9k/btcoex.h 2012-11-28 16:59:37.612619297 +0530
+@@ -120,5 +120,6 @@
+ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
+ enum ath_stomp_type stomp_type);
+ void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio);
++void ath9k_hw_btcoex_set_sleep(struct ath_hw *ah, u8 state);
+
+ #endif
+Index: compat-drivers/drivers/net/wireless/ath/ath9k/gpio.c
+===================================================================
+--- compat-drivers.orig/drivers/net/wireless/ath/ath9k/gpio.c 2012-11-28 16:59:36.780615171 +0530
++++ compat-drivers/drivers/net/wireless/ath/ath9k/gpio.c 2012-11-28 16:59:37.612619297 +0530
+@@ -234,8 +234,10 @@
+ if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
+ ath_detect_bt_priority(sc);
+
+- if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
++ if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) {
++ ath9k_mci_set_sleep(sc, 0);
+ ath_mci_ftp_adjust(sc);
++ }
+
+ spin_lock_bh(&btcoex->btcoex_lock);
+
+@@ -292,6 +294,7 @@
+ ath_dbg(common, BTCOEX, "no stomp timer running\n");
+
+ ath9k_ps_wakeup(sc);
++ ath9k_mci_set_sleep(sc, 1);
+ spin_lock_bh(&btcoex->btcoex_lock);
+
+ if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
+Index: compat-drivers/drivers/net/wireless/ath/ath9k/mci.c
+===================================================================
+--- compat-drivers.orig/drivers/net/wireless/ath/ath9k/mci.c 2012-11-28 16:59:36.780615171 +0530
++++ compat-drivers/drivers/net/wireless/ath/ath9k/mci.c 2012-11-28 17:01:20.281128402 +0530
+@@ -745,6 +745,7 @@
+
+ btcoex->stomp_audio++;
+ }
++
+ void ath9k_mci_update_rssi(struct ath_softc *sc)
+ {
+ struct ath_hw *ah = sc->sc_ah;
+@@ -772,3 +773,59 @@
+ }
+ }
+ }
++
++static void ath9k_mci_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
++{
++ struct ath_softc *sc = data;
++ struct ath_vif *avp = (void *)vif->drv_priv;
++ struct ieee80211_hdr_3addr *nullfunc;
++ struct sk_buff *skb;
++ struct ath_tx_control txctl;
++
++ if (vif->type != NL80211_IFTYPE_STATION)
++ return;
++
++ if (!avp->primary_sta_vif)
++ return;
++
++ skb = ieee80211_nullfunc_get(sc->hw, vif);
++ if (!skb)
++ return;
++ nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
++ if (sc->btcoex.mci.sleep)
++ nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
++
++ IEEE80211_SKB_CB(skb)->flags |= (IEEE80211_TX_INTFL_DONT_ENCRYPT |
++ IEEE80211_TX_CTL_USE_MINRATE);
++
++ memset(&txctl, 0, sizeof(txctl));
++ txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
++ txctl.inject = 1;
++
++ ath_tx_start(sc->hw, skb, &txctl);
++}
++
++void ath9k_mci_set_sleep(struct ath_softc *sc, u8 state)
++{
++ struct ath_mci_profile *mci = &sc->btcoex.mci;
++
++ if (!AR_SREV_9565(sc->sc_ah))
++ return;
++
++ state = !!(state && (mci->num_pan || mci->num_other_acl));
++
++ if (mci->sleep == state)
++ return;
++
++ mci->sleep = state;
++ if (state && ++sc->btcoex.stomp_pan >= 23) {
++ ieee80211_iterate_active_interfaces_atomic(
++ sc->hw, ath9k_mci_vif_iter, sc);
++ ath9k_hw_btcoex_set_sleep(sc->sc_ah, state);
++ } else if (!state && sc->btcoex.stomp_pan >= 23) {
++ sc->btcoex.stomp_pan = 0;
++ ath9k_hw_btcoex_set_sleep(sc->sc_ah, state);
++ ieee80211_iterate_active_interfaces_atomic(
++ sc->hw, ath9k_mci_vif_iter, sc);
++ }
++}
+Index: compat-drivers/drivers/net/wireless/ath/ath9k/mci.h
+===================================================================
+--- compat-drivers.orig/drivers/net/wireless/ath/ath9k/mci.h 2012-11-28 16:59:35.548609062 +0530
++++ compat-drivers/drivers/net/wireless/ath/ath9k/mci.h 2012-11-28 16:59:37.612619297 +0530
+@@ -137,6 +137,7 @@
+ u8 num_other_acl;
+ u8 num_bdr;
+ u8 voice_priority;
++ u8 sleep;
+ };
+
+ struct ath_mci_buf {
+@@ -155,6 +156,7 @@
+ void ath_mci_cleanup(struct ath_softc *sc);
+ void ath_mci_intr(struct ath_softc *sc);
+ void ath9k_mci_update_rssi(struct ath_softc *sc);
++void ath9k_mci_set_sleep(struct ath_softc *sc, u8 state);
+
+ #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
+ void ath_mci_enable(struct ath_softc *sc);
+Index: compat-drivers/drivers/net/wireless/ath/ath9k/reg.h
+===================================================================
+--- compat-drivers.orig/drivers/net/wireless/ath/ath9k/reg.h 2012-11-28 16:59:35.564609141 +0530
++++ compat-drivers/drivers/net/wireless/ath/ath9k/reg.h 2012-11-28 16:59:37.612619297 +0530
+@@ -1897,10 +1897,13 @@
+ #define AR_PCU_MISC_MODE2_ENABLE_AGGWEP 0x00020000
+ #define AR_PCU_MISC_MODE2_HWWAR1 0x00100000
+ #define AR_PCU_MISC_MODE2_HWWAR2 0x02000000
++#define AR_PCU_MISC_MODE2_PM_FIELD_FOR_DAT 0x04000000
++#define AR_PCU_MISC_MODE2_PM_FIELD_FOR_DAT_S 26
+ #define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000
+
+ #define AR_PCU_MISC_MODE3 0x83d0
+-
++#define AR_PCU_MISC_MODE3_PM_FIELD_FOR_MGT 0x00400000
++#define AR_PCU_MISC_MODE3_PM_FIELD_FOR_MGT_S 22
+ #define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
+ #define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
+ #define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
+Index: compat-drivers/drivers/net/wireless/ath/ath9k/xmit.c
+===================================================================
+--- compat-drivers.orig/drivers/net/wireless/ath/ath9k/xmit.c 2012-11-28 16:59:35.176607217 +0530
++++ compat-drivers/drivers/net/wireless/ath/ath9k/xmit.c 2012-11-28 16:59:37.612619297 +0530
+@@ -50,7 +50,8 @@
+ #define IS_HT_RATE(_rate) ((_rate) & 0x80)
+
+ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+- struct ath_atx_tid *tid, struct sk_buff *skb);
++ struct ath_atx_tid *tid, struct sk_buff *skb,
++ u8 inject);
+ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+ int tx_flags, struct ath_txq *txq);
+ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+@@ -189,7 +190,7 @@
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
+ sendbar = true;
+ } else {
+- ath_tx_send_normal(sc, txq, NULL, skb);
++ ath_tx_send_normal(sc, txq, NULL, skb, 0);
+ }
+ }
+
+@@ -1767,7 +1768,8 @@
+ }
+
+ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
+- struct ath_atx_tid *tid, struct sk_buff *skb)
++ struct ath_atx_tid *tid, struct sk_buff *skb,
++ u8 inject)
+ {
+ struct ath_frame_info *fi = get_frame_info(skb);
+ struct list_head bf_head;
+@@ -1777,7 +1779,7 @@
+
+ INIT_LIST_HEAD(&bf_head);
+ list_add_tail(&bf->list, &bf_head);
+- bf->bf_state.bf_type = 0;
++ bf->bf_state.bf_type = inject ? BUF_INJECT : 0;
+
+ bf->bf_next = NULL;
+ bf->bf_lastbf = bf;
+@@ -1928,7 +1930,7 @@
+ } else {
+ bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb);
+ if (!bf) {
+- if (txctl->paprd)
++ if (txctl->paprd || txctl->inject)
+ dev_kfree_skb_any(skb);
+ else
+ ieee80211_free_txskb(sc->hw, skb);
+@@ -1940,7 +1942,7 @@
+ if (txctl->paprd)
+ bf->bf_state.bfs_paprd_timestamp = jiffies;
+
+- ath_tx_send_normal(sc, txctl->txq, tid, skb);
++ ath_tx_send_normal(sc, txctl->txq, tid, skb, txctl->inject);
+ }
+ }
+
+@@ -2103,7 +2105,9 @@
+ dev_kfree_skb_any(skb);
+ else
+ complete(&sc->paprd_complete);
+- } else {
++ } else if (bf->bf_state.bf_type & BUF_INJECT)
++ dev_kfree_skb_any(skb);
++ else {
+ ath_debug_stat_tx(sc, bf, ts, txq, tx_flags);
+ ath_tx_complete(sc, skb, tx_flags, txq);
+ }
--
1.7.4.1



2012-11-29 05:11:01

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH v2 3/3] compat-drivers: Add a crap patch for AR9565

On Wed, Nov 28, 2012 at 4:52 AM, Bala Shanmugam
<[email protected]> wrote:
> This patch is required to improve BT throughput to
> meet customer requirement. This patch is a workaround
> to put WLAN to sleep during BT cycle and cannot be
> upstreamed.
>
> Signed-off-by: Bala Shanmugam <[email protected]>

Thanks applied and pushed all, and new releases made:

http://wireless.kernel.org/en/users/Download/stable#compat-wireless_3.6_stable_releases

Luis