1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include "ar6000_drv.h"
29#include <linux/inetdevice.h>
30#include <linux/platform_device.h>
31#include "wlan_config.h"
32
33#ifdef CONFIG_HAS_WAKELOCK
34#include <linux/wakelock.h>
35#endif
36
37#define WOW_ENABLE_MAX_INTERVAL 0
38#define WOW_SET_SCAN_PARAMS 0
39
40extern unsigned int wmitimeout;
41extern wait_queue_head_t arEvent;
42
43#ifdef CONFIG_PM
44#ifdef CONFIG_HAS_WAKELOCK
45struct wake_lock ar6k_suspend_wake_lock;
46struct wake_lock ar6k_wow_wake_lock;
47#endif
48#endif
49
50#ifdef ANDROID_ENV
51extern void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent);
52#endif
53#undef ATH_MODULE_NAME
54#define ATH_MODULE_NAME pm
55#define ATH_DEBUG_PM ATH_DEBUG_MAKE_MODULE_MASK(0)
56
57#ifdef DEBUG
58static ATH_DEBUG_MASK_DESCRIPTION pm_debug_desc[] = {
59 { ATH_DEBUG_PM , "System power management"},
60};
61
62ATH_DEBUG_INSTANTIATE_MODULE_VAR(pm,
63 "pm",
64 "System Power Management",
65 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_PM,
66 ATH_DEBUG_DESCRIPTION_COUNT(pm_debug_desc),
67 pm_debug_desc);
68
69#endif
70
71A_STATUS ar6000_exit_cut_power_state(AR_SOFTC_T *ar);
72
73#ifdef CONFIG_PM
74static void ar6k_send_asleep_event_to_app(AR_SOFTC_T *ar, A_BOOL asleep)
75{
76 char buf[128];
77 union iwreq_data wrqu;
78
79 snprintf(buf, sizeof(buf), "HOST_ASLEEP=%s", asleep ? "asleep" : "awake");
80 A_MEMZERO(&wrqu, sizeof(wrqu));
81 wrqu.data.length = strlen(buf);
82 wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
83}
84
85static void ar6000_wow_resume(AR_SOFTC_T *ar)
86{
87 if (ar->arWowState!= WLAN_WOW_STATE_NONE) {
88 A_UINT16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
89 A_UINT16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period;
90 WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {TRUE, FALSE};
91 ar->arWowState = WLAN_WOW_STATE_NONE;
92#ifdef CONFIG_HAS_WAKELOCK
93 wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ);
94#endif
95 if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!=A_OK) {
96 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n"));
97 }
98#if WOW_SET_SCAN_PARAMS
99 wmi_scanparams_cmd(ar->arWmi, fg_start_period,
100 ar->scParams.fg_end_period,
101 bg_period,
102 ar->scParams.minact_chdwell_time,
103 ar->scParams.maxact_chdwell_time,
104 ar->scParams.pas_chdwell_time,
105 ar->scParams.shortScanRatio,
106 ar->scParams.scanCtrlFlags,
107 ar->scParams.max_dfsch_act_time,
108 ar->scParams.maxact_scan_per_ssid);
109#else
110 (void)fg_start_period;
111 (void)bg_period;
112#endif
113
114
115#if WOW_ENABLE_MAX_INTERVAL
116 if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == A_OK) {
117 }
118#endif
119 ar6k_send_asleep_event_to_app(ar, FALSE);
120 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Resume WoW successfully\n"));
121 } else {
122 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WoW does not invoked. skip resume"));
123 }
124 ar->arWlanPowerState = WLAN_POWER_STATE_ON;
125}
126
127static void ar6000_wow_suspend(AR_SOFTC_T *ar)
128{
129#define WOW_LIST_ID 1
130 if (ar->arNetworkType != AP_NETWORK) {
131
132
133
134
135 struct in_ifaddr **ifap = NULL;
136 struct in_ifaddr *ifa = NULL;
137 struct in_device *in_dev;
138 A_UINT8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
139 A_STATUS status;
140 WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } };
141 WMI_DEL_WOW_PATTERN_CMD delWowCmd;
142 WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {FALSE, TRUE};
143 WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = TRUE,
144 .hostReqDelay = 500 };
145
146 if (ar->arWowState!= WLAN_WOW_STATE_NONE) {
147 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("System already go into wow mode!\n"));
148 return;
149 }
150
151 ar6000_TxDataCleanup(ar);
152
153#if WOW_ENABLE_MAX_INTERVAL
154 if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == A_OK) {
155 }
156#endif
157
158#if WOW_SET_SCAN_PARAMS
159 status = wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0);
160#endif
161
162 delWowCmd.filter_list_id = WOW_LIST_ID;
163 delWowCmd.filter_id = 0;
164 wmi_del_wow_pattern_cmd(ar->arWmi, &delWowCmd);
165
166
167 if (ar->arNetDev->dev_addr[1]) {
168 addWowCmd.filter_list_id = WOW_LIST_ID;
169 addWowCmd.filter_size = 6;
170 addWowCmd.filter_offset = 0;
171 status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size);
172 if (status != A_OK) {
173 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n"));
174 }
175 }
176
177 if ((in_dev = __in_dev_get_rtnl(ar->arNetDev)) != NULL) {
178 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) {
179 if (!strcmp(ar->arNetDev->name, ifa->ifa_label)) {
180 break;
181 }
182 }
183 }
184 if (ifa && ifa->ifa_local) {
185 WMI_SET_IP_CMD ipCmd;
186 memset(&ipCmd, 0, sizeof(ipCmd));
187 ipCmd.ips[0] = ifa->ifa_local;
188 status = wmi_set_ip_cmd(ar->arWmi, &ipCmd);
189 if (status != A_OK) {
190 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n"));
191 }
192 }
193
194#ifndef ATH6K_CONFIG_OTA_MODE
195 wmi_powermode_cmd(ar->arWmi, REC_POWER);
196#endif
197
198 status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode);
199 if (status != A_OK) {
200 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n"));
201 }
202 ar6k_send_asleep_event_to_app(ar, TRUE);
203
204 status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode);
205 if (status != A_OK) {
206 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n"));
207 }
208
209 ar->arWowState = WLAN_WOW_STATE_SUSPENDING;
210 if (ar->arTxPending[ar->arControlEp]) {
211 A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent,
212 ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ);
213 if (!timeleft || signal_pending(current)) {
214
215 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi control data %d\n", ar->arTxPending[ar->arControlEp]));
216 }
217 }
218
219 status = hifWaitForPendingRecv(ar->arHifDevice);
220
221 ar->arWowState = WLAN_WOW_STATE_SUSPENDED;
222 ar->arWlanPowerState = WLAN_POWER_STATE_WOW;
223 } else {
224 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Not allowed to go to WOW at this moment.\n"));
225 }
226}
227
228A_STATUS ar6000_suspend_ev(void *context)
229{
230 A_STATUS status = A_OK;
231 AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
232 A_INT16 pmmode = ar->arSuspendConfig;
233wow_not_connected:
234 switch (pmmode) {
235 case WLAN_SUSPEND_WOW:
236 if (ar->arWmiReady && ar->arWlanState==WLAN_ENABLED && ar->arConnected) {
237 ar6000_wow_suspend(ar);
238 AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for wow mode %d\n", __func__, ar->arWlanPowerState));
239 } else {
240 pmmode = ar->arWow2Config;
241 goto wow_not_connected;
242 }
243 break;
244 case WLAN_SUSPEND_CUT_PWR:
245
246 case WLAN_SUSPEND_CUT_PWR_IF_BT_OFF:
247
248 case WLAN_SUSPEND_DEEP_SLEEP:
249
250 default:
251 status = ar6000_update_wlan_pwr_state(ar, WLAN_DISABLED, TRUE);
252 if (ar->arWlanPowerState==WLAN_POWER_STATE_ON ||
253 ar->arWlanPowerState==WLAN_POWER_STATE_WOW) {
254 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Strange suspend state for not wow mode %d", ar->arWlanPowerState));
255 }
256 AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for %d mode pwr %d status %d\n", __func__, pmmode, ar->arWlanPowerState, status));
257 status = (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) ? A_OK : A_EBUSY;
258 break;
259 }
260
261 ar->scan_triggered = 0;
262 return status;
263}
264
265A_STATUS ar6000_resume_ev(void *context)
266{
267 AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
268 A_UINT16 powerState = ar->arWlanPowerState;
269
270#ifdef CONFIG_HAS_WAKELOCK
271 wake_lock(&ar6k_suspend_wake_lock);
272#endif
273 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: enter previous state %d wowState %d\n", __func__, powerState, ar->arWowState));
274 switch (powerState) {
275 case WLAN_POWER_STATE_WOW:
276 ar6000_wow_resume(ar);
277 break;
278 case WLAN_POWER_STATE_CUT_PWR:
279
280 case WLAN_POWER_STATE_DEEP_SLEEP:
281 ar6000_update_wlan_pwr_state(ar, WLAN_ENABLED, TRUE);
282 AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Resume for %d mode pwr %d\n", __func__, powerState, ar->arWlanPowerState));
283 break;
284 case WLAN_POWER_STATE_ON:
285 break;
286 default:
287 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n"));
288 break;
289 }
290#ifdef CONFIG_HAS_WAKELOCK
291 wake_unlock(&ar6k_suspend_wake_lock);
292#endif
293 return A_OK;
294}
295
296void ar6000_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent)
297{
298 if (ar->arWowState!=WLAN_WOW_STATE_NONE) {
299 if (ar->arWowState==WLAN_WOW_STATE_SUSPENDING) {
300 AR_DEBUG_PRINTF(ATH_DEBUG_PM,("\n%s: Received IRQ while we are wow suspending!!!\n\n", __func__));
301 return;
302 }
303
304 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: WoW resume from irq thread status %d\n", __func__, ar->arWlanPowerState));
305 ar6000_wow_resume(ar);
306 } else {
307#ifdef ANDROID_ENV
308 android_ar6k_check_wow_status(ar, skb, isEvent);
309#endif
310 }
311}
312
313A_STATUS ar6000_power_change_ev(void *context, A_UINT32 config)
314{
315 AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
316 A_STATUS status = A_OK;
317
318 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: power change event callback %d \n", __func__, config));
319 switch (config) {
320 case HIF_DEVICE_POWER_UP:
321 ar6000_restart_endpoint(ar->arNetDev);
322 status = A_OK;
323 break;
324 case HIF_DEVICE_POWER_DOWN:
325 case HIF_DEVICE_POWER_CUT:
326 status = A_OK;
327 break;
328 }
329 return status;
330}
331
332static int ar6000_pm_probe(struct platform_device *pdev)
333{
334 plat_setup_power(1,1);
335 return 0;
336}
337
338static int ar6000_pm_remove(struct platform_device *pdev)
339{
340 plat_setup_power(0,1);
341 return 0;
342}
343
344static int ar6000_pm_suspend(struct platform_device *pdev, pm_message_t state)
345{
346 return 0;
347}
348
349static int ar6000_pm_resume(struct platform_device *pdev)
350{
351 return 0;
352}
353
354static struct platform_driver ar6000_pm_device = {
355 .probe = ar6000_pm_probe,
356 .remove = ar6000_pm_remove,
357 .suspend = ar6000_pm_suspend,
358 .resume = ar6000_pm_resume,
359 .driver = {
360 .name = "wlan_ar6000_pm",
361 },
362};
363#endif
364
365A_STATUS
366ar6000_setup_cut_power_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
367{
368 A_STATUS status = A_OK;
369 HIF_DEVICE_POWER_CHANGE_TYPE config;
370
371 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Cut power %d %d \n", __func__,state, ar->arWlanPowerState));
372#ifdef CONFIG_PM
373 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff));
374#endif
375 do {
376 if (state == WLAN_ENABLED) {
377
378 if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) {
379 break;
380 }
381
382 plat_setup_power(1,0);
383
384
385 ar->arWlanPowerState = WLAN_POWER_STATE_ON;
386
387
388
389 config = HIF_DEVICE_POWER_UP;
390 status = HIFConfigureDevice(ar->arHifDevice,
391 HIF_DEVICE_POWER_STATE_CHANGE,
392 &config,
393 sizeof(HIF_DEVICE_POWER_CHANGE_TYPE));
394
395 if (status == A_PENDING) {
396#ifdef ANDROID_ENV
397
398 A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent,
399 (ar->arWmiReady == TRUE), wmitimeout * HZ);
400 if (!timeleft || signal_pending(current)) {
401 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000 : Failed to get wmi ready \n"));
402 status = A_ERROR;
403 break;
404 }
405#endif
406 status = A_OK;
407 } else if (status == A_OK) {
408 ar6000_restart_endpoint(ar->arNetDev);
409 status = A_OK;
410 }
411 } else if (state == WLAN_DISABLED) {
412
413
414
415 if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) {
416 break;
417 }
418 ar6000_stop_endpoint(ar->arNetDev, TRUE, FALSE);
419
420 config = HIF_DEVICE_POWER_CUT;
421 status = HIFConfigureDevice(ar->arHifDevice,
422 HIF_DEVICE_POWER_STATE_CHANGE,
423 &config,
424 sizeof(HIF_DEVICE_POWER_CHANGE_TYPE));
425
426 plat_setup_power(0,0);
427
428 ar->arWlanPowerState = WLAN_POWER_STATE_CUT_PWR;
429 }
430 } while (0);
431
432 return status;
433}
434
435A_STATUS
436ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
437{
438 A_STATUS status = A_OK;
439
440 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Deep sleep %d %d \n", __func__,state, ar->arWlanPowerState));
441#ifdef CONFIG_PM
442 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff));
443#endif
444 do {
445 WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode;
446
447 if (state == WLAN_ENABLED) {
448 A_UINT16 fg_start_period;
449
450
451 if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) {
452 if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) {
453 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we resume from deep sleep %d\n", ar->arWlanPowerState));
454 }
455 break;
456 }
457
458 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
459 hostSleepMode.awake = TRUE;
460 hostSleepMode.asleep = FALSE;
461
462 if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != A_OK) {
463 break;
464 }
465
466
467 ar->arWlanPowerState = WLAN_POWER_STATE_ON;
468
469
470 if ((status=wmi_scanparams_cmd(ar->arWmi, fg_start_period,
471 ar->scParams.fg_end_period,
472 ar->scParams.bg_period,
473 ar->scParams.minact_chdwell_time,
474 ar->scParams.maxact_chdwell_time,
475 ar->scParams.pas_chdwell_time,
476 ar->scParams.shortScanRatio,
477 ar->scParams.scanCtrlFlags,
478 ar->scParams.max_dfsch_act_time,
479 ar->scParams.maxact_scan_per_ssid)) != A_OK)
480 {
481 break;
482 }
483
484 if (ar->arNetworkType != AP_NETWORK)
485 {
486 if (ar->arSsidLen) {
487 if (ar6000_connect_to_ap(ar) != A_OK) {
488
489 break;
490 }
491 }
492 }
493 } else if (state == WLAN_DISABLED){
494 WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = FALSE };
495
496
497 if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) {
498 if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) {
499 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange state when we suspend for deep sleep %d\n", ar->arWlanPowerState));
500 }
501 break;
502 }
503
504 if (ar->arNetworkType != AP_NETWORK)
505 {
506
507 AR6000_SPIN_LOCK(&ar->arLock, 0);
508 if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) {
509 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
510 wmi_disconnect_cmd(ar->arWmi);
511 } else {
512 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
513 }
514 }
515
516 ar->scan_triggered = 0;
517
518 if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != A_OK) {
519 break;
520 }
521
522
523 if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!=A_OK)
524 {
525 break;
526 }
527
528 ar6000_TxDataCleanup(ar);
529#ifndef ATH6K_CONFIG_OTA_MODE
530 wmi_powermode_cmd(ar->arWmi, REC_POWER);
531#endif
532
533 hostSleepMode.awake = FALSE;
534 hostSleepMode.asleep = TRUE;
535 if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!=A_OK) {
536 break;
537 }
538 if (ar->arTxPending[ar->arControlEp]) {
539 A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent,
540 ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ);
541 if (!timeleft || signal_pending(current)) {
542 status = A_ERROR;
543 break;
544 }
545 }
546 status = hifWaitForPendingRecv(ar->arHifDevice);
547
548 ar->arWlanPowerState = WLAN_POWER_STATE_DEEP_SLEEP;
549 }
550 } while (0);
551
552 if (status!=A_OK) {
553 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enter/exit deep sleep %d\n", state));
554 }
555
556 return status;
557}
558
559A_STATUS
560ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BOOL pmEvent)
561{
562 A_STATUS status = A_OK;
563 A_UINT16 powerState, oldPowerState;
564 AR6000_WLAN_STATE oldstate = ar->arWlanState;
565 A_BOOL wlanOff = ar->arWlanOff;
566#ifdef CONFIG_PM
567 A_BOOL btOff = ar->arBTOff;
568#endif
569
570 if ((state!=WLAN_DISABLED && state!=WLAN_ENABLED)) {
571 return A_ERROR;
572 }
573
574 if (ar->bIsDestroyProgress) {
575 return A_EBUSY;
576 }
577
578 if (down_interruptible(&ar->arSem)) {
579 return A_ERROR;
580 }
581
582 if (ar->bIsDestroyProgress) {
583 up(&ar->arSem);
584 return A_EBUSY;
585 }
586
587 ar->arWlanState = wlanOff ? WLAN_DISABLED : state;
588 oldPowerState = ar->arWlanPowerState;
589 if (state == WLAN_ENABLED) {
590 powerState = ar->arWlanPowerState;
591 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to ENABLE^^\n"));
592 if (!wlanOff) {
593 if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) {
594 status = ar6000_setup_deep_sleep_state(ar, WLAN_ENABLED);
595 } else if (powerState == WLAN_POWER_STATE_CUT_PWR) {
596 status = ar6000_setup_cut_power_state(ar, WLAN_ENABLED);
597 }
598 }
599#ifdef CONFIG_PM
600 else if (pmEvent && wlanOff) {
601 A_BOOL allowCutPwr = ((!ar->arBTSharing) || btOff);
602 if ((powerState==WLAN_POWER_STATE_CUT_PWR) && (!allowCutPwr)) {
603
604 ar6000_setup_cut_power_state(ar, WLAN_ENABLED);
605 status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED);
606 }
607 }
608#endif
609 } else if (state == WLAN_DISABLED) {
610 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WLAN PWR set to DISABLED~\n"));
611 powerState = WLAN_POWER_STATE_DEEP_SLEEP;
612#ifdef CONFIG_PM
613 if (pmEvent) {
614 A_BOOL suspendCutPwr = (ar->arSuspendConfig == WLAN_SUSPEND_CUT_PWR ||
615 (ar->arSuspendConfig == WLAN_SUSPEND_WOW &&
616 ar->arWow2Config==WLAN_SUSPEND_CUT_PWR));
617 A_BOOL suspendCutIfBtOff = ((ar->arSuspendConfig ==
618 WLAN_SUSPEND_CUT_PWR_IF_BT_OFF ||
619 (ar->arSuspendConfig == WLAN_SUSPEND_WOW &&
620 ar->arWow2Config==WLAN_SUSPEND_CUT_PWR_IF_BT_OFF)) &&
621 (!ar->arBTSharing || btOff));
622 if ((suspendCutPwr) ||
623 (suspendCutIfBtOff) ||
624 (ar->arWlanState==WLAN_POWER_STATE_CUT_PWR))
625 {
626 powerState = WLAN_POWER_STATE_CUT_PWR;
627 }
628 } else {
629 if ((wlanOff) &&
630 (ar->arWlanOffConfig == WLAN_OFF_CUT_PWR) &&
631 (!ar->arBTSharing || btOff))
632 {
633
634 powerState = WLAN_POWER_STATE_CUT_PWR;
635 }
636 }
637#endif
638
639 if (powerState == WLAN_POWER_STATE_DEEP_SLEEP) {
640 if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) {
641 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Load firmware before set to deep sleep\n"));
642 ar6000_setup_cut_power_state(ar, WLAN_ENABLED);
643 }
644 status = ar6000_setup_deep_sleep_state(ar, WLAN_DISABLED);
645 } else if (powerState == WLAN_POWER_STATE_CUT_PWR) {
646 status = ar6000_setup_cut_power_state(ar, WLAN_DISABLED);
647 }
648
649 }
650
651 if (status!=A_OK) {
652 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WLAN state %d\n", ar->arWlanState));
653 ar->arWlanState = oldstate;
654 } else if (status == A_OK) {
655 WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent, *pSleepEvent = NULL;
656 if ((ar->arWlanPowerState == WLAN_POWER_STATE_ON) && (oldPowerState != WLAN_POWER_STATE_ON)) {
657 wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE;
658 pSleepEvent = &wmiSleepEvent;
659 } else if ((ar->arWlanPowerState != WLAN_POWER_STATE_ON) && (oldPowerState == WLAN_POWER_STATE_ON)) {
660 wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP;
661 pSleepEvent = &wmiSleepEvent;
662 }
663 if (pSleepEvent) {
664 AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("SENT WLAN Sleep Event %d\n", wmiSleepEvent.sleepState));
665 ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (A_UINT8*)pSleepEvent,
666 sizeof(WMI_REPORT_SLEEP_STATE_EVENTID));
667 }
668 }
669 up(&ar->arSem);
670 return status;
671}
672
673A_STATUS
674ar6000_set_bt_hw_state(struct ar6_softc *ar, A_UINT32 enable)
675{
676#ifdef CONFIG_PM
677 A_BOOL off = (enable == 0);
678 A_STATUS status;
679 if (ar->arBTOff == off) {
680 return A_OK;
681 }
682 ar->arBTOff = off;
683 status = ar6000_update_wlan_pwr_state(ar, ar->arWlanOff ? WLAN_DISABLED : WLAN_ENABLED, FALSE);
684 return status;
685#else
686 return A_OK;
687#endif
688}
689
690A_STATUS
691ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
692{
693 A_STATUS status;
694 A_BOOL off = (state == WLAN_DISABLED);
695 if (ar->arWlanOff == off) {
696 return A_OK;
697 }
698 ar->arWlanOff = off;
699 status = ar6000_update_wlan_pwr_state(ar, state, FALSE);
700 return status;
701}
702
703void ar6000_pm_init()
704{
705 A_REGISTER_MODULE_DEBUG_INFO(pm);
706#ifdef CONFIG_PM
707#ifdef CONFIG_HAS_WAKELOCK
708 wake_lock_init(&ar6k_suspend_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_suspend");
709 wake_lock_init(&ar6k_wow_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_wow");
710#endif
711
712
713
714
715
716 if (platform_driver_register(&ar6000_pm_device)) {
717 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000: fail to register the power control driver.\n"));
718 }
719#endif
720}
721
722void ar6000_pm_exit()
723{
724#ifdef CONFIG_PM
725 platform_driver_unregister(&ar6000_pm_device);
726#ifdef CONFIG_HAS_WAKELOCK
727 wake_lock_destroy(&ar6k_suspend_wake_lock);
728 wake_lock_destroy(&ar6k_wow_wake_lock);
729#endif
730#endif
731}
732