]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
rtlwifi: btcoexist control to enter/leave LPS
authorPing-Ke Shih <pkshih@realtek.com>
Sun, 18 Jun 2017 16:12:49 +0000 (11:12 -0500)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 21 Jun 2017 15:28:07 +0000 (18:28 +0300)
To yield better user experience, have btcoex control LPS's parameters.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Yan-Hsuan Chuang <yhchuang@realtek.com>
Cc: Birming Chiu <birming@realtek.com>
Cc: Shaofu <shaofu@realtek.com>
Cc: Steven Ting <steventing@realtek.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/realtek/rtlwifi/base.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.h
drivers/net/wireless/realtek/rtlwifi/rtl8192ee/fw.c
drivers/net/wireless/realtek/rtlwifi/rtl8723be/fw.c
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/fw.c
drivers/net/wireless/realtek/rtlwifi/wifi.h

index c6fef54f6543526cc3f5266f4dbdbbb3b4b67bab..180850cb46719f73260ab4c03eeb74df12011e81 100644 (file)
@@ -1802,12 +1802,20 @@ void rtl_watchdog_wq_callback(void *data)
                                                                        false;
                }
 
+               /* PS is controlled by coex. */
+               if (rtlpriv->cfg->ops->get_btc_status() &&
+                   rtlpriv->btcoexist.btc_ops->btc_is_bt_ctrl_lps(rtlpriv))
+                       goto label_lps_done;
+
                if (((rtlpriv->link_info.num_rx_inperiod +
                      rtlpriv->link_info.num_tx_inperiod) > 8) ||
                    (rtlpriv->link_info.num_rx_inperiod > 2))
                        rtl_lps_leave(hw);
                else
                        rtl_lps_enter(hw);
+
+label_lps_done:
+               ;
        }
 
        rtlpriv->link_info.num_rx_inperiod = 0;
index 226927a752f8799d69db84b6587050997d4d690f..eaa916a0727b92eb49638edbed5c7b0ed0e9c7ab 100644 (file)
@@ -242,14 +242,19 @@ static void halbtc_enter_lps(struct btc_coexist *btcoexist)
        }
 
        btcoexist->bt_info.bt_ctrl_lps = true;
-       btcoexist->bt_info.bt_lps_on = false;
+       btcoexist->bt_info.bt_lps_on = true;
        rtl_lps_enter(rtlpriv->mac80211.hw);
 }
 
 static void halbtc_normal_lps(struct btc_coexist *btcoexist)
 {
+       struct rtl_priv *rtlpriv;
+
+       rtlpriv = btcoexist->adapter;
+
        if (btcoexist->bt_info.bt_ctrl_lps) {
                btcoexist->bt_info.bt_lps_on = false;
+               rtl_lps_leave(rtlpriv->mac80211.hw);
                btcoexist->bt_info.bt_ctrl_lps = false;
        }
 }
index 7ee2aa94fd2af33c55a74fc3c808083f00599a39..4366c9817e1e4e920d9d6c6869306f5007ed075f 100644 (file)
@@ -46,6 +46,9 @@ static struct rtl_btc_ops rtl_btc_operation = {
        .btc_is_bt_disabled = rtl_btc_is_bt_disabled,
        .btc_special_packet_notify = rtl_btc_special_packet_notify,
        .btc_record_pwr_mode = rtl_btc_record_pwr_mode,
+       .btc_get_lps_val = rtl_btc_get_lps_val,
+       .btc_get_rpwm_val = rtl_btc_get_rpwm_val,
+       .btc_is_bt_ctrl_lps = rtl_btc_is_bt_ctrl_lps,
        .btc_is_bt_lps_on = rtl_btc_is_bt_lps_on,
        .btc_get_ampdu_cfg = rtl_btc_get_ampdu_cfg,
 };
@@ -62,6 +65,21 @@ void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len)
        memcpy(gl_bt_coexist.pwr_mode_val, buf, safe_len);
 }
 
+u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv)
+{
+       return gl_bt_coexist.bt_info.lps_val;
+}
+
+u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv)
+{
+       return gl_bt_coexist.bt_info.rpwm_val;
+}
+
+bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv)
+{
+       return gl_bt_coexist.bt_info.bt_ctrl_lps;
+}
+
 bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv)
 {
        return gl_bt_coexist.bt_info.bt_lps_on;
index ed46f418eb91408e254a62a1857b8ae1f881114f..6fe521cbe7f0189de21b980ee9bb3a9a20d90e1f 100644 (file)
@@ -44,6 +44,9 @@ bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv);
 bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv);
 void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type);
 void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len);
