Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ps.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2012 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 <[email protected]>
23  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24  * Hsinchu 300, Taiwan.
25  *
26  * Larry Finger <[email protected]>
27  *
28  *****************************************************************************/
29 
30 #include <linux/export.h>
31 #include "wifi.h"
32 #include "base.h"
33 #include "ps.h"
34 
36 {
37  struct rtl_priv *rtlpriv = rtl_priv(hw);
38  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
39  struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
40 
41  /*<1> reset trx ring */
42  if (rtlhal->interface == INTF_PCI)
43  rtlpriv->intf_ops->reset_trx_ring(hw);
44 
45  if (is_hal_stop(rtlhal))
46  RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
47  "Driver is already down!\n");
48 
49  /*<2> Enable Adapter */
50  if (rtlpriv->cfg->ops->hw_init(hw))
51  return 1;
53 
54  /*<3> Enable Interrupt */
55  rtlpriv->cfg->ops->enable_interrupt(hw);
56 
57  /*<enable timer> */
58  rtl_watch_dog_timer_callback((unsigned long)hw);
59 
60  return true;
61 }
63 
65 {
66  struct rtl_priv *rtlpriv = rtl_priv(hw);
67 
68  /*<1> Stop all timer */
70 
71  /*<2> Disable Interrupt */
72  rtlpriv->cfg->ops->disable_interrupt(hw);
73  tasklet_kill(&rtlpriv->works.irq_tasklet);
74 
75  /*<3> Disable Adapter */
76  rtlpriv->cfg->ops->hw_disable(hw);
77 
78  return true;
79 }
81 
83  enum rf_pwrstate state_toset,
84  u32 changesource)
85 {
86  struct rtl_priv *rtlpriv = rtl_priv(hw);
87  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
88  bool actionallowed = false;
89 
90  switch (state_toset) {
91  case ERFON:
92  ppsc->rfoff_reason &= (~changesource);
93 
94  if ((changesource == RF_CHANGE_BY_HW) &&
95  (ppsc->hwradiooff)) {
96  ppsc->hwradiooff = false;
97  }
98 
99  if (!ppsc->rfoff_reason) {
100  ppsc->rfoff_reason = 0;
101  actionallowed = true;
102  }
103 
104  break;
105 
106  case ERFOFF:
107 
108  if ((changesource == RF_CHANGE_BY_HW) && !ppsc->hwradiooff) {
109  ppsc->hwradiooff = true;
110  }
111 
112  ppsc->rfoff_reason |= changesource;
113  actionallowed = true;
114  break;
115 
116  case ERFSLEEP:
117  ppsc->rfoff_reason |= changesource;
118  actionallowed = true;
119  break;
120 
121  default:
122  RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
123  "switch case not processed\n");
124  break;
125  }
126 
127  if (actionallowed)
128  rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
129 
130  return actionallowed;
131 }
133 
134 static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
135 {
136  struct rtl_priv *rtlpriv = rtl_priv(hw);
137  struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
138  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
139 
140  ppsc->swrf_processing = true;
141 
142  if (ppsc->inactive_pwrstate == ERFON &&
143  rtlhal->interface == INTF_PCI) {
144  if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
146  rtlhal->interface == INTF_PCI) {
147  rtlpriv->intf_ops->disable_aspm(hw);
149  }
150  }
151 
153 
154  if (ppsc->inactive_pwrstate == ERFOFF &&
155  rtlhal->interface == INTF_PCI) {
156  if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
158  rtlpriv->intf_ops->enable_aspm(hw);
160  }
161  }
162 
163  ppsc->swrf_processing = false;
164 }
165 
167 {
168  struct rtl_works *rtlworks =
170  struct ieee80211_hw *hw = rtlworks->hw;
171  struct rtl_priv *rtlpriv = rtl_priv(hw);
172  struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
173  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
174  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
175  enum rf_pwrstate rtstate;
176 
177  if (mac->opmode != NL80211_IFTYPE_STATION) {
178  RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
179  "not station return\n");
180  return;
181  }
182 
183  if (mac->link_state > MAC80211_NOLINK)
184  return;
185 
186  if (is_hal_stop(rtlhal))
187  return;
188 
189  if (rtlpriv->sec.being_setkey)
190  return;
191 
192  if (ppsc->inactiveps) {
193  rtstate = ppsc->rfpwr_state;
194 
195  /*
196  *Do not enter IPS in the following conditions:
197  *(1) RF is already OFF or Sleep
198  *(2) swrf_processing (indicates the IPS is still under going)
199  *(3) Connectted (only disconnected can trigger IPS)
200  *(4) IBSS (send Beacon)
201  *(5) AP mode (send Beacon)
202  *(6) monitor mode (rcv packet)
203  */
204 
205  if (rtstate == ERFON &&
206  !ppsc->swrf_processing &&
207  (mac->link_state == MAC80211_NOLINK) &&
208  !mac->act_scanning) {
209  RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
210  "IPSEnter(): Turn off RF\n");
211 
212  ppsc->inactive_pwrstate = ERFOFF;
213  ppsc->in_powersavemode = true;
214 
215  /*rtl_pci_reset_trx_ring(hw); */
216  _rtl_ps_inactive_ps(hw);
217  }
218  }
219 }
220 
222 {
223  struct rtl_priv *rtlpriv = rtl_priv(hw);
224 
225  /*
226  *because when link with ap, mac80211 will ask us
227  *to disable nic quickly after scan before linking,
228  *this will cause link failed, so we delay 100ms here
229  */
230  queue_delayed_work(rtlpriv->works.rtl_wq,
231  &rtlpriv->works.ips_nic_off_wq, MSECS(100));
232 }
233 
234 void rtl_ips_nic_on(struct ieee80211_hw *hw)
235 {
236  struct rtl_priv *rtlpriv = rtl_priv(hw);
237  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
238  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
239  enum rf_pwrstate rtstate;
240  unsigned long flags;
241 
242  if (mac->opmode != NL80211_IFTYPE_STATION)
243  return;
244 
245  spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
246 
247  if (ppsc->inactiveps) {
248  rtstate = ppsc->rfpwr_state;
249 
250  if (rtstate != ERFON &&
251  !ppsc->swrf_processing &&
252  ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) {
253 
254  ppsc->inactive_pwrstate = ERFON;
255  ppsc->in_powersavemode = false;
256 
257  _rtl_ps_inactive_ps(hw);
258  }
259  }
260 
261  spin_unlock_irqrestore(&rtlpriv->locks.ips_lock, flags);
262 }
263 
264 /*for FW LPS*/
265 
266 /*
267  *Determine if we can set Fw into PS mode
268  *in current condition.Return TRUE if it
269  *can enter PS mode.
270  */
271 static bool rtl_get_fwlps_doze(struct ieee80211_hw *hw)
272 {
273  struct rtl_priv *rtlpriv = rtl_priv(hw);
274  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
275  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
276  u32 ps_timediff;
277 
278  ps_timediff = jiffies_to_msecs(jiffies -
280 
281  if (ps_timediff < 2000) {
282  RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
283  "Delay enter Fw LPS for DHCP, ARP, or EAPOL exchanging state\n");
284  return false;
285  }
286 
287  if (mac->link_state != MAC80211_LINKED)
288  return false;
289 
290  if (mac->opmode == NL80211_IFTYPE_ADHOC)
291  return false;
292 
293  return true;
294 }
295 
296 /* Change current and default preamble mode.*/
297 static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
298 {
299  struct rtl_priv *rtlpriv = rtl_priv(hw);
300  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
301  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
302  u8 rpwm_val, fw_pwrmode;
303 
304  if (mac->opmode == NL80211_IFTYPE_ADHOC)
305  return;
306 
307  if (mac->link_state != MAC80211_LINKED)
308  return;
309 
310  if (ppsc->dot11_psmode == rt_psmode)
311  return;
312 
313  /* Update power save mode configured. */
314  ppsc->dot11_psmode = rt_psmode;
315 
316  /*
317  *<FW control LPS>
318  *1. Enter PS mode
319  * Set RPWM to Fw to turn RF off and send H2C fw_pwrmode
320  * cmd to set Fw into PS mode.
321  *2. Leave PS mode
322  * Send H2C fw_pwrmode cmd to Fw to set Fw into Active
323  * mode and set RPWM to turn RF on.
324  */
325 
326  if ((ppsc->fwctrl_lps) && ppsc->report_linked) {
327  bool fw_current_inps;
328  if (ppsc->dot11_psmode == EACTIVE) {
329  RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
330  "FW LPS leave ps_mode:%x\n",
332 
333  rpwm_val = 0x0C; /* RF on */
334  fw_pwrmode = FW_PS_ACTIVE_MODE;
335  rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SET_RPWM,
336  &rpwm_val);
337  rtlpriv->cfg->ops->set_hw_reg(hw,
339  &fw_pwrmode);
340  fw_current_inps = false;
341 
342  rtlpriv->cfg->ops->set_hw_reg(hw,
344  (u8 *) (&fw_current_inps));
345 
346  } else {
347  if (rtl_get_fwlps_doze(hw)) {
348  RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
349  "FW LPS enter ps_mode:%x\n",
350  ppsc->fwctrl_psmode);
351 
352  rpwm_val = 0x02; /* RF off */
353  fw_current_inps = true;
354  rtlpriv->cfg->ops->set_hw_reg(hw,
356  (u8 *) (&fw_current_inps));
357  rtlpriv->cfg->ops->set_hw_reg(hw,
359  &ppsc->fwctrl_psmode);
360 
361  rtlpriv->cfg->ops->set_hw_reg(hw,
363  &rpwm_val);
364  } else {
365  /* Reset the power save related parameters. */
366  ppsc->dot11_psmode = EACTIVE;
367  }
368  }
369  }
370 }
371 
372 /*Enter the leisure power save mode.*/
373 void rtl_lps_enter(struct ieee80211_hw *hw)
374 {
375  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
376  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
377  struct rtl_priv *rtlpriv = rtl_priv(hw);
378 
379  if (!ppsc->fwctrl_lps)
380  return;
381 
382  if (rtlpriv->sec.being_setkey)
383  return;
384 
385  if (rtlpriv->link_info.busytraffic)
386  return;
387 
388  /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
389  if (mac->cnt_after_linked < 5)
390  return;
391 
392  if (mac->opmode == NL80211_IFTYPE_ADHOC)
393  return;
394 
395  if (mac->link_state != MAC80211_LINKED)
396  return;
397 
398  mutex_lock(&rtlpriv->locks.ps_mutex);
399 
400  /* Idle for a while if we connect to AP a while ago. */
401  if (mac->cnt_after_linked >= 2) {
402  if (ppsc->dot11_psmode == EACTIVE) {
403  RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
404  "Enter 802.11 power save mode...\n");
405 
406  rtl_lps_set_psmode(hw, EAUTOPS);
407  }
408  }
409 
410  mutex_unlock(&rtlpriv->locks.ps_mutex);
411 }
412 
413 /*Leave the leisure power save mode.*/
414 void rtl_lps_leave(struct ieee80211_hw *hw)
415 {
416  struct rtl_priv *rtlpriv = rtl_priv(hw);
417  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
418  struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
419 
420  mutex_lock(&rtlpriv->locks.ps_mutex);
421 
422  if (ppsc->fwctrl_lps) {
423  if (ppsc->dot11_psmode != EACTIVE) {
424 
425  /*FIX ME */
426  rtlpriv->cfg->ops->enable_interrupt(hw);
427 
428  if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
430  rtlhal->interface == INTF_PCI) {
431  rtlpriv->intf_ops->disable_aspm(hw);
433  }
434 
435  RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
436  "Busy Traffic,Leave 802.11 power save..\n");
437 
438  rtl_lps_set_psmode(hw, EACTIVE);
439  }
440  }
441  mutex_unlock(&rtlpriv->locks.ps_mutex);
442 }
443 
444 /* For sw LPS*/
445 void rtl_swlps_beacon(struct ieee80211_hw *hw, void *data, unsigned int len)
446 {
447  struct rtl_priv *rtlpriv = rtl_priv(hw);
448  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
449  struct ieee80211_hdr *hdr = data;
450  struct ieee80211_tim_ie *tim_ie;
451  u8 *tim;
452  u8 tim_len;
453  bool u_buffed;
454  bool m_buffed;
455 
456  if (mac->opmode != NL80211_IFTYPE_STATION)
457  return;
458 
459  if (!rtlpriv->psc.swctrl_lps)
460  return;
461 
462  if (rtlpriv->mac80211.link_state != MAC80211_LINKED)
463  return;
464 
465  if (!rtlpriv->psc.sw_ps_enabled)
466  return;
467 
468  if (rtlpriv->psc.fwctrl_lps)
469  return;
470 
471  if (likely(!(hw->conf.flags & IEEE80211_CONF_PS)))
472  return;
473 
474  /* check if this really is a beacon */
475  if (!ieee80211_is_beacon(hdr->frame_control))
476  return;
477 
478  /* min. beacon length + FCS_LEN */
479  if (len <= 40 + FCS_LEN)
480  return;
481 
482  /* and only beacons from the associated BSSID, please */
483  if (!ether_addr_equal(hdr->addr3, rtlpriv->mac80211.bssid))
484  return;
485 
486  rtlpriv->psc.last_beacon = jiffies;
487 
488  tim = rtl_find_ie(data, len - FCS_LEN, WLAN_EID_TIM);
489  if (!tim)
490  return;
491 
492  if (tim[1] < sizeof(*tim_ie))
493  return;
494 
495  tim_len = tim[1];
496  tim_ie = (struct ieee80211_tim_ie *) &tim[2];
497 
498  if (!WARN_ON_ONCE(!hw->conf.ps_dtim_period))
499  rtlpriv->psc.dtim_counter = tim_ie->dtim_count;
500 
501  /* Check whenever the PHY can be turned off again. */
502 
503  /* 1. What about buffered unicast traffic for our AID? */
504  u_buffed = ieee80211_check_tim(tim_ie, tim_len,
505  rtlpriv->mac80211.assoc_id);
506 
507  /* 2. Maybe the AP wants to send multicast/broadcast data? */
508  m_buffed = tim_ie->bitmap_ctrl & 0x01;
509  rtlpriv->psc.multi_buffered = m_buffed;
510 
511  /* unicast will process by mac80211 through
512  * set ~IEEE80211_CONF_PS, So we just check
513  * multicast frames here */
514  if (!m_buffed) {
515  /* back to low-power land. and delay is
516  * prevent null power save frame tx fail */
517  queue_delayed_work(rtlpriv->works.rtl_wq,
518  &rtlpriv->works.ps_work, MSECS(5));
519  } else {
520  RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
521  "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed);
522  }
523 }
524 
526 {
527  struct rtl_priv *rtlpriv = rtl_priv(hw);
528  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
529  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
530 
531  if (!rtlpriv->psc.swctrl_lps)
532  return;
533  if (mac->link_state != MAC80211_LINKED)
534  return;
535 
536  if (ppsc->reg_rfps_level & RT_RF_LPS_LEVEL_ASPM &&
538  rtlpriv->intf_ops->disable_aspm(hw);
540  }
541 
542  mutex_lock(&rtlpriv->locks.ps_mutex);
544  mutex_unlock(&rtlpriv->locks.ps_mutex);
545 }
546 
548 {
549  struct rtl_works *rtlworks =
551  struct ieee80211_hw *hw = rtlworks->hw;
552 
553  rtl_swlps_rf_awake(hw);
554 }
555 
557 {
558  struct rtl_priv *rtlpriv = rtl_priv(hw);
559  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
560  struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
561  u8 sleep_intv;
562 
563  if (!rtlpriv->psc.sw_ps_enabled)
564  return;
565 
566  if ((rtlpriv->sec.being_setkey) ||
567  (mac->opmode == NL80211_IFTYPE_ADHOC))
568  return;
569 
570  /*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
571  if ((mac->link_state != MAC80211_LINKED) || (mac->cnt_after_linked < 5))
572  return;
573 
574  if (rtlpriv->link_info.busytraffic)
575  return;
576 
577  mutex_lock(&rtlpriv->locks.ps_mutex);
579  mutex_unlock(&rtlpriv->locks.ps_mutex);
580 
581  if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
583  rtlpriv->intf_ops->enable_aspm(hw);
585  }
586 
587  /* here is power save alg, when this beacon is DTIM
588  * we will set sleep time to dtim_period * n;
589  * when this beacon is not DTIM, we will set sleep
590  * time to sleep_intv = rtlpriv->psc.dtim_counter or
591  * MAX_SW_LPS_SLEEP_INTV(default set to 5) */
592 
593  if (rtlpriv->psc.dtim_counter == 0) {
594  if (hw->conf.ps_dtim_period == 1)
595  sleep_intv = hw->conf.ps_dtim_period * 2;
596  else
597  sleep_intv = hw->conf.ps_dtim_period;
598  } else {
599  sleep_intv = rtlpriv->psc.dtim_counter;
600  }
601 
602  if (sleep_intv > MAX_SW_LPS_SLEEP_INTV)
603  sleep_intv = MAX_SW_LPS_SLEEP_INTV;
604 
605  /* this print should always be dtim_conter = 0 &
606  * sleep = dtim_period, that meaons, we should
607  * awake before every dtim */
608  RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
609  "dtim_counter:%x will sleep :%d beacon_intv\n",
610  rtlpriv->psc.dtim_counter, sleep_intv);
611 
612  /* we tested that 40ms is enough for sw & hw sw delay */
613  queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq,
614  MSECS(sleep_intv * mac->vif->bss_conf.beacon_int - 40));
615 }
616 
617 
619 {
620  struct rtl_works *rtlworks = container_of_dwork_rtl(data,
621  struct rtl_works,
622  ps_work);
623  struct ieee80211_hw *hw = rtlworks->hw;
624  struct rtl_priv *rtlpriv = rtl_priv(hw);
625  bool ps = false;
626 
627  ps = (hw->conf.flags & IEEE80211_CONF_PS);
628 
629  /* we can sleep after ps null send ok */
630  if (rtlpriv->psc.state_inap) {
631  rtl_swlps_rf_sleep(hw);
632 
633  if (rtlpriv->psc.state && !ps) {
634  rtlpriv->psc.sleep_ms = jiffies_to_msecs(jiffies -
635  rtlpriv->psc.last_action);
636  }
637 
638  if (ps)
639  rtlpriv->psc.last_slept = jiffies;
640 
641  rtlpriv->psc.last_action = jiffies;
642  rtlpriv->psc.state = ps;
643  }
644 }