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#include <usb_ops_linux.h>
  18
  19void rtw_sreset_init(struct rtw_adapter *padapter)
  20{
  21        struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
  22        struct sreset_priv *psrtpriv = &pHalData->srestpriv;
  23
  24        mutex_init(&psrtpriv->silentreset_mutex);
  25        psrtpriv->silent_reset_inprogress = false;
  26        psrtpriv->last_tx_time = 0;
  27        psrtpriv->last_tx_complete_time = 0;
  28}
  29
  30void rtw_sreset_reset_value(struct rtw_adapter *padapter)
  31{
  32        struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
  33        struct sreset_priv *psrtpriv = &pHalData->srestpriv;
  34
  35        psrtpriv->silent_reset_inprogress = false;
  36        psrtpriv->last_tx_time = 0;
  37        psrtpriv->last_tx_complete_time = 0;
  38}
  39
  40bool rtw_sreset_inprogress(struct rtw_adapter *padapter)
  41{
  42        struct rtw_adapter *primary_adapter = GET_PRIMARY_ADAPTER(padapter);
  43        struct hal_data_8723a *pHalData = GET_HAL_DATA(primary_adapter);
  44
  45        return pHalData->srestpriv.silent_reset_inprogress;
  46}
  47
  48static void sreset_restore_security_station(struct rtw_adapter *padapter)
  49{
  50        struct mlme_priv *mlmepriv = &padapter->mlmepriv;
  51        struct sta_priv *pstapriv = &padapter->stapriv;
  52        struct sta_info *psta;
  53        struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
  54        u8 val8;
  55
  56        if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)
  57                val8 = 0xcc;
  58        else
  59                val8 = 0xcf;
  60
  61        rtl8723a_set_sec_cfg(padapter, val8);
  62
  63        if (padapter->securitypriv.dot11PrivacyAlgrthm ==
  64            WLAN_CIPHER_SUITE_TKIP ||
  65            padapter->securitypriv.dot11PrivacyAlgrthm ==
  66            WLAN_CIPHER_SUITE_CCMP) {
  67                psta = rtw_get_stainfo23a(pstapriv, get_bssid(mlmepriv));
  68                if (psta == NULL) {
  69                        /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
  70                } else {
  71                        /* pairwise key */
  72                        rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true);
  73                        /* group key */
  74                        rtw_set_key23a(padapter,&padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0);
  75                }
  76        }
  77}
  78
  79static void sreset_restore_network_station(struct rtw_adapter *padapter)
  80{
  81        struct mlme_priv *mlmepriv = &padapter->mlmepriv;
  82        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
  83        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
  84        u8 threshold;
  85
  86        rtw_setopmode_cmd23a(padapter, NL80211_IFTYPE_STATION);
  87
  88        /*  TH = 1 => means that invalidate usb rx aggregation */
  89        /*  TH = 0 => means that validate usb rx aggregation, use init value. */
  90        if (mlmepriv->htpriv.ht_option) {
  91                if (padapter->registrypriv.wifi_spec == 1)
  92                        threshold = 1;
  93                else
  94                        threshold = 0;
  95        } else
  96                threshold = 1;
  97
  98        rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
  99
 100        set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
 101                              pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
 102
 103        hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
 104        hw_var_set_mlme_join(padapter, 0);
 105
 106        rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
 107
 108        mlmeext_joinbss_event_callback23a(padapter, 1);
 109        /* restore Sequence No. */
 110        rtl8723au_write8(padapter, REG_NQOS_SEQ, padapter->xmitpriv.nqos_ssn);
 111
 112        sreset_restore_security_station(padapter);
 113}
 114
 115static void sreset_restore_network_status(struct rtw_adapter *padapter)
 116{
 117        struct mlme_priv *mlmepriv = &padapter->mlmepriv;
 118
 119        if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
 120                DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_STATION_STATE\n",
 121                          __func__, padapter->pnetdev->name,
 122                          get_fwstate(mlmepriv));
 123                sreset_restore_network_station(padapter);
 124#ifdef CONFIG_8723AU_AP_MODE
 125        } else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) {
 126                DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_AP_STATE\n",
 127                          __func__, padapter->pnetdev->name,
 128                          get_fwstate(mlmepriv));
 129                rtw_ap_restore_network(padapter);
 130#endif
 131        } else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) {
 132                DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_ADHOC_STATE\n",
 133                          __func__, padapter->pnetdev->name,
 134                          get_fwstate(mlmepriv));
 135        } else {
 136                DBG_8723A("%s(%s): fwstate:0x%08x - ???\n", __func__,
 137                          padapter->pnetdev->name, get_fwstate(mlmepriv));
 138        }
 139}
 140
 141static void sreset_stop_adapter(struct rtw_adapter *padapter)
 142{
 143        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 144        struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
 145
 146        if (padapter == NULL)
 147                return;
 148
 149        DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
 150
 151        if (!rtw_netif_queue_stopped(padapter->pnetdev))
 152                netif_tx_stop_all_queues(padapter->pnetdev);
 153
 154        rtw_cancel_all_timer23a(padapter);
 155
 156        /* TODO: OS and HCI independent */
 157        tasklet_kill(&pxmitpriv->xmit_tasklet);
 158
 159        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
 160                rtw_scan_abort23a(padapter);
 161
 162        if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
 163                rtw23a_join_to_handler((unsigned long)padapter);
 164}
 165
 166static void sreset_start_adapter(struct rtw_adapter *padapter)
 167{
 168        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 169        struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
 170
 171        if (padapter == NULL)
 172                return;
 173
 174        DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
 175
 176        if (check_fwstate(pmlmepriv, _FW_LINKED))
 177                sreset_restore_network_status(padapter);
 178
 179        /* TODO: OS and HCI independent */
 180        tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
 181
 182        mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
 183                  jiffies + msecs_to_jiffies(2000));
 184
 185        if (rtw_netif_queue_stopped(padapter->pnetdev))
 186                netif_tx_wake_all_queues(padapter->pnetdev);
 187}
 188
 189void rtw_sreset_reset(struct rtw_adapter *active_adapter)
 190{
 191        struct rtw_adapter *padapter = GET_PRIMARY_ADAPTER(active_adapter);
 192        struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
 193        struct sreset_priv *psrtpriv = &pHalData->srestpriv;
 194        struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
 195        unsigned long start = jiffies;
 196
 197        DBG_8723A("%s\n", __func__);
 198
 199        mutex_lock(&psrtpriv->silentreset_mutex);
 200        psrtpriv->silent_reset_inprogress = true;
 201        pwrpriv->change_rfpwrstate = rf_off;
 202
 203        sreset_stop_adapter(padapter);
 204
 205        ips_enter23a(padapter);
 206        ips_leave23a(padapter);
 207
 208        sreset_start_adapter(padapter);
 209        psrtpriv->silent_reset_inprogress = false;
 210        mutex_unlock(&psrtpriv->silentreset_mutex);
 211
 212        DBG_8723A("%s done in %d ms\n", __func__,
 213                  jiffies_to_msecs(jiffies - start));
 214}
 215