+u8   rtl_btc_get_lps_val(struct rtl_priv *rtlpriv);
+u8   rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv);
+bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv);
 bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv);
 void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
                           u8 *ctrl_agg_size, u8 *agg_size);
index c11f1c04f871f355983d169582c3eead9496aee3..2ba9e613a7f6e670b2babd7dfb21a4c469d2bcc8 100644 (file)
@@ -422,24 +422,71 @@ void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-       u8 rlbm, power_state = 0, byte5 = 0x40;
+       u8 rlbm, power_state = 0, byte5 = 0;
+       u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
        struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+       bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+                           btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
 
-       RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode);
+       RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+                mode, bt_ctrl_lps);
+
+       switch (mode) {
+       case FW_PS_MIN_MODE:
+               rlbm = 0;
+               awake_intvl = 2;
+               break;
+       case FW_PS_MAX_MODE:
+               rlbm = 1;
+               awake_intvl = 2;
+               break;
+       case FW_PS_DTIM_MODE:
+               rlbm = 2;
+               awake_intvl = ppsc->reg_max_lps_awakeintvl;
+               /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+                * is only used in swlps.
+                */
+               break;
+       default:
+               rlbm = 2;
+               awake_intvl = 4;
+               break;
+       }
+
+       if (rtlpriv->mac80211.p2p) {
+               awake_intvl = 2;
+               rlbm = 1;
+       }
+
+       if (mode == FW_PS_ACTIVE_MODE) {
+               byte5 = 0x40;
+               power_state = FW_PWR_STATE_ACTIVE;
+       } else {
+               if (bt_ctrl_lps) {
+                       byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+                       power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+                       if ((rlbm == 2) && (byte5 & BIT(4))) {
+                               /* Keep awake interval to 1 to prevent from
+                                * decreasing coex performance
+                                */
+                               awake_intvl = 2;
+                               rlbm = 2;
+                       }
+               } else {
+                       byte5 = 0x40;
+                       power_state = FW_PWR_STATE_RF_OFF;
+               }
+       }
 
        SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
-       rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
        SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
        SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
                                         (rtlpriv->mac80211.p2p) ?
                                         ppsc->smart_ps : 1);
        SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
-                                              ppsc->reg_max_lps_awakeintvl);
+                                              awake_intvl);
        SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
-       if (mode == FW_PS_ACTIVE_MODE)
-               power_state |= FW_PWR_STATE_ACTIVE;
-       else
-               power_state |= FW_PWR_STATE_RF_OFF;
        SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
        SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
 
index 488376becdcbbce1a9ee59ec8624c3532455e671..a37eb27cefe65cc6df081b29d202cdf4d554c5c1 100644 (file)
@@ -240,24 +240,71 @@ void rtl8723be_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        u8 u1_h2c_set_pwrmode[H2C_PWEMODE_LENGTH] = { 0 };
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-       u8 rlbm, power_state = 0, byte5 = 0x40;
+       u8 rlbm, power_state = 0, byte5 = 0;
+       u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
        struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+       bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+                           btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
 
-       RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
+       RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+                mode, bt_ctrl_lps);
+
+       switch (mode) {
+       case FW_PS_MIN_MODE:
+               rlbm = 0;
+               awake_intvl = 2;
+               break;
+       case FW_PS_MAX_MODE:
+               rlbm = 1;
+               awake_intvl = 2;
+               break;
+       case FW_PS_DTIM_MODE:
+               rlbm = 2;
+               awake_intvl = ppsc->reg_max_lps_awakeintvl;
+               /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+                * is only used in swlps.
+                */
+               break;
+       default:
+               rlbm = 2;
+               awake_intvl = 4;
+               break;
+       }
+
+       if (rtlpriv->mac80211.p2p) {
+               awake_intvl = 2;
+               rlbm = 1;
+       }
+
+       if (mode == FW_PS_ACTIVE_MODE) {
+               byte5 = 0x40;
+               power_state = FW_PWR_STATE_ACTIVE;
+       } else {
+               if (bt_ctrl_lps) {
+                       byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+                       power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+                       if ((rlbm == 2) && (byte5 & BIT(4))) {
+                               /* Keep awake interval to 1 to prevent from
+                                * decreasing coex performance
+                                */
+                               awake_intvl = 2;
+                               rlbm = 2;
+                       }
+               } else {
+                       byte5 = 0x40;
+                       power_state = FW_PWR_STATE_RF_OFF;
+               }
+       }
 
        SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
-       rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
        SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
        SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
                                         (rtlpriv->mac80211.p2p) ?
                                          ppsc->smart_ps : 1);
        SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
