15e93f35209578fcabfa855e427354195e54b491fLarry Finger/******************************************************************************
25e93f35209578fcabfa855e427354195e54b491fLarry Finger *
35e93f35209578fcabfa855e427354195e54b491fLarry Finger * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
45e93f35209578fcabfa855e427354195e54b491fLarry Finger *
55e93f35209578fcabfa855e427354195e54b491fLarry Finger * This program is free software; you can redistribute it and/or modify it
65e93f35209578fcabfa855e427354195e54b491fLarry Finger * under the terms of version 2 of the GNU General Public License as
75e93f35209578fcabfa855e427354195e54b491fLarry Finger * published by the Free Software Foundation.
85e93f35209578fcabfa855e427354195e54b491fLarry Finger *
95e93f35209578fcabfa855e427354195e54b491fLarry Finger * This program is distributed in the hope that it will be useful, but WITHOUT
105e93f35209578fcabfa855e427354195e54b491fLarry Finger * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
115e93f35209578fcabfa855e427354195e54b491fLarry Finger * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
125e93f35209578fcabfa855e427354195e54b491fLarry Finger * more details.
135e93f35209578fcabfa855e427354195e54b491fLarry Finger *
145e93f35209578fcabfa855e427354195e54b491fLarry Finger ******************************************************************************/
155e93f35209578fcabfa855e427354195e54b491fLarry Finger
16b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensen#include <rtw_sreset.h>
17050abc45833c6a66501cb3f938ef6e93ac18da8dJes Sorensen#include <usb_ops_linux.h>
185e93f35209578fcabfa855e427354195e54b491fLarry Finger
19b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensenvoid rtw_sreset_init(struct rtw_adapter *padapter)
205e93f35209578fcabfa855e427354195e54b491fLarry Finger{
21b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensen	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
225e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
235e93f35209578fcabfa855e427354195e54b491fLarry Finger
245e93f35209578fcabfa855e427354195e54b491fLarry Finger	mutex_init(&psrtpriv->silentreset_mutex);
255e93f35209578fcabfa855e427354195e54b491fLarry Finger	psrtpriv->silent_reset_inprogress = false;
265e93f35209578fcabfa855e427354195e54b491fLarry Finger	psrtpriv->last_tx_time = 0;
275e93f35209578fcabfa855e427354195e54b491fLarry Finger	psrtpriv->last_tx_complete_time = 0;
285e93f35209578fcabfa855e427354195e54b491fLarry Finger}
29b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensen
30b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensenvoid rtw_sreset_reset_value(struct rtw_adapter *padapter)
315e93f35209578fcabfa855e427354195e54b491fLarry Finger{
32b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensen	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
335e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
345e93f35209578fcabfa855e427354195e54b491fLarry Finger
355e93f35209578fcabfa855e427354195e54b491fLarry Finger	psrtpriv->silent_reset_inprogress = false;
365e93f35209578fcabfa855e427354195e54b491fLarry Finger	psrtpriv->last_tx_time = 0;
375e93f35209578fcabfa855e427354195e54b491fLarry Finger	psrtpriv->last_tx_complete_time = 0;
385e93f35209578fcabfa855e427354195e54b491fLarry Finger}
395e93f35209578fcabfa855e427354195e54b491fLarry Finger
40b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensenbool rtw_sreset_inprogress(struct rtw_adapter *padapter)
415e93f35209578fcabfa855e427354195e54b491fLarry Finger{
42b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensen	struct rtw_adapter *primary_adapter = GET_PRIMARY_ADAPTER(padapter);
43b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensen	struct hal_data_8723a *pHalData = GET_HAL_DATA(primary_adapter);
445e93f35209578fcabfa855e427354195e54b491fLarry Finger
455e93f35209578fcabfa855e427354195e54b491fLarry Finger	return pHalData->srestpriv.silent_reset_inprogress;
465e93f35209578fcabfa855e427354195e54b491fLarry Finger}
475e93f35209578fcabfa855e427354195e54b491fLarry Finger
485e93f35209578fcabfa855e427354195e54b491fLarry Fingerstatic void sreset_restore_security_station(struct rtw_adapter *padapter)
495e93f35209578fcabfa855e427354195e54b491fLarry Finger{
505e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
515e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct sta_priv *pstapriv = &padapter->stapriv;
525e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct sta_info *psta;
535e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct mlme_ext_info *pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
545e93f35209578fcabfa855e427354195e54b491fLarry Finger	u8 val8;
555e93f35209578fcabfa855e427354195e54b491fLarry Finger
565e93f35209578fcabfa855e427354195e54b491fLarry Finger	if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)
575e93f35209578fcabfa855e427354195e54b491fLarry Finger		val8 = 0xcc;
585e93f35209578fcabfa855e427354195e54b491fLarry Finger	else
595e93f35209578fcabfa855e427354195e54b491fLarry Finger		val8 = 0xcf;
60b8e99163b3181142bb781c3113facb194eae8e49Jes Sorensen
61b8e99163b3181142bb781c3113facb194eae8e49Jes Sorensen	rtl8723a_set_sec_cfg(padapter, val8);
625e93f35209578fcabfa855e427354195e54b491fLarry Finger
639e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	if (padapter->securitypriv.dot11PrivacyAlgrthm ==
649e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    WLAN_CIPHER_SUITE_TKIP ||
659e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    padapter->securitypriv.dot11PrivacyAlgrthm ==
669e3d6df2df8dbc4c2c5fb733dc494dfc82e0e2aeJes Sorensen	    WLAN_CIPHER_SUITE_CCMP) {
675e93f35209578fcabfa855e427354195e54b491fLarry Finger		psta = rtw_get_stainfo23a(pstapriv, get_bssid(mlmepriv));
685e93f35209578fcabfa855e427354195e54b491fLarry Finger		if (psta == NULL) {
695e93f35209578fcabfa855e427354195e54b491fLarry Finger			/* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
705e93f35209578fcabfa855e427354195e54b491fLarry Finger		} else {
715e93f35209578fcabfa855e427354195e54b491fLarry Finger			/* pairwise key */
725e93f35209578fcabfa855e427354195e54b491fLarry Finger			rtw_setstakey_cmd23a(padapter, (unsigned char *)psta, true);
735e93f35209578fcabfa855e427354195e54b491fLarry Finger			/* group key */
745e93f35209578fcabfa855e427354195e54b491fLarry Finger			rtw_set_key23a(padapter,&padapter->securitypriv, padapter->securitypriv.dot118021XGrpKeyid, 0);
755e93f35209578fcabfa855e427354195e54b491fLarry Finger		}
765e93f35209578fcabfa855e427354195e54b491fLarry Finger	}
775e93f35209578fcabfa855e427354195e54b491fLarry Finger}
785e93f35209578fcabfa855e427354195e54b491fLarry Finger
795e93f35209578fcabfa855e427354195e54b491fLarry Fingerstatic void sreset_restore_network_station(struct rtw_adapter *padapter)
805e93f35209578fcabfa855e427354195e54b491fLarry Finger{
815e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
825e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
835e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
845e93f35209578fcabfa855e427354195e54b491fLarry Finger	u8 threshold;
855e93f35209578fcabfa855e427354195e54b491fLarry Finger
86efc7144ff163bb1305ec8585e9e2f93ad9b06bd9Jes Sorensen	rtw_setopmode_cmd23a(padapter, NL80211_IFTYPE_STATION);
875e93f35209578fcabfa855e427354195e54b491fLarry Finger
885e93f35209578fcabfa855e427354195e54b491fLarry Finger	/*  TH = 1 => means that invalidate usb rx aggregation */
895e93f35209578fcabfa855e427354195e54b491fLarry Finger	/*  TH = 0 => means that validate usb rx aggregation, use init value. */
905e93f35209578fcabfa855e427354195e54b491fLarry Finger	if (mlmepriv->htpriv.ht_option) {
915e93f35209578fcabfa855e427354195e54b491fLarry Finger		if (padapter->registrypriv.wifi_spec == 1)
925e93f35209578fcabfa855e427354195e54b491fLarry Finger			threshold = 1;
935e93f35209578fcabfa855e427354195e54b491fLarry Finger		else
945e93f35209578fcabfa855e427354195e54b491fLarry Finger			threshold = 0;
951e7b6ebe193a23faf3f559c9611dc1b5ca87c287Jes Sorensen	} else
965e93f35209578fcabfa855e427354195e54b491fLarry Finger		threshold = 1;
975e93f35209578fcabfa855e427354195e54b491fLarry Finger
981e7b6ebe193a23faf3f559c9611dc1b5ca87c287Jes Sorensen	rtl8723a_set_rxdma_agg_pg_th(padapter, threshold);
991e7b6ebe193a23faf3f559c9611dc1b5ca87c287Jes Sorensen
1001e7b6ebe193a23faf3f559c9611dc1b5ca87c287Jes Sorensen	set_channel_bwmode23a(padapter, pmlmeext->cur_channel,
1011e7b6ebe193a23faf3f559c9611dc1b5ca87c287Jes Sorensen			      pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
1025e93f35209578fcabfa855e427354195e54b491fLarry Finger
10338dd10b59b726e05cce1abc797cd7f2ead1bc681Jes Sorensen	hw_var_set_bssid(padapter, pmlmeinfo->network.MacAddress);
104ea0cd73023ec317ea92ea69e0193746f44c236d4Jes Sorensen	hw_var_set_mlme_join(padapter, 0);
1055e93f35209578fcabfa855e427354195e54b491fLarry Finger
106ee225f0f19b88909b53c8d612e7195379b0553e7Jes Sorensen	rtl8723a_set_media_status(padapter, pmlmeinfo->state & 0x3);
1075e93f35209578fcabfa855e427354195e54b491fLarry Finger
1085e93f35209578fcabfa855e427354195e54b491fLarry Finger	mlmeext_joinbss_event_callback23a(padapter, 1);
1095e93f35209578fcabfa855e427354195e54b491fLarry Finger	/* restore Sequence No. */
110edbfd672cacb0d417096a1ed75e0070f1672c861Jes Sorensen	rtl8723au_write8(padapter, 0x4dc, padapter->xmitpriv.nqos_ssn);
1115e93f35209578fcabfa855e427354195e54b491fLarry Finger
1125e93f35209578fcabfa855e427354195e54b491fLarry Finger	sreset_restore_security_station(padapter);
1135e93f35209578fcabfa855e427354195e54b491fLarry Finger}
1145e93f35209578fcabfa855e427354195e54b491fLarry Finger
1155e93f35209578fcabfa855e427354195e54b491fLarry Fingerstatic void sreset_restore_network_status(struct rtw_adapter *padapter)
1165e93f35209578fcabfa855e427354195e54b491fLarry Finger{
1175e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
1185e93f35209578fcabfa855e427354195e54b491fLarry Finger
1195e93f35209578fcabfa855e427354195e54b491fLarry Finger	if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
1209cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_STATION_STATE\n",
1219cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  __func__, padapter->pnetdev->name,
1229cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  get_fwstate(mlmepriv));
1235e93f35209578fcabfa855e427354195e54b491fLarry Finger		sreset_restore_network_station(padapter);
124c17416ef707312429aafcdc4597db73906f3572eLarry Finger#ifdef CONFIG_8723AU_AP_MODE
1255e93f35209578fcabfa855e427354195e54b491fLarry Finger	} else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) {
1269cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_AP_STATE\n",
1279cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  __func__, padapter->pnetdev->name,
1289cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  get_fwstate(mlmepriv));
1295e93f35209578fcabfa855e427354195e54b491fLarry Finger		rtw_ap_restore_network(padapter);
130c17416ef707312429aafcdc4597db73906f3572eLarry Finger#endif
1315e93f35209578fcabfa855e427354195e54b491fLarry Finger	} else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) {
1329cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): fwstate:0x%08x - WIFI_ADHOC_STATE\n",
1339cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  __func__, padapter->pnetdev->name,
1349cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  get_fwstate(mlmepriv));
1355e93f35209578fcabfa855e427354195e54b491fLarry Finger	} else {
1369cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen		DBG_8723A("%s(%s): fwstate:0x%08x - ???\n", __func__,
1379cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen			  padapter->pnetdev->name, get_fwstate(mlmepriv));
1385e93f35209578fcabfa855e427354195e54b491fLarry Finger	}
1395e93f35209578fcabfa855e427354195e54b491fLarry Finger}
1405e93f35209578fcabfa855e427354195e54b491fLarry Finger
1415e93f35209578fcabfa855e427354195e54b491fLarry Fingerstatic void sreset_stop_adapter(struct rtw_adapter *padapter)
1425e93f35209578fcabfa855e427354195e54b491fLarry Finger{
1435e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1445e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
1455e93f35209578fcabfa855e427354195e54b491fLarry Finger
1465e93f35209578fcabfa855e427354195e54b491fLarry Finger	if (padapter == NULL)
1475e93f35209578fcabfa855e427354195e54b491fLarry Finger		return;
1485e93f35209578fcabfa855e427354195e54b491fLarry Finger
1499cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
1505e93f35209578fcabfa855e427354195e54b491fLarry Finger
1515e93f35209578fcabfa855e427354195e54b491fLarry Finger	if (!rtw_netif_queue_stopped(padapter->pnetdev))
1525e93f35209578fcabfa855e427354195e54b491fLarry Finger		netif_tx_stop_all_queues(padapter->pnetdev);
1535e93f35209578fcabfa855e427354195e54b491fLarry Finger
1545e93f35209578fcabfa855e427354195e54b491fLarry Finger	rtw_cancel_all_timer23a(padapter);
1555e93f35209578fcabfa855e427354195e54b491fLarry Finger
1565e93f35209578fcabfa855e427354195e54b491fLarry Finger	/* TODO: OS and HCI independent */
1575e93f35209578fcabfa855e427354195e54b491fLarry Finger	tasklet_kill(&pxmitpriv->xmit_tasklet);
1585e93f35209578fcabfa855e427354195e54b491fLarry Finger
1595e93f35209578fcabfa855e427354195e54b491fLarry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
1605e93f35209578fcabfa855e427354195e54b491fLarry Finger		rtw_scan_abort23a(padapter);
1615e93f35209578fcabfa855e427354195e54b491fLarry Finger
1625e93f35209578fcabfa855e427354195e54b491fLarry Finger	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
1635e93f35209578fcabfa855e427354195e54b491fLarry Finger		rtw23a_join_to_handler((unsigned long)padapter);
1645e93f35209578fcabfa855e427354195e54b491fLarry Finger}
1655e93f35209578fcabfa855e427354195e54b491fLarry Finger
1665e93f35209578fcabfa855e427354195e54b491fLarry Fingerstatic void sreset_start_adapter(struct rtw_adapter *padapter)
1675e93f35209578fcabfa855e427354195e54b491fLarry Finger{
1685e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1695e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
1705e93f35209578fcabfa855e427354195e54b491fLarry Finger
1715e93f35209578fcabfa855e427354195e54b491fLarry Finger	if (padapter == NULL)
1725e93f35209578fcabfa855e427354195e54b491fLarry Finger		return;
1735e93f35209578fcabfa855e427354195e54b491fLarry Finger
1749cd613c739ee436862e681acad8ded18ff85fd9aJes Sorensen	DBG_8723A("%s(%s)\n", __func__, padapter->pnetdev->name);
1755e93f35209578fcabfa855e427354195e54b491fLarry Finger
1768c09757d91703ccbf0da9fc67764de9714c9e615Aybuke Ozdemir	if (check_fwstate(pmlmepriv, _FW_LINKED))
1775e93f35209578fcabfa855e427354195e54b491fLarry Finger		sreset_restore_network_status(padapter);
1785e93f35209578fcabfa855e427354195e54b491fLarry Finger
1795e93f35209578fcabfa855e427354195e54b491fLarry Finger	/* TODO: OS and HCI independent */
1805e93f35209578fcabfa855e427354195e54b491fLarry Finger	tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
1815e93f35209578fcabfa855e427354195e54b491fLarry Finger
1825e93f35209578fcabfa855e427354195e54b491fLarry Finger	mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
1835e93f35209578fcabfa855e427354195e54b491fLarry Finger		  jiffies + msecs_to_jiffies(2000));
1845e93f35209578fcabfa855e427354195e54b491fLarry Finger
1855e93f35209578fcabfa855e427354195e54b491fLarry Finger	if (rtw_netif_queue_stopped(padapter->pnetdev))
1865e93f35209578fcabfa855e427354195e54b491fLarry Finger		netif_tx_wake_all_queues(padapter->pnetdev);
1875e93f35209578fcabfa855e427354195e54b491fLarry Finger}
1885e93f35209578fcabfa855e427354195e54b491fLarry Finger
189b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensenvoid rtw_sreset_reset(struct rtw_adapter *active_adapter)
1905e93f35209578fcabfa855e427354195e54b491fLarry Finger{
191b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensen	struct rtw_adapter *padapter = GET_PRIMARY_ADAPTER(active_adapter);
192b7c19c276a230aee012ba7adef036689633c4cd8Jes Sorensen	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1935e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
1945e93f35209578fcabfa855e427354195e54b491fLarry Finger	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
1955e93f35209578fcabfa855e427354195e54b491fLarry Finger	unsigned long start = jiffies;
1965e93f35209578fcabfa855e427354195e54b491fLarry Finger
1975e93f35209578fcabfa855e427354195e54b491fLarry Finger	DBG_8723A("%s\n", __func__);
1985e93f35209578fcabfa855e427354195e54b491fLarry Finger
1995e93f35209578fcabfa855e427354195e54b491fLarry Finger	mutex_lock(&psrtpriv->silentreset_mutex);
2005e93f35209578fcabfa855e427354195e54b491fLarry Finger	psrtpriv->silent_reset_inprogress = true;
2015e93f35209578fcabfa855e427354195e54b491fLarry Finger	pwrpriv->change_rfpwrstate = rf_off;
2025e93f35209578fcabfa855e427354195e54b491fLarry Finger
2035e93f35209578fcabfa855e427354195e54b491fLarry Finger	sreset_stop_adapter(padapter);
2045e93f35209578fcabfa855e427354195e54b491fLarry Finger
2055e93f35209578fcabfa855e427354195e54b491fLarry Finger	ips_enter23a(padapter);
2065e93f35209578fcabfa855e427354195e54b491fLarry Finger	ips_leave23a(padapter);
2075e93f35209578fcabfa855e427354195e54b491fLarry Finger
2085e93f35209578fcabfa855e427354195e54b491fLarry Finger	sreset_start_adapter(padapter);
2095e93f35209578fcabfa855e427354195e54b491fLarry Finger	psrtpriv->silent_reset_inprogress = false;
2105e93f35209578fcabfa855e427354195e54b491fLarry Finger	mutex_unlock(&psrtpriv->silentreset_mutex);
2115e93f35209578fcabfa855e427354195e54b491fLarry Finger
2125e93f35209578fcabfa855e427354195e54b491fLarry Finger	DBG_8723A("%s done in %d ms\n", __func__,
2135e93f35209578fcabfa855e427354195e54b491fLarry Finger		  jiffies_to_msecs(jiffies - start));
2145e93f35209578fcabfa855e427354195e54b491fLarry Finger}
215