Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /* Copyright(c) 2019-2020  Realtek Corporation
0003  */
0004 
0005 #include "coex.h"
0006 #include "core.h"
0007 #include "debug.h"
0008 #include "fw.h"
0009 #include "mac.h"
0010 #include "ps.h"
0011 #include "reg.h"
0012 #include "util.h"
0013 
0014 static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid)
0015 {
0016     u32 pwr_en_bit = 0xE;
0017     u32 chk_msk = pwr_en_bit << (4 * macid);
0018     u32 polling;
0019     int ret;
0020 
0021     ret = read_poll_timeout_atomic(rtw89_read32_mask, polling, !polling,
0022                        1000, 50000, false, rtwdev,
0023                        R_AX_PPWRBIT_SETTING, chk_msk);
0024     if (ret) {
0025         rtw89_info(rtwdev, "rtw89: failed to leave lps state\n");
0026         return -EBUSY;
0027     }
0028 
0029     return 0;
0030 }
0031 
0032 static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
0033                         bool enter)
0034 {
0035     ieee80211_stop_queues(rtwdev->hw);
0036     rtwdev->hci.paused = true;
0037     flush_work(&rtwdev->txq_work);
0038     ieee80211_wake_queues(rtwdev->hw);
0039 
0040     rtw89_hci_pause(rtwdev, true);
0041     rtw89_mac_power_mode_change(rtwdev, enter);
0042     rtw89_hci_switch_mode(rtwdev, enter);
0043     rtw89_hci_pause(rtwdev, false);
0044 
0045     rtwdev->hci.paused = false;
0046 
0047     if (!enter) {
0048         local_bh_disable();
0049         napi_schedule(&rtwdev->napi);
0050         local_bh_enable();
0051     }
0052 }
0053 
0054 static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
0055 {
0056     if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode))
0057         rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
0058     else
0059         rtw89_mac_power_mode_change(rtwdev, enter);
0060 }
0061 
0062 static void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev)
0063 {
0064     if (!rtwdev->ps_mode)
0065         return;
0066 
0067     if (test_and_set_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags))
0068         return;
0069 
0070     rtw89_ps_power_mode_change(rtwdev, true);
0071 }
0072 
0073 void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
0074 {
0075     if (!rtwdev->ps_mode)
0076         return;
0077 
0078     if (test_and_clear_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags))
0079         rtw89_ps_power_mode_change(rtwdev, false);
0080 }
0081 
0082 static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, u8 mac_id)
0083 {
0084     struct rtw89_lps_parm lps_param = {
0085         .macid = mac_id,
0086         .psmode = RTW89_MAC_AX_PS_MODE_LEGACY,
0087         .lastrpwm = RTW89_LAST_RPWM_PS,
0088     };
0089 
0090     rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL);
0091     rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
0092 }
0093 
0094 static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, u8 mac_id)
0095 {
0096     struct rtw89_lps_parm lps_param = {
0097         .macid = mac_id,
0098         .psmode = RTW89_MAC_AX_PS_MODE_ACTIVE,
0099         .lastrpwm = RTW89_LAST_RPWM_ACTIVE,
0100     };
0101 
0102     rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
0103     rtw89_fw_leave_lps_check(rtwdev, 0);
0104     rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON);
0105 }
0106 
0107 void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
0108 {
0109     lockdep_assert_held(&rtwdev->mutex);
0110 
0111     __rtw89_leave_ps_mode(rtwdev);
0112 }
0113 
0114 void rtw89_enter_lps(struct rtw89_dev *rtwdev, u8 mac_id)
0115 {
0116     lockdep_assert_held(&rtwdev->mutex);
0117 
0118     if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
0119         return;
0120 
0121     __rtw89_enter_lps(rtwdev, mac_id);
0122     __rtw89_enter_ps_mode(rtwdev);
0123 }
0124 
0125 static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
0126 {
0127     if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
0128         return;
0129 
0130     __rtw89_leave_ps_mode(rtwdev);
0131     __rtw89_leave_lps(rtwdev, rtwvif->mac_id);
0132 }
0133 
0134 void rtw89_leave_lps(struct rtw89_dev *rtwdev)
0135 {
0136     struct rtw89_vif *rtwvif;
0137 
0138     lockdep_assert_held(&rtwdev->mutex);
0139 
0140     if (!test_and_clear_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
0141         return;
0142 
0143     rtw89_for_each_rtwvif(rtwdev, rtwvif)
0144         rtw89_leave_lps_vif(rtwdev, rtwvif);
0145 }
0146 
0147 void rtw89_enter_ips(struct rtw89_dev *rtwdev)
0148 {
0149     struct rtw89_vif *rtwvif;
0150 
0151     set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
0152 
0153     rtw89_for_each_rtwvif(rtwdev, rtwvif)
0154         rtw89_mac_vif_deinit(rtwdev, rtwvif);
0155 
0156     rtw89_core_stop(rtwdev);
0157 }
0158 
0159 void rtw89_leave_ips(struct rtw89_dev *rtwdev)
0160 {
0161     struct rtw89_vif *rtwvif;
0162     int ret;
0163 
0164     ret = rtw89_core_start(rtwdev);
0165     if (ret)
0166         rtw89_err(rtwdev, "failed to leave idle state\n");
0167 
0168     rtw89_set_channel(rtwdev);
0169 
0170     rtw89_for_each_rtwvif(rtwdev, rtwvif)
0171         rtw89_mac_vif_init(rtwdev, rtwvif);
0172 
0173     clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
0174 }
0175 
0176 void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl)
0177 {
0178     if (btc_ctrl)
0179         rtw89_leave_lps(rtwdev);
0180 }