static void ar6000_wow_resume(AR_SOFTC_T *ar) { if (ar->arWowState!= WLAN_WOW_STATE_NONE) { A_UINT16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period; A_UINT16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period; WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {TRUE, FALSE}; ar->arWowState = WLAN_WOW_STATE_NONE; #ifdef CONFIG_HAS_WAKELOCK wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ); #endif if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!=A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n")); } #if WOW_SET_SCAN_PARAMS wmi_scanparams_cmd(ar->arWmi, fg_start_period, ar->scParams.fg_end_period, bg_period, ar->scParams.minact_chdwell_time, ar->scParams.maxact_chdwell_time, ar->scParams.pas_chdwell_time, ar->scParams.shortScanRatio, ar->scParams.scanCtrlFlags, ar->scParams.max_dfsch_act_time, ar->scParams.maxact_scan_per_ssid); #else (void)fg_start_period; (void)bg_period; #endif #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == A_OK) { } #endif ar6k_send_asleep_event_to_app(ar, FALSE); AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Resume WoW successfully\n")); } else { AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WoW does not invoked. skip resume")); } ar->arWlanPowerState = WLAN_POWER_STATE_ON; }
A_STATUS ar6000_enter_exit_deep_sleep_state(AR_SOFTC_T *ar, A_BOOL exit) { A_STATUS status = A_OK; if (down_interruptible(&ar->arSem)) { return A_ERROR; } AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Deep sleep %d %d \n", __func__,exit, ar->arWlanPowerState)); #ifdef CONFIG_PM AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Wlan OFF %d BT OFf %d \n", ar->arWlanOff, ar->arBTOff)); #endif do { WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent ; WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode; if (exit) { A_UINT16 fg_start_period; /* Not in deep sleep state.. exit */ if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) { break; } fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period; hostSleepMode.awake = TRUE; hostSleepMode.asleep = FALSE; if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != A_OK) { break; } wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE; ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (A_UINT8*)&wmiSleepEvent, sizeof(WMI_REPORT_SLEEP_STATE_EVENTID)); /* Enable foreground scanning */ if ((status=wmi_scanparams_cmd(ar->arWmi, fg_start_period, ar->scParams.fg_end_period, ar->scParams.bg_period, ar->scParams.minact_chdwell_time, ar->scParams.maxact_chdwell_time, ar->scParams.pas_chdwell_time, ar->scParams.shortScanRatio, ar->scParams.scanCtrlFlags, ar->scParams.max_dfsch_act_time, ar->scParams.maxact_scan_per_ssid)) != A_OK) { break; } if (ar->arSsidLen) { if (ar6000_connect_to_ap(ar) != A_OK) { /* no need to report error if connection failed */ break; } } /* Change the state to ON */ ar->arWlanPowerState = WLAN_POWER_STATE_ON; } else { WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = FALSE }; /* Already in deep sleep state.. exit */ if (ar->arWlanPowerState == WLAN_POWER_STATE_DEEP_SLEEP) { break; } /* make sure we disable wow for deep sleep */ if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!=A_OK) { break; } wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP; ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (A_UINT8*)&wmiSleepEvent, sizeof(WMI_REPORT_SLEEP_STATE_EVENTID)); /* Disconnect from the AP and disable foreground scanning */ AR6000_SPIN_LOCK(&ar->arLock, 0); if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) { AR6000_SPIN_UNLOCK(&ar->arLock, 0); wmi_disconnect_cmd(ar->arWmi); } else { AR6000_SPIN_UNLOCK(&ar->arLock, 0); } ar->scan_triggered = 0; if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != A_OK) { break; } ar6000_TxDataCleanup(ar); #ifndef ATH6K_CONFIG_OTA_MODE wmi_powermode_cmd(ar->arWmi, REC_POWER); #endif hostSleepMode.awake = FALSE; hostSleepMode.asleep = TRUE; if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!=A_OK) { break; } if (ar->arTxPending[ar->arControlEp]) { A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent, ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); if (!timeleft || signal_pending(current)) { status = A_ERROR; break; } } status = hifWaitForPendingRecv(ar->arHifDevice); ar->arWlanPowerState = WLAN_POWER_STATE_DEEP_SLEEP; } } while (0); if (status!=A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enter/exit deep sleep %d\n", exit)); } up(&ar->arSem); return status; }
void CAR6KMini::rssiScanTimeout() { static int reScanCounter=255; A_UINT16 fgenable, bkenable; // Return if WMI is not ready yet if (!m_WMIReady) return; if (!m_Connected) return; //get stats from target if (ar6000_get_target_stats() != A_OK) return; if (m_Config.bkScanEnable) { bkenable = (A_UINT16)m_Config.bkScanPeriod; } else { bkenable = 0xFFFF; } if (m_Config.fgScanEnable) { fgenable = 0; } else { fgenable = 0xFFFF; } //Post the RSSI value relative to the Standard Noise floor value. if (RSSI_TO_NDIS(m_RSSI) >= -60) { m_RSSIlevel = 0; reScanCounter = 10; A_TIMEOUT_MS(&m_rssiScanTimer, 1000, 0); } else if ((RSSI_TO_NDIS(m_RSSI) >= -65) && (RSSI_TO_NDIS(m_RSSI) < -60)) { reScanCounter = 10; A_TIMEOUT_MS(&m_rssiScanTimer, 1000, 0); } else if ((RSSI_TO_NDIS(m_RSSI) >= -70) && (RSSI_TO_NDIS(m_RSSI) < -65)) { reScanCounter = 10; if ((1 != m_RSSIlevel) && (2 != m_RSSIlevel)) { m_RSSIlevel = 1; wmi_bssfilter_cmd ((struct wmi_t *)m_pWMI, PROBED_SSID_FILTER, 0); wmi_scanparams_cmd((wmi_t *)m_pWMI,fgenable,0,bkenable, 0,0,20,WMI_SHORTSCANRATIO_DEFAULT, 0, 0, 0); wmi_startscan_cmd((wmi_t *)m_pWMI,WMI_LONG_SCAN,TRUE,FALSE,0,100,0,NULL); } A_TIMEOUT_MS(&m_rssiScanTimer, 1000, 0); } else if ((RSSI_TO_NDIS(m_RSSI) >= -75) && (RSSI_TO_NDIS(m_RSSI) < -70)) { reScanCounter = 10; if ((2 != m_RSSIlevel) && (3 != m_RSSIlevel)) { m_RSSIlevel = 2; wmi_startscan_cmd((wmi_t *)m_pWMI,WMI_SHORT_SCAN,TRUE,FALSE,0,100,0,NULL); } A_TIMEOUT_MS(&m_rssiScanTimer, 500, 0); } else if ((RSSI_TO_NDIS(m_RSSI) >= -80) && (RSSI_TO_NDIS(m_RSSI) < -75)) { reScanCounter = 10; if ((3 != m_RSSIlevel) && (4 != m_RSSIlevel)) { m_RSSIlevel = 3; wmi_bssfilter_cmd ((struct wmi_t *)m_pWMI, PROBED_SSID_FILTER, 0); wmi_scanparams_cmd((wmi_t *)m_pWMI,fgenable,0,bkenable, 0,0,20,WMI_SHORTSCANRATIO_DEFAULT, 0, 0, 0); wmi_startscan_cmd((wmi_t *)m_pWMI,WMI_LONG_SCAN,TRUE,FALSE,0,100,0,NULL); } A_TIMEOUT_MS(&m_rssiScanTimer, 400, 0); } else if ((RSSI_TO_NDIS(m_RSSI) >= -85) && (RSSI_TO_NDIS(m_RSSI) < -80)) { if ((4 != m_RSSIlevel) && (5 != m_RSSIlevel)) { reScanCounter = 7; m_RSSIlevel = 4; wmi_startscan_cmd((wmi_t *)m_pWMI,WMI_SHORT_SCAN,TRUE,FALSE,0,100,0,NULL); } if ((0 == reScanCounter) && (4 == m_RSSIlevel)) { reScanCounter = 7; if (m_roamTblEntryCount > 1) { wmi_startscan_cmd((wmi_t *)m_pWMI,WMI_SHORT_SCAN,TRUE,FALSE,0,100,0,NULL); } } reScanCounter--; A_TIMEOUT_MS(&m_rssiScanTimer, 400, 0); } else if (RSSI_TO_NDIS(m_RSSI) < -85) { if (5 != m_RSSIlevel) { m_RSSIlevel = 5; reScanCounter = 10; wmi_bssfilter_cmd ((struct wmi_t *)m_pWMI, PROBED_SSID_FILTER, 0); wmi_scanparams_cmd((wmi_t *)m_pWMI,fgenable,0,bkenable, 0,0,20,WMI_SHORTSCANRATIO_DEFAULT, 0, 0, 0); wmi_startscan_cmd((wmi_t *)m_pWMI,WMI_LONG_SCAN,TRUE,FALSE,0,100,0,NULL); } if ((0 == reScanCounter) && (5 == m_RSSIlevel)) { reScanCounter = 6; if (m_roamTblEntryCount > 1) { wmi_startscan_cmd((wmi_t *)m_pWMI,WMI_SHORT_SCAN,TRUE,FALSE,0,100,0,NULL); } } reScanCounter--; A_TIMEOUT_MS(&m_rssiScanTimer, 400, 0); } else { A_TIMEOUT_MS(&m_rssiScanTimer, 1000, 0); } wmi_get_roam_tbl_cmd((wmi_t *)m_pWMI); }
static void ar6000_wow_suspend(AR_SOFTC_T *ar) { #define WOW_LIST_ID 1 if (ar->arNetworkType != AP_NETWORK) { /* Setup WoW for unicast & Arp request for our own IP disable background scan. Set listen interval into 1000 TUs Enable keepliave for 110 seconds */ struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; struct in_device *in_dev; A_UINT8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; A_STATUS status; WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } }; WMI_DEL_WOW_PATTERN_CMD delWowCmd; WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {FALSE, TRUE}; WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = TRUE, .hostReqDelay = 500 };/*500 ms delay*/ if (ar->arWowState!= WLAN_WOW_STATE_NONE) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("System already go into wow mode!\n")); return; } ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/ #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */ if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == A_OK) { } #endif #if WOW_SET_SCAN_PARAMS status = wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0); #endif /* clear up our WoW pattern first */ delWowCmd.filter_list_id = WOW_LIST_ID; delWowCmd.filter_id = 0; wmi_del_wow_pattern_cmd(ar->arWmi, &delWowCmd); /* setup unicast packet pattern for WoW */ if (ar->arNetDev->dev_addr[1]) { addWowCmd.filter_list_id = WOW_LIST_ID; addWowCmd.filter_size = 6; /* MAC address */ addWowCmd.filter_offset = 0; status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n")); } } /* setup ARP request for our own IP */ if ((in_dev = __in_dev_get_rtnl(ar->arNetDev)) != NULL) { for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { if (!strcmp(ar->arNetDev->name, ifa->ifa_label)) { break; /* found */ } } } if (ifa && ifa->ifa_local) { WMI_SET_IP_CMD ipCmd; memset(&ipCmd, 0, sizeof(ipCmd)); ipCmd.ips[0] = ifa->ifa_local; status = wmi_set_ip_cmd(ar->arWmi, &ipCmd); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n")); } } #ifndef ATH6K_CONFIG_OTA_MODE wmi_powermode_cmd(ar->arWmi, REC_POWER); #endif status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n")); } ar6k_send_asleep_event_to_app(ar, TRUE); status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode); if (status != A_OK) { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n")); } ar->arWowState = WLAN_WOW_STATE_SUSPENDING; if (ar->arTxPending[ar->arControlEp]) { A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent, ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ); if (!timeleft || signal_pending(current)) { /* what can I do? wow resume at once */ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WoW. Pending wmi control data %d\n", ar->arTxPending[ar->arControlEp])); } } status = hifWaitForPendingRecv(ar->arHifDevice); ar->arWowState = WLAN_WOW_STATE_SUSPENDED; ar->arWlanPowerState = WLAN_POWER_STATE_WOW; } else { AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Not allowed to go to WOW at this moment.\n")); } }
void CAR6KMini::WMIScanCompleteEvent() { A_UINT16 fgenable, bkenable; if (m_Config.hostAssistedRoaming) { wmi_bssfilter_cmd ((struct wmi_t *)m_pWMI, m_WMIBssFilter, 0); // Restore scan parameters if (m_Config.bkScanEnable) { bkenable = (A_UINT16)m_Config.bkScanPeriod; } else { bkenable = 0xFFFF; } if (m_Config.fgScanEnable) { fgenable = 0; } else { fgenable = 0xFFFF; } wmi_scanparams_cmd((wmi_t *)m_pWMI,fgenable,0,bkenable, 0,0,0,WMI_SHORTSCANRATIO_DEFAULT, 0, 0, 0); } #ifdef OS_ROAM_MANAGEMENT if ((m_ChannelScan) && (!m_osRoamControl)) #else if (m_ChannelScan) #endif { // // Restore channel parameters // wmi_set_channelParams_cmd ((wmi_t *)m_pWMI, TRUE, (WMI_PHY_MODE)m_80211PhyCapability, 0, NULL); if (m_Connected) { // Restore scan parameters if (m_Config.bkScanEnable) { bkenable = (A_UINT16)m_Config.bkScanPeriod; } else { bkenable = 0xFFFF; } if (m_Config.fgScanEnable) { fgenable = 0; } else { fgenable = 0xFFFF; } wmi_scanparams_cmd((wmi_t *)m_pWMI,fgenable,0,bkenable, 0,0,0,WMI_SHORTSCANRATIO_DEFAULT, 0, 0, 0); } m_ChannelScan = FALSE; } #ifdef OS_ROAM_MANAGEMENT if (m_osRoamControl) { wmi_scan_indication ((wmi_t *)m_pWMI); } #endif }