rtw88: remove redundant flag check helper function
[linux-2.6-block.git] / drivers / net / wireless / realtek / rtw88 / ps.c
CommitLineData
e3037485
YHC
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"
4136214f 9#include "coex.h"
e3037485
YHC
10#include "debug.h"
11
12static 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);
3c519605 21 clear_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
e3037485
YHC
22
23 return ret;
24}
25
26int rtw_enter_ips(struct rtw_dev *rtwdev)
27{
3c519605 28 set_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
e3037485 29
4136214f
YHC
30 rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
31
e3037485
YHC
32 rtw_core_stop(rtwdev);
33
34 return 0;
35}
36
37static 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
47int 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
4136214f
YHC
59 rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE);
60
e3037485
YHC
61 return 0;
62}
63
64static 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);
3c519605 74 clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
4136214f
YHC
75
76 rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE);
e3037485
YHC
77}
78
79static 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
4136214f
YHC
88 rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE);
89
e3037485 90 rtw_fw_set_pwr_mode(rtwdev);
3c519605 91 set_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
e3037485
YHC
92}
93
94void 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
110void 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
124void 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
138bool rtw_in_lps(struct rtw_dev *rtwdev)
139{
3c519605 140 return test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
e3037485
YHC
141}
142
143void 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
160void 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}