The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/rtw89/ps.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
    2 /* Copyright(c) 2019-2020  Realtek Corporation
    3  */
    4 
    5 #include "coex.h"
    6 #include "core.h"
    7 #include "debug.h"
    8 #include "fw.h"
    9 #include "mac.h"
   10 #include "ps.h"
   11 #include "reg.h"
   12 #include "util.h"
   13 
   14 static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid)
   15 {
   16         u32 pwr_en_bit = 0xE;
   17         u32 chk_msk = pwr_en_bit << (4 * macid);
   18         u32 polling;
   19         int ret;
   20 
   21         ret = read_poll_timeout_atomic(rtw89_read32_mask, polling, !polling,
   22                                        1000, 50000, false, rtwdev,
   23                                        R_AX_PPWRBIT_SETTING, chk_msk);
   24         if (ret) {
   25                 rtw89_info(rtwdev, "rtw89: failed to leave lps state\n");
   26                 return -EBUSY;
   27         }
   28 
   29         return 0;
   30 }
   31 
   32 static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
   33                                                 bool enter)
   34 {
   35         ieee80211_stop_queues(rtwdev->hw);
   36         rtwdev->hci.paused = true;
   37         flush_work(&rtwdev->txq_work);
   38         ieee80211_wake_queues(rtwdev->hw);
   39 
   40         rtw89_hci_pause(rtwdev, true);
   41         rtw89_mac_power_mode_change(rtwdev, enter);
   42         rtw89_hci_switch_mode(rtwdev, enter);
   43         rtw89_hci_pause(rtwdev, false);
   44 
   45         rtwdev->hci.paused = false;
   46 
   47         if (!enter) {
   48                 local_bh_disable();
   49                 napi_schedule(&rtwdev->napi);
   50                 local_bh_enable();
   51         }
   52 }
   53 
   54 static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
   55 {
   56         if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode))
   57                 rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
   58         else
   59                 rtw89_mac_power_mode_change(rtwdev, enter);
   60 }
   61 
   62 static void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev)
   63 {
   64         if (!rtwdev->ps_mode)
   65                 return;
   66 
   67         if (test_and_set_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags))
   68                 return;
   69 
   70         rtw89_ps_power_mode_change(rtwdev, true);
   71 }
   72 
   73 void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
   74 {
   75         if (!rtwdev->ps_mode)
   76                 return;
   77 
   78         if (test_and_clear_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags))
   79                 rtw89_ps_power_mode_change(rtwdev, false);
   80 }
   81 
   82 static void __rtw89_enter_lps(struct rtw89_dev *rtwdev, u8 mac_id)
   83 {
   84         struct rtw89_lps_parm lps_param = {
   85                 .macid = mac_id,
   86                 .psmode = RTW89_MAC_AX_PS_MODE_LEGACY,
   87                 .lastrpwm = RTW89_LAST_RPWM_PS,
   88         };
   89 
   90         rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL);
   91         rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
   92 }
   93 
   94 static void __rtw89_leave_lps(struct rtw89_dev *rtwdev, u8 mac_id)
   95 {
   96         struct rtw89_lps_parm lps_param = {
   97                 .macid = mac_id,
   98                 .psmode = RTW89_MAC_AX_PS_MODE_ACTIVE,
   99                 .lastrpwm = RTW89_LAST_RPWM_ACTIVE,
  100         };
  101 
  102         rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
  103         rtw89_fw_leave_lps_check(rtwdev, 0);
  104         rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON);
  105 }
  106 
  107 void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
  108 {
  109         lockdep_assert_held(&rtwdev->mutex);
  110 
  111         __rtw89_leave_ps_mode(rtwdev);
  112 }
  113 
  114 void rtw89_enter_lps(struct rtw89_dev *rtwdev, u8 mac_id)
  115 {
  116         lockdep_assert_held(&rtwdev->mutex);
  117 
  118         if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
  119                 return;
  120 
  121         __rtw89_enter_lps(rtwdev, mac_id);
  122         __rtw89_enter_ps_mode(rtwdev);
  123 }
  124 
  125 static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
  126 {
  127         if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
  128                 return;
  129 
  130         __rtw89_leave_lps(rtwdev, rtwvif->mac_id);
  131 }
  132 
  133 void rtw89_leave_lps(struct rtw89_dev *rtwdev)
  134 {
  135         struct rtw89_vif *rtwvif;
  136 
  137         lockdep_assert_held(&rtwdev->mutex);
  138 
  139         if (!test_and_clear_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
  140                 return;
  141 
  142         __rtw89_leave_ps_mode(rtwdev);
  143 
  144         rtw89_for_each_rtwvif(rtwdev, rtwvif)
  145                 rtw89_leave_lps_vif(rtwdev, rtwvif);
  146 }
  147 
  148 void rtw89_enter_ips(struct rtw89_dev *rtwdev)
  149 {
  150         struct rtw89_vif *rtwvif;
  151 
  152         set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
  153 
  154         rtw89_for_each_rtwvif(rtwdev, rtwvif)
  155                 rtw89_mac_vif_deinit(rtwdev, rtwvif);
  156 
  157         rtw89_core_stop(rtwdev);
  158 }
  159 
  160 void rtw89_leave_ips(struct rtw89_dev *rtwdev)
  161 {
  162         struct rtw89_vif *rtwvif;
  163         int ret;
  164 
  165         ret = rtw89_core_start(rtwdev);
  166         if (ret)
  167                 rtw89_err(rtwdev, "failed to leave idle state\n");
  168 
  169         rtw89_set_channel(rtwdev);
  170 
  171         rtw89_for_each_rtwvif(rtwdev, rtwvif)
  172                 rtw89_mac_vif_init(rtwdev, rtwvif);
  173 
  174         clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
  175 }
  176 
  177 void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl)
  178 {
  179         if (btc_ctrl)
  180                 rtw89_leave_lps(rtwdev);
  181 }

Cache object: e5c2ed805a14c28063cacd2df38841ea


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.