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