root/drivers/net/wireless/realtek/rtw88/ps.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtw_ips_pwr_up
  2. rtw_enter_ips
  3. rtw_restore_port_cfg_iter
  4. rtw_leave_ips
  5. rtw_leave_lps_core
  6. rtw_enter_lps_core
  7. rtw_lps_work
  8. rtw_enter_lps_irqsafe
  9. rtw_leave_lps_irqsafe
  10. rtw_in_lps
  11. rtw_enter_lps
  12. rtw_leave_lps

   1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2 /* Copyright(c) 2018-2019  Realtek Corporation
   3  */
   4 
   5 #include "main.h"
   6 #include "fw.h"
   7 #include "ps.h"
   8 #include "mac.h"
   9 #include "coex.h"
  10 #include "debug.h"
  11 
  12 static int rtw_ips_pwr_up(struct rtw_dev *rtwdev)
  13 {
  14         int ret;
  15 
  16         ret = rtw_core_start(rtwdev);
  17         if (ret)
  18                 rtw_err(rtwdev, "leave idle state failed\n");
  19 
  20         rtw_set_channel(rtwdev);
  21         rtw_flag_clear(rtwdev, RTW_FLAG_INACTIVE_PS);
  22 
  23         return ret;
  24 }
  25 
  26 int rtw_enter_ips(struct rtw_dev *rtwdev)
  27 {
  28         rtw_flag_set(rtwdev, RTW_FLAG_INACTIVE_PS);
  29 
  30         rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
  31 
  32         rtw_core_stop(rtwdev);
  33 
  34         return 0;
  35 }
  36 
  37 static void rtw_restore_port_cfg_iter(void *data, u8 *mac,
  38                                       struct ieee80211_vif *vif)
  39 {
  40         struct rtw_dev *rtwdev = data;
  41         struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
  42         u32 config = ~0;
  43 
  44         rtw_vif_port_config(rtwdev, rtwvif, config);
  45 }
  46 
  47 int rtw_leave_ips(struct rtw_dev *rtwdev)
  48 {
  49         int ret;
  50 
  51         ret = rtw_ips_pwr_up(rtwdev);
  52         if (ret) {
  53                 rtw_err(rtwdev, "failed to leave ips state\n");
  54                 return ret;
  55         }
  56 
  57         rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
  58 
  59         rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
  60 
  61         return 0;
  62 }
  63 
  64 static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
  65 {
  66         struct rtw_lps_conf *conf = &rtwdev->lps_conf;
  67 
  68         conf->state = RTW_ALL_ON;
  69         conf->awake_interval = 1;
  70         conf->rlbm = 0;
  71         conf->smart_ps = 0;
  72 
  73         rtw_fw_set_pwr_mode(rtwdev);
  74         rtw_flag_clear(rtwdev, RTW_FLAG_LEISURE_PS);
  75 
  76         rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE);
  77 }
  78 
  79 static void rtw_enter_lps_core(struct rtw_dev *rtwdev)
  80 {
  81         struct rtw_lps_conf *conf = &rtwdev->lps_conf;
  82 
  83         conf->state = RTW_RF_OFF;
  84         conf->awake_interval = 1;
  85         conf->rlbm = 1;
  86         conf->smart_ps = 2;
  87 
  88         rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE);
  89 
  90         rtw_fw_set_pwr_mode(rtwdev);
  91         rtw_flag_set(rtwdev, RTW_FLAG_LEISURE_PS);
  92 }
  93 
  94 void rtw_lps_work(struct work_struct *work)
  95 {
  96         struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
  97                                               lps_work.work);
  98         struct rtw_lps_conf *conf = &rtwdev->lps_conf;
  99         struct rtw_vif *rtwvif = conf->rtwvif;
 100 
 101         if (WARN_ON(!rtwvif))
 102                 return;
 103 
 104         if (conf->mode == RTW_MODE_LPS)
 105                 rtw_enter_lps_core(rtwdev);
 106         else
 107                 rtw_leave_lps_core(rtwdev);
 108 }
 109 
 110 void rtw_enter_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
 111 {
 112         struct rtw_lps_conf *conf = &rtwdev->lps_conf;
 113 
 114         if (rtwvif->in_lps)
 115                 return;
 116 
 117         conf->mode = RTW_MODE_LPS;
 118         conf->rtwvif = rtwvif;
 119         rtwvif->in_lps = true;
 120 
 121         ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->lps_work, 0);
 122 }
 123 
 124 void rtw_leave_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
 125 {
 126         struct rtw_lps_conf *conf = &rtwdev->lps_conf;
 127 
 128         if (!rtwvif->in_lps)
 129                 return;
 130 
 131         conf->mode = RTW_MODE_ACTIVE;
 132         conf->rtwvif = rtwvif;
 133         rtwvif->in_lps = false;
 134 
 135         ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->lps_work, 0);
 136 }
 137 
 138 bool rtw_in_lps(struct rtw_dev *rtwdev)
 139 {
 140         return rtw_flag_check(rtwdev, RTW_FLAG_LEISURE_PS);
 141 }
 142 
 143 void rtw_enter_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
 144 {
 145         struct rtw_lps_conf *conf = &rtwdev->lps_conf;
 146 
 147         if (WARN_ON(!rtwvif))
 148                 return;
 149 
 150         if (rtwvif->in_lps)
 151                 return;
 152 
 153         conf->mode = RTW_MODE_LPS;
 154         conf->rtwvif = rtwvif;
 155         rtwvif->in_lps = true;
 156 
 157         rtw_enter_lps_core(rtwdev);
 158 }
 159 
 160 void rtw_leave_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
 161 {
 162         struct rtw_lps_conf *conf = &rtwdev->lps_conf;
 163 
 164         if (WARN_ON(!rtwvif))
 165                 return;
 166 
 167         if (!rtwvif->in_lps)
 168                 return;
 169 
 170         conf->mode = RTW_MODE_ACTIVE;
 171         conf->rtwvif = rtwvif;
 172         rtwvif->in_lps = false;
 173 
 174         rtw_leave_lps_core(rtwdev);
 175 }

/* [<][>][^][v][top][bottom][index][help] */