• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * PM implementation for XRadio drivers
3  *
4  * Copyright (c) 2013
5  * Xradio Technology Co., Ltd. <www.xradiotech.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 
12 #include <linux/platform_device.h>
13 #include <linux/if_ether.h>
14 #include "xradio.h"
15 #include "pm.h"
16 #include "sta.h"
17 #include "bh.h"
18 #include "sbus.h"
19 #include "platform.h"
20 #ifdef CONFIG_XRADIO_EXTEND_SUSPEND
21 #include <linux/power/scenelock.h>
22 #endif
23 
24 #ifdef CONFIG_XRADIO_NOMAL_SUSPEND_FORCE
25 #include <linux/power/scenelock.h>
26 struct scene_lock  wifi_lock;
27 #endif
28 
29 #define XRADIO_BEACON_SKIPPING_MULTIPLIER 3
30 
31 struct xradio_udp_port_filter {
32 	struct wsm_udp_port_filter_hdr hdr;
33 	struct wsm_udp_port_filter dhcp;
34 	struct wsm_udp_port_filter upnp;
35 } __packed;
36 
37 struct xradio_ether_type_filter {
38 	struct wsm_ether_type_filter_hdr hdr;
39 	struct wsm_ether_type_filter ip;
40 	struct wsm_ether_type_filter pae;
41 	struct wsm_ether_type_filter wapi;
42 } __packed;
43 
44 static struct xradio_udp_port_filter xradio_udp_port_filter_on = {
45 	.hdr.nrFilters = 2,
46 	.dhcp = {
47 		.filterAction = WSM_FILTER_ACTION_FILTER_OUT,
48 		.portType = WSM_FILTER_PORT_TYPE_DST,
49 		.udpPort = __cpu_to_le16(67),
50 	},
51 	.upnp = {
52 		.filterAction = WSM_FILTER_ACTION_FILTER_OUT,
53 		.portType = WSM_FILTER_PORT_TYPE_DST,
54 		.udpPort = __cpu_to_le16(1900),
55 	},
56 	/* Please add other known ports to be filtered out here and
57 	 * update nrFilters field in the header.
58 	 * Up to 4 filters are allowed. */
59 };
60 
61 static struct wsm_udp_port_filter_hdr xradio_udp_port_filter_off = {
62 	.nrFilters = 0,
63 };
64 
65 #ifndef ETH_P_WAPI
66 #define ETH_P_WAPI     0x88B4
67 #endif
68 
69 #ifdef TES_P2P_000B_DISABLE_EAPOL_FILTER
70 /* TES_P2P_000B WorkAround:
71  * when the link keep 10min more or less(i am not sure),
72  * wpa_s session maybe expired, and want to update group key.
73  * it will use eapol frame(802.1x, 0x888E).
74  * if driver suspend, and discard eapol frame, then session end.
75  * i don't know why original code discards eapol frame in suspend.
76  * but now make this filter disable as WorkAround.*/
77 static struct xradio_ether_type_filter xradio_ether_type_filter_on = {
78 	.hdr.nrFilters = 1,
79 /*	.ip = {
80 		.filterAction = WSM_FILTER_ACTION_FILTER_IN,
81 		.etherType = __cpu_to_le16(ETH_P_IP),
82 	}, */
83 /*	.pae = {
84 		.filterAction = WSM_FILTER_ACTION_FILTER_IN,
85 		.etherType = __cpu_to_le16(ETH_P_PAE),
86 	}, */
87 	.wapi = {
88 		.filterAction = WSM_FILTER_ACTION_FILTER_IN,
89 		.etherType = __cpu_to_le16(ETH_P_WAPI),
90 	},
91 	/* Please add other known ether types to be filtered out here and
92 	 * update nrFilters field in the header.
93 	 * Up to 4 filters are allowed. */
94 };
95 #else
96 static struct xradio_ether_type_filter xradio_ether_type_filter_on = {
97 	.hdr.nrFilters = 2,
98 /*	.ip = {
99 		.filterAction = WSM_FILTER_ACTION_FILTER_IN,
100 		.etherType = __cpu_to_le16(ETH_P_IP),
101 	}, */
102 	.pae = {
103 		.filterAction = WSM_FILTER_ACTION_FILTER_IN,
104 		.etherType = __cpu_to_le16(ETH_P_PAE),
105 	},
106 	.wapi = {
107 		.filterAction = WSM_FILTER_ACTION_FILTER_IN,
108 		.etherType = __cpu_to_le16(ETH_P_WAPI),
109 	},
110 	/* Please add other known ether types to be filtered out here and
111 	 * update nrFilters field in the header.
112 	 * Up to 4 filters are allowed. */
113 };
114 #endif
115 
116 static struct wsm_ether_type_filter_hdr xradio_ether_type_filter_off = {
117 	.nrFilters = 0,
118 };
119 
120 static int xradio_suspend_late(struct device *dev);
121 static void xradio_pm_release(struct device *dev);
122 static int xradio_pm_probe(struct platform_device *pdev);
123 static int __xradio_wow_suspend(struct xradio_vif *priv,
124 				struct cfg80211_wowlan *wowlan);
125 static int __xradio_wow_resume(struct xradio_vif *priv);
126 #ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
127 static int xradio_poweroff_suspend(struct xradio_common *hw_priv);
128 static int xradio_poweroff_resume(struct xradio_common *hw_priv);
129 #endif
130 
131 
132 /* private */
133 struct xradio_suspend_state {
134 	unsigned long bss_loss_tmo;
135 	unsigned long connection_loss_tmo;
136 	unsigned long join_tmo;
137 	unsigned long direct_probe;
138 	unsigned long link_id_gc;
139 	bool beacon_skipping;
140 };
141 
142 static const struct dev_pm_ops xradio_pm_ops = {
143 	.suspend_noirq = xradio_suspend_late,
144 };
145 
146 static struct platform_driver xradio_power_driver = {
147 	.probe = xradio_pm_probe,
148 	.driver = {
149 		.name = XRADIO_PLAT_DEVICE,
150 		.pm = &xradio_pm_ops,
151 	},
152 };
153 
154 #ifdef CONFIG_XRADIO_DEBUG
155 struct timespec64 suspend_time;
156 struct timespec64 resume_time;
xradio_realtime_interval(struct timespec64 * oldtime,struct timespec64 * newtime)157 u32 xradio_realtime_interval(struct timespec64 *oldtime, struct timespec64 *newtime)
158 {
159 	u32 time_int;
160 	xr_do_gettimeofday(newtime);
161 	time_int = (newtime->tv_sec - oldtime->tv_sec) * 1000 + \
162 			    (newtime->tv_nsec - oldtime->tv_nsec) / 1000000;
163 	return time_int;
164 }
165 #endif
166 
xradio_pm_init_common(struct xradio_pm_state * pm,struct xradio_common * hw_priv)167 static int xradio_pm_init_common(struct xradio_pm_state *pm,
168 				  struct xradio_common *hw_priv)
169 {
170 	int ret;
171 	pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
172 #ifdef CONFIG_XRADIO_DEBUG
173 	xr_do_gettimeofday(&resume_time);
174 #endif
175 
176 	spin_lock_init(&pm->lock);
177 	/* Register pm driver. */
178 	ret = platform_driver_register(&xradio_power_driver);
179 	if (ret) {
180 		pm_printk(XRADIO_DBG_ERROR,
181 			  "%s:platform_driver_register failed(%d)!\n",
182 			  __func__, ret);
183 	}
184 
185 #ifdef CONFIG_XRADIO_NOMAL_SUSPEND_FORCE
186 	scene_lock_init(&wifi_lock, SCENE_NORMAL_STANDBY, "wifinormal_standby");
187 	scene_lock(&wifi_lock);
188 	if (!check_scene_locked(SCENE_NORMAL_STANDBY))
189 		pm_printk(XRADIO_DBG_NIY, "normal standby lock success!\n");
190 	else
191 		pm_printk(XRADIO_DBG_ERROR, "normal standby lock failed!\n");
192 #endif
193 
194 	return ret;
195 }
196 
xradio_pm_deinit_common(struct xradio_pm_state * pm)197 static void xradio_pm_deinit_common(struct xradio_pm_state *pm)
198 {
199 	pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
200 	platform_driver_unregister(&xradio_power_driver);
201 #ifdef CONFIG_XRADIO_NOMAL_SUSPEND_FORCE
202 	scene_unlock(&wifi_lock);
203 	if (!check_scene_locked(SCENE_NORMAL_STANDBY))
204 		pm_printk(XRADIO_DBG_ERROR, "normal standby unlock failed!\n");
205 	else
206 		pm_printk(XRADIO_DBG_NIY, "normal standby unlock success!\n");
207 #endif
208 }
209 
210 #ifdef CONFIG_WAKELOCK
211 
xradio_pm_init(struct xradio_pm_state * pm,struct xradio_common * hw_priv)212 int xradio_pm_init(struct xradio_pm_state *pm,
213 		   struct xradio_common *hw_priv)
214 {
215 	int ret = 0;
216 	pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
217 
218 	ret = xradio_pm_init_common(pm, hw_priv);
219 	if (!ret)
220 		wake_lock_init(&pm->wakelock, WAKE_LOCK_SUSPEND, XRADIO_WAKE_LOCK);
221 	else
222 		pm_printk(XRADIO_DBG_ERROR, "xradio_pm_init_common failed!\n");
223 	return ret;
224 }
225 
xradio_pm_deinit(struct xradio_pm_state * pm)226 void xradio_pm_deinit(struct xradio_pm_state *pm)
227 {
228 	pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
229 	if (wake_lock_active(&pm->wakelock))
230 		wake_unlock(&pm->wakelock);
231 	wake_lock_destroy(&pm->wakelock);
232 	xradio_pm_deinit_common(pm);
233 }
234 
xradio_pm_stay_awake(struct xradio_pm_state * pm,unsigned long tmo)235 void xradio_pm_stay_awake(struct xradio_pm_state *pm,
236 			  unsigned long tmo)
237 {
238 	long cur_tmo;
239 	pm_printk(XRADIO_DBG_MSG, "%s\n", __func__);
240 
241 	spin_lock_bh(&pm->lock);
242 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
243 	cur_tmo = pm->wakelock.ws.timer.expires - jiffies;
244 #else
245 	cur_tmo = pm->wakelock.expires - jiffies;
246 #endif
247 	if (!wake_lock_active(&pm->wakelock) || cur_tmo < (long)tmo)
248 		wake_lock_timeout(&pm->wakelock, tmo);
249 	spin_unlock_bh(&pm->lock);
250 }
xradio_pm_lock_awake(struct xradio_pm_state * pm)251 void xradio_pm_lock_awake(struct xradio_pm_state *pm)
252 {
253 	pm_printk(XRADIO_DBG_NIY, "%s\n", __func__);
254 	spin_lock_bh(&pm->lock);
255 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
256 	pm->expires_save = pm->wakelock.ws.timer.expires;
257 #else
258 	pm->expires_save = pm->wakelock.expires;
259 #endif
260 	if (!wake_lock_active(&pm->wakelock) ||
261 		time_before((unsigned long)pm->expires_save, jiffies)) {
262 		pm->expires_save = 0;
263 	}
264 	wake_lock(&pm->wakelock);
265 	spin_unlock_bh(&pm->lock);
266 }
xradio_pm_unlock_awake(struct xradio_pm_state * pm)267 void xradio_pm_unlock_awake(struct xradio_pm_state *pm)
268 {
269 	pm_printk(XRADIO_DBG_NIY, "%s\n", __func__);
270 	spin_lock_bh(&pm->lock);
271 	if (wake_lock_active(&pm->wakelock)) {
272 		wake_unlock(&pm->wakelock);
273 		if (pm->expires_save &&
274 			time_before(jiffies, (unsigned long)pm->expires_save)) {
275 			pm->expires_save -= jiffies;
276 			wake_lock_timeout(&pm->wakelock, pm->expires_save);
277 		}
278 	}
279 	pm->expires_save = 0;
280 	spin_unlock_bh(&pm->lock);
281 }
282 
283 #else /* CONFIG_WAKELOCK */
284 
xradio_pm_stay_awake_tmo(struct timer_list * t)285 static void xradio_pm_stay_awake_tmo(struct timer_list *t)
286 {
287 	struct xradio_pm_state *pm = from_timer(pm, t, stay_awake);
288 
289 	atomic_set(&pm->status, XRADIO_PM_STATE_ALLOW_SUSPEND);
290 }
291 
xradio_pm_init(struct xradio_pm_state * pm,struct xradio_common * hw_priv)292 int xradio_pm_init(struct xradio_pm_state *pm,
293 		   struct xradio_common *hw_priv)
294 {
295 	int ret = 0;
296 	pm_printk(XRADIO_DBG_MSG, "%s\n", __func__);
297 
298 	ret = xradio_pm_init_common(pm, hw_priv);
299 	if (!ret) {
300 		timer_setup(&pm->stay_awake, xradio_pm_stay_awake_tmo, 0);
301 		atomic_set(&pm->status, XRADIO_PM_STATE_ALLOW_SUSPEND);
302 	} else
303 		pm_printk(XRADIO_DBG_ERROR, "xradio_pm_init_common failed!\n");
304 	return ret;
305 }
306 
xradio_pm_deinit(struct xradio_pm_state * pm)307 void xradio_pm_deinit(struct xradio_pm_state *pm)
308 {
309 	pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
310 	del_timer_sync(&pm->stay_awake);
311 	xradio_pm_deinit_common(pm);
312 }
313 
xradio_pm_stay_awake(struct xradio_pm_state * pm,unsigned long tmo)314 void xradio_pm_stay_awake(struct xradio_pm_state *pm,
315 			  unsigned long tmo)
316 {
317 	long cur_tmo;
318 	pm_printk(XRADIO_DBG_MSG, "%s\n", __func__);
319 
320 	spin_lock_bh(&pm->lock);
321 	atomic_set(&pm->status, XRADIO_PM_STATE_KEEP_WAKE);
322 	cur_tmo = pm->stay_awake.expires - jiffies;
323 	if (!timer_pending(&pm->stay_awake) || cur_tmo < (long)tmo)
324 		mod_timer(&pm->stay_awake, jiffies + tmo);
325 	spin_unlock_bh(&pm->lock);
326 }
xradio_pm_lock_awake(struct xradio_pm_state * pm)327 void xradio_pm_lock_awake(struct xradio_pm_state *pm)
328 {
329 	pm_printk(XRADIO_DBG_NIY, "%s\n", __func__);
330 	spin_lock_bh(&pm->lock);
331 	if (timer_pending(&pm->stay_awake))
332 		pm->expires_save = pm->stay_awake.expires;
333 	else
334 		pm->expires_save = jiffies;
335 	mod_timer(&pm->stay_awake, jiffies + LONG_MAX);
336 	spin_unlock_bh(&pm->lock);
337 }
xradio_pm_unlock_awake(struct xradio_pm_state * pm)338 void xradio_pm_unlock_awake(struct xradio_pm_state *pm)
339 {
340 	pm_printk(XRADIO_DBG_NIY, "%s\n", __func__);
341 	spin_lock_bh(&pm->lock);
342 	if (time_before(jiffies, (unsigned long)pm->expires_save))
343 		mod_timer(&pm->stay_awake, pm->expires_save);
344 	else
345 		mod_timer(&pm->stay_awake, jiffies + 5);
346 	spin_unlock_bh(&pm->lock);
347 }
348 #endif /* CONFIG_WAKELOCK */
349 
xradio_suspend_work(struct delayed_work * work)350 static long xradio_suspend_work(struct delayed_work *work)
351 {
352 	int ret = cancel_delayed_work(work);
353 	long tmo;
354 	pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
355 
356 	if (ret > 0) {
357 		/* Timer is pending */
358 		tmo = work->timer.expires - jiffies;
359 		if (tmo < 0)
360 			tmo = 0;
361 	} else {
362 		tmo = -1;
363 	}
364 	return tmo;
365 }
366 
xradio_resume_work(struct xradio_common * hw_priv,struct delayed_work * work,unsigned long tmo)367 static int xradio_resume_work(struct xradio_common *hw_priv,
368 			       struct delayed_work *work,
369 			       unsigned long tmo)
370 {
371 	pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
372 	if ((long)tmo < 0)
373 		return 1;
374 
375 	return queue_delayed_work(hw_priv->workqueue, work, tmo);
376 }
377 
xradio_suspend_late(struct device * dev)378 static int xradio_suspend_late(struct device *dev)
379 {
380 	struct xradio_common *hw_priv = dev->platform_data;
381 	pm_printk(XRADIO_DBG_NIY, "%s\n", __func__);
382 #ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
383 	if (XRADIO_POWEROFF_SUSP == atomic_read(&hw_priv->suspend_state)) {
384 		return 0; /* we don't rx data when power down wifi.*/
385 	}
386 #endif
387 
388 	if (atomic_read(&hw_priv->bh_rx)) {
389 		pm_printk(XRADIO_DBG_WARN, "%s: Suspend interrupted.\n", __func__);
390 		return -EAGAIN;
391 	}
392 	return 0;
393 }
394 
xradio_pm_release(struct device * dev)395 static void xradio_pm_release(struct device *dev)
396 {
397 	pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
398 }
399 
xradio_pm_probe(struct platform_device * pdev)400 static int xradio_pm_probe(struct platform_device *pdev)
401 {
402 	pm_printk(XRADIO_DBG_TRC, "%s\n", __func__);
403 	pdev->dev.release = xradio_pm_release;
404 	return 0;
405 }
406 
xradio_wow_suspend(struct ieee80211_hw * hw,struct cfg80211_wowlan * wowlan)407 int xradio_wow_suspend(struct ieee80211_hw *hw,
408 			       struct cfg80211_wowlan *wowlan)
409 {
410 	struct xradio_common *hw_priv = hw->priv;
411 	struct xradio_vif *priv;
412 	int i, ret = 0;
413 	int suspend_lock_state;
414 	pm_printk(XRADIO_DBG_NIY, "%s, Activetime=%dms\n", __func__,
415 			  xradio_realtime_interval(&resume_time, &suspend_time));
416 
417 	if (hw_priv->bh_error) {
418 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
419 			   "because of bh_error occurs.\n");
420 		return -EBUSY;
421 	}
422 	if (!atomic_read(&hw_priv->num_vifs))
423 		pm_printk(XRADIO_DBG_WARN, "%s num_vifs=0\n", __func__);
424 
425 #ifdef HW_RESTART
426 	if (hw_priv->hw_restart == true) {
427 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
428 			   "because of hw_restart is working.\n");
429 		return -EBUSY;
430 	}
431 
432 	if (work_pending(&hw_priv->hw_restart_work)) {
433 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
434 				"because of hw_restart_work prepare to worked.\n");
435 		return -EBUSY;
436 	}
437 
438 	if (hw_priv->hw_restart_work_running == true) {
439 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
440 				"because of hw_restart_work is working.\n");
441 		return -EBUSY;
442 	}
443 #endif
444 
445 #ifndef CONFIG_WAKELOCK
446 	if (atomic_read(&hw_priv->pm_state.status) == XRADIO_PM_STATE_KEEP_WAKE) {
447 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
448 			"because of pm_state need keep awake.\n");
449 		return -EBUSY;
450 	}
451 #endif
452 
453 	if (work_pending(&hw_priv->query_work)) {
454 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
455 				"because of query_work is working.\n");
456 		return -EBUSY;
457 	}
458 
459 #ifdef ROAM_OFFLOAD
460 	xradio_for_each_vif(hw_priv, priv, i) {
461 #ifdef P2P_MULTIVIF
462 		if ((i == (XRWL_MAX_VIFS - 1)) || !priv)
463 #else
464 		if (!priv)
465 #endif
466 			continue;
467 		if ((priv->vif->type == NL80211_IFTYPE_STATION)
468 		&& (priv->join_status == XRADIO_JOIN_STATUS_STA)) {
469 			down(&hw_priv->scan.lock);
470 			hw_priv->scan.if_id = priv->if_id;
471 			xradio_sched_scan_work(&hw_priv->scan.swork);
472 		}
473 	}
474 #endif /*ROAM_OFFLOAD*/
475 
476 	/* Do not suspend when datapath is not idle */
477 	if (hw_priv->tx_queue_stats.num_queued[0] +
478 		  hw_priv->tx_queue_stats.num_queued[1]) {
479 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
480 			   "because of tx_queue is not empty.\n");
481 		return -EBUSY;
482 	}
483 
484 #ifdef BH_PROC_THREAD
485 	if (atomic_read(&hw_priv->proc.rx_queued) +
486 		atomic_read(&hw_priv->proc.tx_queued)) {
487 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
488 			   "because of proc_queue is not empty.\n");
489 		return -EBUSY;
490 	}
491 #endif
492 	suspend_lock_state = atomic_cmpxchg(&hw_priv->suspend_lock_state,
493 									XRADIO_SUSPEND_LOCK_IDEL, XRADIO_SUSPEND_LOCK_SUSPEND);
494 	if (suspend_lock_state == XRADIO_SUSPEND_LOCK_OTHERS) {
495 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
496 			   "because others are waiting for lock.\n");
497 		goto revertm1;
498 	}
499 
500 	/* Make sure there is no configuration requests in progress. */
501 	if (down_trylock(&hw_priv->conf_lock)) {
502 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
503 			   "because of configuration requests.\n");
504 		goto revertm1;
505 	}
506 
507 	/* Make sure there is no wsm_oper_lock in progress. */
508 	if (down_trylock(&hw_priv->wsm_oper_lock)) {
509 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
510 			   "because of wsm_oper_lock.\n");
511 		goto revert0;
512 	}
513 
514 	/* Do not suspend when scanning or ROC*/
515 	if (down_trylock(&hw_priv->scan.lock)) {
516 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
517 			   "because of scan requests.\n");
518 		goto revert1;
519 	}
520 
521 	if (delayed_work_pending(&hw_priv->scan.probe_work)) {
522 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
523 			   "because of probe frames tx in progress.\n");
524 		goto revert2;
525 	}
526 
527 	/* Lock TX. */
528 	wsm_lock_tx_async(hw_priv);
529 
530 	/* Wait to avoid possible race with bh code.
531 	 * But do not wait too long... */
532 	if (wait_event_timeout(hw_priv->bh_evt_wq,
533 			       !hw_priv->hw_bufs_used, HZ / 10) <= 0) {
534 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
535 			   "because of there are frames not confirm.\n");
536 		goto revert3;
537 	}
538 
539 #ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
540 #ifdef CONFIG_XRADIO_EXTEND_SUSPEND
541 	if (check_scene_locked(SCENE_SUPER_STANDBY) == 0) {
542 		if (xradio_poweroff_suspend(hw_priv)) {
543 			pm_printk(XRADIO_DBG_WARN, "Don't suspend "	\
544 				"because of xradio_poweroff_suspend failed.\n");
545 			goto revert3;
546 		}
547 		return 0;
548 	}
549 
550 #else
551 	if (xradio_poweroff_suspend(hw_priv)) {
552 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "	\
553 			"because of xradio_poweroff_suspend failed.\n");
554 		goto revert3;
555 	}
556 	return 0;
557 
558 #endif
559 #endif
560 
561 	xradio_for_each_vif(hw_priv, priv, i) {
562 #ifdef P2P_MULTIVIF
563 		if ((i == (XRWL_MAX_VIFS - 1)) || !priv)
564 #else
565 		if (!priv)
566 #endif
567 			continue;
568 
569 		ret = __xradio_wow_suspend(priv, wowlan);
570 		if (ret) {
571 			for (; i >= 0; i--) {
572 				if (!hw_priv->vif_list[i])
573 					continue;
574 				priv = (struct xradio_vif *)hw_priv->vif_list[i]->drv_priv;
575 				__xradio_wow_resume(priv);
576 			}
577 			pm_printk(XRADIO_DBG_WARN, "Don't suspend "
578 				   "because of __xradio_wow_suspend failed!\n");
579 			goto revert3;
580 		}
581 	}
582 
583 	/* Stop serving thread */
584 	if (xradio_bh_suspend(hw_priv)) {
585 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
586 			   "because of xradio_bh_suspend failed!\n");
587 		goto revert4;
588 	}
589 
590 	/* Enable IRQ wake */
591 	ret = hw_priv->sbus_ops->power_mgmt(hw_priv->sbus_priv, true);
592 	if (ret) {
593 		pm_printk(XRADIO_DBG_WARN, "Don't suspend sbus pm failed\n");
594 		goto revert5;
595 	}
596 
597 	/* Force resume if event is coming from the device. */
598 	if (atomic_read(&hw_priv->bh_rx)) {
599 		pm_printk(XRADIO_DBG_WARN, "Don't suspend "
600 			   "because of recieved rx event!\n");
601 		goto revert6;
602 	}
603 	atomic_set(&hw_priv->suspend_state, XRADIO_CONNECT_SUSP);
604 	return 0;
605 
606 revert6:
607 	hw_priv->sbus_ops->power_mgmt(hw_priv->sbus_priv, false);
608 revert5:
609 	xradio_bh_resume(hw_priv);
610 revert4:
611 	xradio_for_each_vif(hw_priv, priv, i) {
612 #ifdef P2P_MULTIVIF
613 		if ((i == (XRWL_MAX_VIFS - 1)) || !priv)
614 #else
615 		if (!priv)
616 #endif
617 			continue;
618 		ret = __xradio_wow_resume(priv);
619 		if (ret) {
620 			pm_printk(XRADIO_DBG_ERROR,
621 				  "%s:__xradio_wow_resume failed!\n", __func__);
622 			break;
623 		}
624 	}
625 revert3:
626 	wsm_unlock_tx(hw_priv);
627 revert2:
628 	up(&hw_priv->scan.lock);
629 revert1:
630 	up(&hw_priv->wsm_oper_lock);
631 revert0:
632 	up(&hw_priv->conf_lock);
633 revertm1:
634 	return -EBUSY;
635 }
636 
__xradio_wow_suspend(struct xradio_vif * priv,struct cfg80211_wowlan * wowlan)637 static int __xradio_wow_suspend(struct xradio_vif *priv,
638 				struct cfg80211_wowlan *wowlan)
639 {
640 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
641 	struct xradio_pm_state_vif *pm_state_vif = &priv->pm_state_vif;
642 	struct xradio_suspend_state *state;
643 	int ret;
644 #ifdef MCAST_FWDING
645 	struct wsm_forwarding_offload fwdoffload = {
646 		.fwenable = 0x1,
647 		.flags    = 0x1,
648 	};
649 #endif
650 	pm_printk(XRADIO_DBG_NIY, "%s\n", __func__);
651 
652 	/* Do not suspend when join work is scheduled */
653 	if (work_pending(&priv->join_work)) {
654 		pm_printk(XRADIO_DBG_WARN, "%s:Do not suspend "
655 			   "when join work is scheduled\n", __func__);
656 		goto revert1;
657 	}
658 
659 	/* Set UDP filter */
660 	wsm_set_udp_port_filter(hw_priv, &xradio_udp_port_filter_on.hdr,
661 				priv->if_id);
662 
663 	/* Set ethernet frame type filter */
664 	wsm_set_ether_type_filter(hw_priv, &xradio_ether_type_filter_on.hdr,
665 				  priv->if_id);
666 
667 	/* Set IP multicast filter */
668     wsm_set_host_sleep(hw_priv, 1, priv->if_id);
669 
670 	if (priv->join_status == XRADIO_JOIN_STATUS_AP)
671 		WARN_ON(wsm_set_keepalive_filter(priv, true));
672 
673 #ifdef XRADIO_SUSPEND_RESUME_FILTER_ENABLE
674 	/* Set Multicast Address Filter */
675 	if (priv->multicast_filter.numOfAddresses) {
676 		priv->multicast_filter.enable = 1;
677 		wsm_set_multicast_filter(hw_priv, &priv->multicast_filter,
678 					 priv->if_id);
679 	}
680 
681 	/* Set Enable Broadcast Address Filter */
682 	priv->broadcast_filter.action_mode = 1;
683 	if (priv->join_status == XRADIO_JOIN_STATUS_AP)
684 		priv->broadcast_filter.address_mode = 3;
685 
686 	xradio_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter);
687 #endif
688 
689 #ifdef MCAST_FWDING
690 	if (priv->join_status == XRADIO_JOIN_STATUS_AP)
691 		WARN_ON(wsm_set_forwarding_offlad(hw_priv, &fwdoffload, priv->if_id));
692 #endif
693 
694 	/* Allocate state */
695 	state = xr_kzalloc(sizeof(struct xradio_suspend_state), false);
696 	if (!state) {
697 		pm_printk(XRADIO_DBG_WARN, "%s:Do not suspend "
698 			   "alloc xradio_suspend_state failed.\n", __func__);
699 		goto revert2;
700 	}
701 	/* Store delayed work states. */
702 	state->bss_loss_tmo        = xradio_suspend_work(&priv->bss_loss_work);
703 	state->connection_loss_tmo = xradio_suspend_work(&priv->connection_loss_work);
704 	state->join_tmo   = xradio_suspend_work(&priv->join_timeout);
705 	state->link_id_gc = xradio_suspend_work(&priv->link_id_gc_work);
706 
707 #ifndef XRADIO_USE_LONG_DTIM_PERIOD
708 	/* Enable beacon skipping */
709 	if (priv->join_status == XRADIO_JOIN_STATUS_STA &&
710 		priv->join_dtim_period < 3) {
711 		/* priv->join_dtim_period &&  !priv->has_multicast_subscription) { */
712 		state->beacon_skipping = true;
713 		wsm_set_beacon_wakeup_period(hw_priv,
714 			priv->join_dtim_period * XRADIO_BEACON_SKIPPING_MULTIPLIER,
715 			0, priv->if_id);
716 		pm_printk(XRADIO_DBG_NIY, "%s:Skip Beacons period(%d).\n", __func__,
717 				priv->join_dtim_period*XRADIO_BEACON_SKIPPING_MULTIPLIER);
718 	} else {
719 		pm_printk(XRADIO_DBG_NIY, "%s:Do not Skip Beacons(DTIM=%d).\n",
720 				__func__, priv->join_dtim_period);
721 	}
722 #endif
723 
724 	ret = timer_pending(&priv->mcast_timeout);
725 	if (ret) {
726 		pm_printk(XRADIO_DBG_WARN, "%s:Do not suspend "
727 			   "mcast timeout timer_pending failed.\n", __func__);
728 		goto revert3;
729 	}
730 
731 	/* Store suspend state */
732 	pm_state_vif->suspend_state = state;
733 
734 	return 0;
735 
736 revert3:
737 	xradio_resume_work(hw_priv, &priv->bss_loss_work, state->bss_loss_tmo);
738 	xradio_resume_work(hw_priv, &priv->connection_loss_work,
739 			   state->connection_loss_tmo);
740 	xradio_resume_work(hw_priv, &priv->join_timeout, state->join_tmo);
741 	xradio_resume_work(hw_priv, &priv->link_id_gc_work, state->link_id_gc);
742 	kfree(state);
743 
744 revert2:
745 	wsm_set_udp_port_filter(hw_priv, &xradio_udp_port_filter_off,
746 				priv->if_id);
747 	wsm_set_ether_type_filter(hw_priv, &xradio_ether_type_filter_off,
748 				  priv->if_id);
749     wsm_set_host_sleep(hw_priv, 0, priv->if_id);
750 
751 	if (priv->join_status == XRADIO_JOIN_STATUS_AP)
752 		WARN_ON(wsm_set_keepalive_filter(priv, false));
753 
754 #ifdef XRADIO_SUSPEND_RESUME_FILTER_ENABLE
755 	/* Set Multicast Address Filter */
756 	if (priv->multicast_filter.numOfAddresses) {
757 		priv->multicast_filter.enable = 0;
758 		wsm_set_multicast_filter(hw_priv, &priv->multicast_filter,
759 					 priv->if_id);
760 	}
761 
762 	/* Set Enable Broadcast Address Filter */
763 	priv->broadcast_filter.action_mode = 0;
764 	if (priv->join_status == XRADIO_JOIN_STATUS_AP)
765 		priv->broadcast_filter.address_mode = 0;
766 	xradio_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter);
767 #endif
768 
769 #ifdef MCAST_FWDING
770 	fwdoffload.flags = 0x0;
771 	if (priv->join_status == XRADIO_JOIN_STATUS_AP)
772 		WARN_ON(wsm_set_forwarding_offlad(hw_priv, &fwdoffload, priv->if_id));
773 #endif
774 
775 revert1:
776 	/* up(&hw_priv->conf_lock); */
777 	return -EBUSY;
778 }
779 
xradio_wow_resume(struct ieee80211_hw * hw)780 int xradio_wow_resume(struct ieee80211_hw *hw)
781 {
782 
783 	struct xradio_common *hw_priv = hw->priv;
784 	struct xradio_vif *priv;
785 	int i, ret = 0;
786 
787 	pm_printk(XRADIO_DBG_NIY, "%s, Sleeptime=%dms\n", __func__,
788 			  xradio_realtime_interval(&suspend_time, &resume_time));
789 
790 	if (!atomic_read(&hw_priv->num_vifs))
791 		pm_printk(XRADIO_DBG_WARN, "%s num_vifs=0\n", __func__);
792 
793 	if (hw_priv->bh_error) {
794 		pm_printk(XRADIO_DBG_ERROR, "%s bh_error(%d) occurs already.\n",
795 				__func__, hw_priv->bh_error);
796 	}
797 
798 	if (atomic_read(&hw_priv->suspend_state) < XRADIO_CONNECT_SUSP) {
799 		pm_printk(XRADIO_DBG_WARN, "%s not in suspend(%d).\n",
800 				__func__, atomic_read(&hw_priv->suspend_state));
801 		/*
802 		 * xradio_wow_suspend failed last time, and xradio_wow_resume is called
803 		 * by mac80211_reconfig in umac. return 1 to do hw restart.
804 		 */
805 		return 1;
806 	}
807 
808 	atomic_set(&hw_priv->suspend_lock_state, XRADIO_SUSPEND_LOCK_IDEL);
809 
810 #ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
811 	if (XRADIO_POWEROFF_SUSP == atomic_read(&hw_priv->suspend_state)) {
812 		return xradio_poweroff_resume(hw_priv);
813 	}
814 #endif
815 
816 	/* Disable IRQ wake */
817 	hw_priv->sbus_ops->power_mgmt(hw_priv->sbus_priv, false);
818 
819 	up(&hw_priv->scan.lock);
820 
821 	/* Resume BH thread */
822 	WARN_ON(xradio_bh_resume(hw_priv));
823 
824 	xradio_for_each_vif(hw_priv, priv, i) {
825 #ifdef P2P_MULTIVIF
826 		if ((i == (XRWL_MAX_VIFS - 1)) || !priv)
827 #else
828 		if (!priv)
829 #endif
830 			continue;
831 		ret = __xradio_wow_resume(priv);
832 		if (ret) {
833 			pm_printk(XRADIO_DBG_ERROR,
834 				  "%s:__xradio_wow_resume failed!\n", __func__);
835 			break;
836 		}
837 	}
838 
839 	wsm_unlock_tx(hw_priv);
840 
841 	/* we always return to XRADIO_RESUME no matter errors occurs.*/
842 	atomic_set(&hw_priv->suspend_state, XRADIO_RESUME);
843 
844 	/* Unlock configuration mutex */
845 	up(&hw_priv->wsm_oper_lock);
846 	up(&hw_priv->conf_lock);
847 	return 0;
848 }
849 
__xradio_wow_resume(struct xradio_vif * priv)850 static int __xradio_wow_resume(struct xradio_vif *priv)
851 {
852 	struct xradio_common *hw_priv = xrwl_vifpriv_to_hwpriv(priv);
853 	struct xradio_pm_state_vif *pm_state_vif = &priv->pm_state_vif;
854 	struct xradio_suspend_state *state;
855 #ifdef MCAST_FWDING
856 	struct wsm_forwarding_offload fwdoffload = {
857 		.fwenable = 0x1,
858 		.flags = 0x0,
859 	};
860 #endif
861 	pm_printk(XRADIO_DBG_NIY, "%s\n", __func__);
862 
863 	/* Restore suspend state */
864 	state = pm_state_vif->suspend_state;
865 	pm_state_vif->suspend_state = NULL;
866 
867 #ifdef ROAM_OFFLOAD
868 	if ((priv->vif->type == NL80211_IFTYPE_STATION)
869 	&& (priv->join_status == XRADIO_JOIN_STATUS_STA))
870 		xradio_hw_sched_scan_stop(hw_priv);
871 #endif /*ROAM_OFFLOAD*/
872 
873 	if (state->beacon_skipping) {
874 #ifdef XRADIO_USE_LONG_DTIM_PERIOD
875 		int join_dtim_period_extend;
876 		if (priv->join_dtim_period <= 3) {
877 			join_dtim_period_extend = priv->join_dtim_period * 3;
878 		} else if (priv->join_dtim_period <= 5) {
879 			join_dtim_period_extend = priv->join_dtim_period * 2;
880 		} else {
881 			join_dtim_period_extend = priv->join_dtim_period;
882 		}
883 		wsm_set_beacon_wakeup_period(hw_priv,
884 			((priv->beacon_int * join_dtim_period_extend) >
885 			 MAX_BEACON_SKIP_TIME_MS ?
886 			 1 : join_dtim_period_extend), 0, priv->if_id);
887 #else
888 		wsm_set_beacon_wakeup_period(hw_priv,
889 			(priv->beacon_int * priv->join_dtim_period >
890 			 MAX_BEACON_SKIP_TIME_MS) ? 1 : priv->join_dtim_period,
891 			 0, priv->if_id);
892 #endif
893 		state->beacon_skipping = false;
894 	}
895 
896 	if (priv->join_status == XRADIO_JOIN_STATUS_AP)
897 		WARN_ON(wsm_set_keepalive_filter(priv, false));
898 
899 #ifdef XRADIO_SUSPEND_RESUME_FILTER_ENABLE
900 	/* Set Multicast Address Filter */
901 	if (priv->multicast_filter.numOfAddresses) {
902 		priv->multicast_filter.enable = 0;
903 		wsm_set_multicast_filter(hw_priv, &priv->multicast_filter,
904 					 priv->if_id);
905 	}
906 	/* Set Enable Broadcast Address Filter */
907 	priv->broadcast_filter.action_mode = 0;
908 	if (priv->join_status == XRADIO_JOIN_STATUS_AP)
909 		priv->broadcast_filter.address_mode = 0;
910 	xradio_set_macaddrfilter(hw_priv, priv, (u8 *)&priv->broadcast_filter);
911 #endif
912 
913 #ifdef MCAST_FWDING
914 	if (priv->join_status == XRADIO_JOIN_STATUS_AP)
915 		WARN_ON(wsm_set_forwarding_offlad(hw_priv, &fwdoffload, priv->if_id));
916 #endif
917 
918 	/* Resume delayed work */
919 	xradio_resume_work(hw_priv, &priv->bss_loss_work, state->bss_loss_tmo);
920 	xradio_resume_work(hw_priv, &priv->connection_loss_work,
921 			   state->connection_loss_tmo);
922 	xradio_resume_work(hw_priv, &priv->join_timeout, state->join_tmo);
923 	xradio_resume_work(hw_priv, &priv->link_id_gc_work, state->link_id_gc);
924 
925 	/* Remove UDP port filter */
926 	wsm_set_udp_port_filter(hw_priv, &xradio_udp_port_filter_off,
927 				priv->if_id);
928 
929 	/* Remove ethernet frame type filter */
930 	wsm_set_ether_type_filter(hw_priv, &xradio_ether_type_filter_off,
931 				  priv->if_id);
932 
933 	/* Remove IP multicast filter */
934     wsm_set_host_sleep(hw_priv, 0, priv->if_id);
935 	/* Free memory */
936 	kfree(state);
937 
938 	return 0;
939 }
940 
941 #ifdef CONFIG_XRADIO_SUSPEND_POWER_OFF
xradio_poweroff_suspend(struct xradio_common * hw_priv)942 static int xradio_poweroff_suspend(struct xradio_common *hw_priv)
943 {
944 	pm_printk(XRADIO_DBG_NIY, "%s\n", __func__);
945 	/* Flush all works. */
946 	cancel_work_sync(&hw_priv->query_work);
947 	flush_workqueue(hw_priv->workqueue);
948 	flush_workqueue(hw_priv->spare_workqueue);
949 
950 	/* Stop serving thread */
951 	if (xradio_bh_suspend(hw_priv)) {
952 		pm_printk(XRADIO_DBG_WARN, "%s, xradio_bh_suspend failed!\n",
953 			  __func__);
954 		return -EBUSY;
955 	}
956 
957 	/* Schedule hardware restart, ensure no cmds in progress.*/
958 	down(&hw_priv->wsm_cmd_sema);
959 	atomic_set(&hw_priv->suspend_state, XRADIO_POWEROFF_SUSP);
960 	hw_priv->hw_restart = true;
961 	up(&hw_priv->wsm_cmd_sema);
962 
963 	/* Going to sleep with wifi power down. */
964 	xradio_wlan_power(0);
965 	return 0;
966 }
967 
xradio_poweroff_resume(struct xradio_common * hw_priv)968 static int xradio_poweroff_resume(struct xradio_common *hw_priv)
969 {
970 	pm_printk(XRADIO_DBG_NIY, "%s\n", __func__);
971 	/* Revert locks */
972 	wsm_unlock_tx(hw_priv);
973 	up(&hw_priv->scan.lock);
974 	up(&hw_priv->conf_lock);
975 	up(&hw_priv->wsm_oper_lock);
976 
977 	down(&hw_priv->wsm_cmd_sema);
978 	if (!hw_priv->exit_sync)
979 		if (schedule_work(&hw_priv->hw_restart_work) <= 0)
980 			pm_printk(XRADIO_DBG_ERROR, "%s restart_work failed!\n", __func__);
981 	up(&hw_priv->wsm_cmd_sema);
982 	return 0;
983 }
984 
985 
986 #endif
987