Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);

}
Esempio n. 4
0
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"));
    }
}
Esempio n. 5
0
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
}