xref: /linux/drivers/net/wireless/realtek/rtw89/ps.c (revision 23ca32e4ead48f68e37000f2552b973ef1439acb)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2019-2020  Realtek Corporation
3  */
4 
5 #include "chan.h"
6 #include "coex.h"
7 #include "core.h"
8 #include "debug.h"
9 #include "fw.h"
10 #include "mac.h"
11 #include "phy.h"
12 #include "ps.h"
13 #include "reg.h"
14 #include "util.h"
15 
16 static int rtw89_fw_leave_lps_check(struct rtw89_dev *rtwdev, u8 macid)
17 {
18 	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
19 	u32 pwr_en_bit = 0xE;
20 	u32 chk_msk = pwr_en_bit << (4 * macid);
21 	u32 polling;
22 	int ret;
23 
24 	ret = read_poll_timeout_atomic(rtw89_read32_mask, polling, !polling,
25 				       1000, 50000, false, rtwdev,
26 				       mac->ps_status, chk_msk);
27 	if (ret) {
28 		rtw89_info(rtwdev, "rtw89: failed to leave lps state\n");
29 		return -EBUSY;
30 	}
31 
32 	return 0;
33 }
34 
35 static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
36 						bool enter)
37 {
38 	ieee80211_stop_queues(rtwdev->hw);
39 	rtwdev->hci.paused = true;
40 	flush_work(&rtwdev->txq_work);
41 	ieee80211_wake_queues(rtwdev->hw);
42 
43 	rtw89_hci_pause(rtwdev, true);
44 	rtw89_mac_power_mode_change(rtwdev, enter);
45 	rtw89_hci_switch_mode(rtwdev, enter);
46 	rtw89_hci_pause(rtwdev, false);
47 
48 	rtwdev->hci.paused = false;
49 
50 	if (!enter) {
51 		local_bh_disable();
52 		napi_schedule(&rtwdev->napi);
53 		local_bh_enable();
54 	}
55 }
56 
57 static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
58 {
59 	if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
60 	    !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
61 		rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
62 	else
63 		rtw89_mac_power_mode_change(rtwdev, enter);
64 }
65 
66 void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev)
67 {
68 	if (!rtwdev->ps_mode)
69 		return;
70 
71 	if (test_and_set_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags))
72 		return;
73 
74 	rtw89_ps_power_mode_change(rtwdev, true);
75 }
76 
77 void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
78 {
79 	if (!rtwdev->ps_mode)
80 		return;
81 
82 	if (test_and_clear_bit(RTW89_FLAG_LOW_POWER_MODE, rtwdev->flags))
83 		rtw89_ps_power_mode_change(rtwdev, false);
84 }
85 
86 static void __rtw89_enter_lps_link(struct rtw89_dev *rtwdev,
87 				   struct rtw89_vif_link *rtwvif_link)
88 {
89 	struct rtw89_lps_parm lps_param = {
90 		.macid = rtwvif_link->mac_id,
91 		.psmode = RTW89_MAC_AX_PS_MODE_LEGACY,
92 		.lastrpwm = RTW89_LAST_RPWM_PS,
93 	};
94 
95 	rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL);
96 	rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
97 }
98 
99 static void __rtw89_leave_lps(struct rtw89_dev *rtwdev,
100 			      struct rtw89_vif_link *rtwvif_link)
101 {
102 	struct rtw89_lps_parm lps_param = {
103 		.macid = rtwvif_link->mac_id,
104 		.psmode = RTW89_MAC_AX_PS_MODE_ACTIVE,
105 		.lastrpwm = RTW89_LAST_RPWM_ACTIVE,
106 	};
107 
108 	rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
109 	rtw89_fw_leave_lps_check(rtwdev, 0);
110 	rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON);
111 	rtw89_chip_digital_pwr_comp(rtwdev, rtwvif_link->phy_idx);
112 }
113 
114 void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
115 {
116 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
117 
118 	__rtw89_leave_ps_mode(rtwdev);
119 }
120 
121 void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
122 		     bool ps_mode)
123 {
124 	struct rtw89_vif_link *rtwvif_link;
125 	bool can_ps_mode = true;
126 	unsigned int link_id;
127 
128 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
129 
130 	if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
131 		return;
132 
133 	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
134 		__rtw89_enter_lps_link(rtwdev, rtwvif_link);
135 
136 		if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT)
137 			can_ps_mode = false;
138 	}
139 
140 	rtw89_fw_h2c_rf_ps_info(rtwdev, rtwvif);
141 
142 	if (RTW89_CHK_FW_FEATURE(LPS_CH_INFO, &rtwdev->fw))
143 		rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif);
144 	else
145 		rtw89_fw_h2c_lps_ml_cmn_info(rtwdev, rtwvif);
146 
147 	if (ps_mode && can_ps_mode)
148 		__rtw89_enter_ps_mode(rtwdev);
149 }
150 
151 static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev,
152 				struct rtw89_vif_link *rtwvif_link)
153 {
154 	if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION &&
155 	    rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT)
156 		return;
157 
158 	__rtw89_leave_lps(rtwdev, rtwvif_link);
159 }
160 
161 void rtw89_leave_lps(struct rtw89_dev *rtwdev)
162 {
163 	struct rtw89_vif_link *rtwvif_link;
164 	struct rtw89_vif *rtwvif;
165 	unsigned int link_id;
166 
167 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
168 
169 	if (!test_and_clear_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
170 		return;
171 
172 	__rtw89_leave_ps_mode(rtwdev);
173 
174 	rtw89_phy_dm_reinit(rtwdev);
175 
176 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
177 		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
178 			rtw89_leave_lps_vif(rtwdev, rtwvif_link);
179 }
180 
181 void rtw89_enter_ips(struct rtw89_dev *rtwdev)
182 {
183 	struct rtw89_vif_link *rtwvif_link;
184 	struct rtw89_vif *rtwvif;
185 	unsigned int link_id;
186 
187 	set_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
188 
189 	if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
190 		return;
191 
192 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
193 		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
194 			rtw89_mac_vif_deinit(rtwdev, rtwvif_link);
195 
196 	rtw89_core_stop(rtwdev);
197 }
198 
199 void rtw89_leave_ips(struct rtw89_dev *rtwdev)
200 {
201 	struct rtw89_vif_link *rtwvif_link;
202 	struct rtw89_vif *rtwvif;
203 	unsigned int link_id;
204 	int ret;
205 
206 	if (test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
207 		return;
208 
209 	ret = rtw89_core_start(rtwdev);
210 	if (ret)
211 		rtw89_err(rtwdev, "failed to leave idle state\n");
212 
213 	rtw89_set_channel(rtwdev);
214 
215 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
216 		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
217 			rtw89_mac_vif_init(rtwdev, rtwvif_link);
218 
219 	clear_bit(RTW89_FLAG_INACTIVE_PS, rtwdev->flags);
220 }
221 
222 void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl)
223 {
224 	if (btc_ctrl)
225 		rtw89_leave_lps(rtwdev);
226 }
227 
228 static void rtw89_tsf32_toggle(struct rtw89_dev *rtwdev,
229 			       struct rtw89_vif_link *rtwvif_link,
230 			       enum rtw89_p2pps_action act)
231 {
232 	if (act == RTW89_P2P_ACT_UPDATE || act == RTW89_P2P_ACT_REMOVE)
233 		return;
234 
235 	if (act == RTW89_P2P_ACT_INIT)
236 		rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, true);
237 	else if (act == RTW89_P2P_ACT_TERMINATE)
238 		rtw89_fw_h2c_tsf32_toggle(rtwdev, rtwvif_link, false);
239 }
240 
241 void rtw89_p2p_disable_all_noa(struct rtw89_dev *rtwdev,
242 			       struct rtw89_vif_link *rtwvif_link,
243 			       struct ieee80211_bss_conf *bss_conf)
244 {
245 	enum rtw89_p2pps_action act;
246 	u8 oppps_ctwindow;
247 	u8 noa_id;
248 
249 	rcu_read_lock();
250 
251 	if (!bss_conf)
252 		bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
253 
254 	oppps_ctwindow = bss_conf->p2p_noa_attr.oppps_ctwindow;
255 
256 	rcu_read_unlock();
257 
258 	if (rtwvif_link->last_noa_nr == 0)
259 		return;
260 
261 	for (noa_id = 0; noa_id < rtwvif_link->last_noa_nr; noa_id++) {
262 		if (noa_id == rtwvif_link->last_noa_nr - 1)
263 			act = RTW89_P2P_ACT_TERMINATE;
264 		else
265 			act = RTW89_P2P_ACT_REMOVE;
266 		rtw89_tsf32_toggle(rtwdev, rtwvif_link, act);
267 		rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, NULL,
268 				     act, noa_id, oppps_ctwindow);
269 	}
270 }
271 
272 static void rtw89_p2p_update_noa(struct rtw89_dev *rtwdev,
273 				 struct rtw89_vif_link *rtwvif_link,
274 				 struct ieee80211_bss_conf *bss_conf)
275 {
276 	struct ieee80211_p2p_noa_desc *desc;
277 	enum rtw89_p2pps_action act;
278 	u8 noa_id;
279 
280 	for (noa_id = 0; noa_id < RTW89_P2P_MAX_NOA_NUM; noa_id++) {
281 		desc = &bss_conf->p2p_noa_attr.desc[noa_id];
282 		if (!desc->count || !desc->duration)
283 			break;
284 
285 		if (noa_id == 0)
286 			act = RTW89_P2P_ACT_INIT;
287 		else
288 			act = RTW89_P2P_ACT_UPDATE;
289 		rtw89_tsf32_toggle(rtwdev, rtwvif_link, act);
290 		rtw89_fw_h2c_p2p_act(rtwdev, rtwvif_link, desc, act, noa_id,
291 				     bss_conf->p2p_noa_attr.oppps_ctwindow);
292 	}
293 	rtwvif_link->last_noa_nr = noa_id;
294 }
295 
296 void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev,
297 			  struct rtw89_vif_link *rtwvif_link,
298 			  struct ieee80211_bss_conf *bss_conf)
299 {
300 	rtw89_p2p_disable_all_noa(rtwdev, rtwvif_link, bss_conf);
301 	rtw89_p2p_update_noa(rtwdev, rtwvif_link, bss_conf);
302 }
303 
304 void rtw89_recalc_lps(struct rtw89_dev *rtwdev)
305 {
306 	struct ieee80211_vif *vif, *found_vif = NULL;
307 	struct rtw89_vif *rtwvif;
308 	enum rtw89_entity_mode mode;
309 	int count = 0;
310 
311 	mode = rtw89_get_entity_mode(rtwdev);
312 	if (mode == RTW89_ENTITY_MODE_MCC)
313 		goto disable_lps;
314 
315 	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
316 		vif = rtwvif_to_vif(rtwvif);
317 
318 		if (vif->type != NL80211_IFTYPE_STATION) {
319 			count = 0;
320 			break;
321 		}
322 
323 		count++;
324 		found_vif = vif;
325 	}
326 
327 	if (count == 1 && found_vif->cfg.ps) {
328 		rtwdev->lps_enabled = true;
329 		return;
330 	}
331 
332 disable_lps:
333 	rtw89_leave_lps(rtwdev);
334 	rtwdev->lps_enabled = false;
335 }
336 
337 void rtw89_p2p_noa_renew(struct rtw89_vif_link *rtwvif_link)
338 {
339 	struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa;
340 	struct rtw89_p2p_noa_ie *ie = &setter->ie;
341 	struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head;
342 	struct rtw89_noa_attr_head *noa_head = &ie->noa_head;
343 
344 	if (setter->noa_count) {
345 		setter->noa_index++;
346 		setter->noa_count = 0;
347 	}
348 
349 	memset(ie, 0, sizeof(*ie));
350 
351 	p2p_head->eid = WLAN_EID_VENDOR_SPECIFIC;
352 	p2p_head->ie_len = 4 + sizeof(*noa_head);
353 	p2p_head->oui[0] = (WLAN_OUI_WFA >> 16) & 0xff;
354 	p2p_head->oui[1] = (WLAN_OUI_WFA >> 8) & 0xff;
355 	p2p_head->oui[2] = (WLAN_OUI_WFA >> 0) & 0xff;
356 	p2p_head->oui_type = WLAN_OUI_TYPE_WFA_P2P;
357 
358 	noa_head->attr_type = IEEE80211_P2P_ATTR_ABSENCE_NOTICE;
359 	noa_head->attr_len = cpu_to_le16(2);
360 	noa_head->index = setter->noa_index;
361 	noa_head->oppps_ctwindow = 0;
362 }
363 
364 void rtw89_p2p_noa_append(struct rtw89_vif_link *rtwvif_link,
365 			  const struct ieee80211_p2p_noa_desc *desc)
366 {
367 	struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa;
368 	struct rtw89_p2p_noa_ie *ie = &setter->ie;
369 	struct rtw89_p2p_ie_head *p2p_head = &ie->p2p_head;
370 	struct rtw89_noa_attr_head *noa_head = &ie->noa_head;
371 
372 	if (!desc->count || !desc->duration)
373 		return;
374 
375 	if (setter->noa_count >= RTW89_P2P_MAX_NOA_NUM)
376 		return;
377 
378 	p2p_head->ie_len += sizeof(*desc);
379 	le16_add_cpu(&noa_head->attr_len, sizeof(*desc));
380 
381 	ie->noa_desc[setter->noa_count++] = *desc;
382 }
383 
384 u8 rtw89_p2p_noa_fetch(struct rtw89_vif_link *rtwvif_link, void **data)
385 {
386 	struct rtw89_p2p_noa_setter *setter = &rtwvif_link->p2p_noa;
387 	struct rtw89_p2p_noa_ie *ie = &setter->ie;
388 	void *tail;
389 
390 	if (!setter->noa_count)
391 		return 0;
392 
393 	*data = ie;
394 	tail = ie->noa_desc + setter->noa_count;
395 	return tail - *data;
396 }
397 
398 static void rtw89_ps_noa_once_set_work(struct wiphy *wiphy, struct wiphy_work *work)
399 {
400 	struct rtw89_ps_noa_once_handler *noa_once =
401 		container_of(work, struct rtw89_ps_noa_once_handler, set_work.work);
402 
403 	lockdep_assert_wiphy(wiphy);
404 
405 	noa_once->in_duration = true;
406 }
407 
408 static void rtw89_ps_noa_once_clr_work(struct wiphy *wiphy, struct wiphy_work *work)
409 {
410 	struct rtw89_ps_noa_once_handler *noa_once =
411 		container_of(work, struct rtw89_ps_noa_once_handler, clr_work.work);
412 	struct rtw89_vif_link *rtwvif_link =
413 		container_of(noa_once, struct rtw89_vif_link, noa_once);
414 	struct rtw89_dev *rtwdev = rtwvif_link->rtwvif->rtwdev;
415 
416 	lockdep_assert_wiphy(wiphy);
417 
418 	rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
419 	noa_once->in_duration = false;
420 }
421 
422 void rtw89_p2p_noa_once_init(struct rtw89_vif_link *rtwvif_link)
423 {
424 	struct rtw89_ps_noa_once_handler *noa_once = &rtwvif_link->noa_once;
425 
426 	noa_once->in_duration = false;
427 	noa_once->tsf_begin = 0;
428 	noa_once->tsf_end = 0;
429 
430 	wiphy_delayed_work_init(&noa_once->set_work, rtw89_ps_noa_once_set_work);
431 	wiphy_delayed_work_init(&noa_once->clr_work, rtw89_ps_noa_once_clr_work);
432 }
433 
434 static void rtw89_p2p_noa_once_cancel(struct rtw89_vif_link *rtwvif_link)
435 {
436 	struct rtw89_ps_noa_once_handler *noa_once = &rtwvif_link->noa_once;
437 	struct rtw89_dev *rtwdev = rtwvif_link->rtwvif->rtwdev;
438 	struct wiphy *wiphy = rtwdev->hw->wiphy;
439 
440 	wiphy_delayed_work_cancel(wiphy, &noa_once->set_work);
441 	wiphy_delayed_work_cancel(wiphy, &noa_once->clr_work);
442 }
443 
444 void rtw89_p2p_noa_once_deinit(struct rtw89_vif_link *rtwvif_link)
445 {
446 	rtw89_p2p_noa_once_cancel(rtwvif_link);
447 	rtw89_p2p_noa_once_init(rtwvif_link);
448 }
449 
450 void rtw89_p2p_noa_once_recalc(struct rtw89_vif_link *rtwvif_link)
451 {
452 	struct rtw89_ps_noa_once_handler *noa_once = &rtwvif_link->noa_once;
453 	struct rtw89_dev *rtwdev = rtwvif_link->rtwvif->rtwdev;
454 	const struct ieee80211_p2p_noa_desc *noa_desc;
455 	struct wiphy *wiphy = rtwdev->hw->wiphy;
456 	struct ieee80211_bss_conf *bss_conf;
457 	u64 tsf_begin = U64_MAX, tsf_end;
458 	u64 set_delay_us = 0;
459 	u64 clr_delay_us = 0;
460 	u32 start_time;
461 	u32 interval;
462 	u32 duration;
463 	u64 tsf;
464 	int ret;
465 	int i;
466 
467 	lockdep_assert_wiphy(wiphy);
468 
469 	ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
470 	if (ret) {
471 		rtw89_warn(rtwdev, "%s: failed to get tsf\n", __func__);
472 		return;
473 	}
474 
475 	rcu_read_lock();
476 
477 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
478 
479 	for (i = 0; i < ARRAY_SIZE(bss_conf->p2p_noa_attr.desc); i++) {
480 		bool first = tsf_begin == U64_MAX;
481 		u64 tmp;
482 
483 		noa_desc = &bss_conf->p2p_noa_attr.desc[i];
484 		if (noa_desc->count == 0 || noa_desc->count == 255)
485 			continue;
486 
487 		start_time = le32_to_cpu(noa_desc->start_time);
488 		interval = le32_to_cpu(noa_desc->interval);
489 		duration = le32_to_cpu(noa_desc->duration);
490 
491 		if (unlikely(duration == 0 ||
492 			     (noa_desc->count > 1 && interval == 0)))
493 			continue;
494 
495 		tmp = start_time + interval * (noa_desc->count - 1) + duration;
496 		tmp = (tsf & GENMASK_ULL(63, 32)) + tmp;
497 		if (unlikely(tmp <= tsf))
498 			continue;
499 		tsf_end = first ? tmp : max(tsf_end, tmp);
500 
501 		tmp = (tsf & GENMASK_ULL(63, 32)) | start_time;
502 		tsf_begin = first ? tmp : min(tsf_begin, tmp);
503 	}
504 
505 	rcu_read_unlock();
506 
507 	if (tsf_begin == U64_MAX)
508 		return;
509 
510 	rtw89_p2p_noa_once_cancel(rtwvif_link);
511 
512 	if (noa_once->tsf_end > tsf) {
513 		tsf_begin = min(tsf_begin, noa_once->tsf_begin);
514 		tsf_end = max(tsf_end, noa_once->tsf_end);
515 	}
516 
517 	clr_delay_us = min_t(u64, tsf_end - tsf, UINT_MAX);
518 
519 	if (tsf_begin <= tsf) {
520 		noa_once->in_duration = true;
521 		goto out;
522 	}
523 
524 	set_delay_us = tsf_begin - tsf;
525 	if (unlikely(set_delay_us > UINT_MAX)) {
526 		rtw89_warn(rtwdev, "%s: unhandled begin\n", __func__);
527 		set_delay_us = 0;
528 		clr_delay_us = 0;
529 		rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
530 		noa_once->in_duration = false;
531 	}
532 
533 out:
534 	if (set_delay_us)
535 		wiphy_delayed_work_queue(wiphy, &noa_once->set_work,
536 					 usecs_to_jiffies(set_delay_us));
537 	if (clr_delay_us)
538 		wiphy_delayed_work_queue(wiphy, &noa_once->clr_work,
539 					 usecs_to_jiffies(clr_delay_us));
540 
541 	noa_once->tsf_begin = tsf_begin;
542 	noa_once->tsf_end = tsf_end;
543 }
544