void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent) { #ifdef CONFIG_PM if (ar->arWowState!=WOW_STATE_NONE) { if (ar->arWowState==WOW_STATE_SUSPENDING) { AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND,("%s: Received IRQ while we are wow suspending!!!\n", __func__)); return; } /* Wow resume from irq interrupt */ AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND, ("%s: WoW resume from irq thread status %d\n", __func__, ar->arOsPowerCtrl)); ar6000_wow_resume(ar); ar->arOsPowerCtrl = WLAN_PWR_CTRL_UP; } else if (screen_is_off && skb && ar->arConnected) { A_BOOL needWake = FALSE; if (isEvent) { if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) { A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb); switch (cmd) { case WMI_CONNECT_EVENTID: case WMI_DISCONNECT_EVENTID: needWake = TRUE; break; default: /* dont wake lock the system for other event */ break; } } } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) { ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb); if (!IEEE80211_IS_MULTICAST(datap->dstMac)) { switch (A_BE2CPU16(datap->typeOrLen)) { case 0x0800: /* IP */ case 0x888e: /* EAPOL */ case 0x88c7: /* RSN_PREAUTH */ case 0x88b4: /* WAPI */ needWake = TRUE; break; case 0x0806: /* ARP is not important to hold wake lock */ default: break; } } } if (needWake) { /* keep host wake up if there is any event and packate comming in*/ wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ); if (wowledon) { char buf[32]; int len = sprintf(buf, "on"); android_readwrite_file("/sys/power/state", NULL, buf, len); len = sprintf(buf, "%d", 127); android_readwrite_file("/sys/class/leds/lcd-backlight/brightness", NULL, buf,len); } } } #endif /* CONFIG_PM */ }
static A_STATUS ar6000_resume_ev(void *context) { AR_SOFTC_T *ar = (AR_SOFTC_T *)context; A_UINT16 powerCtrl = ar->arOsPowerCtrl; wake_lock(&ar6k_init_wake_lock); AR_DEBUG_PRINTF(ATH_DEBUG_SUSPEND, ("%s: enter previous state %d wowState %d\n", __func__, powerCtrl, ar->arWowState)); ar->arOsPowerCtrl = WLAN_PWR_CTRL_UP; switch (powerCtrl) { case WLAN_PWR_CTRL_WOW: ar6000_wow_resume(ar); break; case WLAN_PWR_CTRL_CUT_PWR: ar6000_restart_endpoint(ar->arNetDev); break; case WLAN_PWR_CTRL_DEEP_SLEEP: ar6000_set_wlan_state(ar, WLAN_ENABLED); break; case WLAN_PWR_CTRL_DEEP_SLEEP_DISABLED: break; case WLAN_PWR_CTRL_UP: break; default: AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n")); break; } wake_unlock(&ar6k_init_wake_lock); return A_OK; }
A_STATUS ar6000_resume_ev(void *context) { AR_SOFTC_T *ar = (AR_SOFTC_T *)context; A_UINT16 powerState = ar->arWlanPowerState; #ifdef CONFIG_HAS_WAKELOCK wake_lock(&ar6k_suspend_wake_lock); #endif AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: enter previous state %d wowState %d\n", __func__, powerState, ar->arWowState)); switch (powerState) { case WLAN_POWER_STATE_WOW: ar6000_wow_resume(ar); break; case WLAN_POWER_STATE_CUT_PWR: /* WiFi is ON before suspend */ if (!ar->arWlanOff) { ar6000_enter_exit_cut_power_state(ar, TRUE); ar->arWlanState = WLAN_ENABLED; } else { /* * WiFi is OFF before suspend. * For BT clock sharing designs, exit cut_power mode * and enter deep sleep mode, if BT is ON. */ if ((ar->arBTSharing) && (!ar->arBTOff)) { ar6000_enter_exit_cut_power_state(ar, TRUE); ar6000_enter_exit_deep_sleep_state(ar, FALSE); } } break; case WLAN_POWER_STATE_DEEP_SLEEP: /* WiFi is ON before suspend */ if (!ar->arWlanOff) { ar6000_enter_exit_deep_sleep_state(ar, TRUE); ar->arWlanState = WLAN_ENABLED; } break; case WLAN_POWER_STATE_ON: break; default: AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n")); break; } #ifdef CONFIG_HAS_WAKELOCK wake_unlock(&ar6k_suspend_wake_lock); #endif return A_OK; }
void ar6000_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent) { if (ar->arWowState!=WLAN_WOW_STATE_NONE) { if (ar->arWowState==WLAN_WOW_STATE_SUSPENDING) { AR_DEBUG_PRINTF(ATH_DEBUG_PM,("\n%s: Received IRQ while we are wow suspending!!!\n\n", __func__)); return; } /* Wow resume from irq interrupt */ AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: WoW resume from irq thread status %d\n", __func__, ar->arWlanPowerState)); ar6000_wow_resume(ar); } else { #ifdef ANDROID_ENV android_ar6k_check_wow_status(ar, skb, isEvent); #endif } }