1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2012 Realtek Corporation.*/
7 #include <linux/export.h>
8 #include "btcoexist/rtl_btc.h"
10 bool rtl_ps_enable_nic(struct ieee80211_hw
*hw
)
12 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
13 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
14 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
15 struct rtl_mac
*rtlmac
= rtl_mac(rtl_priv(hw
));
17 /*<1> reset trx ring */
18 if (rtlhal
->interface
== INTF_PCI
)
19 rtlpriv
->intf_ops
->reset_trx_ring(hw
);
21 if (is_hal_stop(rtlhal
))
22 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
23 "Driver is already down!\n");
25 /*<2> Enable Adapter */
26 if (rtlpriv
->cfg
->ops
->hw_init(hw
))
28 rtlpriv
->cfg
->ops
->set_hw_reg(hw
, HW_VAR_RETRY_LIMIT
,
30 RT_CLEAR_PS_LEVEL(ppsc
, RT_RF_OFF_LEVL_HALT_NIC
);
32 rtlpriv
->cfg
->ops
->switch_channel(hw
);
33 rtlpriv
->cfg
->ops
->set_channel_access(hw
);
34 rtlpriv
->cfg
->ops
->set_bw_mode(hw
,
35 cfg80211_get_chandef_type(&hw
->conf
.chandef
));
37 /*<3> Enable Interrupt */
38 rtlpriv
->cfg
->ops
->enable_interrupt(hw
);
41 rtl_watch_dog_timer_callback(&rtlpriv
->works
.watchdog_timer
);
45 EXPORT_SYMBOL(rtl_ps_enable_nic
);
47 bool rtl_ps_disable_nic(struct ieee80211_hw
*hw
)
49 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
51 /*<1> Stop all timer */
52 rtl_deinit_deferred_work(hw
, true);
54 /*<2> Disable Interrupt */
55 rtlpriv
->cfg
->ops
->disable_interrupt(hw
);
56 tasklet_kill(&rtlpriv
->works
.irq_tasklet
);
58 /*<3> Disable Adapter */
59 rtlpriv
->cfg
->ops
->hw_disable(hw
);
63 EXPORT_SYMBOL(rtl_ps_disable_nic
);
65 static bool rtl_ps_set_rf_state(struct ieee80211_hw
*hw
,
66 enum rf_pwrstate state_toset
,
69 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
70 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
71 enum rf_pwrstate rtstate
;
72 bool actionallowed
= false;
75 /*Only one thread can change
76 *the RF state at one time, and others
77 *should wait to be executed.
80 spin_lock(&rtlpriv
->locks
.rf_ps_lock
);
81 if (ppsc
->rfchange_inprogress
) {
82 spin_unlock(&rtlpriv
->locks
.rf_ps_lock
);
84 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
85 "RF Change in progress! Wait to set..state_toset(%d).\n",
88 /* Set RF after the previous action is done. */
89 while (ppsc
->rfchange_inprogress
) {
92 /*Wait too long, return false to avoid
99 ppsc
->rfchange_inprogress
= true;
100 spin_unlock(&rtlpriv
->locks
.rf_ps_lock
);
105 rtstate
= ppsc
->rfpwr_state
;
107 switch (state_toset
) {
109 ppsc
->rfoff_reason
&= (~changesource
);
111 if ((changesource
== RF_CHANGE_BY_HW
) &&
112 (ppsc
->hwradiooff
)) {
113 ppsc
->hwradiooff
= false;
116 if (!ppsc
->rfoff_reason
) {
117 ppsc
->rfoff_reason
= 0;
118 actionallowed
= true;
125 if ((changesource
== RF_CHANGE_BY_HW
) && !ppsc
->hwradiooff
) {
126 ppsc
->hwradiooff
= true;
129 ppsc
->rfoff_reason
|= changesource
;
130 actionallowed
= true;
134 ppsc
->rfoff_reason
|= changesource
;
135 actionallowed
= true;
139 pr_err("switch case %#x not processed\n", state_toset
);
144 rtlpriv
->cfg
->ops
->set_rf_power_state(hw
, state_toset
);
146 spin_lock(&rtlpriv
->locks
.rf_ps_lock
);
147 ppsc
->rfchange_inprogress
= false;
148 spin_unlock(&rtlpriv
->locks
.rf_ps_lock
);
150 return actionallowed
;
153 static void _rtl_ps_inactive_ps(struct ieee80211_hw
*hw
)
155 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
156 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
157 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
159 ppsc
->swrf_processing
= true;
161 if (ppsc
->inactive_pwrstate
== ERFON
&&
162 rtlhal
->interface
== INTF_PCI
) {
163 if ((ppsc
->reg_rfps_level
& RT_RF_OFF_LEVL_ASPM
) &&
164 RT_IN_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
) &&
165 rtlhal
->interface
== INTF_PCI
) {
166 rtlpriv
->intf_ops
->disable_aspm(hw
);
167 RT_CLEAR_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
);
171 rtl_ps_set_rf_state(hw
, ppsc
->inactive_pwrstate
,
174 if (ppsc
->inactive_pwrstate
== ERFOFF
&&
175 rtlhal
->interface
== INTF_PCI
) {
176 if (ppsc
->reg_rfps_level
& RT_RF_OFF_LEVL_ASPM
&&
177 !RT_IN_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
)) {
178 rtlpriv
->intf_ops
->enable_aspm(hw
);
179 RT_SET_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
);
183 ppsc
->swrf_processing
= false;
186 void rtl_ips_nic_off_wq_callback(void *data
)
188 struct rtl_works
*rtlworks
=
189 container_of_dwork_rtl(data
, struct rtl_works
, ips_nic_off_wq
);
190 struct ieee80211_hw
*hw
= rtlworks
->hw
;
191 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
192 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
193 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
194 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
195 enum rf_pwrstate rtstate
;
197 if (mac
->opmode
!= NL80211_IFTYPE_STATION
) {
198 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_WARNING
,
199 "not station return\n");
206 if (mac
->link_state
> MAC80211_NOLINK
)
209 if (is_hal_stop(rtlhal
))
212 if (rtlpriv
->sec
.being_setkey
)
215 if (rtlpriv
->cfg
->ops
->bt_coex_off_before_lps
)
216 rtlpriv
->cfg
->ops
->bt_coex_off_before_lps(hw
);
218 if (ppsc
->inactiveps
) {
219 rtstate
= ppsc
->rfpwr_state
;
222 *Do not enter IPS in the following conditions:
223 *(1) RF is already OFF or Sleep
224 *(2) swrf_processing (indicates the IPS is still under going)
225 *(3) Connectted (only disconnected can trigger IPS)
226 *(4) IBSS (send Beacon)
227 *(5) AP mode (send Beacon)
228 *(6) monitor mode (rcv packet)
231 if (rtstate
== ERFON
&&
232 !ppsc
->swrf_processing
&&
233 (mac
->link_state
== MAC80211_NOLINK
) &&
234 !mac
->act_scanning
) {
235 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
236 "IPSEnter(): Turn off RF\n");
238 ppsc
->inactive_pwrstate
= ERFOFF
;
239 ppsc
->in_powersavemode
= true;
241 /* call before RF off */
242 if (rtlpriv
->cfg
->ops
->get_btc_status())
243 rtlpriv
->btcoexist
.btc_ops
->btc_ips_notify(rtlpriv
,
244 ppsc
->inactive_pwrstate
);
246 /*rtl_pci_reset_trx_ring(hw); */
247 _rtl_ps_inactive_ps(hw
);
252 void rtl_ips_nic_off(struct ieee80211_hw
*hw
)
254 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
256 /* because when link with ap, mac80211 will ask us
257 * to disable nic quickly after scan before linking,
258 * this will cause link failed, so we delay 100ms here
260 queue_delayed_work(rtlpriv
->works
.rtl_wq
,
261 &rtlpriv
->works
.ips_nic_off_wq
, MSECS(100));
264 /* NOTICE: any opmode should exc nic_on, or disable without
265 * nic_on may something wrong, like adhoc TP
267 void rtl_ips_nic_on(struct ieee80211_hw
*hw
)
269 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
270 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
271 enum rf_pwrstate rtstate
;
273 cancel_delayed_work_sync(&rtlpriv
->works
.ips_nic_off_wq
);
275 mutex_lock(&rtlpriv
->locks
.ips_mutex
);
276 if (ppsc
->inactiveps
) {
277 rtstate
= ppsc
->rfpwr_state
;
279 if (rtstate
!= ERFON
&&
280 !ppsc
->swrf_processing
&&
281 ppsc
->rfoff_reason
<= RF_CHANGE_BY_IPS
) {
283 ppsc
->inactive_pwrstate
= ERFON
;
284 ppsc
->in_powersavemode
= false;
285 _rtl_ps_inactive_ps(hw
);
286 /* call after RF on */
287 if (rtlpriv
->cfg
->ops
->get_btc_status())
288 rtlpriv
->btcoexist
.btc_ops
->btc_ips_notify(rtlpriv
,
289 ppsc
->inactive_pwrstate
);
292 mutex_unlock(&rtlpriv
->locks
.ips_mutex
);
294 EXPORT_SYMBOL_GPL(rtl_ips_nic_on
);
299 *Determine if we can set Fw into PS mode
300 *in current condition.Return TRUE if it
303 static bool rtl_get_fwlps_doze(struct ieee80211_hw
*hw
)
305 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
306 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
307 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
310 ps_timediff
= jiffies_to_msecs(jiffies
-
311 ppsc
->last_delaylps_stamp_jiffies
);
313 if (ps_timediff
< 2000) {
314 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
,
315 "Delay enter Fw LPS for DHCP, ARP, or EAPOL exchanging state\n");
319 if (mac
->link_state
!= MAC80211_LINKED
)
322 if (mac
->opmode
== NL80211_IFTYPE_ADHOC
)
328 /* Change current and default preamble mode.*/
329 void rtl_lps_set_psmode(struct ieee80211_hw
*hw
, u8 rt_psmode
)
331 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
332 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
333 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
336 if (mac
->opmode
== NL80211_IFTYPE_ADHOC
)
339 if (mac
->link_state
!= MAC80211_LINKED
)
342 if (ppsc
->dot11_psmode
== rt_psmode
&& rt_psmode
== EACTIVE
)
345 /* Update power save mode configured. */
346 ppsc
->dot11_psmode
= rt_psmode
;
351 * Set RPWM to Fw to turn RF off and send H2C fw_pwrmode
352 * cmd to set Fw into PS mode.
354 * Send H2C fw_pwrmode cmd to Fw to set Fw into Active
355 * mode and set RPWM to turn RF on.
358 if ((ppsc
->fwctrl_lps
) && ppsc
->report_linked
) {
359 if (ppsc
->dot11_psmode
== EACTIVE
) {
360 RT_TRACE(rtlpriv
, COMP_RF
, DBG_DMESG
,
361 "FW LPS leave ps_mode:%x\n",
364 ppsc
->pwr_mode
= FW_PS_ACTIVE_MODE
;
366 rtlpriv
->cfg
->ops
->set_hw_reg(hw
, HW_VAR_FW_LPS_ACTION
,
367 (u8
*)(&enter_fwlps
));
368 if (ppsc
->p2p_ps_info
.opp_ps
)
369 rtl_p2p_ps_cmd(hw
, P2P_PS_ENABLE
);
371 if (rtlpriv
->cfg
->ops
->get_btc_status())
372 rtlpriv
->btcoexist
.btc_ops
->btc_lps_notify(rtlpriv
, rt_psmode
);
374 if (rtl_get_fwlps_doze(hw
)) {
375 RT_TRACE(rtlpriv
, COMP_RF
, DBG_DMESG
,
376 "FW LPS enter ps_mode:%x\n",
377 ppsc
->fwctrl_psmode
);
378 if (rtlpriv
->cfg
->ops
->get_btc_status())
379 rtlpriv
->btcoexist
.btc_ops
->btc_lps_notify(rtlpriv
, rt_psmode
);
381 ppsc
->pwr_mode
= ppsc
->fwctrl_psmode
;
383 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
384 HW_VAR_FW_LPS_ACTION
,
385 (u8
*)(&enter_fwlps
));
388 /* Reset the power save related parameters. */
389 ppsc
->dot11_psmode
= EACTIVE
;
395 /* Interrupt safe routine to enter the leisure power save mode.*/
396 static void rtl_lps_enter_core(struct ieee80211_hw
*hw
)
398 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
399 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
400 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
402 if (!ppsc
->fwctrl_lps
)
405 if (rtlpriv
->sec
.being_setkey
)
408 if (rtlpriv
->link_info
.busytraffic
)
411 /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
412 if (mac
->cnt_after_linked
< 5)
415 if (mac
->opmode
== NL80211_IFTYPE_ADHOC
)
418 if (mac
->link_state
!= MAC80211_LINKED
)
421 mutex_lock(&rtlpriv
->locks
.lps_mutex
);
423 /* Don't need to check (ppsc->dot11_psmode == EACTIVE), because
424 * bt_ccoexist may ask to enter lps.
425 * In normal case, this constraint move to rtl_lps_set_psmode().
427 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
,
428 "Enter 802.11 power save mode...\n");
429 rtl_lps_set_psmode(hw
, EAUTOPS
);
431 mutex_unlock(&rtlpriv
->locks
.lps_mutex
);
434 /* Interrupt safe routine to leave the leisure power save mode.*/
435 static void rtl_lps_leave_core(struct ieee80211_hw
*hw
)
437 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
438 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
439 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
441 mutex_lock(&rtlpriv
->locks
.lps_mutex
);
443 if (ppsc
->fwctrl_lps
) {
444 if (ppsc
->dot11_psmode
!= EACTIVE
) {
447 /*rtlpriv->cfg->ops->enable_interrupt(hw); */
449 if (ppsc
->reg_rfps_level
& RT_RF_LPS_LEVEL_ASPM
&&
450 RT_IN_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
) &&
451 rtlhal
->interface
== INTF_PCI
) {
452 rtlpriv
->intf_ops
->disable_aspm(hw
);
453 RT_CLEAR_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
);
456 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_LOUD
,
457 "Busy Traffic,Leave 802.11 power save..\n");
459 rtl_lps_set_psmode(hw
, EACTIVE
);
462 mutex_unlock(&rtlpriv
->locks
.lps_mutex
);
466 void rtl_swlps_beacon(struct ieee80211_hw
*hw
, void *data
, unsigned int len
)
468 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
469 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
470 struct ieee80211_hdr
*hdr
= data
;
471 struct ieee80211_tim_ie
*tim_ie
;
477 if (mac
->opmode
!= NL80211_IFTYPE_STATION
)
480 if (!rtlpriv
->psc
.swctrl_lps
)
483 if (rtlpriv
->mac80211
.link_state
!= MAC80211_LINKED
)
486 if (!rtlpriv
->psc
.sw_ps_enabled
)
489 if (rtlpriv
->psc
.fwctrl_lps
)
492 if (likely(!(hw
->conf
.flags
& IEEE80211_CONF_PS
)))
495 /* check if this really is a beacon */
496 if (!ieee80211_is_beacon(hdr
->frame_control
))
499 /* min. beacon length + FCS_LEN */
500 if (len
<= 40 + FCS_LEN
)
503 /* and only beacons from the associated BSSID, please */
504 if (!ether_addr_equal_64bits(hdr
->addr3
, rtlpriv
->mac80211
.bssid
))
507 rtlpriv
->psc
.last_beacon
= jiffies
;
509 tim
= rtl_find_ie(data
, len
- FCS_LEN
, WLAN_EID_TIM
);
513 if (tim
[1] < sizeof(*tim_ie
))
517 tim_ie
= (struct ieee80211_tim_ie
*) &tim
[2];
519 if (!WARN_ON_ONCE(!hw
->conf
.ps_dtim_period
))
520 rtlpriv
->psc
.dtim_counter
= tim_ie
->dtim_count
;
522 /* Check whenever the PHY can be turned off again. */
524 /* 1. What about buffered unicast traffic for our AID? */
525 u_buffed
= ieee80211_check_tim(tim_ie
, tim_len
,
526 rtlpriv
->mac80211
.assoc_id
);
528 /* 2. Maybe the AP wants to send multicast/broadcast data? */
529 m_buffed
= tim_ie
->bitmap_ctrl
& 0x01;
530 rtlpriv
->psc
.multi_buffered
= m_buffed
;
532 /* unicast will process by mac80211 through
533 * set ~IEEE80211_CONF_PS, So we just check
534 * multicast frames here */
536 /* back to low-power land. and delay is
537 * prevent null power save frame tx fail */
538 queue_delayed_work(rtlpriv
->works
.rtl_wq
,
539 &rtlpriv
->works
.ps_work
, MSECS(5));
541 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_DMESG
,
542 "u_bufferd: %x, m_buffered: %x\n", u_buffed
, m_buffed
);
545 EXPORT_SYMBOL_GPL(rtl_swlps_beacon
);
547 void rtl_swlps_rf_awake(struct ieee80211_hw
*hw
)
549 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
550 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
551 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
553 if (!rtlpriv
->psc
.swctrl_lps
)
555 if (mac
->link_state
!= MAC80211_LINKED
)
558 if (ppsc
->reg_rfps_level
& RT_RF_LPS_LEVEL_ASPM
&&
559 RT_IN_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
)) {
560 rtlpriv
->intf_ops
->disable_aspm(hw
);
561 RT_CLEAR_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
);
564 mutex_lock(&rtlpriv
->locks
.lps_mutex
);
565 rtl_ps_set_rf_state(hw
, ERFON
, RF_CHANGE_BY_PS
);
566 mutex_unlock(&rtlpriv
->locks
.lps_mutex
);
569 void rtl_swlps_rfon_wq_callback(void *data
)
571 struct rtl_works
*rtlworks
=
572 container_of_dwork_rtl(data
, struct rtl_works
, ps_rfon_wq
);
573 struct ieee80211_hw
*hw
= rtlworks
->hw
;
575 rtl_swlps_rf_awake(hw
);
578 void rtl_swlps_rf_sleep(struct ieee80211_hw
*hw
)
580 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
581 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
582 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
585 if (!rtlpriv
->psc
.sw_ps_enabled
)
588 if ((rtlpriv
->sec
.being_setkey
) ||
589 (mac
->opmode
== NL80211_IFTYPE_ADHOC
))
592 /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
593 if ((mac
->link_state
!= MAC80211_LINKED
) || (mac
->cnt_after_linked
< 5))
596 if (rtlpriv
->link_info
.busytraffic
)
599 spin_lock(&rtlpriv
->locks
.rf_ps_lock
);
600 if (rtlpriv
->psc
.rfchange_inprogress
) {
601 spin_unlock(&rtlpriv
->locks
.rf_ps_lock
);
604 spin_unlock(&rtlpriv
->locks
.rf_ps_lock
);
606 mutex_lock(&rtlpriv
->locks
.lps_mutex
);
607 rtl_ps_set_rf_state(hw
, ERFSLEEP
, RF_CHANGE_BY_PS
);
608 mutex_unlock(&rtlpriv
->locks
.lps_mutex
);
610 if (ppsc
->reg_rfps_level
& RT_RF_OFF_LEVL_ASPM
&&
611 !RT_IN_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
)) {
612 rtlpriv
->intf_ops
->enable_aspm(hw
);
613 RT_SET_PS_LEVEL(ppsc
, RT_PS_LEVEL_ASPM
);
616 /* here is power save alg, when this beacon is DTIM
617 * we will set sleep time to dtim_period * n;
618 * when this beacon is not DTIM, we will set sleep
619 * time to sleep_intv = rtlpriv->psc.dtim_counter or
620 * MAX_SW_LPS_SLEEP_INTV(default set to 5) */
622 if (rtlpriv
->psc
.dtim_counter
== 0) {
623 if (hw
->conf
.ps_dtim_period
== 1)
624 sleep_intv
= hw
->conf
.ps_dtim_period
* 2;
626 sleep_intv
= hw
->conf
.ps_dtim_period
;
628 sleep_intv
= rtlpriv
->psc
.dtim_counter
;
631 if (sleep_intv
> MAX_SW_LPS_SLEEP_INTV
)
632 sleep_intv
= MAX_SW_LPS_SLEEP_INTV
;
634 /* this print should always be dtim_conter = 0 &
635 * sleep = dtim_period, that meaons, we should
636 * awake before every dtim */
637 RT_TRACE(rtlpriv
, COMP_POWER
, DBG_DMESG
,
638 "dtim_counter:%x will sleep :%d beacon_intv\n",
639 rtlpriv
->psc
.dtim_counter
, sleep_intv
);
641 /* we tested that 40ms is enough for sw & hw sw delay */
642 queue_delayed_work(rtlpriv
->works
.rtl_wq
, &rtlpriv
->works
.ps_rfon_wq
,
643 MSECS(sleep_intv
* mac
->vif
->bss_conf
.beacon_int
- 40));
646 void rtl_lps_change_work_callback(struct work_struct
*work
)
648 struct rtl_works
*rtlworks
=
649 container_of(work
, struct rtl_works
, lps_change_work
);
650 struct ieee80211_hw
*hw
= rtlworks
->hw
;
651 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
653 if (rtlpriv
->enter_ps
)
654 rtl_lps_enter_core(hw
);
656 rtl_lps_leave_core(hw
);
658 EXPORT_SYMBOL_GPL(rtl_lps_change_work_callback
);
660 void rtl_lps_enter(struct ieee80211_hw
*hw
)
662 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
665 return rtl_lps_enter_core(hw
);
666 rtlpriv
->enter_ps
= true;
667 schedule_work(&rtlpriv
->works
.lps_change_work
);
669 EXPORT_SYMBOL_GPL(rtl_lps_enter
);
671 void rtl_lps_leave(struct ieee80211_hw
*hw
)
673 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
676 return rtl_lps_leave_core(hw
);
677 rtlpriv
->enter_ps
= false;
678 schedule_work(&rtlpriv
->works
.lps_change_work
);
680 EXPORT_SYMBOL_GPL(rtl_lps_leave
);
682 void rtl_swlps_wq_callback(void *data
)
684 struct rtl_works
*rtlworks
= container_of_dwork_rtl(data
,
687 struct ieee80211_hw
*hw
= rtlworks
->hw
;
688 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
691 ps
= (hw
->conf
.flags
& IEEE80211_CONF_PS
);
693 /* we can sleep after ps null send ok */
694 if (rtlpriv
->psc
.state_inap
) {
695 rtl_swlps_rf_sleep(hw
);
697 if (rtlpriv
->psc
.state
&& !ps
) {
698 rtlpriv
->psc
.sleep_ms
= jiffies_to_msecs(jiffies
-
699 rtlpriv
->psc
.last_action
);
703 rtlpriv
->psc
.last_slept
= jiffies
;
705 rtlpriv
->psc
.last_action
= jiffies
;
706 rtlpriv
->psc
.state
= ps
;
710 static void rtl_p2p_noa_ie(struct ieee80211_hw
*hw
, void *data
,
713 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
714 struct ieee80211_mgmt
*mgmt
= data
;
715 struct rtl_p2p_ps_info
*p2pinfo
= &(rtlpriv
->psc
.p2p_ps_info
);
718 static u8 p2p_oui_ie_type
[4] = {0x50, 0x6f, 0x9a, 0x09};
719 u8 noa_num
, index
, i
, noa_index
= 0;
720 bool find_p2p_ie
= false , find_p2p_ps_ie
= false;
722 pos
= (u8
*)mgmt
->u
.beacon
.variable
;
726 while (pos
+ 1 < end
) {
727 if (pos
+ 2 + pos
[1] > end
)
730 if (pos
[0] == 221 && pos
[1] > 4) {
731 if (memcmp(&pos
[2], p2p_oui_ie_type
, 4) == 0) {
743 while (ie
+ 1 < end
) {
744 noa_len
= READEF2BYTE((__le16
*)&ie
[1]);
745 if (ie
+ 3 + ie
[1] > end
)
749 find_p2p_ps_ie
= true;
750 if ((noa_len
- 2) % 13 != 0) {
751 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
752 "P2P notice of absence: invalid length.%d\n",
756 noa_num
= (noa_len
- 2) / 13;
757 if (noa_num
> P2P_MAX_NOA_NUM
)
758 noa_num
= P2P_MAX_NOA_NUM
;
762 if (rtlpriv
->psc
.p2p_ps_info
.p2p_ps_mode
==
763 P2P_PS_NONE
|| noa_index
!= p2pinfo
->noa_index
) {
764 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
,
766 p2pinfo
->noa_index
= noa_index
;
767 p2pinfo
->opp_ps
= (ie
[4] >> 7);
768 p2pinfo
->ctwindow
= ie
[4] & 0x7F;
769 p2pinfo
->noa_num
= noa_num
;
771 for (i
= 0; i
< noa_num
; i
++) {
772 p2pinfo
->noa_count_type
[i
] =
773 READEF1BYTE(ie
+index
);
775 p2pinfo
->noa_duration
[i
] =
776 READEF4BYTE((__le32
*)ie
+index
);
778 p2pinfo
->noa_interval
[i
] =
779 READEF4BYTE((__le32
*)ie
+index
);
781 p2pinfo
->noa_start_time
[i
] =
782 READEF4BYTE((__le32
*)ie
+index
);
786 if (p2pinfo
->opp_ps
== 1) {
787 p2pinfo
->p2p_ps_mode
= P2P_PS_CTWINDOW
;
788 /* Driver should wait LPS entering
791 if (rtlpriv
->psc
.fw_current_inpsmode
)
794 } else if (p2pinfo
->noa_num
> 0) {
795 p2pinfo
->p2p_ps_mode
= P2P_PS_NOA
;
796 rtl_p2p_ps_cmd(hw
, P2P_PS_ENABLE
);
797 } else if (p2pinfo
->p2p_ps_mode
> P2P_PS_NONE
) {
798 rtl_p2p_ps_cmd(hw
, P2P_PS_DISABLE
);
806 if (find_p2p_ie
== true) {
807 if ((p2pinfo
->p2p_ps_mode
> P2P_PS_NONE
) &&
808 (find_p2p_ps_ie
== false))
809 rtl_p2p_ps_cmd(hw
, P2P_PS_DISABLE
);
813 static void rtl_p2p_action_ie(struct ieee80211_hw
*hw
, void *data
,
816 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
817 struct ieee80211_mgmt
*mgmt
= data
;
818 struct rtl_p2p_ps_info
*p2pinfo
= &(rtlpriv
->psc
.p2p_ps_info
);
819 u8 noa_num
, index
, i
, noa_index
= 0;
822 static u8 p2p_oui_ie_type
[4] = {0x50, 0x6f, 0x9a, 0x09};
824 pos
= (u8
*)&mgmt
->u
.action
.category
;
828 if (pos
[0] == 0x7f) {
829 if (memcmp(&pos
[1], p2p_oui_ie_type
, 4) == 0)
836 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "action frame find P2P IE.\n");
838 while (ie
+ 1 < end
) {
839 noa_len
= READEF2BYTE((__le16
*)&ie
[1]);
840 if (ie
+ 3 + ie
[1] > end
)
844 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "find NOA IE.\n");
845 RT_PRINT_DATA(rtlpriv
, COMP_FW
, DBG_LOUD
, "noa ie ",
847 if ((noa_len
- 2) % 13 != 0) {
848 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
,
849 "P2P notice of absence: invalid length.%d\n",
853 noa_num
= (noa_len
- 2) / 13;
854 if (noa_num
> P2P_MAX_NOA_NUM
)
855 noa_num
= P2P_MAX_NOA_NUM
;
859 if (rtlpriv
->psc
.p2p_ps_info
.p2p_ps_mode
==
860 P2P_PS_NONE
|| noa_index
!= p2pinfo
->noa_index
) {
861 p2pinfo
->noa_index
= noa_index
;
862 p2pinfo
->opp_ps
= (ie
[4] >> 7);
863 p2pinfo
->ctwindow
= ie
[4] & 0x7F;
864 p2pinfo
->noa_num
= noa_num
;
866 for (i
= 0; i
< noa_num
; i
++) {
867 p2pinfo
->noa_count_type
[i
] =
868 READEF1BYTE(ie
+index
);
870 p2pinfo
->noa_duration
[i
] =
871 READEF4BYTE((__le32
*)ie
+index
);
873 p2pinfo
->noa_interval
[i
] =
874 READEF4BYTE((__le32
*)ie
+index
);
876 p2pinfo
->noa_start_time
[i
] =
877 READEF4BYTE((__le32
*)ie
+index
);
881 if (p2pinfo
->opp_ps
== 1) {
882 p2pinfo
->p2p_ps_mode
= P2P_PS_CTWINDOW
;
883 /* Driver should wait LPS entering
886 if (rtlpriv
->psc
.fw_current_inpsmode
)
889 } else if (p2pinfo
->noa_num
> 0) {
890 p2pinfo
->p2p_ps_mode
= P2P_PS_NOA
;
891 rtl_p2p_ps_cmd(hw
, P2P_PS_ENABLE
);
892 } else if (p2pinfo
->p2p_ps_mode
> P2P_PS_NONE
) {
893 rtl_p2p_ps_cmd(hw
, P2P_PS_DISABLE
);
902 void rtl_p2p_ps_cmd(struct ieee80211_hw
*hw
, u8 p2p_ps_state
)
904 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
905 struct rtl_ps_ctl
*rtlps
= rtl_psc(rtl_priv(hw
));
906 struct rtl_p2p_ps_info
*p2pinfo
= &(rtlpriv
->psc
.p2p_ps_info
);
908 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, " p2p state %x\n" , p2p_ps_state
);
909 switch (p2p_ps_state
) {
911 p2pinfo
->p2p_ps_state
= p2p_ps_state
;
912 rtlpriv
->cfg
->ops
->set_hw_reg(hw
, HW_VAR_H2C_FW_P2P_PS_OFFLOAD
,
914 p2pinfo
->noa_index
= 0;
915 p2pinfo
->ctwindow
= 0;
917 p2pinfo
->noa_num
= 0;
918 p2pinfo
->p2p_ps_mode
= P2P_PS_NONE
;
919 if (rtlps
->fw_current_inpsmode
) {
920 if (rtlps
->smart_ps
== 0) {
922 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
923 HW_VAR_H2C_FW_PWRMODE
,
930 if (p2pinfo
->p2p_ps_mode
> P2P_PS_NONE
) {
931 p2pinfo
->p2p_ps_state
= p2p_ps_state
;
933 if (p2pinfo
->ctwindow
> 0) {
934 if (rtlps
->smart_ps
!= 0) {
936 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
937 HW_VAR_H2C_FW_PWRMODE
,
941 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
942 HW_VAR_H2C_FW_P2P_PS_OFFLOAD
,
948 case P2P_PS_SCAN_DONE
:
949 case P2P_PS_ALLSTASLEEP
:
950 if (p2pinfo
->p2p_ps_mode
> P2P_PS_NONE
) {
951 p2pinfo
->p2p_ps_state
= p2p_ps_state
;
952 rtlpriv
->cfg
->ops
->set_hw_reg(hw
,
953 HW_VAR_H2C_FW_P2P_PS_OFFLOAD
,
960 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
,
961 "ctwindow %x oppps %x\n",
962 p2pinfo
->ctwindow
, p2pinfo
->opp_ps
);
963 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
,
964 "count %x duration %x index %x interval %x start time %x noa num %x\n",
965 p2pinfo
->noa_count_type
[0],
966 p2pinfo
->noa_duration
[0],
968 p2pinfo
->noa_interval
[0],
969 p2pinfo
->noa_start_time
[0],
971 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
, "end\n");
974 void rtl_p2p_info(struct ieee80211_hw
*hw
, void *data
, unsigned int len
)
976 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
977 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
978 struct ieee80211_hdr
*hdr
= data
;
982 if (mac
->link_state
!= MAC80211_LINKED
)
984 /* min. beacon length + FCS_LEN */
985 if (len
<= 40 + FCS_LEN
)
988 /* and only beacons from the associated BSSID, please */
989 if (!ether_addr_equal_64bits(hdr
->addr3
, rtlpriv
->mac80211
.bssid
))
992 /* check if this really is a beacon */
993 if (!(ieee80211_is_beacon(hdr
->frame_control
) ||
994 ieee80211_is_probe_resp(hdr
->frame_control
) ||
995 ieee80211_is_action(hdr
->frame_control
)))
998 if (ieee80211_is_action(hdr
->frame_control
))
999 rtl_p2p_action_ie(hw
, data
, len
- FCS_LEN
);
1001 rtl_p2p_noa_ie(hw
, data
, len
- FCS_LEN
);
1003 EXPORT_SYMBOL_GPL(rtl_p2p_info
);