xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/phl_ps.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2021 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _PHL_PS_C_
16 #include "phl_headers.h"
17 #ifdef CONFIG_POWER_SAVE
phl_ps_op_mode_to_str(u8 op_mode)18 const char *phl_ps_op_mode_to_str(u8 op_mode)
19 {
20 	switch (op_mode) {
21 	case PS_OP_MODE_DISABLED:
22 		return "Disabled";
23 	case PS_OP_MODE_FORCE_ENABLED:
24 		return "Force Enabled";
25 	case PS_OP_MODE_AUTO:
26 		return "Auto";
27 	default:
28 		return "-";
29 	}
30 }
31 
phl_ps_ps_mode_to_str(u8 ps_mode)32 const char *phl_ps_ps_mode_to_str(u8 ps_mode)
33 {
34 	switch (ps_mode) {
35 	case PS_MODE_IPS:
36 		return "IPS";
37 	case PS_MODE_LPS:
38 		return "LPS";
39 	default:
40 		return "NONE";
41 	}
42 }
43 
44 #define case_pwr_lvl(src) \
45 	case PS_PWR_LVL_##src: return #src
phl_ps_pwr_lvl_to_str(u8 pwr_lvl)46 const char *phl_ps_pwr_lvl_to_str(u8 pwr_lvl)
47 {
48 	switch (pwr_lvl) {
49 	case_pwr_lvl(PWROFF);
50 	case_pwr_lvl(PWR_GATED);
51 	case_pwr_lvl(CLK_GATED);
52 	case_pwr_lvl(RF_OFF);
53 	case_pwr_lvl(PWRON);
54 	case_pwr_lvl(MAX);
55 	default:
56 		return "Undefined";
57 	}
58 }
59 
phl_ps_judge_pwr_lvl(u8 ps_cap,u8 ps_mode,u8 ps_en)60 u8 phl_ps_judge_pwr_lvl(u8 ps_cap, u8 ps_mode, u8 ps_en)
61 {
62 	if (!ps_en)
63 		return PS_PWR_LVL_PWRON;
64 
65 	if (ps_mode == PS_MODE_IPS) {
66 		if (ps_cap & PS_CAP_PWR_OFF)
67 			return PS_PWR_LVL_PWROFF;
68 		else if (ps_cap & PS_CAP_PWR_GATED)
69 			return PS_PWR_LVL_PWR_GATED;
70 		else if (ps_cap & PS_CAP_CLK_GATED)
71 			return PS_PWR_LVL_CLK_GATED;
72 		else if (ps_cap & PS_CAP_RF_OFF)
73 			return PS_PWR_LVL_RF_OFF;
74 		else
75 			return PS_PWR_LVL_PWROFF; /* ips default support power off */
76 	} else if (ps_mode == PS_MODE_LPS) {
77 		if (ps_cap & PS_CAP_PWR_GATED)
78 			return PS_PWR_LVL_PWR_GATED;
79 		else if (ps_cap & PS_CAP_CLK_GATED)
80 			return PS_PWR_LVL_CLK_GATED;
81 		else if (ps_cap & PS_CAP_RF_OFF)
82 			return PS_PWR_LVL_RF_OFF;
83 		else if (ps_cap & PS_CAP_PWRON)
84 			return PS_PWR_LVL_PWRON;
85 		else
86 			return PS_PWR_LVL_PWRON; /* lps default support protocol */
87 	} else {
88 		PHL_TRACE(COMP_PHL_PS, _PHL_WARNING_, "[PS], %s(): unknown ps mode!\n", __func__);
89 	}
90 
91 	return PS_PWR_LVL_PWRON;
92 }
93 
_ps_ntfy_before_pwr_cfg(struct phl_info_t * phl_info,u8 ps_mode,u8 cur_pwr_lvl,u8 req_pwr_lvl)94 static void _ps_ntfy_before_pwr_cfg(struct phl_info_t *phl_info, u8 ps_mode,
95 			u8 cur_pwr_lvl, u8 req_pwr_lvl)
96 {
97 	PHL_TRACE(COMP_PHL_PS, _PHL_DEBUG_, "[PS], %s(): \n", __func__);
98 
99 	if (cur_pwr_lvl == PS_PWR_LVL_PWRON) { /* enter ps */
100 		if (req_pwr_lvl == PS_PWR_LVL_PWROFF) {
101 			#ifdef CONFIG_BTCOEX
102 			rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_WL_OFF);
103 			#endif
104 			#if defined(CONFIG_PCI_HCI) && defined(RTW_WKARD_DYNAMIC_LTR)
105 			phl_ltr_sw_ctrl_ntfy(phl_info->phl_com, false);
106 			#endif
107 		} else if (req_pwr_lvl <= PS_PWR_LVL_RF_OFF) {
108 			#ifdef CONFIG_BTCOEX
109 			rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_FW_CTRL);
110 			#endif
111 			#if defined(CONFIG_PCI_HCI) && defined(RTW_WKARD_DYNAMIC_LTR)
112 			if (req_pwr_lvl == PS_PWR_LVL_PWR_GATED)
113 				phl_ltr_sw_ctrl_ntfy(phl_info->phl_com, false);
114 			#endif
115 		}
116 	}
117 }
118 
_ps_ntfy_after_pwr_cfg(struct phl_info_t * phl_info,u8 ps_mode,u8 cur_pwr_lvl,u8 req_pwr_lvl,u8 cfg_ok)119 static void _ps_ntfy_after_pwr_cfg(struct phl_info_t *phl_info, u8 ps_mode,
120 			u8 cur_pwr_lvl, u8 req_pwr_lvl, u8 cfg_ok)
121 {
122 	PHL_TRACE(COMP_PHL_PS, _PHL_DEBUG_, "[PS], %s(): \n", __func__);
123 
124 	if (cur_pwr_lvl > req_pwr_lvl) { /* enter ps */
125 		if (!cfg_ok) { /* fail */
126 			if (req_pwr_lvl == PS_PWR_LVL_PWROFF) { /* driver ips */
127 				#ifdef CONFIG_BTCOEX
128 				rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_WL_ON);
129 				#endif
130 				#if defined(CONFIG_PCI_HCI) && defined(RTW_WKARD_DYNAMIC_LTR)
131 				phl_ltr_sw_ctrl_ntfy(phl_info->phl_com, true);
132 				#endif
133 			} else { /* fw control */
134 				#ifdef CONFIG_BTCOEX
135 				if (ps_mode == PS_MODE_LPS)
136 					rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_LPS_WL_ON);
137 				else
138 					rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_WL_ON);
139 				#endif
140 				#if defined(CONFIG_PCI_HCI) && defined(RTW_WKARD_DYNAMIC_LTR)
141 				phl_ltr_sw_ctrl_ntfy(phl_info->phl_com, true);
142 				#endif
143 			}
144 		}
145 	} else { /* leave ps */
146 		if (cfg_ok) { /* ok */
147 			if (cur_pwr_lvl == PS_PWR_LVL_PWROFF) { /* driver ips */
148 				if (req_pwr_lvl == PS_PWR_LVL_PWRON) {
149 					#ifdef CONFIG_BTCOEX
150 					rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_WL_ON);
151 					#endif
152 					#if defined(CONFIG_PCI_HCI) && defined(RTW_WKARD_DYNAMIC_LTR)
153 					phl_ltr_sw_ctrl_ntfy(phl_info->phl_com, true);
154 					#endif
155 				}
156 			} else { /* fw control */
157 				if (req_pwr_lvl == PS_PWR_LVL_PWRON) {
158 					#ifdef CONFIG_BTCOEX
159 					if (ps_mode == PS_MODE_LPS)
160 						rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_LPS_WL_ON);
161 					else
162 						rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_WL_ON);
163 					#endif
164 					#if defined(CONFIG_PCI_HCI) && defined(RTW_WKARD_DYNAMIC_LTR)
165 					phl_ltr_sw_ctrl_ntfy(phl_info->phl_com, true);
166 					#endif
167 				}
168 			}
169 		}
170 	}
171 }
172 
173 enum rtw_phl_status
phl_ps_cfg_pwr_lvl(struct phl_info_t * phl_info,u8 ps_mode,u8 cur_pwr_lvl,u8 req_pwr_lvl)174 phl_ps_cfg_pwr_lvl(struct phl_info_t *phl_info, u8 ps_mode, u8 cur_pwr_lvl, u8 req_pwr_lvl)
175 {
176 	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
177 
178 	PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): from %s to %s.\n",
179 			__func__, phl_ps_pwr_lvl_to_str(cur_pwr_lvl), phl_ps_pwr_lvl_to_str(req_pwr_lvl));
180 
181 	if (cur_pwr_lvl == req_pwr_lvl)
182 		PHL_TRACE(COMP_PHL_PS, _PHL_WARNING_, "[PS], %s(): pwr lvl is not change!\n", __func__);
183 
184 	_ps_ntfy_before_pwr_cfg(phl_info, ps_mode, cur_pwr_lvl, req_pwr_lvl);
185 
186 	hstatus = rtw_hal_ps_pwr_lvl_cfg(phl_info->phl_com, phl_info->hal,
187 				req_pwr_lvl);
188 
189 	_ps_ntfy_after_pwr_cfg(phl_info, ps_mode, cur_pwr_lvl, req_pwr_lvl,
190 						   (hstatus == RTW_HAL_STATUS_SUCCESS ? true : false));
191 
192 	return (hstatus == RTW_HAL_STATUS_SUCCESS) ? RTW_PHL_STATUS_SUCCESS : RTW_PHL_STATUS_FAILURE;
193 }
194 
195 
_ps_ntfy_before_lps_proto_cfg(struct phl_info_t * phl_info,u8 lps_en)196 static void _ps_ntfy_before_lps_proto_cfg(struct phl_info_t *phl_info, u8 lps_en)
197 {
198 	PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): \n", __func__);
199 
200 	if (lps_en) { /* enter lps */
201 		#ifdef CONFIG_BTCOEX
202 		rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_LPS_WL_ON);
203 		#endif
204 	}
205 }
206 
207 static void
_ps_ntfy_after_lps_proto_cfg(struct phl_info_t * phl_info,u8 lps_en,u8 cfg_ok)208 _ps_ntfy_after_lps_proto_cfg(struct phl_info_t *phl_info, u8 lps_en, u8 cfg_ok)
209 {
210 	PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): \n", __func__);
211 
212 	if (lps_en) { /* enter lps */
213 		if (!cfg_ok) { /* fail */
214 			#ifdef CONFIG_BTCOEX
215 			rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_WL_ON);
216 			#endif
217 		}
218 	} else { /* leave lps */
219 		if (cfg_ok) { /* ok */
220 			#ifdef CONFIG_BTCOEX
221 			rtw_hal_btc_radio_state_ntfy(phl_info->hal, BTC_RFCTRL_WL_ON);
222 			#endif
223 		}
224 	}
225 }
226 
_phl_lps_role_config_tbtt_agg(struct phl_info_t * phl_info,struct rtw_wifi_role_t * cur_wrole,u32 tbtt_agg_val)227 static void _phl_lps_role_config_tbtt_agg(struct phl_info_t *phl_info,
228 	struct rtw_wifi_role_t *cur_wrole, u32 tbtt_agg_val)
229 {
230 	u8 role_idx;
231 	struct rtw_wifi_role_t * wrole;
232 	u32 tbtt_agg = tbtt_agg_val;
233 
234 	if (cur_wrole == NULL) {
235 		PHL_ERR("%s cur role is NULL\n", __func__);
236 		return;
237 	}
238 
239 	for (role_idx = 0; role_idx < MAX_WIFI_ROLE_NUMBER; role_idx++) {
240 		wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, role_idx);
241 		if(wrole == NULL || !wrole->active)
242 			continue;
243 
244 		if (wrole == cur_wrole)
245 			continue;
246 
247 		PHL_INFO("%s role %d config tbtt agg = %d\n", __func__, role_idx, tbtt_agg_val);
248 		rtw_hal_role_cfg_ex(phl_info->hal, wrole, PCFG_TBTT_AGG, &tbtt_agg);
249 	}
250 }
251 
_phl_ips_role_config_tbtt_agg(struct phl_info_t * phl_info,u32 tbtt_agg_val)252 static void _phl_ips_role_config_tbtt_agg(struct phl_info_t *phl_info,
253 	 u32 tbtt_agg_val)
254 {
255 	u8 role_idx;
256 	struct rtw_wifi_role_t *wrole;
257 	u32 tbtt_agg = tbtt_agg_val;
258 
259 	for (role_idx = 0; role_idx < MAX_WIFI_ROLE_NUMBER; role_idx++) {
260 		wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, role_idx);
261 		if (wrole == NULL || !wrole->active)
262 			continue;
263 
264 		PHL_INFO("%s role %d config tbtt agg = %d\n", __func__, role_idx,
265 			 tbtt_agg_val);
266 		rtw_hal_role_cfg_ex(phl_info->hal, wrole, PCFG_TBTT_AGG, &tbtt_agg);
267 	}
268 }
269 
270 enum rtw_phl_status
phl_ps_ips_cfg(struct phl_info_t * phl_info,struct ps_cfg * cfg,u8 en)271 phl_ps_ips_cfg(struct phl_info_t *phl_info, struct ps_cfg *cfg, u8 en)
272 {
273 	u32 tbtt_agg = en ? 0 : RTW_MAC_TBTT_AGG_DEF;
274 	struct rtw_hal_ips_info ips_info = {0};
275 
276 	/* avoid waking up at each TBTT under disconnected standby */
277 	_phl_ips_role_config_tbtt_agg(phl_info, tbtt_agg);
278 
279 	ips_info.en = en;
280 	ips_info.macid = cfg->macid;
281 
282 	return rtw_hal_ps_ips_cfg(phl_info->hal, &ips_info);
283 }
284 
285 enum rtw_phl_status
phl_ps_lps_cfg(struct phl_info_t * phl_info,struct ps_cfg * cfg,u8 en)286 phl_ps_lps_cfg(struct phl_info_t *phl_info, struct ps_cfg *cfg, u8 en)
287 {
288 	enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
289 	struct rtw_hal_lps_info lps_info;
290 	struct rtw_wifi_role_t *wrole = NULL;
291 	struct rtw_phl_stainfo_t *sta = NULL;
292 
293 	sta = rtw_phl_get_stainfo_by_macid(phl_info, cfg->macid);
294 	if (sta != NULL) {
295 		wrole = sta->wrole;
296 	} else {
297 		PHL_TRACE(COMP_PHL_PS, _PHL_WARNING_, "[PS], %s(): cannot get sta!\n", __func__);
298 	}
299 
300 	if (RTW_PHL_STATUS_SUCCESS != phl_snd_cmd_ntfy_ps(phl_info, wrole, en)) {
301 		status = RTW_PHL_STATUS_FAILURE;
302 		return status;
303 	}
304 
305 	if (en) {
306 		PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): enter lps, macid %d.\n", __func__, cfg->macid);
307 		_phl_lps_role_config_tbtt_agg(phl_info, wrole, 0);
308 	} else {
309 		PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): leave lps, macid %d.\n", __func__, cfg->macid);
310 		_phl_lps_role_config_tbtt_agg(phl_info, wrole, RTW_MAC_TBTT_AGG_DEF);
311 	}
312 
313 	lps_info.en = en;
314 	lps_info.macid = cfg->macid;
315 	lps_info.listen_bcn_mode = cfg->listen_bcn_mode;
316 	lps_info.awake_interval = cfg->awake_interval;
317 	lps_info.smart_ps_mode = cfg->smart_ps_mode;
318 
319 	_ps_ntfy_before_lps_proto_cfg(phl_info, en);
320 
321 	if (rtw_hal_ps_lps_cfg(phl_info->hal, &lps_info) != RTW_HAL_STATUS_SUCCESS) {
322 		PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config lps fail.\n", __func__);
323 		rtw_hal_notification(phl_info->hal, MSG_EVT_DBG_TX_DUMP, HW_PHY_0);
324 		status = RTW_PHL_STATUS_FAILURE;
325 	}
326 
327 	_ps_ntfy_after_lps_proto_cfg(phl_info, en, (status == RTW_PHL_STATUS_SUCCESS ? true : false));
328 
329 	return status;
330 }
331 
_lps_enter_proto_cfg(struct phl_info_t * phl_info,struct ps_cfg * cfg)332 static enum rtw_phl_status _lps_enter_proto_cfg(struct phl_info_t *phl_info, struct ps_cfg *cfg)
333 {
334 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
335 	struct rtw_pkt_ofld_null_info null_info = {0};
336 	struct rtw_phl_stainfo_t *phl_sta = NULL;
337 	void *d = phl_to_drvpriv(phl_info);
338 
339 	PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): \n", __func__);
340 
341 #ifdef CONFIG_PHL_PS_FW_DBG
342 	rtw_hal_cfg_fw_ps_log(phl_info->hal, true);
343 #endif
344 
345 	phl_sta = rtw_phl_get_stainfo_by_macid(phl_info, cfg->macid);
346 	if (phl_sta == NULL)
347 		return RTW_PHL_STATUS_FAILURE;
348 
349 	_os_mem_cpy(d, &(null_info.a1[0]), &(phl_sta->mac_addr[0]),
350 		MAC_ADDRESS_LENGTH);
351 
352 	_os_mem_cpy(d,&(null_info.a2[0]), &(phl_sta->wrole->mac_addr[0]),
353 			MAC_ADDRESS_LENGTH);
354 
355 	_os_mem_cpy(d, &(null_info.a3[0]), &(phl_sta->mac_addr[0]),
356 			MAC_ADDRESS_LENGTH);
357 
358 	status = RTW_PHL_PKT_OFLD_REQ(phl_info, cfg->macid,
359 				PKT_TYPE_NULL_DATA, cfg->token, &null_info);
360 	if (status != RTW_PHL_STATUS_SUCCESS) {
361 		PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): add null pkt ofld fail!\n", __func__);
362 		return status;
363 	}
364 
365 	status = phl_ps_lps_cfg(phl_info, cfg, true);
366 	if (status != RTW_PHL_STATUS_SUCCESS) {
367 		PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config lps fail!\n", __func__);
368 		return status;
369 	}
370 
371 	return RTW_PHL_STATUS_SUCCESS;
372 }
373 
_lps_leave_proto_cfg(struct phl_info_t * phl_info,struct ps_cfg * cfg)374 static enum rtw_phl_status _lps_leave_proto_cfg(struct phl_info_t *phl_info, struct ps_cfg *cfg)
375 {
376 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
377 
378 	PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): \n", __func__);
379 
380 	status = phl_ps_lps_cfg(phl_info, cfg, false);
381 	if (status != RTW_PHL_STATUS_SUCCESS) {
382 		PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config lps fail!\n", __func__);
383 		return status;
384 	}
385 
386 	status = phl_pkt_ofld_cancel(phl_info, cfg->macid,
387 				PKT_TYPE_NULL_DATA, cfg->token);
388 	if (status != RTW_PHL_STATUS_SUCCESS) {
389 		PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): del null pkt ofld fail!\n", __func__);
390 		return status;
391 	}
392 
393 	return RTW_PHL_STATUS_SUCCESS;
394 }
395 
phl_ps_lps_proto_cfg(struct phl_info_t * phl_info,struct ps_cfg * cfg,bool lps_en)396 enum rtw_phl_status phl_ps_lps_proto_cfg(struct phl_info_t *phl_info, struct ps_cfg *cfg, bool lps_en)
397 {
398 	if (lps_en)
399 		return _lps_enter_proto_cfg(phl_info, cfg);
400 	else
401 		return _lps_leave_proto_cfg(phl_info, cfg);
402 }
403 
phl_ps_lps_enter(struct phl_info_t * phl_info,struct ps_cfg * cfg)404 enum rtw_phl_status phl_ps_lps_enter(struct phl_info_t *phl_info, struct ps_cfg *cfg)
405 {
406 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
407 
408 	if (cfg->proto_cfg) {
409 		status = phl_ps_lps_proto_cfg(phl_info, cfg, true);
410 		if (status != RTW_PHL_STATUS_SUCCESS) {
411 			PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config lps protocol fail!\n", __func__);
412 			return status;
413 		}
414 	}
415 
416 	if (cfg->pwr_cfg) {
417 		status = phl_ps_cfg_pwr_lvl(phl_info, cfg->ps_mode, cfg->cur_pwr_lvl, cfg->pwr_lvl);
418 		if (status != RTW_PHL_STATUS_SUCCESS) {
419 			PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config lps pwr lvl fail!\n", __func__);
420 			return status;
421 		}
422 	}
423 
424 	return RTW_PHL_STATUS_SUCCESS;
425 }
426 
phl_ps_lps_leave(struct phl_info_t * phl_info,struct ps_cfg * cfg)427 enum rtw_phl_status phl_ps_lps_leave(struct phl_info_t *phl_info, struct ps_cfg *cfg)
428 {
429 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
430 
431 	if (cfg->pwr_cfg) {
432 		status = phl_ps_cfg_pwr_lvl(phl_info, cfg->ps_mode, cfg->cur_pwr_lvl, cfg->pwr_lvl);
433 		if (status != RTW_PHL_STATUS_SUCCESS) {
434 			PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config lps pwr lvl fail!\n", __func__);
435 			return status;
436 		}
437 	}
438 
439 	if (cfg->proto_cfg) {
440 		status = phl_ps_lps_proto_cfg(phl_info, cfg, false);
441 		if (status != RTW_PHL_STATUS_SUCCESS) {
442 			PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config lps protocol fail!\n", __func__);
443 			return status;
444 		}
445 	}
446 
447 	return RTW_PHL_STATUS_SUCCESS;
448 }
449 
phl_ps_ips_proto_cfg(struct phl_info_t * phl_info,struct ps_cfg * cfg,bool ips_en)450 enum rtw_phl_status phl_ps_ips_proto_cfg(struct phl_info_t *phl_info, struct ps_cfg *cfg, bool ips_en)
451 {
452 	/* ips protocol config */
453 	PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): \n", __func__);
454 
455 	phl_ps_ips_cfg(phl_info, cfg, ips_en);
456 
457 	return RTW_PHL_STATUS_SUCCESS;
458 }
459 
phl_ps_ips_enter(struct phl_info_t * phl_info,struct ps_cfg * cfg)460 enum rtw_phl_status phl_ps_ips_enter(struct phl_info_t *phl_info, struct ps_cfg *cfg)
461 {
462 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
463 
464 	if (cfg->proto_cfg) {
465 		status = phl_ps_ips_proto_cfg(phl_info, cfg, true);
466 		if (status != RTW_PHL_STATUS_SUCCESS) {
467 			PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config ips protocol fail!\n", __func__);
468 			return status;
469 		}
470 	}
471 
472 	if (cfg->pwr_cfg) {
473 		status = phl_ps_cfg_pwr_lvl(phl_info, cfg->ps_mode, cfg->cur_pwr_lvl, cfg->pwr_lvl);
474 		if (status != RTW_PHL_STATUS_SUCCESS) {
475 			PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config ips pwr lvl fail!\n", __func__);
476 			return status;
477 		}
478 	}
479 
480 	return status;
481 }
482 
phl_ps_ips_leave(struct phl_info_t * phl_info,struct ps_cfg * cfg)483 enum rtw_phl_status phl_ps_ips_leave(struct phl_info_t *phl_info, struct ps_cfg *cfg)
484 {
485 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
486 
487 	if (cfg->pwr_cfg) {
488 		status = phl_ps_cfg_pwr_lvl(phl_info, cfg->ps_mode, cfg->cur_pwr_lvl, cfg->pwr_lvl);
489 		if (status != RTW_PHL_STATUS_SUCCESS) {
490 			PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config ips pwr lvl fail!\n", __func__);
491 			return status;
492 		}
493 	}
494 
495 	if (cfg->proto_cfg) {
496 		status = phl_ps_ips_proto_cfg(phl_info, cfg, false);
497 		if (status != RTW_PHL_STATUS_SUCCESS) {
498 			PHL_TRACE(COMP_PHL_PS, _PHL_ERR_, "[PS], %s(): config ips protocol fail!\n", __func__);
499 			return status;
500 		}
501 	}
502 
503 	return status;
504 }
505 
506 enum rtw_phl_status
phl_ps_enter_ps(struct phl_info_t * phl_info,struct ps_cfg * cfg)507 phl_ps_enter_ps(struct phl_info_t *phl_info, struct ps_cfg *cfg)
508 {
509 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
510 
511 	PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): ps mode(%s), pwr lvl(%s), macid(%d), token(0x%x), proto_cfg(%d), pwr_cfg(%d)\n",
512 			__func__, phl_ps_ps_mode_to_str(cfg->ps_mode), phl_ps_pwr_lvl_to_str(cfg->pwr_lvl),
513 			cfg->macid, (cfg->token == NULL) ? 0xFF : *cfg->token, cfg->proto_cfg, cfg->pwr_cfg);
514 
515 	if (cfg->ps_mode == PS_MODE_LPS)
516 		status = phl_ps_lps_enter(phl_info, cfg);
517 	else if (cfg->ps_mode == PS_MODE_IPS)
518 		status = phl_ps_ips_enter(phl_info, cfg);
519 
520 	return status;
521 }
522 
523 enum rtw_phl_status
phl_ps_leave_ps(struct phl_info_t * phl_info,struct ps_cfg * cfg)524 phl_ps_leave_ps(struct phl_info_t *phl_info, struct ps_cfg *cfg)
525 {
526 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
527 
528 	PHL_TRACE(COMP_PHL_PS, _PHL_INFO_, "[PS], %s(): current ps mode(%s), pwr lvl(%s), macid(%d), token(0x%x), proto_cfg(%d), pwr_cfg(%d)\n",
529 			__func__, phl_ps_ps_mode_to_str(cfg->ps_mode), phl_ps_pwr_lvl_to_str(cfg->pwr_lvl),
530 			cfg->macid, (cfg->token == NULL) ? 0xFF : *cfg->token, cfg->proto_cfg, cfg->pwr_cfg);
531 
532 	if (cfg->ps_mode == PS_MODE_LPS)
533 		status = phl_ps_lps_leave(phl_info, cfg);
534 	else if (cfg->ps_mode == PS_MODE_IPS)
535 		status = phl_ps_ips_leave(phl_info, cfg);
536 
537 	return status;
538 }
539 #endif
540