Exemplo n.º 1
0
static void
ar6000_restart_endpoint(struct net_device *dev)
{
    A_STATUS status = A_OK;
    AR_SOFTC_T *ar = (AR_SOFTC_T*)netdev_priv(dev);
    if (down_interruptible(&ar->arSem)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s(): down_interruptible failed \n", __func__));
        return ;
    }
    if (ar->bIsDestroyProgress) {
        up(&ar->arSem);
        return;
    }
    BMIInit();
    do {        
        if ( (status=ar6000_configure_target(ar))!=A_OK)
            break;
		if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != A_OK)
		{
			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_bmi_get_config failed\n"));
			break;
		}     
        rtnl_lock();
        status = (ar6000_init(dev)==0) ? A_OK : A_ERROR;
        rtnl_unlock();

        if (status!=A_OK) {
            break;
        }  
        if (ar->arWlanState==WLAN_ENABLED) {
            if (ar->arSsidLen) {
                ar6000_connect_to_ap(ar);
            }
        } else {
            WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = FALSE };
            WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = { .awake = FALSE, .asleep = TRUE };
            WMI_REPORT_SLEEP_STATE_EVENT wmiSleepEvent = {
                .sleepState = WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP
            };

            wmi_set_wow_mode_cmd(ar->arWmi, &wowMode);
            ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (A_UINT8*)&wmiSleepEvent, 
                                    sizeof(WMI_REPORT_SLEEP_STATE_EVENTID));
            wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode);            
        }
    } while (0);

    up(&ar->arSem);    
    if (status==A_OK) {
        return;
    }

    ar6000_devices[ar->arDeviceIndex] = NULL;
    ar6000_destroy(ar->arNetDev, 1);
}
Exemplo 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;
}
Exemplo n.º 3
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"));
    }
}