blob: 5a9bbf025e251da4a2bd3daca44e50232e1d6600 [file] [log] [blame]
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -08001/******************************************************************************
2 *
3 * Copyright(c) 2009-2010 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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
20 *
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
25 *
26 * Larry Finger <Larry.Finger@lwfinger.net>
27 *
28 *****************************************************************************/
29
30#include "wifi.h"
31#include "base.h"
32#include "ps.h"
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -080033#include <linux/export.h>
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -080034#include "btcoexist/rtl_btc.h"
35
36bool rtl_ps_enable_nic(struct ieee80211_hw *hw)
37{
38 struct rtl_priv *rtlpriv = rtl_priv(hw);
39 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
40 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
41 bool init_status = true;
42
43 /*<1> reset trx ring */
44 if (rtlhal->interface == INTF_PCI)
45 rtlpriv->intf_ops->reset_trx_ring(hw);
46
47 if (is_hal_stop(rtlhal))
48 RT_TRACE(COMP_ERR, DBG_WARNING, ("Driver is already down!\n"));
49
50 /*<2> Enable Adapter */
51 rtlpriv->cfg->ops->hw_init(hw);
52 RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
53 /*init_status = false; */
54
55 /*<3> Enable Interrupt */
56 rtlpriv->cfg->ops->enable_interrupt(hw);
57
58 /*<enable timer> */
59 rtl_watch_dog_timer_callback((unsigned long)hw);
60
61 return init_status;
62}
63//EXPORT_SYMBOL(rtl_ps_enable_nic);
64
65bool rtl_ps_disable_nic(struct ieee80211_hw *hw)
66{
67 bool status = true;
68 struct rtl_priv *rtlpriv = rtl_priv(hw);
69
70 /*<1> Stop all timer */
71 rtl_deinit_deferred_work(hw);
72
73 /*<2> Disable Interrupt */
74 rtlpriv->cfg->ops->disable_interrupt(hw);
75
76 /*<3> Disable Adapter */
77 rtlpriv->cfg->ops->hw_disable(hw);
78
79 return status;
80}
81//EXPORT_SYMBOL(rtl_ps_disable_nic);
82
83bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
84 enum rf_pwrstate state_toset,
85 u32 changesource, bool protect_or_not)
86{
87 struct rtl_priv *rtlpriv = rtl_priv(hw);
88 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
89 enum rf_pwrstate rtstate;
90 bool b_actionallowed = false;
91 u16 rfwait_cnt = 0;
92
93 /*protect_or_not = true; */
94
95 if (protect_or_not)
96 goto no_protect;
97
98 /*
99 *Only one thread can change
100 *the RF state at one time, and others
101 *should wait to be executed.
102 */
103 while (true) {
104 spin_lock(&rtlpriv->locks.rf_ps_lock);
105 if (ppsc->rfchange_inprogress) {
106 spin_unlock(&rtlpriv->locks.rf_ps_lock);
107
108 RT_TRACE(COMP_ERR, DBG_WARNING,
109 ("RF Change in progress!"
110 "Wait to set..state_toset(%d).\n",
111 state_toset));
112
113 /* Set RF after the previous action is done. */
114 while (ppsc->rfchange_inprogress) {
115 rfwait_cnt++;
116 mdelay(1);
117 /*
118 *Wait too long, return false to avoid
119 *to be stuck here.
120 */
121 if (rfwait_cnt > 100)
122 return false;
123 }
124 } else {
125 ppsc->rfchange_inprogress = true;
126 spin_unlock(&rtlpriv->locks.rf_ps_lock);
127 break;
128 }
129 }
130
131no_protect:
132 rtstate = ppsc->rfpwr_state;
133
134 switch (state_toset) {
135 case ERFON:
136 ppsc->rfoff_reason &= (~changesource);
137
138 if ((changesource == RF_CHANGE_BY_HW) &&
139 (ppsc->b_hwradiooff == true)) {
140 ppsc->b_hwradiooff = false;
141 }
142
143 if (!ppsc->rfoff_reason) {
144 ppsc->rfoff_reason = 0;
145 b_actionallowed = true;
146 }
147
148 break;
149
150 case ERFOFF:
151
152 if ((changesource == RF_CHANGE_BY_HW) &&
153 (ppsc->b_hwradiooff == false)) {
154 ppsc->b_hwradiooff = true;
155 }
156
157 ppsc->rfoff_reason |= changesource;
158 b_actionallowed = true;
159 break;
160
161 case ERFSLEEP:
162 ppsc->rfoff_reason |= changesource;
163 b_actionallowed = true;
164 break;
165
166 default:
167 RT_TRACE(COMP_ERR, DBG_EMERG, ("switch case not process \n"));
168 break;
169 }
170
171 if (b_actionallowed)
172 rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
173
174 if (!protect_or_not) {
175 spin_lock(&rtlpriv->locks.rf_ps_lock);
176 ppsc->rfchange_inprogress = false;
177 spin_unlock(&rtlpriv->locks.rf_ps_lock);
178 }
179
180 return b_actionallowed;
181}
182//EXPORT_SYMBOL(rtl_ps_set_rf_state);
183
184static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
185{
186 struct rtl_priv *rtlpriv = rtl_priv(hw);
187 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
188 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
189
190 ppsc->b_swrf_processing = true;
191
192 if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) {
193 if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
194 RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) &&
195 rtlhal->interface == INTF_PCI) {
196 rtlpriv->intf_ops->disable_aspm(hw);
197 RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
198 }
199 }
200
201 if (rtlpriv->cfg->ops->get_btc_status()){
202 rtlpriv->btcoexist.btc_ops->btc_ips_notify(rtlpriv,
203 ppsc->inactive_pwrstate);
204 }
205 rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate,
206 RF_CHANGE_BY_IPS, false);
207
208 if (ppsc->inactive_pwrstate == ERFOFF &&
209 rtlhal->interface == INTF_PCI) {
210 if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
211 !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
212 rtlpriv->intf_ops->enable_aspm(hw);
213 RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
214 }
215 }
216
217 ppsc->b_swrf_processing = false;
218}
219
220void rtl_ips_nic_off_wq_callback(void *data)
221{
222 struct rtl_works *rtlworks =
223 container_of_dwork_rtl(data, struct rtl_works, ips_nic_off_wq);
224 struct ieee80211_hw *hw = rtlworks->hw;
225 struct rtl_priv *rtlpriv = rtl_priv(hw);
226 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
227 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
228 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
229 enum rf_pwrstate rtstate;
230
231 if (mac->opmode != NL80211_IFTYPE_STATION) {
232 RT_TRACE(COMP_ERR, DBG_WARNING, ("not station return\n"));
233 return;
234 }
235
236 if (mac->p2p_in_use)
237 return;
238
239 if (mac->link_state > MAC80211_NOLINK)
240 return;
241
242 if (is_hal_stop(rtlhal))
243 return;
244
245 if (rtlpriv->sec.being_setkey)
246 return;
247
248 if(rtlpriv->cfg->ops->bt_turn_off_bt_coexist_before_enter_lps)
249 rtlpriv->cfg->ops->bt_turn_off_bt_coexist_before_enter_lps(hw);
250
251 if (ppsc->b_inactiveps) {
252 rtstate = ppsc->rfpwr_state;
253
254 /*
255 *Do not enter IPS in the following conditions:
256 *(1) RF is already OFF or Sleep
257 *(2) b_swrf_processing (indicates the IPS is still under going)
Masanari Iidada4d2012014-02-25 23:54:39 +0900258 *(3) Connected (only disconnected can trigger IPS)
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -0800259 *(4) IBSS (send Beacon)
260 *(5) AP mode (send Beacon)
261 *(6) monitor mode (rcv packet)
262 */
263
264 if (rtstate == ERFON &&
265 !ppsc->b_swrf_processing &&
266 (mac->link_state == MAC80211_NOLINK) &&
267 !mac->act_scanning) {
268 RT_TRACE(COMP_RF, DBG_LOUD,
269 ("IPSEnter(): Turn off RF.\n"));
270
271 ppsc->inactive_pwrstate = ERFOFF;
272 ppsc->b_in_powersavemode = true;
273
274 /*rtl_pci_reset_trx_ring(hw); */
275 _rtl_ps_inactive_ps(hw);
276 }
277 }
278}
279
280void rtl_ips_nic_off(struct ieee80211_hw *hw)
281{
282 struct rtl_priv *rtlpriv = rtl_priv(hw);
283
284 /*
285 *because when link with ap, mac80211 will ask us
286 *to disable nic quickly after scan before linking,
287 *this will cause link failed, so we delay 100ms here
288 */
289 queue_delayed_work(rtlpriv->works.rtl_wq,
290 &rtlpriv->works.ips_nic_off_wq, MSECS(100));
291}
292
293/* NOTICE: any opmode should exc nic_on, or disable without
294 * nic_on may something wrong, like adhoc TP*/
295void rtl_ips_nic_on(struct ieee80211_hw *hw)
296{
297 struct rtl_priv *rtlpriv = rtl_priv(hw);
298 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
299 enum rf_pwrstate rtstate;
300
301 cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq);
302
303 spin_lock(&rtlpriv->locks.ips_lock);
304 if (ppsc->b_inactiveps) {
305 rtstate = ppsc->rfpwr_state;
306
307 if (rtstate != ERFON &&
308 !ppsc->b_swrf_processing &&
309 ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) {
310
311 ppsc->inactive_pwrstate = ERFON;
312 ppsc->b_in_powersavemode = false;
313 _rtl_ps_inactive_ps(hw);
314 }
315 }
316 spin_unlock(&rtlpriv->locks.ips_lock);
317}
318
319/*for FW LPS*/
320
321/*
322 *Determine if we can set Fw into PS mode
323 *in current condition.Return true if it
324 *can enter PS mode.
325 */
326static bool rtl_get_fwlps_doze(struct ieee80211_hw *hw)
327{
328 struct rtl_priv *rtlpriv = rtl_priv(hw);
329 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
330 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
331 u32 ps_timediff;
332
333 ps_timediff = jiffies_to_msecs(jiffies -
334 ppsc->last_delaylps_stamp_jiffies);
335
336 if (ps_timediff < 2000) {
337 RT_TRACE(COMP_POWER, DBG_LOUD,
338 ("Delay enter Fw LPS for DHCP, ARP,"
339 " or EAPOL exchanging state.\n"));
340 return false;
341 }
342
343 if (mac->link_state != MAC80211_LINKED)
344 return false;
345
346 if (mac->opmode == NL80211_IFTYPE_ADHOC)
347 return false;
348
349 return true;
350}
351
352/* Change current and default preamble mode.*/
353void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
354{
355 struct rtl_priv *rtlpriv = rtl_priv(hw);
356 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
357 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
358 bool enter_fwlps;
359
360 if (mac->opmode == NL80211_IFTYPE_ADHOC)
361 return;
362
363 if (mac->link_state != MAC80211_LINKED)
364 return;
365
366 if (ppsc->dot11_psmode == rt_psmode)
367 return;
368
369 /* Update power save mode configured. */
370 ppsc->dot11_psmode = rt_psmode;
371
372 /*
373 *<FW control LPS>
374 *1. Enter PS mode
375 * Set RPWM to Fw to turn RF off and send H2C fw_pwrmode
376 * cmd to set Fw into PS mode.
377 *2. Leave PS mode
378 * Send H2C fw_pwrmode cmd to Fw to set Fw into Active
379 * mode and set RPWM to turn RF on.
380 */
381
382 if ((ppsc->b_fwctrl_lps) && ppsc->report_linked) {
383 if (ppsc->dot11_psmode == EACTIVE) {
384 RT_TRACE(COMP_RF, DBG_DMESG,
385 ("FW LPS leave ps_mode:%x\n",
386 FW_PS_ACTIVE_MODE));
387 enter_fwlps = false;
388 ppsc->pwr_mode = FW_PS_ACTIVE_MODE;
389 ppsc->smart_ps = 0;
390 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_FW_LPS_ACTION,
391 (u8 *)(&enter_fwlps));
392 if (ppsc->p2p_ps_info.opp_ps)
393 rtl_p2p_ps_cmd(hw,P2P_PS_ENABLE);
394
395 } else {
396 if (rtl_get_fwlps_doze(hw)) {
397 RT_TRACE(COMP_RF, DBG_DMESG,
398 ("FW LPS enter ps_mode:%x\n",
399 ppsc->fwctrl_psmode));
400 enter_fwlps = true;
401 ppsc->pwr_mode = ppsc->fwctrl_psmode;
402 ppsc->smart_ps = 2;
403 rtlpriv->cfg->ops->set_hw_reg(hw,
404 HW_VAR_FW_LPS_ACTION,
405 (u8 *)(&enter_fwlps));
406
407 } else {
408 /* Reset the power save related parameters. */
409 ppsc->dot11_psmode = EACTIVE;
410 }
411 }
412 }
413}
414
415/*Enter the leisure power save mode.*/
416void rtl_lps_enter(struct ieee80211_hw *hw)
417{
418 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
419 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
420 struct rtl_priv *rtlpriv = rtl_priv(hw);
421 unsigned long flag;
422
423 if (!ppsc->b_fwctrl_lps)
424 return;
425
426 if (rtlpriv->sec.being_setkey)
427 return;
428
429 if (rtlpriv->link_info.b_busytraffic)
430 return;
431
432 /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
433 if (mac->cnt_after_linked < 5)
434 return;
435
436 if (mac->opmode == NL80211_IFTYPE_ADHOC)
437 return;
438
439 if (mac->link_state != MAC80211_LINKED)
440 return;
441
442 spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
443
444 /* Idle for a while if we connect to AP a while ago. */
445 if (mac->cnt_after_linked >= 2) {
446 if (ppsc->dot11_psmode == EACTIVE) {
447 RT_TRACE(COMP_POWER, DBG_LOUD,
448 ("Enter 802.11 power save mode...\n"));
449
450 rtl_lps_set_psmode(hw, EAUTOPS);
451 }
452 }
453
454 spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
455}
456
457/*Leave the leisure power save mode.*/
458void rtl_lps_leave(struct ieee80211_hw *hw)
459{
460 struct rtl_priv *rtlpriv = rtl_priv(hw);
461 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
462 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
463 unsigned long flag;
464
465 spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
466
467 if (ppsc->b_fwctrl_lps) {
468 if (ppsc->dot11_psmode != EACTIVE) {
469
470 /*FIX ME */
471 rtlpriv->cfg->ops->enable_interrupt(hw);
472
473 if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
474 RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM) &&
475 rtlhal->interface == INTF_PCI) {
476 rtlpriv->intf_ops->disable_aspm(hw);
477 RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
478 }
479
480 RT_TRACE(COMP_POWER, DBG_LOUD,
481 ("Busy Traffic,Leave 802.11 power save..\n"));
482
483 rtl_lps_set_psmode(hw, EACTIVE);
484 }
485 }
486 spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
487}
488
489/* For sw LPS*/
490void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
491{
492 struct rtl_priv *rtlpriv = rtl_priv(hw);
493 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
494 struct ieee80211_hdr *hdr = (void *) data;
495 struct ieee80211_tim_ie *tim_ie;
496 u8 *tim;
497 u8 tim_len;
498 bool u_buffed;
499 bool m_buffed;
500
501 if (mac->opmode != NL80211_IFTYPE_STATION)
502 return;
503
504 if (!rtlpriv->psc.b_swctrl_lps)
505 return;
506
507 if (rtlpriv->mac80211.link_state != MAC80211_LINKED)
508 return;
509
510 if (!rtlpriv->psc.sw_ps_enabled)
511 return;
512
513 if (rtlpriv->psc.b_fwctrl_lps)
514 return;
515
516 if (likely(!(hw->conf.flags & IEEE80211_CONF_PS)))
517 return;
518
519 /* check if this really is a beacon */
520 if (!ieee80211_is_beacon(hdr->frame_control))
521 return;
522
523 /* min. beacon length + FCS_LEN */
524 if (len <= 40 + FCS_LEN)
525 return;
526
527 /* and only beacons from the associated BSSID, please */
Larry Fingeree5de8d2014-01-26 13:17:33 -0600528 if (ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -0800529 return;
530
531 rtlpriv->psc.last_beacon = jiffies;
532
533 tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM);
534 if (!tim)
535 return;
536
537 if (tim[1] < sizeof(*tim_ie))
538 return;
539
540 tim_len = tim[1];
541 tim_ie = (struct ieee80211_tim_ie *) &tim[2];
542
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -0800543 if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period))
544 rtlpriv->psc.dtim_counter = tim_ie->dtim_count;
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -0800545
546 /* Check whenever the PHY can be turned off again. */
547
548 /* 1. What about buffered unicast traffic for our AID? */
549 u_buffed = ieee80211_check_tim(tim_ie, tim_len,
550 rtlpriv->mac80211.assoc_id);
551
552 /* 2. Maybe the AP wants to send multicast/broadcast data? */
553 m_buffed = tim_ie->bitmap_ctrl & 0x01;
554 rtlpriv->psc.multi_buffered = m_buffed;
555
556 /* unicast will process by mac80211 through
557 * set ~IEEE80211_CONF_PS, So we just check
558 * multicast frames here */
559 if (!m_buffed ) {//&&) {// !rtlpriv->psc.tx_doing) {
560 /* back to low-power land. and delay is
561 * prevent null power save frame tx fail */
562 queue_delayed_work(rtlpriv->works.rtl_wq,
563 &rtlpriv->works.ps_work, MSECS(5));
564 } else {
565 RT_TRACE(COMP_POWER, DBG_DMESG,
566 ("u_bufferd: %x, m_buffered: %x\n",
567 u_buffed, m_buffed));
568 }
569}
570
571void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
572{
573 struct rtl_priv *rtlpriv = rtl_priv(hw);
574 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
575 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
576 unsigned long flag;
577
578 if (!rtlpriv->psc.b_swctrl_lps)
579 return;
580 if (mac->link_state != MAC80211_LINKED)
581 return;
582
583 if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
584 RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
585 rtlpriv->intf_ops->disable_aspm(hw);
586 RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
587 }
588
589 spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
590 rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false);
591 spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
592}
593
594void rtl_swlps_rfon_wq_callback(void *data)
595{
596 struct rtl_works *rtlworks =
597 container_of_dwork_rtl(data, struct rtl_works, ps_rfon_wq);
598 struct ieee80211_hw *hw = rtlworks->hw;
599
600 rtl_swlps_rf_awake(hw);
601}
602
603void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
604{
605 struct rtl_priv *rtlpriv = rtl_priv(hw);
606 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
607 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
608 unsigned long flag;
609 u8 sleep_intv;
610
611 if (!rtlpriv->psc.sw_ps_enabled)
612 return;
613
614 if ((rtlpriv->sec.being_setkey) ||
615 (mac->opmode == NL80211_IFTYPE_ADHOC))
616 return;
617
618 /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
619 if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5))
620 return;
621
622 if (rtlpriv->link_info.b_busytraffic)
623 return;
624
625 spin_lock(&rtlpriv->locks.rf_ps_lock);
626 if (rtlpriv->psc.rfchange_inprogress) {
627 spin_unlock(&rtlpriv->locks.rf_ps_lock);
628 return;
629 }
630 spin_unlock(&rtlpriv->locks.rf_ps_lock);
631
632 spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
633 rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS,false);
634 spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flag);
635
636 if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
637 !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
638 rtlpriv->intf_ops->enable_aspm(hw);
639 RT_SET_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
640 }
641
642 /* here is power save alg, when this beacon is DTIM
643 * we will set sleep time to dtim_period * n;
644 * when this beacon is not DTIM, we will set sleep
645 * time to sleep_intv = rtlpriv->psc.dtim_counter or
646 * MAX_SW_LPS_SLEEP_INTV(default set to 5) */
647
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -0800648 if (rtlpriv->psc.dtim_counter == 0) {
649 if (hw->conf.ps_dtim_period == 1)
650 sleep_intv = hw->conf.ps_dtim_period * 2;
651 else
652 sleep_intv = hw->conf.ps_dtim_period;
653 } else {
654 sleep_intv = rtlpriv->psc.dtim_counter;
655 }
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -0800656
657 if (sleep_intv > MAX_SW_LPS_SLEEP_INTV)
658 sleep_intv = MAX_SW_LPS_SLEEP_INTV;
659
660 /* this print should always be dtim_conter = 0 &
661 * sleep = dtim_period, that meaons, we should
662 * awake before every dtim */
663 RT_TRACE(COMP_POWER, DBG_DMESG,
664 ("dtim_counter:%x will sleep :%d beacon_intv\n",
665 rtlpriv->psc.dtim_counter, sleep_intv));
666
667 /* we tested that 40ms is enough for sw & hw sw delay */
668 queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq,
669 MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40));
670}
671
672
673void rtl_swlps_wq_callback(void *data)
674{
675 struct rtl_works *rtlworks =
676 container_of_dwork_rtl(data, struct rtl_works, ps_work);
677 struct ieee80211_hw *hw = rtlworks->hw;
678 struct rtl_priv *rtlpriv = rtl_priv(hw);
679 bool ps = false;
680
681 ps = (hw->conf.flags & IEEE80211_CONF_PS);
682
683 /* we can sleep after ps null send ok */
684 if (rtlpriv->psc.state_inap) {
685 rtl_swlps_rf_sleep(hw);
686
687 if (rtlpriv->psc.state && !ps) {
688 rtlpriv->psc.sleep_ms =
689 jiffies_to_msecs(jiffies -
690 rtlpriv->psc.last_action);
691 }
692
693 if (ps)
694 rtlpriv->psc.last_slept = jiffies;
695
696 rtlpriv->psc.last_action = jiffies;
697 rtlpriv->psc.state = ps;
698 }
699}
700
701
702void rtl_p2p_noa_ie(struct ieee80211_hw *hw, void *data, unsigned int len)
703{
704 struct rtl_priv *rtlpriv = rtl_priv(hw);
705 struct ieee80211_mgmt *mgmt = (void *)data;
706 struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
707 u8 *pos, *end, *ie;
708 u16 noa_len;
709 static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09};
710 u8 noa_num, index,i, noa_index = 0;
711 bool find_p2p_ie = false , find_p2p_ps_ie = false;
712 pos = (u8 *)mgmt->u.beacon.variable;
713 end = data + len;
714 ie = NULL;
715
716 while (pos + 1 < end) {
717
718 if (pos + 2 + pos[1] > end)
719 return;
720
721 if (pos[0] == 221 && pos[1] > 4) {
722 if (memcmp(&pos[2], p2p_oui_ie_type, 4) == 0) {
723 ie = pos + 2+4;
724 break;
725 }
726 }
727 pos += 2 + pos[1];
728 }
729
730 if (ie == NULL)
731 return;
732 find_p2p_ie = true;
733 /*to find noa ie*/
734 while (ie + 1 < end) {
735 noa_len = READEF2BYTE(&ie[1]);
736 if (ie + 3 + ie[1] > end)
737 return;
738
739 if (ie[0] == 12) {
740 find_p2p_ps_ie = true;
741 if ( (noa_len - 2) % 13 != 0){
742 RT_TRACE(COMP_INIT, DBG_LOUD,
743 ("P2P notice of absence: "
744 "invalid length.%d\n",noa_len));
745 return;
746 } else {
747 noa_num = (noa_len - 2) / 13;
748 }
749 noa_index = ie[3];
750 if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == P2P_PS_NONE
751 || noa_index != p2pinfo->noa_index) {
752 RT_TRACE(COMP_FW, DBG_LOUD,
753 ("update NOA ie.\n"));
754 p2pinfo->noa_index = noa_index;
755 p2pinfo->opp_ps= (ie[4] >> 7);
756 p2pinfo->ctwindow = ie[4] & 0x7F;
757 p2pinfo->noa_num = noa_num;
758 index = 5;
759 for (i = 0; i< noa_num; i++){
760 p2pinfo->noa_count_type[i] =
761 READEF1BYTE(ie+index);
762 index += 1;
763 p2pinfo->noa_duration[i] =
764 READEF4BYTE(ie+index);
765 index += 4;
766 p2pinfo->noa_interval[i] =
767 READEF4BYTE(ie+index);
768 index += 4;
769 p2pinfo->noa_start_time[i] =
770 READEF4BYTE(ie+index);
771 index += 4;
772 }
773
774 if (p2pinfo->opp_ps == 1) {
775 p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
776 /* Driver should wait LPS
777 * entering CTWindow*/
778 if (rtlpriv->psc.b_fw_current_inpsmode){
779 rtl_p2p_ps_cmd(hw,
780 P2P_PS_ENABLE);
781 }
782 } else if (p2pinfo->noa_num > 0) {
783 p2pinfo->p2p_ps_mode = P2P_PS_NOA;
784 rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE);
785 } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
786 rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
787 }
788 }
789
790 break;
791 }
792 ie += 3 + noa_len;
793 }
794
795 if (find_p2p_ie == true) {
796 if ((p2pinfo->p2p_ps_mode > P2P_PS_NONE) &&
797 (find_p2p_ps_ie == false))
798 rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
799 }
800}
801
802void rtl_p2p_action_ie(struct ieee80211_hw *hw, void *data, unsigned int len)
803{
804 struct rtl_priv *rtlpriv = rtl_priv(hw);
805 struct ieee80211_mgmt *mgmt = (void *)data;
806 struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
807 bool find_p2p_ie = false , find_p2p_ps_ie = false;
808 u8 noa_num, index,i, noa_index = 0;
809 u8 *pos, *end, *ie;
810 u16 noa_len;
811 static u8 p2p_oui_ie_type[4] = {0x50, 0x6f, 0x9a, 0x09};
812
813 pos = (u8 *) &mgmt->u.action.category;
814 end = data + len;
815 ie = NULL;
816
817 if (pos[0] == 0x7f ) {
818 if (memcmp(&pos[1], p2p_oui_ie_type, 4) == 0) {
819 ie = pos + 3+4;
820 }
821 }
822
823 if (ie == NULL)
824 return;
825 find_p2p_ie = true;
826
827 RT_TRACE(COMP_FW, DBG_LOUD, ("action frame find P2P IE.\n"));
828 /*to find noa ie*/
829 while (ie + 1 < end) {
830 noa_len = READEF2BYTE(&ie[1]);
831 if (ie + 3 + ie[1] > end)
832 return;
833
834 if (ie[0] == 12) {
835 RT_TRACE(COMP_FW, DBG_LOUD, ("find NOA IE.\n"));
836 RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, ("noa ie "),
837 ie, noa_len);
838 find_p2p_ps_ie = true;
839 if ( (noa_len - 2) % 13 != 0){
840 RT_TRACE(COMP_FW, DBG_LOUD,
841 ("P2P notice of absence: "
842 "invalid length.%d\n",noa_len));
843 return;
844 } else {
845 noa_num = (noa_len - 2) / 13;
846 }
847 noa_index = ie[3];
848 if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode == P2P_PS_NONE
849 || noa_index != p2pinfo->noa_index) {
850 p2pinfo->noa_index = noa_index;
851 p2pinfo->opp_ps= (ie[4] >> 7);
852 p2pinfo->ctwindow = ie[4] & 0x7F;
853 p2pinfo->noa_num = noa_num;
854 index = 5;
855 for (i = 0; i< noa_num; i++){
856 p2pinfo->noa_count_type[i] =
857 READEF1BYTE(ie+index);
858 index += 1;
859 p2pinfo->noa_duration[i] =
860 READEF4BYTE(ie+index);
861 index += 4;
862 p2pinfo->noa_interval[i] =
863 READEF4BYTE(ie+index);
864 index += 4;
865 p2pinfo->noa_start_time[i] =
866 READEF4BYTE(ie+index);
867 index += 4;
868 }
869
870 if (p2pinfo->opp_ps == 1) {
871 p2pinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
872 /* Driver should wait LPS
873 * entering CTWindow */
874 if (rtlpriv->psc.b_fw_current_inpsmode){
875 rtl_p2p_ps_cmd(hw,
876 P2P_PS_ENABLE);
877 }
878 } else if (p2pinfo->noa_num > 0) {
879 p2pinfo->p2p_ps_mode = P2P_PS_NOA;
880 rtl_p2p_ps_cmd(hw, P2P_PS_ENABLE);
881 } else if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
882 rtl_p2p_ps_cmd(hw, P2P_PS_DISABLE);
883 }
884 }
885
886 break;
887 }
888 ie += 3 + noa_len;
889 }
890
891
892}
893
894
895void rtl_p2p_ps_cmd(struct ieee80211_hw *hw,u8 p2p_ps_state)
896{
897 struct rtl_priv *rtlpriv = rtl_priv(hw);
898 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
899 struct rtl_p2p_ps_info *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
900
901 RT_TRACE(COMP_FW, DBG_LOUD, (" p2p state %x\n",p2p_ps_state));
902 switch (p2p_ps_state) {
903 case P2P_PS_DISABLE:
904 p2pinfo->p2p_ps_state = p2p_ps_state;
905 rtlpriv->cfg->ops->set_hw_reg(hw,
906 HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
907 (u8 *)(&p2p_ps_state));
908
909 p2pinfo->noa_index = 0;
910 p2pinfo->ctwindow = 0;
911 p2pinfo->opp_ps = 0;
912 p2pinfo->noa_num = 0;
913 p2pinfo->p2p_ps_mode = P2P_PS_NONE;
914 if (rtlps->b_fw_current_inpsmode == true) {
915 if (rtlps->smart_ps == 0) {
916 rtlps->smart_ps = 2;
917 rtlpriv->cfg->ops->set_hw_reg(hw,
918 HW_VAR_H2C_FW_PWRMODE,
919 (u8 *)(&rtlps->pwr_mode));
920 }
921
922 }
923 break;
924 case P2P_PS_ENABLE:
925 if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
926 p2pinfo->p2p_ps_state = p2p_ps_state;
927
928 if (p2pinfo->ctwindow > 0) {
929 if (rtlps->smart_ps != 0){
930 rtlps->smart_ps = 0;
931 rtlpriv->cfg->ops->set_hw_reg(
932 hw, HW_VAR_H2C_FW_PWRMODE,
933 (u8 *)(&rtlps->pwr_mode));
934 }
935 }
936 rtlpriv->cfg->ops->set_hw_reg(hw,
937 HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
938 (u8 *)(&p2p_ps_state));
939
940 }
941 break;
942 case P2P_PS_SCAN:
943 case P2P_PS_SCAN_DONE:
944 case P2P_PS_ALLSTASLEEP:
945 if (p2pinfo->p2p_ps_mode > P2P_PS_NONE) {
946 p2pinfo->p2p_ps_state = p2p_ps_state;
947 rtlpriv->cfg->ops->set_hw_reg(hw,
948 HW_VAR_H2C_FW_P2P_PS_OFFLOAD,
949 (u8 *)(&p2p_ps_state));
950 }
951 break;
952 default:
953 break;
954
955 }
956 RT_TRACE(COMP_FW, DBG_LOUD, (" ctwindow %x oppps %x \n",
957 p2pinfo->ctwindow,p2pinfo->opp_ps));
958 RT_TRACE(COMP_FW, DBG_LOUD, ("count %x duration %x index %x interval %x"
959 " start time %x noa num %x\n",
960 p2pinfo->noa_count_type[0],
961 p2pinfo->noa_duration[0],
962 p2pinfo->noa_index,
963 p2pinfo->noa_interval[0],
964 p2pinfo->noa_start_time[0],
965 p2pinfo->noa_num));
966 RT_TRACE(COMP_FW, DBG_LOUD, ("end\n"));
967}
968
969void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len)
970{
971 struct rtl_priv *rtlpriv = rtl_priv(hw);
972 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
973 struct ieee80211_hdr *hdr = (void *) data;
974
975 if (!mac->p2p)
976 return;
977 if (mac->link_state != MAC80211_LINKED)
978 return;
979 /* min. beacon length + FCS_LEN */
980 if (len <= 40 + FCS_LEN)
981 return;
982
983 /* and only beacons from the associated BSSID, please */
Larry Fingeree5de8d2014-01-26 13:17:33 -0600984 if (ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
Greg Kroah-Hartman3c05bed2014-01-21 11:20:45 -0800985 return;
986
987 /* check if this really is a beacon */
988 if (!(ieee80211_is_beacon(hdr->frame_control) ||
989 ieee80211_is_probe_resp(hdr->frame_control) ||
990 ieee80211_is_action(hdr->frame_control)))
991 return;
992
993 if (ieee80211_is_action(hdr->frame_control)) {
994 rtl_p2p_action_ie(hw,data,len - FCS_LEN);
995 } else {
996 rtl_p2p_noa_ie(hw,data,len - FCS_LEN);
997 }
998
999}