1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2018-2019 Realtek Corporation
12 static int rtw_ips_pwr_up(struct rtw_dev *rtwdev)
16 ret = rtw_core_start(rtwdev);
18 rtw_err(rtwdev, "leave idle state failed\n");
20 rtw_set_channel(rtwdev);
21 rtw_flag_clear(rtwdev, RTW_FLAG_INACTIVE_PS);
26 int rtw_enter_ips(struct rtw_dev *rtwdev)
28 rtw_flag_set(rtwdev, RTW_FLAG_INACTIVE_PS);
30 rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
32 rtw_core_stop(rtwdev);
37 static void rtw_restore_port_cfg_iter(void *data, u8 *mac,
38 struct ieee80211_vif *vif)
40 struct rtw_dev *rtwdev = data;
41 struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
44 rtw_vif_port_config(rtwdev, rtwvif, config);
47 int rtw_leave_ips(struct rtw_dev *rtwdev)
51 ret = rtw_ips_pwr_up(rtwdev);
53 rtw_err(rtwdev, "failed to leave ips state\n");
57 rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev);
59 rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
64 static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
66 struct rtw_lps_conf *conf = &rtwdev->lps_conf;
68 conf->state = RTW_ALL_ON;
69 conf->awake_interval = 1;
73 rtw_fw_set_pwr_mode(rtwdev);
74 rtw_flag_clear(rtwdev, RTW_FLAG_LEISURE_PS);
76 rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE);
79 static void rtw_enter_lps_core(struct rtw_dev *rtwdev)
81 struct rtw_lps_conf *conf = &rtwdev->lps_conf;
83 conf->state = RTW_RF_OFF;
84 conf->awake_interval = 1;
88 rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE);
90 rtw_fw_set_pwr_mode(rtwdev);
91 rtw_flag_set(rtwdev, RTW_FLAG_LEISURE_PS);
94 void rtw_lps_work(struct work_struct *work)
96 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
98 struct rtw_lps_conf *conf = &rtwdev->lps_conf;
99 struct rtw_vif *rtwvif = conf->rtwvif;
101 if (WARN_ON(!rtwvif))
104 if (conf->mode == RTW_MODE_LPS)
105 rtw_enter_lps_core(rtwdev);
107 rtw_leave_lps_core(rtwdev);
110 void rtw_enter_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
112 struct rtw_lps_conf *conf = &rtwdev->lps_conf;
117 conf->mode = RTW_MODE_LPS;
118 conf->rtwvif = rtwvif;
119 rtwvif->in_lps = true;
121 ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->lps_work, 0);
124 void rtw_leave_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
126 struct rtw_lps_conf *conf = &rtwdev->lps_conf;
131 conf->mode = RTW_MODE_ACTIVE;
132 conf->rtwvif = rtwvif;
133 rtwvif->in_lps = false;
135 ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->lps_work, 0);
138 bool rtw_in_lps(struct rtw_dev *rtwdev)
140 return rtw_flag_check(rtwdev, RTW_FLAG_LEISURE_PS);
143 void rtw_enter_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
145 struct rtw_lps_conf *conf = &rtwdev->lps_conf;
147 if (WARN_ON(!rtwvif))
153 conf->mode = RTW_MODE_LPS;
154 conf->rtwvif = rtwvif;
155 rtwvif->in_lps = true;
157 rtw_enter_lps_core(rtwdev);
160 void rtw_leave_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
162 struct rtw_lps_conf *conf = &rtwdev->lps_conf;
164 if (WARN_ON(!rtwvif))
170 conf->mode = RTW_MODE_ACTIVE;
171 conf->rtwvif = rtwvif;
172 rtwvif->in_lps = false;
174 rtw_leave_lps_core(rtwdev);