-                                              ppsc->reg_max_lps_awakeintvl);
+                                              awake_intvl);
        SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
-       if (mode == FW_PS_ACTIVE_MODE)
-               power_state |= FW_PWR_STATE_ACTIVE;
-       else
-               power_state |= FW_PWR_STATE_RF_OFF;
        SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
        SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
 
index 96b8a9bdaf55106fbe72e03ff26477523632076c..cc03f9813824fab32e1ac92143fc5fb42a3676e0 100644 (file)
@@ -489,25 +489,71 @@ void rtl8821ae_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        u8 u1_h2c_set_pwrmode[H2C_8821AE_PWEMODE_LENGTH] = { 0 };
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-       u8 rlbm, power_state = 0, byte5 = 0x40;
+       u8 rlbm, power_state = 0, byte5 = 0;
+       u8 awake_intvl; /* DTIM = (awake_intvl - 1) */
        struct rtl_btc_ops *btc_ops = rtlpriv->btcoexist.btc_ops;
+       bool bt_ctrl_lps = (rtlpriv->cfg->ops->get_btc_status() ?
+                           btc_ops->btc_is_bt_ctrl_lps(rtlpriv) : false);
 
-       RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
+       RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "FW LPS mode = %d (coex:%d)\n",
+                mode, bt_ctrl_lps);
+
+       switch (mode) {
+       case FW_PS_MIN_MODE:
+               rlbm = 0;
+               awake_intvl = 2;
+               break;
+       case FW_PS_MAX_MODE:
+               rlbm = 1;
+               awake_intvl = 2;
+               break;
+       case FW_PS_DTIM_MODE:
+               rlbm = 2;
+               awake_intvl = ppsc->reg_max_lps_awakeintvl;
+               /* hw->conf.ps_dtim_period or mac->vif->bss_conf.dtim_period
+                * is only used in swlps.
+                */
+               break;
+       default:
+               rlbm = 2;
+               awake_intvl = 4;
+               break;
+       }
+
+       if (rtlpriv->mac80211.p2p) {
+               awake_intvl = 2;
+               rlbm = 1;
+       }
+
+       if (mode == FW_PS_ACTIVE_MODE) {
+               byte5 = 0x40;
+               power_state = FW_PWR_STATE_ACTIVE;
+       } else {
+               if (bt_ctrl_lps) {
+                       byte5 = btc_ops->btc_get_lps_val(rtlpriv);
+                       power_state = btc_ops->btc_get_rpwm_val(rtlpriv);
+
+                       if ((rlbm == 2) && (byte5 & BIT(4))) {
+                               /* Keep awake interval to 1 to prevent from
+                                * decreasing coex performance
+                                */
+                               awake_intvl = 2;
+                               rlbm = 2;
+                       }
+               } else {
+                       byte5 = 0x40;
+                       power_state = FW_PWR_STATE_RF_OFF;
+               }
+       }
 
        SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
-       rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
        SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
        SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
                                         (rtlpriv->mac80211.p2p) ?
                                         ppsc->smart_ps : 1);
        SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
-                                              ppsc->reg_max_lps_awakeintvl);
+                                              awake_intvl);
        SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
-       if (mode == FW_PS_ACTIVE_MODE)
-               power_state |= FW_PWR_STATE_ACTIVE;
-       else
-               power_state |= FW_PWR_STATE_RF_OFF;
-
        SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
        SET_H2CCMD_PWRMODE_PARM_BYTE5(u1_h2c_set_pwrmode, byte5);
 
index 23d869bcb90d5b3f9ad6e05209fca6067441fc9d..49c0d222927460316ec33837b9a2f56f2004519f 100644 (file)
@@ -2561,6 +2561,9 @@ struct rtl_btc_ops {
        void (*btc_special_packet_notify)(struct rtl_priv *rtlpriv,
                                          u8 pkt_type);
        void (*btc_record_pwr_mode)(struct rtl_priv *rtlpriv, u8 *buf, u8 len);
+       u8   (*btc_get_lps_val)(struct rtl_priv *rtlpriv);
+       u8   (*btc_get_rpwm_val)(struct rtl_priv *rtlpriv);
+       bool (*btc_is_bt_ctrl_lps)(struct rtl_priv *rtlpriv);
        void (*btc_get_ampdu_cfg)(struct rtl_priv *rtlpriv, u8 *reject_agg,
                                  u8 *ctrl_agg_size, u8 *agg_size);
        bool (*btc_is_bt_lps_on)(struct rtl_priv *rtlpriv);