static int rtw_hw_suspend(struct adapter *padapter) { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; struct net_device *pnetdev = padapter->pnetdev; if ((!padapter->bup) || (padapter->bDriverStopped) || (padapter->bSurpriseRemoved)) { DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", padapter->bup, padapter->bDriverStopped, padapter->bSurpriseRemoved); goto error_exit; } /* system suspend */ LeaveAllPowerSaveMode(padapter); DBG_88E("==> rtw_hw_suspend\n"); _enter_pwrlock(&pwrpriv->lock); pwrpriv->bips_processing = true; /* s1. */ if (pnetdev) { netif_carrier_off(pnetdev); netif_tx_stop_all_queues(pnetdev); } /* s2. */ rtw_disassoc_cmd(padapter, 500, false); /* s2-2. indicate disconnect to os */ { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; if (check_fwstate(pmlmepriv, _FW_LINKED)) { _clr_fwstate_(pmlmepriv, _FW_LINKED); rtw_led_control(padapter, LED_CTL_NO_LINK); rtw_os_indicate_disconnect(padapter); /* donnot enqueue cmd */ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 0); } } /* s2-3. */ rtw_free_assoc_resources(padapter); /* s2-4. */ rtw_free_network_queue(padapter, true); rtw_ips_dev_unload(padapter); pwrpriv->rf_pwrstate = rf_off; pwrpriv->bips_processing = false; _exit_pwrlock(&pwrpriv->lock); return 0; error_exit: DBG_88E("%s, failed\n", __func__); return -1; }
/* * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend * @adapter: pointer to _adapter structure * @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup * Return _SUCCESS or _FAIL */ int _rtw_pwr_wakeup(struct rtw_adapter *padapter, u32 ips_deffer_ms, const char *caller) { struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; int ret = _SUCCESS; u32 start = rtw_get_current_time(); #ifdef CONFIG_CONCURRENT_MODE if (padapter->pbuddy_adapter) LeaveAllPowerSaveMode(padapter->pbuddy_adapter); if ((padapter->isprimary == false) && padapter->pbuddy_adapter) { padapter = padapter->pbuddy_adapter; pwrpriv = &padapter->pwrctrlpriv; pmlmepriv = &padapter->mlmepriv; } #endif if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms)) pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms); if (pwrpriv->ps_processing) { DBG_8192D("%s wait ps_processing...\n", __func__); while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000) rtw_msleep_os(10); if (pwrpriv->ps_processing) DBG_8192D("%s wait ps_processing timeout\n", __func__); else DBG_8192D("%s wait ps_processing done\n", __func__); } if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) { DBG_8192D("%s wait bInSuspend...\n", __func__); while (pwrpriv->bInSuspend && ((rtw_get_passing_time_ms(start) <= 3000 && !rtw_is_do_late_resume(pwrpriv)) || (rtw_get_passing_time_ms(start) <= 500 && rtw_is_do_late_resume(pwrpriv)))) { rtw_msleep_os(10); } if (pwrpriv->bInSuspend) DBG_8192D("%s wait bInSuspend timeout\n", __func__); else DBG_8192D("%s wait bInSuspend done\n", __func__); } /* System suspend is not allowed to wakeup */ if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) { ret = _FAIL; goto exit; } /* block??? */ if ((pwrpriv->bInternalAutoSuspend == true) && (padapter->net_closed == true)) { ret = _FAIL; goto exit; } /* I think this should be check in IPS, LPS, autosuspend functions... */ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { ret = _SUCCESS; goto exit; } if (rf_off == pwrpriv->rf_pwrstate) { #ifdef CONFIG_AUTOSUSPEND if (pwrpriv->brfoffbyhw == true) { DBG_8192D("hw still in rf_off state ...........\n"); ret = _FAIL; goto exit; } else if (padapter->registrypriv.usbss_enable) { DBG_8192D("%s call autoresume_enter....\n", __func__); if (_FAIL == autoresume_enter(padapter)) { DBG_8192D ("======> autoresume fail.............\n"); ret = _FAIL; goto exit; } } else #endif { #ifdef CONFIG_IPS DBG_8192D("%s call ips_leave....\n", __func__); if (_FAIL == ips_leave(padapter)) { DBG_8192D ("======> ips_leave fail.............\n"); ret = _FAIL; goto exit; } #endif } } /* TODO: the following checking need to be merged... */ if (padapter->bDriverStopped || !padapter->bup || !padapter->hw_init_completed) { DBG_8192D ("%s: bDriverStopped=%d, bup=%d, hw_init_completed=%u\n", caller, padapter->bDriverStopped, padapter->bup, padapter->hw_init_completed); ret = false; goto exit; } exit: if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms)) pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms); return ret; }
static void shutdown_card(void) { u32 addr; u8 tmp8, cnt=0; if (NULL == g_test_adapter) { NDEBUG("%s: padapter==NULL\n", __FUNCTION__); return; } #ifdef CONFIG_FWLPS_IN_IPS LeaveAllPowerSaveMode(g_test_adapter); #endif // CONFIG_FWLPS_IN_IPS // Leave SDIO HCI Suspend addr = 0x10250086; rtw_write8(g_test_adapter, addr, 0); do { tmp8 = rtw_read8(g_test_adapter, addr); cnt++; NDEBUG(FUNC_ADPT_FMT ": polling SDIO_HSUS_CTRL(0x%x)=0x%x, cnt=%d\n", FUNC_ADPT_ARG(g_test_adapter), addr, tmp8, cnt); if (tmp8 & BIT(1)) break; if (cnt >= 100) { NDEBUG(FUNC_ADPT_FMT ": polling 0x%x[1]==1 FAIL!!\n", FUNC_ADPT_ARG(g_test_adapter), addr); break; } rtw_mdelay_os(10); } while (1); // unlock register I/O rtw_write8(g_test_adapter, 0x1C, 0); // enable power down function // 0x04[4] = 1 // 0x05[7] = 1 addr = 0x04; tmp8 = rtw_read8(g_test_adapter, addr); tmp8 |= BIT(4); rtw_write8(g_test_adapter, addr, tmp8); NDEBUG(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n", FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr)); addr = 0x05; tmp8 = rtw_read8(g_test_adapter, addr); tmp8 |= BIT(7); rtw_write8(g_test_adapter, addr, tmp8); NDEBUG(FUNC_ADPT_FMT ": read after write 0x%x=0x%x\n", FUNC_ADPT_ARG(g_test_adapter), addr, rtw_read8(g_test_adapter, addr)); // lock register page0 0x0~0xB read/write rtw_write8(g_test_adapter, 0x1C, 0x0E); g_test_adapter->bSurpriseRemoved = _TRUE; NDEBUG(FUNC_ADPT_FMT ": bSurpriseRemoved=%d\n", FUNC_ADPT_ARG(g_test_adapter), g_test_adapter->bSurpriseRemoved); #ifdef CONFIG_CONCURRENT_MODE if (g_test_adapter->pbuddy_adapter) { PADAPTER pbuddy; pbuddy = g_test_adapter->pbuddy_adapter; pbuddy->bSurpriseRemoved = _TRUE; NDEBUG(FUNC_ADPT_FMT ": buddy(" ADPT_FMT ") bSurpriseRemoved=%d\n", FUNC_ADPT_ARG(g_test_adapter), ADPT_ARG(pbuddy), pbuddy->bSurpriseRemoved); } #endif // CONFIG_CONCURRENT_MODE }
static int rtw_sdio_suspend(struct device *dev) { struct sdio_func *func =dev_to_sdio_func(dev); struct dvobj_priv *psdpriv = sdio_get_drvdata(func); _adapter *padapter = psdpriv->padapter; struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct net_device *pnetdev = padapter->pnetdev; int ret = 0; u32 start_time = rtw_get_current_time(); _func_enter_; DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid); if((!padapter->bup) || (padapter->bDriverStopped)||(padapter->bSurpriseRemoved)) { DBG_871X("%s bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", __FUNCTION__ ,padapter->bup, padapter->bDriverStopped,padapter->bSurpriseRemoved); goto exit; } pwrpriv->bInSuspend = _TRUE; rtw_cancel_all_timer(padapter); LeaveAllPowerSaveMode(padapter); //padapter->net_closed = _TRUE; //s1. if(pnetdev) { netif_carrier_off(pnetdev); netif_stop_queue(pnetdev); } #ifdef CONFIG_WOWLAN padapter->pwrctrlpriv.bSupportWakeOnWlan=_TRUE; #else //s2. //s2-1. issue rtw_disassoc_cmd to fw disconnect_hdl(padapter, NULL); //rtw_disassoc_cmd(padapter); #endif #ifdef CONFIG_LAYER2_ROAMING_RESUME if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) ) { DBG_871X("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n",__FUNCTION__, pmlmepriv->cur_network.network.Ssid.Ssid, MAC_ARG(pmlmepriv->cur_network.network.MacAddress), pmlmepriv->cur_network.network.Ssid.SsidLength, pmlmepriv->assoc_ssid.SsidLength); pmlmepriv->to_roaming = 1; } #endif //s2-2. indicate disconnect to os rtw_indicate_disconnect(padapter); //s2-3. rtw_free_assoc_resources(padapter, 1); //s2-4. rtw_free_network_queue(padapter, _TRUE); rtw_led_control(padapter, LED_CTL_POWER_OFF); rtw_dev_unload(padapter); exit: DBG_871X("<=== %s return %d.............. in %dms\n", __FUNCTION__ , ret, rtw_get_passing_time_ms(start_time)); /*depends on sunxi power control */ #if defined(CONFIG_MMC_SUNXI_POWER_CONTROL) // sunximmc_rescan_card(SDIOID, 0); // rtl8723as_sdio_poweroff(); printk("[rtl8723as] %s: suspend end.\n", __FUNCTION__); #endif _func_exit_; return ret; }
static void rtw_dev_remove(struct sdio_func *func) { PADAPTER padapter; struct net_device *pnetdev; #ifdef CONFIG_IOCTL_CFG80211 struct wireless_dev *wdev; #endif _func_enter_; RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_dev_remove\n")); padapter = ((struct dvobj_priv*)sdio_get_drvdata(func))->padapter; #ifdef CONFIG_IOCTL_CFG80211 wdev = padapter->rtw_wdev; #endif #if defined(CONFIG_HAS_EARLYSUSPEND ) || defined(CONFIG_ANDROID_POWER) rtw_unregister_early_suspend(&padapter->pwrctrlpriv); #endif if (padapter->bSurpriseRemoved == _FALSE) { // test surprise remove int err; sdio_claim_host(func); sdio_readb(func, 0, &err); sdio_release_host(func); if (err == -ENOMEDIUM) { padapter->bSurpriseRemoved = _TRUE; DBG_871X(KERN_NOTICE "%s: device had been removed!\n", __func__); } } #ifdef CONFIG_HOSTAPD_MLME hostapd_mode_unload(padapter); #endif LeaveAllPowerSaveMode(padapter); pnetdev = (struct net_device*)padapter->pnetdev; if (pnetdev) { unregister_netdev(pnetdev); //will call netdev_close() RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("rtw_dev_remove: unregister netdev\n")); #ifdef CONFIG_PROC_DEBUG rtw_proc_remove_one(pnetdev); #endif } else { RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("rtw_dev_remove: NO padapter->pnetdev!\n")); } rtw_cancel_all_timer(padapter); rtw_dev_unload(padapter); // interface deinit sdio_deinit(padapter); RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("rtw_dev_remove: deinit intf complete!\n")); rtw_free_drv_sw(padapter); #ifdef CONFIG_IOCTL_CFG80211 rtw_wdev_free(wdev); #endif RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_dev_remove\n")); _func_exit_; }
static int rtw_gspi_suspend(struct spi_device *spi, pm_message_t mesg) { struct dvobj_priv *dvobj = spi_get_drvdata(spi); PADAPTER padapter = dvobj->if1; struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct net_device *pnetdev = padapter->pnetdev; int ret = 0; u32 start_time = rtw_get_current_time(); _func_enter_; DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid); pwrpriv->bInSuspend = _TRUE; while (pwrpriv->bips_processing == _TRUE) rtw_msleep_os(1); if((!padapter->bup) || (padapter->bDriverStopped)||(padapter->bSurpriseRemoved)) { DBG_871X("%s bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", __FUNCTION__ ,padapter->bup, padapter->bDriverStopped,padapter->bSurpriseRemoved); goto exit; } rtw_cancel_all_timer(padapter); LeaveAllPowerSaveMode(padapter); //padapter->net_closed = _TRUE; //s1. if(pnetdev) { netif_carrier_off(pnetdev); rtw_netif_stop_queue(pnetdev); } #ifdef CONFIG_WOWLAN padapter->pwrctrlpriv.bSupportRemoteWakeup=_TRUE; #else //s2. //s2-1. issue rtw_disassoc_cmd to fw disconnect_hdl(padapter, NULL); //rtw_disassoc_cmd(padapter); #endif #ifdef CONFIG_LAYER2_ROAMING_RESUME if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) ) { DBG_871X("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n",__FUNCTION__, pmlmepriv->cur_network.network.Ssid.Ssid, MAC_ARG(pmlmepriv->cur_network.network.MacAddress), pmlmepriv->cur_network.network.Ssid.SsidLength, pmlmepriv->assoc_ssid.SsidLength); pmlmepriv->to_roaming = 1; } #endif //s2-2. indicate disconnect to os rtw_indicate_disconnect(padapter); //s2-3. rtw_free_assoc_resources(padapter, 1); //s2-4. rtw_free_network_queue(padapter, _TRUE); rtw_led_control(padapter, LED_CTL_POWER_OFF); rtw_dev_unload(padapter); if(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) rtw_indicate_scan_done(padapter, 1); if(check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) rtw_indicate_disconnect(padapter); // interface deinit gspi_deinit(dvobj); RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("%s: deinit GSPI complete!\n", __FUNCTION__)); rtw_wifi_gpio_wlan_ctrl(WLAN_PWDN_OFF); rtw_mdelay_os(1); exit: DBG_871X("<=== %s return %d.............. in %dms\n", __FUNCTION__ , ret, rtw_get_passing_time_ms(start_time)); _func_exit_; return ret; }
int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller) { struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj); struct mlme_priv *pmlmepriv; int ret = _SUCCESS; unsigned long start = jiffies; unsigned long deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms); /* for LPS */ LeaveAllPowerSaveMode(padapter); /* IPS still bound with primary adapter */ padapter = GET_PRIMARY_ADAPTER(padapter); pmlmepriv = &padapter->mlmepriv; if (time_before(pwrpriv->ips_deny_time, deny_time)) pwrpriv->ips_deny_time = deny_time; if (pwrpriv->ps_processing) { DBG_871X("%s wait ps_processing...\n", __func__); while (pwrpriv->ps_processing && jiffies_to_msecs(jiffies - start) <= 3000) msleep(10); if (pwrpriv->ps_processing) DBG_871X("%s wait ps_processing timeout\n", __func__); else DBG_871X("%s wait ps_processing done\n", __func__); } if (pwrpriv->bInternalAutoSuspend == false && pwrpriv->bInSuspend) { DBG_871X("%s wait bInSuspend...\n", __func__); while (pwrpriv->bInSuspend && jiffies_to_msecs(jiffies - start) <= 3000 ) { msleep(10); } if (pwrpriv->bInSuspend) DBG_871X("%s wait bInSuspend timeout\n", __func__); else DBG_871X("%s wait bInSuspend done\n", __func__); } /* System suspend is not allowed to wakeup */ if ((pwrpriv->bInternalAutoSuspend == false) && (true == pwrpriv->bInSuspend)) { ret = _FAIL; goto exit; } /* block??? */ if ((pwrpriv->bInternalAutoSuspend == true) && (padapter->net_closed == true)) { ret = _FAIL; goto exit; } /* I think this should be check in IPS, LPS, autosuspend functions... */ if (check_fwstate(pmlmepriv, _FW_LINKED) == true) { ret = _SUCCESS; goto exit; } if (rf_off == pwrpriv->rf_pwrstate) { { DBG_8192C("%s call ips_leave....\n", __func__); if (_FAIL == ips_leave(padapter)) { DBG_8192C("======> ips_leave fail.............\n"); ret = _FAIL; goto exit; } } } /* TODO: the following checking need to be merged... */ if (padapter->bDriverStopped || !padapter->bup || !padapter->hw_init_completed ) { DBG_8192C("%s: bDriverStopped =%d, bup =%d, hw_init_completed =%u\n" , caller , padapter->bDriverStopped , padapter->bup , padapter->hw_init_completed); ret = false; goto exit; } exit: deny_time = jiffies + msecs_to_jiffies(ips_deffer_ms); if (time_before(pwrpriv->ips_deny_time, deny_time)) pwrpriv->ips_deny_time = deny_time; return ret; }
static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message) { struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf); struct adapter *padapter = dvobj->if1; struct net_device *pnetdev = padapter->pnetdev; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv; int ret = 0; u32 start_time = jiffies; DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid); if ((!padapter->bup) || (padapter->bDriverStopped) || (padapter->bSurpriseRemoved)) { DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", padapter->bup, padapter->bDriverStopped, padapter->bSurpriseRemoved); goto exit; } pwrpriv->bInSuspend = true; rtw_cancel_all_timer(padapter); LeaveAllPowerSaveMode(padapter); _enter_pwrlock(&pwrpriv->lock); /* s1. */ if (pnetdev) { netif_carrier_off(pnetdev); netif_tx_stop_all_queues(pnetdev); } /* s2. */ rtw_disassoc_cmd(padapter, 0, false); if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED)) { DBG_88E("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n", __func__, __LINE__, pmlmepriv->cur_network.network.Ssid.Ssid, pmlmepriv->cur_network.network.MacAddress, pmlmepriv->cur_network.network.Ssid.SsidLength, pmlmepriv->assoc_ssid.SsidLength); pmlmepriv->to_roaming = 1; } /* s2-2. indicate disconnect to os */ rtw_indicate_disconnect(padapter); /* s2-3. */ rtw_free_assoc_resources(padapter, 1); /* s2-4. */ rtw_free_network_queue(padapter, true); rtw_dev_unload(padapter); _exit_pwrlock(&pwrpriv->lock); if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) rtw_indicate_scan_done(padapter, 1); if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) rtw_indicate_disconnect(padapter); exit: DBG_88E("<=== %s return %d.............. in %dms\n", __func__ , ret, rtw_get_passing_time_ms(start_time)); return ret; }