linux/drivers/staging/rtl8723au/core/rtw_sreset.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 ******************************************************************************/
  15
  16#include<rtw_sreset.h>
  17
  18void sreset_init_value23a(struct rtw_adapter *padapter)
  19{
  20        struct hal_data_8723a   *pHalData = GET_HAL_DATA(padapter);
  21        struct sreset_priv *psrtpriv = &pHalData->srestpriv;
  22
  23        mutex_init(&psrtpriv->silentreset_mutex);
  24        psrtpriv->silent_reset_inprogress = false;
  25        psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
  26        psrtpriv->last_tx_time = 0;
  27        psrtpriv->last_tx_complete_time = 0;
  28}
  29void sreset_reset_value23a(struct rtw_adapter *padapter)
  30{
  31        struct hal_data_8723a   *pHalData = GET_HAL_DATA(padapter);
  32        struct sreset_priv *psrtpriv = &pHalData->srestpriv;
  33
  34        psrtpriv->silent_reset_inprogress = false;
  35        psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
  36        psrtpriv->last_tx_time = 0;
  37        psrtpriv->last_tx_complete_time = 0;
  38}
  39
  40u8 sreset_get_wifi_status23a(struct rtw_adapter *padapter)
  41{
  42        struct hal_data_8723a   *pHalData = GET_HAL_DATA(padapter);
  43        struct sreset_priv *psrtpriv = &pHalData->srestpriv;
  44        u8 status = WIFI_STATUS_SUCCESS;
  45        u32 val32 = 0;
  46
  47        if (psrtpriv->silent_reset_inprogress)
  48                return status;
  49        val32 = rtw_read32(padapter, REG_TXDMA_STATUS);
  50        if (val32 == 0xeaeaeaea) {
  51                psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
  52        } else if (val32 != 0) {
  53                DBG_8723A("txdmastatu(%x)\n", val32);
  54                psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
  55        }
  56
  57        if (WIFI_STATUS_SUCCESS != psrtpriv->Wifi_Error_Status) {
  58                DBG_8723A("==>%s error_status(0x%x)\n", __func__, psrtpriv->Wifi_Error_Status);
  59                status = (psrtpriv->Wifi_Error_Status &~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL));
  60        }
  61        DBG_8723A("==> %s wifi_status(0x%x)\n", __func__, status);
  62
  63        /* status restore */
  64        psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
  65
  66        return status;
  67}
  68
  69void sreset_set_wifi_error_status23a(struct rtw_adapter *padapter, u32 status)
  70{
  71        struct hal_data_8723a   *pHalData = GET_HAL_DATA(padapter);
  72
  73        pHalData->srestpriv.Wifi_Error_Status = status;
  74}
  75
  76void sreset_set_trigger_point(struct rtw_adapter *padapter, s32 tgp)
  77{
  78        struct hal_data_8723a   *pHalData = GET_HAL_DATA(padapter);
  79
  80        pHalData->srestpriv.dbg_trigger_point = tgp;
  81}
  82
  83bool sreset_inprogress(struct rtw_adapter *padapter)
  84{
  85        struct hal_data_8723a   *pHalData = GET_HAL_DATA(padapter);
  86
  87        return pHalData->srestpriv.silent_reset_inprogress;
  88}
  89
  90static void sreset_restore_security_station(struct rtw_adapter *padapter)
  91{
  92        struct mlme_priv *mlmepriv = &padapter->mlmepriv;
  93        struct sta_priv *pstapriv = &padapter->stapriv;
  94        struct sta_info *psta;
  95        struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
  96        u8 val8;
  97
  98        if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)
  99                val8 = 0xcc;
 100        else
 101                val8 = 0xcf;
 102        rtw_hal_set_hwreg23a(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
 103
 104        if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
 105            (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {
 106                psta = rtw_get_stainfo23a(pstapriv, get_bssid(mlmepriv));
 107                if (psta == NULL) {
 108                        /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
 109                } else {
 110                        /* pairwise key */
 111                        rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true);
 112                        /* group key */
 113                        rtw_set_key23a(padapter,&padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0);
 114                }
 115        }
 116}
 117
 118static void sreset_restore_network_station(struct rtw_adapter *padapter)
 119{
 120        struct mlme_priv *mlmepriv = &padapter->mlmepriv;
 121        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 122        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 123        u8 threshold;
 124
 125        rtw_setopmode_cmd23a(padapter, Ndis802_11Infrastructure);
 126
 127        /*  TH = 1 => means that invalidate usb rx aggregation */
 128        /*  TH = 0 => means that validate usb rx aggregation, use init value. */
 129        if (mlmepriv->htpriv.ht_option) {
 130                if (padapter->registrypriv.wifi_spec == 1)
 131                        threshold = 1;
 132                else
 133                        threshold = 0;
 134                rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
 135        } else {
 136                threshold = 1;
 137                rtw_hal_set_hwreg23a(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
 138        }
 139
 140        set_channel_bwmode23a(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
 141
 142        /* disable dynamic functions, such as high power, DIG */
 143        /* Switch_DM_Func23a(padapter, DYNAMIC_FUNC_DISABLE, false); */
 144
 145        rtw_hal_set_hwreg23a(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
 146
 147        {
 148                u8      join_type = 0;
 149                rtw_hal_set_hwreg23a(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
 150        }
 151
 152        Set_MSR23a(padapter, (pmlmeinfo->state & 0x3));
 153
 154        mlmeext_joinbss_event_callback23a(padapter, 1);
 155        /* restore Sequence No. */
 156        rtw_write8(padapter, 0x4dc, padapter->xmitpriv.nqos_ssn);
 157
 158        sreset_restore_security_station(padapter);
 159}
 160
 161static void sreset_restore_network_status(struct rtw_adapter *padapter)
 162{
 163        struct mlme_priv *mlmepriv = &padapter->mlmepriv;
 164
 165        if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
 166                DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
 167                sreset_restore_network_station(padapter);
 168#ifdef CONFIG_8723AU_AP_MODE
 169        } else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) {
 170                DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
 171                rtw_ap_restore_network(padapter);
 172#endif
 173        } else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) {
 174                DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
 175        } else {
 176                DBG_8723A(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
 177        }
 178}
 179
 180static void sreset_stop_adapter(struct rtw_adapter *padapter)
 181{
 182        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 183        struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
 184
 185        if (padapter == NULL)
 186                return;
 187
 188        DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
 189
 190        if (!rtw_netif_queue_stopped(padapter->pnetdev))
 191                netif_tx_stop_all_queues(padapter->pnetdev);
 192
 193        rtw_cancel_all_timer23a(padapter);
 194
 195        /* TODO: OS and HCI independent */
 196        tasklet_kill(&pxmitpriv->xmit_tasklet);
 197
 198        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
 199                rtw_scan_abort23a(padapter);
 200
 201        if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
 202                rtw23a_join_to_handler((unsigned long)padapter);
 203}
 204
 205static void sreset_start_adapter(struct rtw_adapter *padapter)
 206{
 207        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 208        struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
 209
 210        if (padapter == NULL)
 211                return;
 212
 213        DBG_8723A(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
 214
 215        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 216                sreset_restore_network_status(padapter);
 217        }
 218
 219        /* TODO: OS and HCI independent */
 220        tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
 221
 222        mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
 223                  jiffies + msecs_to_jiffies(2000));
 224
 225        if (rtw_netif_queue_stopped(padapter->pnetdev))
 226                netif_tx_wake_all_queues(padapter->pnetdev);
 227}
 228
 229void sreset_reset(struct rtw_adapter *padapter)
 230{
 231        struct hal_data_8723a   *pHalData = GET_HAL_DATA(padapter);
 232        struct sreset_priv *psrtpriv = &pHalData->srestpriv;
 233        struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 234        unsigned long start = jiffies;
 235
 236        DBG_8723A("%s\n", __func__);
 237
 238        psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
 239
 240        mutex_lock(&psrtpriv->silentreset_mutex);
 241        psrtpriv->silent_reset_inprogress = true;
 242        pwrpriv->change_rfpwrstate = rf_off;
 243
 244        sreset_stop_adapter(padapter);
 245
 246        ips_enter23a(padapter);
 247        ips_leave23a(padapter);
 248
 249        sreset_start_adapter(padapter);
 250        psrtpriv->silent_reset_inprogress = false;
 251        mutex_unlock(&psrtpriv->silentreset_mutex);
 252
 253        DBG_8723A("%s done in %d ms\n", __func__,
 254                  jiffies_to_msecs(jiffies - start));
 255}
 256